gdk/surface: Handle clicks outside client surfaces
authorCarlos Garnacho <carlosg@gnome.org>
Fri, 23 Dec 2022 15:04:02 +0000 (16:04 +0100)
committerCarlos Garnacho <carlosg@gnome.org>
Fri, 23 Dec 2022 15:12:03 +0000 (16:12 +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.

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 f57bccdf97826b996f76efc8b5e1fba64e14aa0b..8847511bffb36d656be9c100e1582f8897fd261b 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;