GNOME Bugzilla – Bug 733679
GDK does not handle WM_NCHITTEST
Last modified: 2014-07-29 01:39:00 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.
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).
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.
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.
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).
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?
(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...
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.
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 ?
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.
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.
Created attachment 281741 [details] [review] W32: report input shapes as supported, fix comments
Review of attachment 281741 [details] [review]: I'd say squash both patches so it is easier to read.
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.
Review of attachment 281757 [details] [review]: Looks good to me, get an ack from mclasen though.
ack
Attachment 281757 [details] pushed as a23c29c - W32: Implement rudimentary WM_NCHITTEST handling