kathenas / rpms / mutter

Forked from rpms/mutter 5 years ago
Clone

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

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