After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 796151 - Small border on side of single-window screenshot on Windows
Small border on side of single-window screenshot on Windows
Status: RESOLVED OBSOLETE
Product: GIMP
Classification: Other
Component: Plugins
git master
Other Windows
: Normal normal
: ---
Assigned To: GIMP Bugs
GIMP Bugs
Depends on:
Blocks:
 
 
Reported: 2018-05-15 23:24 UTC by Jehan
Modified: 2018-05-30 10:18 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
A possible solution but not tested (938 bytes, patch)
2018-05-16 07:16 UTC, Gil Eliyahu
needs-work Details | Review
Screenshot, taken on Windows 7 (110.00 KB, image/png)
2018-05-16 09:12 UTC, Simon Müller
  Details
VB.net Code (Sample) (2.26 KB, text/plain)
2018-05-17 12:11 UTC, ShiroYuki_Mot
  Details
Vb.net Executing Screen Shots (145.53 KB, image/png)
2018-05-17 12:14 UTC, ShiroYuki_Mot
  Details
Fix bug 796151 - using dwm api (11.50 KB, patch)
2018-05-19 15:58 UTC, Gil Eliyahu
none Details | Review
Updated patch (12.99 KB, patch)
2018-05-20 16:16 UTC, Gil Eliyahu
none Details | Review

Description Jehan 2018-05-15 23:24:58 UTC
After fixes from bug 793722, I can see that single-window screenshots seems to be slightly bigger than they should (by just a few pixels), so they snap a bit more than they should.

Ideally this should be fixed.
Comment 1 Simon Müller 2018-05-15 23:39:07 UTC
Just typed this as a reply in the old report but you were faster :D


First of all, thanks, Gil for fixing the bug as fast as you did and sorry that I was not able to participate for some time now, this semester brought more work with it than I initially thought :/

Regarding the additional pixels around the window borders: I also noticed those with my first simple patch. But while playing around for a bit, I noticed that they indeed seem to be a part of the window. You can check this by bringing your mouse cursor close to the window border. You'll notice that for the bottom, left and right window sides, your cursor switches to the resize-window-cursor before you even reach the real, visible window boundaries. My guess is that this is the area where the window border would have been if Windows 10's windows still had borders on all four sides. 

If this is correct, you can't really cut this part away because on older Windows versions it might actually contain pixels that belong to the window. I will test this on a Windows 7 system in my university tomorrow and report back.
Comment 2 Jehan 2018-05-16 00:39:03 UTC
Oh ok. If that's really the case, it's a bit crappy that Windows don't have proper accurate API.

Anyway tell us how the tests go. :-)
Comment 3 Gil Eliyahu 2018-05-16 06:23:28 UTC
I am very happy to help and contribute from my experience.

According to my experience with Windows, I confirm that Microsoft makes life difficult.

But I believe there is no such thing as "no solution" in most cases.

I know about the problem. It's a bug that always existed also before my patch.

This is one of the few bugs I could not solve.
I did found a kind of start of a solution .. but it creates problems in other cases. I need to check it further.
Comment 4 Michael Schumacher 2018-05-16 07:05:00 UTC
Is this maybe some theme-related shadow?
Comment 5 Gil Eliyahu 2018-05-16 07:16:33 UTC
Created attachment 372109 [details] [review]
A possible solution but not tested

This is a possible solution. it may be a start.

I changed the line 
if (!GetWindowRect (selectedHwnd, &rect))

to
if (!GetClientRect(selectedHwnd,&rect) || !ClientToScreen(selectedHwnd,&rect))


It's important to note that I was not able to check it out properly -
I have a problem in build system now so I could not build gimp.

However, it should work. I am surprised.. I did a test code and always it gave me the correct and accurate RECT data.

I have not found a case where I get wrong RECT data.
So maybe it's a solution. But it needs loads of testing!
Comment 6 Gil Eliyahu 2018-05-16 07:30:32 UTC
Sorry,
I was wrong. It should be this:

.............
.............

