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 733679 - GDK does not handle WM_NCHITTEST
GDK does not handle WM_NCHITTEST
Status: RESOLVED FIXED
Product: gtk+
Classification: Platform
Component: Backend: Win32
unspecified
Other Windows
: Normal minor
: ---
Assigned To: gtk-win32 maintainers
gtk-bugs
Depends on:
Blocks:
 
 
Reported: 2014-07-24 14:20 UTC by LRN
Modified: 2014-07-29 01:39 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
W32: Implement rudimentary WM_NCHITTEST handling (2.95 KB, patch)
2014-07-24 17:08 UTC, LRN
reviewed Details | Review
Re-sizing CSDed window - before (2.89 KB, image/png)
2014-07-24 17:10 UTC, LRN
  Details
Re-sizing CSDed window - after (3.06 KB, image/png)
2014-07-24 17:11 UTC, LRN
  Details
W32: report input shapes as supported, fix comments (1.63 KB, patch)
2014-07-25 23:49 UTC, LRN
needs-work Details | Review
W32: Implement rudimentary WM_NCHITTEST handling (4.22 KB, patch)
2014-07-26 09:00 UTC, LRN
committed Details | Review

Description LRN 2014-07-24 14:20:24 UTC
WM_NCHITTEST http://msdn.microsoft.com/en-us/library/windows/desktop/ms645618%28v=vs.85%29.aspx message is used for W32 WM to get information about a point on the screen being inside or not inside a window, and if it is inside, then in which part of the window it is (titlebar, one of the titlebar buttons, border, corner, client area).

Normally (and that is currently all that GDK does) this message is handled by DefWindowProc(), but since W32 has no input regions that i know of, a more elaborate handling of WM_NCHITTEST may be used as a substitute.

I.e. check whether a point is in the cairo region that describes window input region, and return HTNOWHERE if it isn't; otherwise defer to DefWindowProc() for its usual processing. Also, currently W32 WM considers the whole outside-of-the-window region of the CSD (the one used to draw a shadow) as a resize grip (for resizeable windows), which looks ugly and out of place (because this region is big, much bigger than the shadow). Handling of WM_NCHITTEST could help with that too.
Comment 1 LRN 2014-07-24 17:08:08 UTC
Created attachment 281624 [details] [review]
W32: Implement rudimentary WM_NCHITTEST handling

Use (cairo) input shape of the window to check whether a point is inside or not
inside the window.
If it is, let the default window procedure do its thing (which seems to be
working all right in all known cases).
If it isn't, override the default window procedure and tell WM what we think.

Don't do any of the above if the window has CSD-incompatible styles (WS_BORDER
or WS_THICKFRAME).

This is a crude kind of substitute for window input shape support (which W32
does not seem to have).
Comment 2 LRN 2014-07-24 17:10:36 UTC
Created attachment 281625 [details]
Re-sizing CSDed window - before

