[gtk+] W32: Implement rudimentary WM_NCHITTEST handling



commit a23c29c0fb7c9f5064fd16f42c66a79f8f386352
Author: Руслан Ижбулатов <lrn1986 gmail com>
Date:   Thu Jul 24 16:27:09 2014 +0000

    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.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=733679

 gdk/win32/gdkdisplay-win32.c |    7 +----
 gdk/win32/gdkevents-win32.c  |   45 ++++++++++++++++++++++++++++++++++++++++++
 gdk/win32/gdkwindow-win32.c  |    5 +--
 3 files changed, 49 insertions(+), 8 deletions(-)
---
diff --git a/gdk/win32/gdkdisplay-win32.c b/gdk/win32/gdkdisplay-win32.c
index 3f83a83..4976e77 100644
--- a/gdk/win32/gdkdisplay-win32.c
+++ b/gdk/win32/gdkdisplay-win32.c
@@ -533,11 +533,8 @@ gdk_win32_display_supports_input_shapes (GdkDisplay *display)
 {
   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
 
-  /* Not yet implemented. See comment in
-   * gdk_window_input_shape_combine_mask().
-   */
-
-  return FALSE;
+  /* Partially supported, see WM_NCHITTEST handler. */
+  return TRUE;
 }
 
 static gboolean
diff --git a/gdk/win32/gdkevents-win32.c b/gdk/win32/gdkevents-win32.c
index 5a4efee..8d1d90e 100644
--- a/gdk/win32/gdkevents-win32.c
+++ b/gdk/win32/gdkevents-win32.c
@@ -1616,6 +1616,45 @@ handle_display_change (void)
   g_signal_emit_by_name (_gdk_screen, "size_changed");
 }
 
+static gboolean
+handle_nchittest (HWND hwnd,
+                  GdkWindow *window,
+                  gint16 screen_x,
+                  gint16 screen_y,
+                  gint *ret_valp)
+{
+  RECT rect;
+  LONG style;
+
+  if (window == NULL || window->input_shape == NULL)
+    return FALSE;
+
+  style = GetWindowLong (hwnd, GWL_STYLE);
+
+  /* Assume that these styles are incompatible with CSD,
+   * so there's no reason for us to override the defaults.
+   */
+  if (style & (WS_BORDER | WS_THICKFRAME))
+    return FALSE;
+
+  if (!GetWindowRect (hwnd, &rect))
+    return FALSE;
+
+  rect.left = screen_x - rect.left;
+  rect.top = screen_y - rect.top;
+
+  /* If it's inside the rect, return FALSE and let DefWindowProc() handle it */
+  if (cairo_region_contains_point (window->input_shape, rect.left, rect.top))
+    return FALSE;
+
+  /* Otherwise override DefWindowProc() and tell WM that the point is not
+   * within the window
+   */
+  *ret_valp = HTNOWHERE;
+  return TRUE;
+}
+
+
 static void
 generate_button_event (GdkEventType      type,
                        gint              button,
@@ -3236,6 +3275,12 @@ gdk_event_translate (MSG  *msg,
       if (msg->wParam && GDK_WINDOW_IS_MAPPED (window))
        ensure_stacking_on_activate_app (msg, window);
       break;
+    case WM_NCHITTEST:
+      /* TODO: pass all messages to DwmDefWindowProc() first! */
+      return_val = handle_nchittest (msg->hwnd, window,
+                                     GET_X_LPARAM (msg->lParam),
+                                     GET_Y_LPARAM (msg->lParam), ret_valp);
+      break;
 
       /* Handle WINTAB events here, as we know that gdkinput.c will
        * use the fixed WT_DEFBASE as lcMsgBase, and we thus can use the
diff --git a/gdk/win32/gdkwindow-win32.c b/gdk/win32/gdkwindow-win32.c
index 0088206..3d222a8 100644
--- a/gdk/win32/gdkwindow-win32.c
+++ b/gdk/win32/gdkwindow-win32.c
@@ -3227,9 +3227,8 @@ gdk_win32_input_shape_combine_region (GdkWindow *window,
                                      gint offset_x,
                                      gint offset_y)
 {
-  /* Input shapes are not supported: input shape is always the same as
-   * the window shape; pixels with alpha == 0 are usually not clickable,
-   * clickability can be overriden by handling WM_NCHITTEST.
+  /* Partial input shape support is implemented by handling the
+   * WM_NCHITTEST message.
    */
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]