static gboolean
doCapture (HWND selectedHwnd)
{
  RECT rect;
  POINT point;

  /* Try and get everything out of the way before the
   * capture.
   */
  Sleep (500 + winsnapvals.delay * 1000);

  /* Are we capturing a window or the whole screen */
  if (selectedHwnd)
    {
      ZeroMemory(&point, sizeof(POINT));
      if (!GetClientRect(selectedHwnd,&rect) || !ClientToScreen(selectedHwnd,&point))
      /* For some reason it works only if we return here TRUE. strange... */
          return TRUE;

      rect.left = point.x;
      rect.top = point.y;
      rect.right += point.x;
      rect.bottom += point.y;



.............
.............
Comment 7 Gil Eliyahu 2018-05-16 08:02:24 UTC
As I feared,
It does not work properly for everything.
If it build and you try it, it may give good result on lot of windows..
but for notepad for example it will not capture everything. the title border of the notepad window will not be included in the image.

I think we can still use combination of:
*Output of ClientToScreen
*Output of GetClientRect
*Output of GetWindowRect

This is probably a crazy trick .. but it can solve the problem and that is what matters.

Tomorrow I will submit a patch based on the idea. Assuming it will work correctly.
Comment 8 Simon Müller 2018-05-16 09:12:31 UTC
Created attachment 372115 [details]
Screenshot, taken on Windows 7

As promised I just checked on Windows 7 and attached the result. As you can see, there was a border around the window that is pretty much the same size as the small border of "wrong pixels" you see on Windows 10.

Regarding Michael's idea that it might be the result of the window shadows:
This was my first thought, too. But Windows 10's windows have shadows all around them and at least for me the wrong pixels only occur on three borders: left, bottom and right. For the top border everything is fine although there is a shadow. 

Now we have the following problem: We can't simply check for the Windows version and cut a piece of the image away if we are on Windows 10 because someone might install a different theme that brings back the border around the windows. 

@Gil: What is your solution supposed to do? 
I just tried to understand what you are doing and it does not make much sense to me right now. If GetClientRect succeeds, the left part of the condition is 0 and ClientToScreen gets executed - which overwrites the result we just got from GetClientRect. If GetClientRect does not succeed though, the left side is 1 and ClientToScreen is short-circuited.
Comment 9 Gil Eliyahu 2018-05-16 10:05:18 UTC
@Simon Müller,
Look at the code in comment 7.

If one of the functions fails in the condition then we return TRUE in order to avoid continue.

The only way that the condition will not return TRUE is if both functions in the condition returned non-zero.

The condition first check if the first function failed.
If in the left side of the condition we did not got  false, then it must be true.
otherwise, in case that we got false (zero), the condition will immediately return to stop the function.

In the second case that the left side is not false (non-zero), then it must be true. (so the first function call did not failed) so the machine will continue to the next part of the condition - "is the second function failed?"
If second function returned zero=failed=false then the answer to the question is yes -> the condition will return to stop the doCapture function
if no, (that means that the second function returned non-zero = not failed) then condition will not return to stop the doCapture function.

in such a case, both functions did NOTNOT succeeded = succeeded we should continue to run the doCapture function.

This can also be easily explained by boolean algebra
http://prntscr.com/jij8hy


Maybe I'm wrong .. I'd love to learn from mistakes.
In any case, with regard to the solution itself, I did not behave professionally.
Next time I will check the patch in depth (as I did before) before I publish.
Comment 10 Simon Müller 2018-05-16 13:20:51 UTC
Oh, my brain somehow projected the snippet from comment 5 into the one in comment 6. This is why I thought you were overwriting &rect with the call to ClientToScreen. Sorry for that...
Comment 11 Jehan 2018-05-16 13:22:22 UTC
> In any case, with regard to the solution itself, I did not behave professionally.
> Next time I will check the patch in depth (as I did before) before I publish.

No need to self-blame yourself. You are doing a good job and sharing ideas on bugzilla (even when still untested) is actually a very good practice.

And if you make mistakes, so what? Professionals do make mistakes too. This is not a problem at all and nobody will chastise you for it. :-)
Comment 12 Gil Eliyahu 2018-05-16 22:14:43 UTC
Thanks Jehan!


Simon Müller,
I now understand your findings

You seem to have come to the correct conclusion that the borders are simply invisible. in Windows 7 we do not feel there is a problem at all because the same borders are not invisible.

As you say, we may cut the borders but then could be a bug when the user changed the theme...

Therefore, I believe that a perfect solution to the problem is not possible.

Perhaps we should think of a solution based on image processing.
It can sound crazy and it's indeed crazy.

This is not the first time doing crazy ideas. I have already written an algorithm that separates between pixels that are texts and pixels that are background.. 

This time I have an idea for algorithm that find sharp corners. it's starting point is the output of GetWindowRect.

Jehan, (Or anyone else that in charge) Do you want me to work in that direction?
Comment 13 Jehan 2018-05-16 22:57:12 UTC
> Jehan, (Or anyone else that in charge) Do you want me to work in that direction?

I want you to work in any direction you feel appropriate. :-)