This is the farthest extent of the resize hitbox (one pixel to the left, and it's gone). Obviously, it's extends much further than it should be, and much further than the window shadow, in particular.
Comment 3 LRN 2014-07-24 17:11:51 UTC
Created attachment 281626 [details]
Re-sizing CSDed window - after

This is the outside of the hitbox extents (one pixel to the left, and the cursor will change to a resize cursor). Much smaller and nicer, IMO.
Comment 4 LRN 2014-07-24 17:17:11 UTC
Ouch, s/left/right/ for attachment 281626 [details], obviously.

Non-CSDed windows are unaffected by this (they have appropriate W32 decorations, and the code sees that).

Also, i feel i should note that GTK arranges resize hitbox differently from W32.

W32 adds a border *within* the window (i.e. pads the contents of the window, or adds a thick frame, depends on your point of view), and lets you grip that, whereas window shadow is non-clickable.

GTK puts resize hitbox in the same area where shadow is (so you, basically, catch and drag the shadow to resize the window).
Comment 5 Ignacio Casal Quinteiro (nacho) 2014-07-24 18:19:43 UTC
Review of attachment 281624 [details] [review]:

See the comment. Apart from that I am ok with it, if you tested with all kind of window types and it works fine I'd say get an ack from mclasen.

::: gdk/win32/gdkevents-win32.c
@@ +3277,3 @@
       break;
+    case WM_NCHITTEST:
+      /* TODO: pass all messages to DwmDefWindowProc() first! */

what about this? is it safe? should we open a new bug report for this?
Comment 6 LRN 2014-07-24 18:51:42 UTC
(In reply to comment #5)
> Review of attachment 281624 [details] [review]:
> 
> See the comment. Apart from that I am ok with it, if you tested with all kind
> of window types and it works fine I'd say get an ack from mclasen.
> 
> ::: gdk/win32/gdkevents-win32.c
> @@ +3277,3 @@
>        break;
> +    case WM_NCHITTEST:
> +      /* TODO: pass all messages to DwmDefWindowProc() first! */
> 
> what about this? is it safe? should we open a new bug report for this?

While looking at MSDN http://msdn.microsoft.com/en-us/library/windows/desktop/ms645618%28v=vs.85%29.aspx for docs on WM_NCHITTEST, i found this little factoid:

> Windows Vista: When creating custom frames that include the standard caption buttons, this message should first be passed to the DwmDefWindowProc function. This enables the Desktop Window Manager (DWM) to provide hit-testing for the captions buttons. If DwmDefWindowProc does not handle the message, further processing of WM_NCHITTEST may be needed.

I'm not sure whether GTK is affected or not.
Here's a simpler case of how things got screwed up because of this:
http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/9a8a63c8-79b5-43a8-82eb-f659be947add/how-to-hit-test-nonclient-buttons-in-vista
GTK doesn't seem to be relying on this at the moment though...
Comment 7 LRN 2014-07-24 19:07:44 UTC
OK, apparently, this only applies to nonstandard frames, i.e. when you partially disable the standard frame, leaving only min/max/close buttons, and draw your own stuff over it - in that case you need to use DwmDefWindowProc().

Since GTK either uses the standard frame, or throws it away completely, it shouldn't be concerned.
Comment 8 Matthias Clasen 2014-07-25 02:17:08 UTC
Review of attachment 281624 [details] [review]:

I guess now that we are actually handling input shapes, the comments in gdk_window_input_shape_combine_region are somewhat misleading, and gdk_win32_display_supports_input_shapes should be updated to return TRUE ?
Comment 9 LRN 2014-07-25 05:27:30 UTC
That depends on how gdk_win32_display_supports_input_shapes() return value is interpreted by the callers.

And now that we're talkin thinking about it, remember that gdk_display_supports_input_shapes() is only used by the x11 backend, so there's no actual code to investigate.

Changing gdk_win32_display_supports_input_shapes() to return TRUE may be acceptable, if we establish what "supports input shapes" means, and what guarantees could be provided about its support on W32.
Comment 10 Matthias Clasen 2014-07-25 11:07:02 UTC
It is supposed to tell users of the API that they can use gdk_window_input_shape_combine_mask() to modify where input has an effect. Seeing that not event GTK+ calls it before applying input shapes, maybe it is not worth worrying about. Returning TRUE would seem right to me, though, if input shapes basically work now.
Comment 11 LRN 2014-07-25 23:49:11 UTC
Created attachment 281741 [details] [review]
W32: report input shapes as supported, fix comments
Comment 12 Ignacio Casal Quinteiro (nacho) 2014-07-26 08:13:17 UTC
Review of attachment 281741 [details] [review]:

I'd say squash both patches so it is easier to read.
Comment 13 LRN 2014-07-26 09:00:56 UTC
Created attachment 281757 [details] [review]
W32: Implement rudimentary WM_NCHITTEST handling

Use (cairo) input shape of the window to check whether a point is inside or not
inside the window.
If it is, let the default window procedure do its thing (which seems to be
working all right in all known cases).
If it isn't, override the default window procedure and tell WM what we think.

Don't do any of the above if the window has CSD-incompatible styles (WS_BORDER
or WS_THICKFRAME).

This is a crude kind of substitute for window input shape support (which W32
does not seem to have). Still probably enough to be positive about input shapes
support.
Comment 14 Ignacio Casal Quinteiro (nacho) 2014-07-26 10:14:12 UTC
Review of attachment 281757 [details] [review]:

Looks good to me, get an ack from mclasen though.
Comment 15 Matthias Clasen 2014-07-28 22:04:25 UTC
ack
Comment 16 LRN 2014-07-29 01:38:54 UTC
Attachment 281757 [details] pushed as a23c29c - W32: Implement rudimentary WM_NCHITTEST handling