diff --git a/SOURCES/0001-window-free-close-dialog-before-unmanaging-window-fr.patch b/SOURCES/0001-window-free-close-dialog-before-unmanaging-window-fr.patch new file mode 100644 index 0000000..df3eeae --- /dev/null +++ b/SOURCES/0001-window-free-close-dialog-before-unmanaging-window-fr.patch @@ -0,0 +1,47 @@ +From 376225cea044d050f8fc2923e7149d320150bab7 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 29 Apr 2019 13:46:37 -0400 +Subject: [PATCH] window: free close dialog before unmanaging window from + compositor + +When an application stops responding, the shell darkens its windows. + +If a window from a not-responding application gets unmanaged +then the shell will currently throw an exception trying to retrieve +the now-dissociated window actor. + +That leads to a "stuck window" ghost on screen and a traceback +in the log. + +This commit addresses the problem by making sure the effect is cleaned +up before the actor is disocciated from its window. + +https://gitlab.gnome.org/GNOME/mutter/issues/575 +--- + src/core/window.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/core/window.c b/src/core/window.c +index cc0813ac4..aa85806f1 100644 +--- a/src/core/window.c ++++ b/src/core/window.c +@@ -1388,6 +1388,8 @@ meta_window_unmanage (MetaWindow *window, + meta_verbose ("Unmanaging %s\n", window->desc); + window->unmanaging = TRUE; + ++ meta_window_free_delete_dialog (window); ++ + #ifdef HAVE_WAYLAND + /* This needs to happen for both Wayland and XWayland clients, + * so it can't be in MetaWindowWayland. */ +@@ -1510,7 +1512,6 @@ meta_window_unmanage (MetaWindow *window, + meta_window_unqueue (window, META_QUEUE_CALC_SHOWING | + META_QUEUE_MOVE_RESIZE | + META_QUEUE_UPDATE_ICON); +- meta_window_free_delete_dialog (window); + + set_workspace_state (window, FALSE, NULL); + +-- +2.23.0 + diff --git a/SOURCES/input-after-long-idle-fix.patch b/SOURCES/input-after-long-idle-fix.patch new file mode 100644 index 0000000..1f26abd --- /dev/null +++ b/SOURCES/input-after-long-idle-fix.patch @@ -0,0 +1,381 @@ +From a86f1085d1f5056fb4b19f1d7f72a1905122cc24 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Thu, 24 Oct 2019 21:19:36 +0200 +Subject: [PATCH 1/2] display: Move finishing of touch sequence to the backend + +We need to manipulate an X11 grab when a touch sequence ends; move that +logic to where it belongs - in the X11 backend. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/886 +--- + src/backends/meta-backend-private.h | 16 ++++++++++++ + src/backends/meta-backend.c | 14 +++++++++++ + src/backends/x11/meta-backend-x11.c | 23 +++++++++++++++++ + src/core/display.c | 33 +++++++++++-------------- + src/core/meta-gesture-tracker-private.h | 7 +----- + src/core/meta-gesture-tracker.c | 1 + + 6 files changed, 70 insertions(+), 24 deletions(-) + +diff --git a/src/backends/meta-backend-private.h b/src/backends/meta-backend-private.h +index a25275499..7f4a4ea0f 100644 +--- a/src/backends/meta-backend-private.h ++++ b/src/backends/meta-backend-private.h +@@ -51,6 +51,14 @@ + #define META_TYPE_BACKEND (meta_backend_get_type ()) + G_DECLARE_DERIVABLE_TYPE (MetaBackend, meta_backend, META, BACKEND, GObject) + ++typedef enum _MetaSequenceState ++{ ++ META_SEQUENCE_NONE, ++ META_SEQUENCE_ACCEPTED, ++ META_SEQUENCE_REJECTED, ++ META_SEQUENCE_PENDING_END ++} MetaSequenceState; ++ + struct _MetaBackendClass + { + GObjectClass parent_class; +@@ -73,6 +81,10 @@ struct _MetaBackendClass + int device_id, + uint32_t timestamp); + ++ void (* finish_touch_sequence) (MetaBackend *backend, ++ ClutterEventSequence *sequence, ++ MetaSequenceState state); ++ + void (* warp_pointer) (MetaBackend *backend, + int x, + int y); +@@ -134,6 +146,10 @@ gboolean meta_backend_ungrab_device (MetaBackend *backend, + int device_id, + uint32_t timestamp); + ++void meta_backend_finish_touch_sequence (MetaBackend *backend, ++ ClutterEventSequence *sequence, ++ MetaSequenceState state); ++ + void meta_backend_warp_pointer (MetaBackend *backend, + int x, + int y); +diff --git a/src/backends/meta-backend.c b/src/backends/meta-backend.c +index ce7e385b9..fb4f69fe6 100644 +--- a/src/backends/meta-backend.c ++++ b/src/backends/meta-backend.c +@@ -846,6 +846,20 @@ meta_backend_ungrab_device (MetaBackend *backend, + return META_BACKEND_GET_CLASS (backend)->ungrab_device (backend, device_id, timestamp); + } + ++/** ++ * meta_backend_finish_touch_sequence: (skip) ++ */ ++void ++meta_backend_finish_touch_sequence (MetaBackend *backend, ++ ClutterEventSequence *sequence, ++ MetaSequenceState state) ++{ ++ if (META_BACKEND_GET_CLASS (backend)->finish_touch_sequence) ++ META_BACKEND_GET_CLASS (backend)->finish_touch_sequence (backend, ++ sequence, ++ state); ++} ++ + /** + * meta_backend_warp_pointer: (skip) + */ +diff --git a/src/backends/x11/meta-backend-x11.c b/src/backends/x11/meta-backend-x11.c +index 2b131d2d0..2835d47d6 100644 +--- a/src/backends/x11/meta-backend-x11.c ++++ b/src/backends/x11/meta-backend-x11.c +@@ -583,6 +583,28 @@ meta_backend_x11_ungrab_device (MetaBackend *backend, + return (ret == Success); + } + ++static void ++meta_backend_x11_finish_touch_sequence (MetaBackend *backend, ++ ClutterEventSequence *sequence, ++ MetaSequenceState state) ++{ ++ MetaBackendX11 *x11 = META_BACKEND_X11 (backend); ++ MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); ++ int event_mode; ++ ++ if (state == META_SEQUENCE_ACCEPTED) ++ event_mode = XIAcceptTouch; ++ else if (state == META_SEQUENCE_REJECTED) ++ event_mode = XIRejectTouch; ++ else ++ g_return_if_reached (); ++ ++ XIAllowTouchEvents (priv->xdisplay, ++ META_VIRTUAL_CORE_POINTER_ID, ++ clutter_x11_event_sequence_get_touch_detail (sequence), ++ DefaultRootWindow (priv->xdisplay), event_mode); ++} ++ + static void + meta_backend_x11_warp_pointer (MetaBackend *backend, + int x, +@@ -768,6 +790,7 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass) + backend_class->post_init = meta_backend_x11_post_init; + backend_class->grab_device = meta_backend_x11_grab_device; + backend_class->ungrab_device = meta_backend_x11_ungrab_device; ++ backend_class->finish_touch_sequence = meta_backend_x11_finish_touch_sequence; + backend_class->warp_pointer = meta_backend_x11_warp_pointer; + backend_class->get_current_logical_monitor = meta_backend_x11_get_current_logical_monitor; + backend_class->get_keymap = meta_backend_x11_get_keymap; +diff --git a/src/core/display.c b/src/core/display.c +index e7dd4534b..d4775cec3 100644 +--- a/src/core/display.c ++++ b/src/core/display.c +@@ -55,6 +55,7 @@ + #include "backends/x11/meta-backend-x11.h" + #include "backends/meta-stage-private.h" + #include "backends/meta-input-settings-private.h" ++#include "backends/meta-backend-private.h" + #include + + #ifdef HAVE_RANDR +@@ -533,27 +534,23 @@ gesture_tracker_state_changed (MetaGestureTracker *tracker, + MetaSequenceState state, + MetaDisplay *display) + { +- if (meta_is_wayland_compositor ()) ++ switch (state) + { +- if (state == META_SEQUENCE_ACCEPTED) +- meta_display_cancel_touch (display); +- } +- else +- { +- MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ()); +- int event_mode; ++ case META_SEQUENCE_NONE: ++ case META_SEQUENCE_PENDING_END: ++ return; ++ case META_SEQUENCE_ACCEPTED: ++ meta_display_cancel_touch (display); + +- if (state == META_SEQUENCE_ACCEPTED) +- event_mode = XIAcceptTouch; +- else if (state == META_SEQUENCE_REJECTED) +- event_mode = XIRejectTouch; +- else +- return; ++ /* Intentional fall-through */ ++ case META_SEQUENCE_REJECTED: ++ { ++ MetaBackend *backend; + +- XIAllowTouchEvents (meta_backend_x11_get_xdisplay (backend), +- META_VIRTUAL_CORE_POINTER_ID, +- clutter_x11_event_sequence_get_touch_detail (sequence), +- DefaultRootWindow (display->xdisplay), event_mode); ++ backend = meta_get_backend (); ++ meta_backend_finish_touch_sequence (backend, sequence, state); ++ break; ++ } + } + } + +diff --git a/src/core/meta-gesture-tracker-private.h b/src/core/meta-gesture-tracker-private.h +index 0e39af27f..b4fb02a1e 100644 +--- a/src/core/meta-gesture-tracker-private.h ++++ b/src/core/meta-gesture-tracker-private.h +@@ -38,12 +38,7 @@ + typedef struct _MetaGestureTracker MetaGestureTracker; + typedef struct _MetaGestureTrackerClass MetaGestureTrackerClass; + +-typedef enum { +- META_SEQUENCE_NONE, +- META_SEQUENCE_ACCEPTED, +- META_SEQUENCE_REJECTED, +- META_SEQUENCE_PENDING_END +-} MetaSequenceState; ++typedef enum _MetaSequenceState MetaSequenceState; + + struct _MetaGestureTracker + { +diff --git a/src/core/meta-gesture-tracker.c b/src/core/meta-gesture-tracker.c +index e3b702f56..1313aad6d 100644 +--- a/src/core/meta-gesture-tracker.c ++++ b/src/core/meta-gesture-tracker.c +@@ -31,6 +31,7 @@ + #include "config.h" + #include "meta-gesture-tracker-private.h" + #include "meta-surface-actor.h" ++#include "meta-backend-private.h" + + #define DISTANCE_THRESHOLD 30 + +-- +2.23.0 + + +From 651a45057bce8d1dd8d493d1f6a0486e04d6571b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Fri, 25 Oct 2019 10:06:55 +0200 +Subject: [PATCH 2/2] x11: Limit touch replay pointer events to when replaying + +When a touch sequence was rejected, the emulated pointer events would be +replayed with old timestamps. This caused issues with grabs as they +would be ignored due to being too old. This was mitigated by making sure +device event timestamps never travelled back in time by tampering with +any event that had a timestamp seemingly in the past. + +This failed when the most recent timestamp that had been received were +much older than the timestamp of the new event. This could for example +happen when a session was left not interacted with for 40+ days or so; +when interacted with again, as any new timestamp would according to +XSERVER_TIME_IS_BEFORE() still be in the past compared to the "most +recent" one. The effect is that we'd always use the `latest_evtime` for +all new device events without ever updating it. + +The end result of this was that passive grabs would become active when +interacted with, but would then newer be released, as the timestamps to +XIAllowEvents() would out of date, resulting in the desktop effectively +freezing, as the Shell would have an active pointer grab. + +To avoid the situation where we get stuck with an old `latest_evtime` +timestamp, limit the tampering with device event timestamp to 1) only +pointer events, and 2) only during the replay sequence. The second part +is implemented by sending an asynchronous message via the X server after +rejecting a touch sequence, only potentially tampering with the device +event timestamps until the reply. This should avoid the stuck timestamp +as in those situations, we'll always have a relatively up to date +`latest_evtime` meaning XSERVER_TIME_IS_BEFORE() will not get confused. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/886 +--- + src/backends/x11/meta-backend-x11.c | 67 +++++++++++++++++++++++------ + 1 file changed, 54 insertions(+), 13 deletions(-) + +diff --git a/src/backends/x11/meta-backend-x11.c b/src/backends/x11/meta-backend-x11.c +index 2835d47d6..7b8ff1b94 100644 +--- a/src/backends/x11/meta-backend-x11.c ++++ b/src/backends/x11/meta-backend-x11.c +@@ -60,6 +60,10 @@ struct _MetaBackendX11Private + XSyncAlarm user_active_alarm; + XSyncCounter counter; + ++ int current_touch_replay_sync_serial; ++ int pending_touch_replay_sync_serial; ++ Atom touch_replay_sync_atom; ++ + int xinput_opcode; + int xinput_event_base; + int xinput_error_base; +@@ -168,6 +172,26 @@ meta_backend_x11_translate_device_event (MetaBackendX11 *x11, + backend_x11_class->translate_device_event (x11, device_event); + } + ++static void ++maybe_translate_touch_replay_pointer_event (MetaBackendX11 *x11, ++ XIDeviceEvent *device_event) ++{ ++ MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); ++ ++ if (!device_event->send_event && ++ device_event->time != CurrentTime && ++ priv->current_touch_replay_sync_serial != ++ priv->pending_touch_replay_sync_serial && ++ XSERVER_TIME_IS_BEFORE (device_event->time, priv->latest_evtime)) ++ { ++ /* Emulated pointer events received after XIRejectTouch is received ++ * on a passive touch grab will contain older timestamps, update those ++ * so we dont get InvalidTime at grabs. ++ */ ++ device_event->time = priv->latest_evtime; ++ } ++} ++ + static void + translate_device_event (MetaBackendX11 *x11, + XIDeviceEvent *device_event) +@@ -177,19 +201,7 @@ translate_device_event (MetaBackendX11 *x11, + meta_backend_x11_translate_device_event (x11, device_event); + + if (!device_event->send_event && device_event->time != CurrentTime) +- { +- if (XSERVER_TIME_IS_BEFORE (device_event->time, priv->latest_evtime)) +- { +- /* Emulated pointer events received after XIRejectTouch is received +- * on a passive touch grab will contain older timestamps, update those +- * so we dont get InvalidTime at grabs. +- */ +- device_event->time = priv->latest_evtime; +- } +- +- /* Update the internal latest evtime, for any possible later use */ +- priv->latest_evtime = device_event->time; +- } ++ priv->latest_evtime = device_event->time; + } + + static void +@@ -254,6 +266,9 @@ maybe_spoof_event_as_stage_event (MetaBackendX11 *x11, + case XI_Motion: + case XI_ButtonPress: + case XI_ButtonRelease: ++ maybe_translate_touch_replay_pointer_event (x11, ++ (XIDeviceEvent *) input_event); ++ /* Intentional fall-through */ + case XI_KeyPress: + case XI_KeyRelease: + case XI_TouchBegin: +@@ -321,6 +336,17 @@ handle_host_xevent (MetaBackend *backend, + MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); + gboolean bypass_clutter = FALSE; + ++ switch (event->type) ++ { ++ case ClientMessage: ++ if (event->xclient.window == meta_backend_x11_get_xwindow (x11) && ++ event->xclient.message_type == priv->touch_replay_sync_atom) ++ priv->current_touch_replay_sync_serial = event->xclient.data.l[0]; ++ break; ++ default: ++ break; ++ } ++ + XGetEventData (priv->xdisplay, &event->xcookie); + + { +@@ -528,6 +554,10 @@ meta_backend_x11_post_init (MetaBackend *backend) + monitor_manager = meta_backend_get_monitor_manager (backend); + g_signal_connect (monitor_manager, "monitors-changed-internal", + G_CALLBACK (on_monitors_changed), backend); ++ ++ priv->touch_replay_sync_atom = XInternAtom (priv->xdisplay, ++ "_MUTTER_TOUCH_SEQUENCE_SYNC", ++ False); + } + + static ClutterBackend * +@@ -591,6 +621,7 @@ meta_backend_x11_finish_touch_sequence (MetaBackend *backend, + MetaBackendX11 *x11 = META_BACKEND_X11 (backend); + MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); + int event_mode; ++ XClientMessageEvent ev; + + if (state == META_SEQUENCE_ACCEPTED) + event_mode = XIAcceptTouch; +@@ -603,6 +634,16 @@ meta_backend_x11_finish_touch_sequence (MetaBackend *backend, + META_VIRTUAL_CORE_POINTER_ID, + clutter_x11_event_sequence_get_touch_detail (sequence), + DefaultRootWindow (priv->xdisplay), event_mode); ++ ++ ev = (XClientMessageEvent) { ++ .type = ClientMessage, ++ .window = meta_backend_x11_get_xwindow (x11), ++ .message_type = priv->touch_replay_sync_atom, ++ .format = 32, ++ .data.l[0] = ++priv->pending_touch_replay_sync_serial, ++ }; ++ XSendEvent (priv->xdisplay, meta_backend_x11_get_xwindow (x11), ++ False, 0, (XEvent *) &ev); + } + + static void +-- +2.23.0 + diff --git a/SPECS/mutter.spec b/SPECS/mutter.spec index 074e383..5b356ee 100644 --- a/SPECS/mutter.spec +++ b/SPECS/mutter.spec @@ -10,7 +10,7 @@ Name: mutter Version: 3.28.3 -Release: 12%{?dist} +Release: 14%{?dist} Summary: Window and compositing manager based on Clutter License: GPLv2+ @@ -85,6 +85,12 @@ Patch272: 0001-events-Sync-pending-pointer-events-without-a-window.patch Patch273: 0001-monitor-Use-current-monitor-mode-to-check-whether-ac.patch Patch274: 0002-window-Return-1-if-meta_window_get_monitor-is-called.patch +# Don't freeze if input happens after many days of inactivity (#1778212) +Patch275: input-after-long-idle-fix.patch + +# Prevent orphaned animation actors getting stuck on screen (#1753799) +Patch 283: 0001-window-free-close-dialog-before-unmanaging-window-fr.patch + BuildRequires: chrpath BuildRequires: pango-devel BuildRequires: startup-notification-devel @@ -240,6 +246,14 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || : %{_libdir}/pkgconfig/* %changelog +* Thu Dec 12 2019 Florian Müllner - 3.28.3-14 +- Free close dialog before unmanaging parent + Related: #1780030 + +* Tue Dec 03 2019 Jonas Ådahl - 3.28.3-13 +- Don't freeze if input happens after many days of inactivity + Resolves: #1778212 + * Fri Oct 11 2019 Jonas Ådahl - 3.28.3-12 - Fix crash in meta_monitor_mode_get_resolution() Resolves #1760738