If you both believe that there is no correct solution to the problem because of invisible borders, then do not hesitate to close yourself the report as NOTABUG.

If you think there is a solution, but it is not worth the effort (because too complicated/convoluted), then nobody will resent you for not doing it (then you can close as WONTFIX).

Basically: contribute in a comfortable way. This is how we hope you will stay around, and hopefully contribute more and more! ;-)

But really *seriously*: I want you to choose if you think this is worth the effort. I personally feel that your idea is a complicated path and sounds like over-engineering. If you really want to try and it turns out to work without any drawback, why not. But don't do it if you think you'd be wasting your time for a very minor issue in the end. I'm perfectly fine with just closing this report as a WONTFIX.

By the way, regarding "who is in charge", as far as we are concerned, for all Windows-specific matters, you could both be considered in charge if you continue contributing on regular basis. You are what we are the closest to Windows expert since we are seriously lacking Windows developers. We have a loooot of other bugs which can be fixed on the Windows build and we welcome any Windows developer to help us. So don't worry, if we close this one now, you can start right away on another bug. :p
Comment 14 Simon Müller 2018-05-16 23:03:44 UTC
Fun fact: Microsoft seems to have had this same exact problem: https://blogs.msdn.microsoft.com/oldnewthing/20171024-00/?p=97275

But they somehow fixed it for their screenshot tools (Alt+PrtScr, Snipping Tool).

After all, there has to be a better way to do this without falling back to some hacky analysis of image contents.
Comment 15 Simon Müller 2018-05-16 23:09:30 UTC
Aaand right after posting I found this: https://www.cyotek.com/blog/getting-a-window-rectangle-without-the-drop-shadow ...

This article mentions a function called DwmGetWindowAttribute (from dwmapi.dll, available on Windows Vista and higher, docs: https://msdn.microsoft.com/de-de/library/windows/desktop/aa969515(v=vs.85).aspx) that is supposed to be able to return the correct window position without that additional border.

The example uses C# but it should be rather easy to transfer it over to C.
Comment 16 Jehan 2018-05-16 23:37:41 UTC
(In reply to Simon Müller from comment #15)
> Aaand right after posting I found this:
> https://www.cyotek.com/blog/getting-a-window-rectangle-without-the-drop-
> shadow ...
> 
> This article mentions a function called DwmGetWindowAttribute (from
> dwmapi.dll, available on Windows Vista and higher, docs:
> https://msdn.microsoft.com/de-de/library/windows/desktop/aa969515(v=vs.85).
> aspx) that is supposed to be able to return the correct window position
> without that additional border.
> 
> The example uses C# but it should be rather easy to transfer it over to C.

Sounds like a better option!
Comment 17 Gil Eliyahu 2018-05-16 23:58:03 UTC
Jehan, I'm not sure I would have done it anyway. It is indeed too much work for a small bug.

Simon Müller, well done.
You did what I did in the previous bug - giving a working solution to a problem previously considered as unsolvable. 

Good work!
Comment 18 ShiroYuki_Mot 2018-05-17 05:59:13 UTC
Same as Comment 15.

'Keyword' = 'DwmGetWindowAttribute() API' or 'DwmExtendFrameIntoClientArea() API'
https://msdn.microsoft.com/en-us/library/windows/desktop/aa969512(v=vs.85).aspx
Ref; ja/jp) http://www.webtech.co.jp/blog/os/win10/8445/  (Japanese! But Pictures are useful)

PS: Please Not Add Me into CC list.  :)
Comment 19 ShiroYuki_Mot 2018-05-17 12:07:41 UTC
I got time, so I wrote the code, Please see it. It is VB.net.
For me, there are almost no cases to operate the API, so please take a look at that.
Although the title bar and the part of the window frame are unfine, the client area seems to have no problem.
I have not had time anymore, so it's end.
Separately, how about overlapping the acquired title part etc?
Also, because it is GDI, I feel that the image becomes a bit dirty.
Is it helpful? :)
Comment 20 ShiroYuki_Mot 2018-05-17 12:11:02 UTC
Created attachment 372142 [details]
VB.net Code (Sample)

