Blame SOURCES/input-after-long-idle-fix.patch

1a3082
From 05bca153bb92c5daa5b961214ff7f80af88cb7cf Mon Sep 17 00:00:00 2001
1a3082
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
1a3082
Date: Thu, 24 Oct 2019 21:19:36 +0200
1a3082
Subject: [PATCH 1/2] display: Move finishing of touch sequence to the backend
1a3082
1a3082
We need to manipulate an X11 grab when a touch sequence ends; move that
1a3082
logic to where it belongs - in the X11 backend.
1a3082
1a3082
https://gitlab.gnome.org/GNOME/mutter/merge_requests/886
1a3082
---
1a3082
 src/backends/meta-backend-private.h     | 16 ++++++++++++
1a3082
 src/backends/meta-backend.c             | 14 +++++++++++
1a3082
 src/backends/x11/meta-backend-x11.c     | 23 +++++++++++++++++
1a3082
 src/core/display.c                      | 33 +++++++++++--------------
1a3082
 src/core/meta-gesture-tracker-private.h |  9 +------
1a3082
 5 files changed, 69 insertions(+), 26 deletions(-)
1a3082
1a3082
diff --git a/src/backends/meta-backend-private.h b/src/backends/meta-backend-private.h
1a3082
index 7eba1806b..81ec81e5f 100644
1a3082
--- a/src/backends/meta-backend-private.h
1a3082
+++ b/src/backends/meta-backend-private.h
1a3082
@@ -49,6 +49,14 @@
1a3082
 #define DEFAULT_XKB_RULES_FILE "evdev"
1a3082
 #define DEFAULT_XKB_MODEL "pc105+inet"
1a3082
 
1a3082
+typedef enum
1a3082
+{
1a3082
+  META_SEQUENCE_NONE,
1a3082
+  META_SEQUENCE_ACCEPTED,
1a3082
+  META_SEQUENCE_REJECTED,
1a3082
+  META_SEQUENCE_PENDING_END
1a3082
+} MetaSequenceState;
1a3082
+
1a3082
 struct _MetaBackendClass
1a3082
 {
1a3082
   GObjectClass parent_class;
1a3082
@@ -71,6 +79,10 @@ struct _MetaBackendClass
1a3082
                               int          device_id,
1a3082
                               uint32_t     timestamp);
1a3082
 
1a3082
+  void (* finish_touch_sequence) (MetaBackend          *backend,
1a3082
+                                  ClutterEventSequence *sequence,
1a3082
+                                  MetaSequenceState     state);
1a3082
+
1a3082
   void (* warp_pointer) (MetaBackend *backend,
1a3082
                          int          x,
1a3082
                          int          y);
1a3082
@@ -135,6 +147,10 @@ gboolean meta_backend_ungrab_device (MetaBackend *backend,
1a3082
                                      int          device_id,
1a3082
                                      uint32_t     timestamp);
1a3082
 
1a3082
+void meta_backend_finish_touch_sequence (MetaBackend          *backend,
1a3082
+                                         ClutterEventSequence *sequence,
1a3082
+                                         MetaSequenceState     state);
1a3082
+
1a3082
 void meta_backend_warp_pointer (MetaBackend *backend,
1a3082
                                 int          x,
1a3082
                                 int          y);
1a3082
diff --git a/src/backends/meta-backend.c b/src/backends/meta-backend.c
1a3082
index c980cf150..bb7d66f2a 100644
1a3082
--- a/src/backends/meta-backend.c
1a3082
+++ b/src/backends/meta-backend.c
1a3082
@@ -1086,6 +1086,20 @@ meta_backend_ungrab_device (MetaBackend *backend,
1a3082
   return META_BACKEND_GET_CLASS (backend)->ungrab_device (backend, device_id, timestamp);
1a3082
 }
1a3082
 
