Blame SOURCES/0001-events-Sync-pending-pointer-events-without-a-window.patch

f73620
From 3582d1780c9bf3fc93604963a11b9b60d9895178 Mon Sep 17 00:00:00 2001
f73620
From: Olivier Fourdan <ofourdan@redhat.com>
f73620
Date: Wed, 2 Oct 2019 16:49:28 +0200
f73620
Subject: [PATCH] events: Sync pending pointer events without a window
f73620
f73620
Mutter issues a synchronous grab on the pointer for unfocused client
f73620
windows to be able to catch the button events first and raise/focus
f73620
client windows accordingly.
f73620
f73620
When there is a synchronous grab in effect, all events are queued until
f73620
the grabbing client releases the event queue as it processes the events.
f73620
f73620
Mutter does release the events in its event handler function but does so
f73620
only if it is able to find the window matching the event. If the window
f73620
is a shell widget, that matching may fail and therefore Mutter will not
f73620
release the events, hence causing a freeze in pointer events delivery.
f73620
f73620
To avoid the issue, make sure we sync the pointer events in case we
f73620
can't find a matching window.
f73620
f73620
https://gitlab.gnome.org/GNOME/mutter/merge_requests/821
f73620
---
f73620
 src/core/events.c | 62 ++++++++++++++++++++++++++++++++++++++---------
f73620
 1 file changed, 51 insertions(+), 11 deletions(-)
f73620
f73620
diff --git a/src/core/events.c b/src/core/events.c
f73620
index 92503a168..9b19065fb 100644
f73620
--- a/src/core/events.c
f73620
+++ b/src/core/events.c
f73620
@@ -51,6 +51,12 @@
f73620
 #define IS_KEY_EVENT(e) ((e)->type == CLUTTER_KEY_PRESS || \
f73620
                          (e)->type == CLUTTER_KEY_RELEASE)
f73620
 
f73620
+typedef enum
f73620
+{
f73620
+  EVENTS_UNFREEZE_SYNC,
f73620
+  EVENTS_UNFREEZE_REPLAY,
f73620
+} EventsUnfreezeMethod;
f73620
+
f73620
 static gboolean
f73620
 stage_has_key_focus (void)
f73620
 {
f73620
@@ -167,6 +173,43 @@ sequence_is_pointer_emulated (MetaDisplay        *display,
f73620
   return FALSE;
f73620
 }
f73620
 
f73620
+static void
f73620
+maybe_unfreeze_pointer_events (MetaBackend          *backend,
f73620
+                               const ClutterEvent   *event,
f73620
+                               EventsUnfreezeMethod  unfreeze_method)
f73620
+{
f73620
+  Display *xdisplay;
f73620
+  int event_mode;
f73620
+  int device_id;
f73620
+
f73620
+  if (event->type != CLUTTER_BUTTON_PRESS)
f73620
+    return;
f73620
+
f73620
+  if (!META_IS_BACKEND_X11 (backend))
f73620
+    return;
f73620
+
f73620
+  device_id = clutter_event_get_device_id (event);
f73620
+  switch (unfreeze_method)
f73620
+    {
f73620
+    case EVENTS_UNFREEZE_SYNC:
f73620
+      event_mode = XISyncDevice;
f73620
+      meta_verbose ("Syncing events time %u device %i\n",
f73620
+                    (unsigned int) event->button.time, device_id);
f73620
+      break;
f73620
+    case EVENTS_UNFREEZE_REPLAY:
f73620
+      event_mode = XIReplayDevice;
f73620
+      meta_verbose ("Replaying events time %u device %i\n",
f73620
+                    (unsigned int) event->button.time, device_id);
f73620
+      break;
f73620
+    default:
f73620
+      g_assert_not_reached ();
f73620
+      return;
f73620
+    }
f73620
+
f73620
+  xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
f73620
+  XIAllowEvents (xdisplay, device_id, event_mode, event->button.time);
f73620
+}
f73620
+
f73620
 static gboolean
f73620
 meta_display_handle_event (MetaDisplay        *display,
f73620
                            const ClutterEvent *event)
f73620
@@ -366,17 +409,7 @@ meta_display_handle_event (MetaDisplay        *display,
f73620
         {
f73620
           /* Only replay button press events, since that's where we
f73620
            * have the synchronous grab. */
f73620
-          if (event->type == CLUTTER_BUTTON_PRESS)
f73620
-            {
f73620
-              if (META_IS_BACKEND_X11 (backend))
f73620
-                {
f73620
-                  Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
f73620
-                  meta_verbose ("Allowing events time %u\n",
f73620
-                                (unsigned int)event->button.time);
f73620
-                  XIAllowEvents (xdisplay, clutter_event_get_device_id (event),
f73620
-                                 XIReplayDevice, event->button.time);
f73620
-                }
f73620
-            }
f73620
+          maybe_unfreeze_pointer_events (backend, event, EVENTS_UNFREEZE_REPLAY);
f73620
 
f73620
           /* If the focus window has an active close dialog let clutter
f73620
            * events go through, so fancy clutter dialogs can get to handle
f73620
@@ -392,6 +425,13 @@ meta_display_handle_event (MetaDisplay        *display,
f73620
 
f73620
       goto out;
f73620
     }
f73620
+  else
f73620
+    {
f73620
+      /* We could not match the event with a window, make sure we sync
f73620
+       * the pointer to discard the sequence and don't keep events frozen.
f73620
+       */
f73620
+       maybe_unfreeze_pointer_events (backend, event, EVENTS_UNFREEZE_SYNC);
f73620
+    }
f73620
 
f73620
  out:
f73620
   /* If the compositor has a grab, don't pass that through to Wayland */
f73620
-- 
f73620
2.23.0
f73620