[gtk/wip/chergert/for-macos-1] macos: ignore mouse events outside tracking area



commit a080f1197a25b7108870ff9873c59c8e6e127190
Author: Christian Hergert <christian hergert me>
Date:   Mon Feb 14 02:16:07 2022 -0800

    macos: ignore mouse events outside tracking area
    
    We also need to ignore events outside the tracking areas when we are
    translating them from NSevent into GdkEvent.

 gdk/macos/gdkmacosdisplay-translate.c | 22 ++++++++++++++--------
 gdk/macos/gdkmacosdisplay.c           |  8 ++++++++
 2 files changed, 22 insertions(+), 8 deletions(-)
---
diff --git a/gdk/macos/gdkmacosdisplay-translate.c b/gdk/macos/gdkmacosdisplay-translate.c
index 4eac28a8af..e62a157e50 100644
--- a/gdk/macos/gdkmacosdisplay-translate.c
+++ b/gdk/macos/gdkmacosdisplay-translate.c
@@ -211,6 +211,7 @@ fill_button_event (GdkMacosDisplay *display,
   GdkDevice *pointer = NULL;
   GdkDeviceTool *tool = NULL;
   double *axes = NULL;
+  cairo_region_t *input_region;
 
   g_assert (GDK_IS_MACOS_DISPLAY (display));
   g_assert (GDK_IS_MACOS_SURFACE (surface));
@@ -218,6 +219,7 @@ fill_button_event (GdkMacosDisplay *display,
   seat = gdk_display_get_default_seat (GDK_DISPLAY (display));
   state = get_keyboard_modifiers_from_ns_event (nsevent) |
          _gdk_macos_display_get_current_mouse_modifiers (display);
+  input_region = GDK_SURFACE (surface)->input_region;
 
   switch ((int)[nsevent type])
     {
@@ -244,7 +246,8 @@ fill_button_event (GdkMacosDisplay *display,
    */
   if (type == GDK_BUTTON_PRESS &&
       (x < 0 || x > GDK_SURFACE (surface)->width ||
-       y < 0 || y > GDK_SURFACE (surface)->height))
+       y < 0 || y > GDK_SURFACE (surface)->height ||
+       (input_region && !cairo_region_contains_point (input_region, x, y))))
     return NULL;
 
   if (([nsevent subtype] == NSEventSubtypeTabletPoint) &&
@@ -906,7 +909,13 @@ find_surface_for_mouse_event (GdkMacosDisplay *self,
   GdkDeviceGrabInfo *grab;
   GdkSeat *seat;
 
-  surface = get_surface_from_ns_event (self, nsevent, &point, x, y);
+  /* Even if we had a surface window, it might be for something outside
+   * the input region (shadow) which we might want to ignore. This is
+   * handled for us deeper in the event unwrapping.
+   */
+  if (!(surface = get_surface_from_ns_event (self, nsevent, &point, x, y)))
+    return NULL;
+
   display = gdk_surface_get_display (surface);
   seat = gdk_display_get_default_seat (GDK_DISPLAY (self));
   pointer = gdk_seat_get_pointer (seat);
@@ -1008,11 +1017,6 @@ find_surface_for_ns_event (GdkMacosDisplay *self,
   g_assert (x != NULL);
   g_assert (y != NULL);
 
-  if (!(surface = get_surface_from_ns_event (self, nsevent, &point, x, y)))
-    return NULL;
-
-  view = (GdkMacosBaseView *)[GDK_MACOS_SURFACE (surface)->window contentView];
-
   _gdk_macos_display_from_display_coords (self, point.x, point.y, &x_tmp, &y_tmp);
 
   switch ((int)[nsevent type])
@@ -1037,7 +1041,9 @@ find_surface_for_ns_event (GdkMacosDisplay *self,
       /* Only handle our own entered/exited events, not the ones for the
        * titlebar buttons.
        */
-      if ([nsevent trackingArea] == [view trackingArea])
+      if ((surface = get_surface_from_ns_event (self, nsevent, &point, x, y)) &&
+          (view = (GdkMacosBaseView *)[GDK_MACOS_SURFACE (surface)->window contentView]) &&
+          ([nsevent trackingArea] == [view trackingArea]))
         return GDK_MACOS_SURFACE (surface);
       else
         return NULL;
diff --git a/gdk/macos/gdkmacosdisplay.c b/gdk/macos/gdkmacosdisplay.c
index a76cc1e111..f14a1b16f8 100644
--- a/gdk/macos/gdkmacosdisplay.c
+++ b/gdk/macos/gdkmacosdisplay.c
@@ -968,6 +968,14 @@ _gdk_macos_display_get_surface_at_coords (GdkMacosDisplay *self,
           *surface_x = x - GDK_MACOS_SURFACE (surface)->root_x;
           *surface_y = y - GDK_MACOS_SURFACE (surface)->root_y;
 
+          /* One last check to make sure that the x,y is within the input
+           * region of the window. Otherwise we might send the event to the
+           * wrong window because of window shadow.
+           */
+          if (surface->input_region != NULL &&
+              !cairo_region_contains_point (surface->input_region, *surface_x, *surface_y))
+            continue;
+
           return GDK_MACOS_SURFACE (surface);
         }
     }


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