for Comment 19
Comment 21 ShiroYuki_Mot 2018-05-17 12:14:27 UTC
Created attachment 372143 [details]
Vb.net Executing Screen Shots
Comment 22 Jehan 2018-05-17 12:21:03 UTC
Thanks ShiroYuki. Unfortunately we cannot use VB.net code in GIMP. But maybe it will help others to write a patch by converting to C calls.
Comment 23 Jehan 2018-05-18 23:49:19 UTC
(In reply to ShiroYuki_Mot from comment #18)
> PS: Please Not Add Me into CC list.  :)

Removing ShiroYuki from Cc as per-request.
I believe you can do it yourself, by the way, just so you know! ;-)
Comment 24 ShiroYuki_Mot 2018-05-19 01:06:26 UTC
Dear Jehan, Thanks for your removing.  (Comment 23)

To me, Windows APIs are too high hurdle...
Perhaps, I'll never be able to resolve the problem of a title-bar popping out of the screen area and the quality of capturing image. Never...
Because of I have too little of that knowledge. X(

... There are a way to ask questions in the msdn forum category of your country (ex.; C++) to get the key to solution.

I hope GIMP's Great Developers resolve it. And I am waiting. :)
Comment 25 Gil Eliyahu 2018-05-19 06:51:54 UTC
Hello, I see that the person who suggested the excellent solution has not yet released a patch. 

Are you waiting for someone else to implement the patch?
I can try to implement the idea you suggested (using the dwm api). I just do not know if you're working on it. If not then I can start working on it now :) !
Comment 26 ShiroYuki_Mot 2018-05-19 08:09:58 UTC
Dear Gil Eliyahu, Is this comment (Comment 25) for me?.

If Yes, the answer is that 'Please Use my idea!'.
(Is my idea helpful?)
I can not write VC++, GCC and C. (only vb.net).
Therefore, a patch ... Oh, Nothing at all...
My position is an end user who can write a script a bit. (... not a developer)
(And really I don't understand English ... Sorry, My Poor English...)

Before that, First!, I'd like to say you that the great function you proposed is that everybodies smile. :)
and, we (the end users) get a new great Developer!. Thanks a lot. :) :)

PS; Removing me from CC list after posting this comment.
Comment 27 Simon Müller 2018-05-19 08:17:24 UTC
Hey Gil, yeah go ahead - I tried to do it myself but I somehow screwed up the dependencies - so now I can't compile GIMP (and therefore don't test the stuff I write) until I sorted everything out. 

I compile with msys2 which has the forbidden new version of glib in its default packages. But as soon as I compile an older glib myself, GIMP's configure script suddenly complains about missing GTK+ and glib-networking.
Comment 28 Gil Eliyahu 2018-05-19 08:32:39 UTC
Ok, I'll try to implement the patch :)

ShiroYuki_Mot, I'm glad to hear your gratitude. Thank you :)
Comment 29 Gil Eliyahu 2018-05-19 15:58:20 UTC
Created attachment 372223 [details] [review]
Fix bug 796151 - using dwm api

Hello, I'm done developing the patch.

