kathenas / rpms / mutter

Forked from rpms/mutter 5 years ago
Clone

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

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