1a3082
+/**
1a3082
+ * meta_backend_finish_touch_sequence: (skip)
1a3082
+ */
1a3082
+void
1a3082
+meta_backend_finish_touch_sequence (MetaBackend          *backend,
1a3082
+                                    ClutterEventSequence *sequence,
1a3082
+                                    MetaSequenceState     state)
1a3082
+{
1a3082
+  if (META_BACKEND_GET_CLASS (backend)->finish_touch_sequence)
1a3082
+    META_BACKEND_GET_CLASS (backend)->finish_touch_sequence (backend,
1a3082
+                                                             sequence,
1a3082
+                                                             state);
1a3082
+}
1a3082
+
1a3082
 /**
1a3082
  * meta_backend_warp_pointer: (skip)
1a3082
  */
1a3082
diff --git a/src/backends/x11/meta-backend-x11.c b/src/backends/x11/meta-backend-x11.c
1a3082
index c10365f9d..cdefa50a9 100644
1a3082
--- a/src/backends/x11/meta-backend-x11.c
1a3082
+++ b/src/backends/x11/meta-backend-x11.c
1a3082
@@ -591,6 +591,28 @@ meta_backend_x11_ungrab_device (MetaBackend *backend,
1a3082
   return (ret == Success);
1a3082
 }
1a3082
 
1a3082
+static void
1a3082
+meta_backend_x11_finish_touch_sequence (MetaBackend          *backend,
1a3082
+                                        ClutterEventSequence *sequence,
1a3082
+                                        MetaSequenceState     state)
1a3082
+{
1a3082
+  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
1a3082
+  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
1a3082
+  int event_mode;
1a3082
+
1a3082
+  if (state == META_SEQUENCE_ACCEPTED)
1a3082
+    event_mode = XIAcceptTouch;
1a3082
+  else if (state == META_SEQUENCE_REJECTED)
1a3082
+    event_mode = XIRejectTouch;
1a3082
+  else
1a3082
+    g_return_if_reached ();
1a3082
+
1a3082
+  XIAllowTouchEvents (priv->xdisplay,
1a3082
+                      META_VIRTUAL_CORE_POINTER_ID,
1a3082
+                      clutter_x11_event_sequence_get_touch_detail (sequence),
1a3082
+                      DefaultRootWindow (priv->xdisplay), event_mode);
1a3082
+}
1a3082
+
1a3082
 static void
1a3082
 meta_backend_x11_warp_pointer (MetaBackend *backend,
1a3082
                                int          x,
1a3082
@@ -776,6 +798,7 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass)
1a3082
   backend_class->post_init = meta_backend_x11_post_init;
1a3082
   backend_class->grab_device = meta_backend_x11_grab_device;
1a3082
   backend_class->ungrab_device = meta_backend_x11_ungrab_device;
1a3082
+  backend_class->finish_touch_sequence = meta_backend_x11_finish_touch_sequence;
1a3082
   backend_class->warp_pointer = meta_backend_x11_warp_pointer;
1a3082
   backend_class->get_current_logical_monitor = meta_backend_x11_get_current_logical_monitor;
1a3082
   backend_class->get_keymap = meta_backend_x11_get_keymap;
1a3082
diff --git a/src/core/display.c b/src/core/display.c
1a3082
index 4c8907f40..eb7dc43b6 100644
1a3082
--- a/src/core/display.c
1a3082
+++ b/src/core/display.c
1a3082
@@ -42,6 +42,7 @@
1a3082
 #include <X11/extensions/Xdamage.h>
1a3082
 #include <X11/extensions/Xfixes.h>
1a3082
 
1a3082
+#include "backends/meta-backend-private.h"
1a3082
 #include "backends/meta-cursor-sprite-xcursor.h"
1a3082
 #include "backends/meta-cursor-tracker-private.h"
1a3082
 #include "backends/meta-idle-monitor-dbus.h"
1a3082
@@ -598,27 +599,23 @@ gesture_tracker_state_changed (MetaGestureTracker   *tracker,
1a3082
                                MetaSequenceState     state,
1a3082
                                MetaDisplay          *display)
