diff --git a/SOURCES/0001-events-Sync-pending-pointer-events-without-a-window.patch b/SOURCES/0001-events-Sync-pending-pointer-events-without-a-window.patch new file mode 100644 index 0000000..14878a7 --- /dev/null +++ b/SOURCES/0001-events-Sync-pending-pointer-events-without-a-window.patch @@ -0,0 +1,122 @@ +From 3582d1780c9bf3fc93604963a11b9b60d9895178 Mon Sep 17 00:00:00 2001 +From: Olivier Fourdan +Date: Wed, 2 Oct 2019 16:49:28 +0200 +Subject: [PATCH] events: Sync pending pointer events without a window + +Mutter issues a synchronous grab on the pointer for unfocused client +windows to be able to catch the button events first and raise/focus +client windows accordingly. + +When there is a synchronous grab in effect, all events are queued until +the grabbing client releases the event queue as it processes the events. + +Mutter does release the events in its event handler function but does so +only if it is able to find the window matching the event. If the window +is a shell widget, that matching may fail and therefore Mutter will not +release the events, hence causing a freeze in pointer events delivery. + +To avoid the issue, make sure we sync the pointer events in case we +can't find a matching window. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/821 +--- + src/core/events.c | 62 ++++++++++++++++++++++++++++++++++++++--------- + 1 file changed, 51 insertions(+), 11 deletions(-) + +diff --git a/src/core/events.c b/src/core/events.c +index 92503a168..9b19065fb 100644 +--- a/src/core/events.c ++++ b/src/core/events.c +@@ -51,6 +51,12 @@ + #define IS_KEY_EVENT(e) ((e)->type == CLUTTER_KEY_PRESS || \ + (e)->type == CLUTTER_KEY_RELEASE) + ++typedef enum ++{ ++ EVENTS_UNFREEZE_SYNC, ++ EVENTS_UNFREEZE_REPLAY, ++} EventsUnfreezeMethod; ++ + static gboolean + stage_has_key_focus (void) + { +@@ -167,6 +173,43 @@ sequence_is_pointer_emulated (MetaDisplay *display, + return FALSE; + } + ++static void ++maybe_unfreeze_pointer_events (MetaBackend *backend, ++ const ClutterEvent *event, ++ EventsUnfreezeMethod unfreeze_method) ++{ ++ Display *xdisplay; ++ int event_mode; ++ int device_id; ++ ++ if (event->type != CLUTTER_BUTTON_PRESS) ++ return; ++ ++ if (!META_IS_BACKEND_X11 (backend)) ++ return; ++ ++ device_id = clutter_event_get_device_id (event); ++ switch (unfreeze_method) ++ { ++ case EVENTS_UNFREEZE_SYNC: ++ event_mode = XISyncDevice; ++ meta_verbose ("Syncing events time %u device %i\n", ++ (unsigned int) event->button.time, device_id); ++ break; ++ case EVENTS_UNFREEZE_REPLAY: ++ event_mode = XIReplayDevice; ++ meta_verbose ("Replaying events time %u device %i\n", ++ (unsigned int) event->button.time, device_id); ++ break; ++ default: ++ g_assert_not_reached (); ++ return; ++ } ++ ++ xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); ++ XIAllowEvents (xdisplay, device_id, event_mode, event->button.time); ++} ++ + static gboolean + meta_display_handle_event (MetaDisplay *display, + const ClutterEvent *event) +@@ -366,17 +409,7 @@ meta_display_handle_event (MetaDisplay *display, + { + /* Only replay button press events, since that's where we + * have the synchronous grab. */ +- if (event->type == CLUTTER_BUTTON_PRESS) +- { +- if (META_IS_BACKEND_X11 (backend)) +- { +- Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); +- meta_verbose ("Allowing events time %u\n", +- (unsigned int)event->button.time); +- XIAllowEvents (xdisplay, clutter_event_get_device_id (event), +- XIReplayDevice, event->button.time); +- } +- } ++ maybe_unfreeze_pointer_events (backend, event, EVENTS_UNFREEZE_REPLAY); + + /* If the focus window has an active close dialog let clutter + * events go through, so fancy clutter dialogs can get to handle +@@ -392,6 +425,13 @@ meta_display_handle_event (MetaDisplay *display, + + goto out; + } ++ else ++ { ++ /* We could not match the event with a window, make sure we sync ++ * the pointer to discard the sequence and don't keep events frozen. ++ */ ++ maybe_unfreeze_pointer_events (backend, event, EVENTS_UNFREEZE_SYNC); ++ } + + out: + /* If the compositor has a grab, don't pass that through to Wayland */ +-- +2.23.0 + diff --git a/SPECS/mutter.spec b/SPECS/mutter.spec index ab0e8b9..7149b2e 100644 --- a/SPECS/mutter.spec +++ b/SPECS/mutter.spec @@ -10,7 +10,7 @@ Name: mutter Version: 3.28.3 -Release: 10%{?dist} +Release: 11%{?dist} Summary: Window and compositing manager based on Clutter License: GPLv2+ @@ -78,6 +78,9 @@ Patch262: 0002-monitor-manager-xrandr-Create-dummy-screen-sized-mon.patch Patch270: 0001-idle-monitor-Use-G_SOURCE_CONTINUE-instead-of-TRUE.patch Patch271: 0002-idle-monitor-Postpone-dispatching-of-idle-timeout-if.patch +# Don't loose pointer button grabs (#1756263) +Patch272: 0001-events-Sync-pending-pointer-events-without-a-window.patch + BuildRequires: chrpath BuildRequires: pango-devel BuildRequires: startup-notification-devel @@ -233,6 +236,10 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || : %{_libdir}/pkgconfig/* %changelog +* Wed Oct 02 2019 Jonas Ådahl ) - 3.28.3-11 +- Don't loose pointer button grabs + Resolves: #1756263 + * Wed Apr 17 2019 Jonas Ådahl - 3.28.3-10 - Fix idle monitor race condition Resolves: #1636460