From 8d38e108c8ed85b834c4b11c92f9d2e591c95af5 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Fri, 23 Dec 2022 16:04:02 +0100 Subject: [PATCH] gdk/surface: Handle clicks outside client surfaces 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 | 26 ++++++++++++++++++-------- gdk/gdksurfaceprivate.h | 1 + 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/gdk/gdksurface.c b/gdk/gdksurface.c index 63d55b223b..bcdff00db3 100644 --- a/gdk/gdksurface.c +++ b/gdk/gdksurface.c @@ -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:; } diff --git a/gdk/gdksurfaceprivate.h b/gdk/gdksurfaceprivate.h index c53368574d..36cc4a9061 100644 --- a/gdk/gdksurfaceprivate.h +++ b/gdk/gdksurfaceprivate.h @@ -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; -- 2.30.2