1a3082
 {
1a3082
-  if (meta_is_wayland_compositor ())
1a3082
+  switch (state)
1a3082
     {
1a3082
-      if (state == META_SEQUENCE_ACCEPTED)
1a3082
-        meta_display_cancel_touch (display);
1a3082
-    }
1a3082
-  else
1a3082
-    {
1a3082
-      MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
1a3082
-      int event_mode;
1a3082
+    case META_SEQUENCE_NONE:
1a3082
+    case META_SEQUENCE_PENDING_END:
1a3082
+      return;
1a3082
+    case META_SEQUENCE_ACCEPTED:
1a3082
+      meta_display_cancel_touch (display);
1a3082
 
1a3082
-      if (state == META_SEQUENCE_ACCEPTED)
1a3082
-        event_mode = XIAcceptTouch;
1a3082
-      else if (state == META_SEQUENCE_REJECTED)
1a3082
-        event_mode = XIRejectTouch;
1a3082
-      else
1a3082
-        return;
1a3082
+      /* Intentional fall-through */
1a3082
+    case META_SEQUENCE_REJECTED:
1a3082
+      {
1a3082
+        MetaBackend *backend;
1a3082
 
1a3082
-      XIAllowTouchEvents (meta_backend_x11_get_xdisplay (backend),
1a3082
-                          META_VIRTUAL_CORE_POINTER_ID,
1a3082
-                          clutter_x11_event_sequence_get_touch_detail (sequence),
1a3082
-                          DefaultRootWindow (display->x11_display->xdisplay), event_mode);
1a3082
+        backend = meta_get_backend ();
1a3082
+        meta_backend_finish_touch_sequence (backend, sequence, state);
1a3082
+        break;
1a3082
+      }
1a3082
     }
1a3082
 }
1a3082
 
1a3082
diff --git a/src/core/meta-gesture-tracker-private.h b/src/core/meta-gesture-tracker-private.h
1a3082
index a9db35ebc..e7bfc5472 100644
1a3082
--- a/src/core/meta-gesture-tracker-private.h
1a3082
+++ b/src/core/meta-gesture-tracker-private.h
1a3082
@@ -26,6 +26,7 @@
1a3082
 
1a3082
 #include <glib-object.h>
1a3082
 
1a3082
+#include "backends/meta-backend-private.h"
1a3082
 #include "clutter/clutter.h"
1a3082
 #include "meta/window.h"
1a3082
 
1a3082
@@ -39,14 +40,6 @@
1a3082
 typedef struct _MetaGestureTracker MetaGestureTracker;
1a3082
 typedef struct _MetaGestureTrackerClass MetaGestureTrackerClass;
1a3082
 
1a3082
-typedef enum
1a3082
-{
1a3082
-  META_SEQUENCE_NONE,
1a3082
-  META_SEQUENCE_ACCEPTED,
1a3082
-  META_SEQUENCE_REJECTED,
1a3082
-  META_SEQUENCE_PENDING_END
1a3082
-} MetaSequenceState;
1a3082
-
1a3082
 struct _MetaGestureTracker
