|
|
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 |
|