gdk/surface: Handle clicks outside client surfaces
authorCarlos Garnacho <carlosg@gnome.org>
Fri, 23 Dec 2022 15:04:02 +0000 (16:04 +0100)
committerSimon McVittie <smcv@debian.org>
Sat, 9 Sep 2023 19:32:02 +0000 (20:32 +0100)
The owner_events=TRUE grab makes GDK on X11 see events happening
outside every client window as received on the grab window.
Additionally check that the pointer is inside the grab window
(i.e. it received GDK_CROSSING_NORMAL crossing events for the
core pointer) in order to handle clicks happening outside client
windows.

These new paths are expected to be a no-op on Wayland, and to
also work for touchscreen input on X11, due to emulated pointer
events.

Bug: https://gitlab.gnome.org/GNOME/gtk/-/issues/5364
Bug: https://gitlab.gnome.org/GNOME/gtk/-/issues/5400
Origin: upstream, 4.8.4, commit:826030dcc2e79dcd76d21c118c6a0a3f0994c284

Gbp-Pq: Name gdk-surface-Handle-clicks-outside-client-surfaces.patch

gdk/gdksurface.c
gdk/gdksurfaceprivate.h

index 63d55b223b495c00c570fc7eb62302970f06d990..bcdff00db3db835f1f0690c8640362c5a1bf6a38 100644 (file)
@@ -2789,9 +2789,10 @@ check_autohide (GdkEvent *event)
 {
   GdkDisplay *display;
   GdkDevice *device;
-  GdkSurface *grab_surface;
+  GdkSurface *grab_surface, *event_surface;
+  GdkEventType evtype = gdk_event_get_event_type (event);
 
- switch ((guint) gdk_event_get_event_type (event))
+ switch ((guint) evtype)
     {
     case GDK_BUTTON_PRESS:
 #if 0
@@ -2810,13 +2811,15 @@ check_autohide (GdkEvent *event)
       device = gdk_event_get_device (event);
       if (gdk_device_grab_info (display, device, &grab_surface, NULL))
         {
-          GdkSurface *event_surface;
-
           event_surface = gdk_event_get_surface (event);
-
-          if (grab_surface != event_surface &&
-              grab_surface != event_surface->parent &&
-              grab_surface->autohide)
+          if (event_surface->autohide &&
+              !event_surface->has_pointer)
+            event_surface = NULL;
+
+          if (grab_surface->autohide &&
+              (!event_surface ||
+               (grab_surface != event_surface &&
+                grab_surface != event_surface->parent)))
             {
               GdkSurface *surface = grab_surface;
 
@@ -2831,6 +2834,13 @@ check_autohide (GdkEvent *event)
             }
         }
       break;
+    case GDK_ENTER_NOTIFY:
+    case GDK_LEAVE_NOTIFY:
+      event_surface = gdk_event_get_surface (event);
+      if (event_surface->autohide &&
+          gdk_crossing_event_get_mode (event) == GDK_CROSSING_NORMAL)
+        event_surface->has_pointer = evtype == GDK_ENTER_NOTIFY;
+      break;
     default:;
     }
 
index c53368574d4d84f5760f20b87736d5f02814b11b..36cc4a90613d9b779aae4a161c28548fef502260 100644 (file)
@@ -77,6 +77,7 @@ struct _GdkSurface
   guint autohide : 1;
   guint shortcuts_inhibited : 1;
   guint request_motion : 1;
+  guint has_pointer : 1;
 
   guint request_motion_id;