1a3082
 {
1a3082
   GObject parent_instance;
1a3082
-- 
1a3082
2.23.0
1a3082
1a3082
1a3082
From 8cf4f500defb421d5c96f2c1f9fcf7bb5545d70d Mon Sep 17 00:00:00 2001
1a3082
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
1a3082
Date: Fri, 25 Oct 2019 10:06:55 +0200
1a3082
Subject: [PATCH 2/2] x11: Limit touch replay pointer events to when replaying
1a3082
1a3082
When a touch sequence was rejected, the emulated pointer events would be
1a3082
replayed with old timestamps. This caused issues with grabs as they
1a3082
would be ignored due to being too old. This was mitigated by making sure
1a3082
device event timestamps never travelled back in time by tampering with
1a3082
any event that had a timestamp seemingly in the past.
1a3082
1a3082
This failed when the most recent timestamp that had been received were
1a3082
much older than the timestamp of the new event. This could for example
1a3082
happen when a session was left not interacted with for 40+ days or so;
1a3082
when interacted with again, as any new timestamp would according to
1a3082
XSERVER_TIME_IS_BEFORE() still be in the past compared to the "most
1a3082
recent" one. The effect is that we'd always use the `latest_evtime` for
1a3082
all new device events without ever updating it.
1a3082
1a3082
The end result of this was that passive grabs would become active when
1a3082
interacted with, but would then newer be released, as the timestamps to
1a3082
XIAllowEvents() would out of date, resulting in the desktop effectively
1a3082
freezing, as the Shell would have an active pointer grab.
1a3082
1a3082
To avoid the situation where we get stuck with an old `latest_evtime`
1a3082
timestamp, limit the tampering with device event timestamp to 1) only
1a3082
pointer events, and 2) only during the replay sequence. The second part
1a3082
is implemented by sending an asynchronous message via the X server after
1a3082
rejecting a touch sequence, only potentially tampering with the device
1a3082
event timestamps until the reply. This should avoid the stuck timestamp
1a3082
as in those situations, we'll always have a relatively up to date
1a3082
`latest_evtime` meaning XSERVER_TIME_IS_BEFORE() will not get confused.
1a3082
1a3082
https://gitlab.gnome.org/GNOME/mutter/merge_requests/886
1a3082
---
1a3082
 src/backends/x11/meta-backend-x11.c | 71 +++++++++++++++++++++++------
1a3082
 1 file changed, 58 insertions(+), 13 deletions(-)
1a3082
1a3082
diff --git a/src/backends/x11/meta-backend-x11.c b/src/backends/x11/meta-backend-x11.c
1a3082
index cdefa50a9..821b30f5b 100644
1a3082
--- a/src/backends/x11/meta-backend-x11.c
1a3082
+++ b/src/backends/x11/meta-backend-x11.c
1a3082
@@ -66,6 +66,10 @@ struct _MetaBackendX11Private
1a3082
   XSyncAlarm user_active_alarm;
1a3082
   XSyncCounter counter;
1a3082
 
1a3082
+  int current_touch_replay_sync_serial;
1a3082
+  int pending_touch_replay_sync_serial;
1a3082
+  Atom touch_replay_sync_atom;
1a3082
+
1a3082
   int xinput_opcode;
1a3082
   int xinput_event_base;
1a3082
   int xinput_error_base;
1a3082
@@ -174,6 +178,26 @@ meta_backend_x11_translate_device_event (MetaBackendX11 *x11,
1a3082
   backend_x11_class->translate_device_event (x11, device_event);
1a3082
 }
1a3082
 
1a3082
+static void
1a3082
+maybe_translate_touch_replay_pointer_event (MetaBackendX11 *x11,
1a3082
+                                            XIDeviceEvent  *device_event)
1a3082
+{
1a3082
+  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
1a3082
+
1a3082
+  if (!device_event->send_event &&
1a3082
+      device_event->time != META_CURRENT_TIME &&
1a3082
+      priv->current_touch_replay_sync_serial !=
1a3082
+      priv->pending_touch_replay_sync_serial &&
1a3082
+      XSERVER_TIME_IS_BEFORE (device_event->time, priv->latest_evtime))
1a3082
+    {
1a3082
+      /* Emulated pointer events received after XIRejectTouch is received
1a3082
+       * on a passive touch grab will contain older timestamps, update those
1a3082
+       * so we dont get InvalidTime at grabs.
1a3082
+       */
1a3082
+      device_event->time = priv->latest_evtime;
1a3082
+    }
1a3082
+}
1a3082
+
1a3082
 static void
1a3082
 translate_device_event (MetaBackendX11 *x11,
1a3082
                         XIDeviceEvent  *device_event)