Please check it out. It need testing undew Windows 7 , vista.
I tested it on Windows 10.

Make sure I did not did anything wrong.


And I think you need to also mention the name of Simon Müller as the a person who gave the idea how to fix the bug



I must say that I also had a problem with bulding gimp.
so I did:
"git reset --hard 1139c00721da11cd1fae1d78b16a02c404346d6b"

it is commit:
Author: Ell <ell_se@yahoo.com>
Date:   Sat May 12 09:23:40 2018 -0400

    app: in GimpHistogramEditor, avoid calculating histogram of detached layers
    
    ... which results in CRITICALs.  This can evidentially happen during
    gimp_image_remove_layer() under certain circumstances (see comment
    in the patch.)


That's the only way I could work on it and check it out.
Please fix this build problem that happens after this commit.


I hope I helped!
Comment 30 Gil Eliyahu 2018-05-19 16:23:21 UTC
Review of attachment 372223 [details] [review]:

::: plug-ins/screenshot/dwm-api-win32.h
@@ +2,3 @@
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * Magnification-win32.h

It should be:
dwm-api-win32.h

@@ +48,3 @@
+void UnloadRequiredDwmFunctions(void)
+{
+	if (dwmApi) return;

It should be:
if (!dwmApi) return;
Comment 31 Jehan 2018-05-19 23:26:46 UTC
Review of attachment 372223 [details] [review]:

Thanks for the patch Gil.

Why do you redefine DWMWINDOWATTRIBUTE? I can see it is in a public API of Windows. Why don't you just include necessary headers?
It's not a very good idea to copy code this way.

Also do you need to create another file just to load/unload an API?

Finally be careful, you add again a lot of tabs, trailing spaces, and various coding style issues (misaligned braces, etc.).
Comment 32 Gil Eliyahu 2018-05-20 04:57:20 UTC
It just did not work when I included
#include <Dwmapi.h>
It did not worked.

DWMWINDOWATTRIBUTE is defined under Dwmapi.h

The problem is that according to Microsoft docs I need also to include Dwmapi.lib (the same case as with magnification api)
There is no way to include lib files in your build system.

So I did custom dwn api header that that eliminates the need of lib file.
I use "Dynamic Link Library" (dll) to disable the need of lib.


"Also do you need to create another file just to load/unload an API?"
I think it's more organized to do it that way.

To me it does not make sense to add lines that related to dwm functionality to the main cdoe of the plugin. 

You want me to do that?

"Finally be careful, you add again a lot of tabs, trailing spaces, and various coding style issues (misaligned braces, etc.)."
Okay, yes I forgot to adjust coding style to the requirements. I'll fix it.
Comment 33 Jehan 2018-05-20 13:10:31 UTC
Ok do it your way then. :-)
Just fix the coding style, and that should be enough.
Comment 34 Gil Eliyahu 2018-05-20 16:16:46 UTC
Created attachment 372248 [details] [review]
Updated patch

Hello,

I did the coding style correction I found and also logic correction in function doCaptureMagnificationAPI - I added the variable round4Rect in my function...

This correction fixed a bug under function sendBMPToGimp. the bug is that it was never did this (when it called from my function) - 
gimp_layer_resize (layer_id, width, height, 0, 0);
gimp_image_resize (new_image_id, width, height, 0, 0);

These two lines are supposed to do cropping when the width was round up.

So the reason for this border bug was also this and it fixed now..

I tested it on Windows 10 and it is perfect!
It should be noted that this was not tested in Windows 7 and 8 and I can't test it so you need to test it on these operating systems also.

I hope that now it is better :)
Comment 35 GNOME Infrastructure Team 2018-05-24 20:01:32 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to GNOME's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.gnome.org/GNOME/gimp/issues/1458.
Comment 36 Jehan 2018-05-30 10:18:06 UTC
Gil > I pushed your patch. Please see my last message on gitlab: https://gitlab.gnome.org/GNOME/gimp/issues/1458#note_227378

Did you make an account on our new gitlab? As you must know by now, we migrated and won't be using bugzilla anymore!