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

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