1a3082
@@ -183,19 +207,7 @@ translate_device_event (MetaBackendX11 *x11,
1a3082
   meta_backend_x11_translate_device_event (x11, device_event);
1a3082
 
1a3082
   if (!device_event->send_event && device_event->time != META_CURRENT_TIME)
1a3082
-    {
1a3082
-      if (XSERVER_TIME_IS_BEFORE (device_event->time, priv->latest_evtime))
1a3082
-        {
1a3082
-          /* Emulated pointer events received after XIRejectTouch is received
1a3082
-           * on a passive touch grab will contain older timestamps, update those
1a3082
-           * so we dont get InvalidTime at grabs.
1a3082
-           */
1a3082
-          device_event->time = priv->latest_evtime;
1a3082
-        }
1a3082
-
1a3082
-      /* Update the internal latest evtime, for any possible later use */
1a3082
-      priv->latest_evtime = device_event->time;
1a3082
-    }
1a3082
+    priv->latest_evtime = device_event->time;
1a3082
 }
1a3082
 
1a3082
 static void
1a3082
@@ -260,6 +272,9 @@ maybe_spoof_event_as_stage_event (MetaBackendX11 *x11,
1a3082
     case XI_Motion:
1a3082
     case XI_ButtonPress:
1a3082
     case XI_ButtonRelease:
1a3082
+      maybe_translate_touch_replay_pointer_event (x11,
1a3082
+                                                  (XIDeviceEvent *) input_event);
1a3082
+      /* Intentional fall-through */
1a3082
     case XI_KeyPress:
1a3082
     case XI_KeyRelease:
1a3082
     case XI_TouchBegin:
1a3082
@@ -327,6 +342,17 @@ handle_host_xevent (MetaBackend *backend,
1a3082
   MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
1a3082
   gboolean bypass_clutter = FALSE;
1a3082
 
1a3082
+  switch (event->type)
1a3082
+    {
1a3082
+    case ClientMessage:
1a3082
+      if (event->xclient.window == meta_backend_x11_get_xwindow (x11) &&
1a3082
+          event->xclient.message_type == priv->touch_replay_sync_atom)
1a3082
+        priv->current_touch_replay_sync_serial = event->xclient.data.l[0];
1a3082
+      break;
1a3082
+    default:
1a3082
+      break;
1a3082
+    }
1a3082
+
1a3082
   XGetEventData (priv->xdisplay, &event->xcookie);
1a3082
 
1a3082
   {
1a3082
@@ -534,6 +560,10 @@ meta_backend_x11_post_init (MetaBackend *backend)
1a3082
   monitor_manager = meta_backend_get_monitor_manager (backend);
1a3082
   g_signal_connect (monitor_manager, "monitors-changed-internal",
1a3082
                     G_CALLBACK (on_monitors_changed), backend);
1a3082
+
1a3082
+  priv->touch_replay_sync_atom = XInternAtom (priv->xdisplay,
1a3082
+                                              "_MUTTER_TOUCH_SEQUENCE_SYNC",
1a3082
+                                              False);
1a3082
 }
1a3082
 
1a3082
 static ClutterBackend *
1a3082
@@ -611,6 +641,21 @@ meta_backend_x11_finish_touch_sequence (MetaBackend          *backend,
1a3082
                       META_VIRTUAL_CORE_POINTER_ID,
1a3082
                       clutter_x11_event_sequence_get_touch_detail (sequence),
1a3082
                       DefaultRootWindow (priv->xdisplay), event_mode);
1a3082
+
1a3082
+  if (state == META_SEQUENCE_REJECTED)
1a3082
+    {
1a3082
+      XClientMessageEvent ev;
1a3082
+
1a3082
+      ev = (XClientMessageEvent) {
1a3082
+        .type = ClientMessage,
1a3082
+        .window = meta_backend_x11_get_xwindow (x11),
1a3082
+        .message_type = priv->touch_replay_sync_atom,
1a3082
+        .format = 32,
1a3082
+        .data.l[0] = ++priv->pending_touch_replay_sync_serial,
1a3082
+      };
1a3082
+      XSendEvent (priv->xdisplay, meta_backend_x11_get_xwindow (x11),
1a3082
+                  False, 0, (XEvent *) &ev;;
1a3082
+    }
1a3082
 }
1a3082
 
1a3082
 static void
1a3082
-- 
1a3082
2.23.0
1a3082