summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBastien Nocera <hadess@hadess.net>2018-04-12 17:36:58 +0200
committerJonas Ã…dahl <jadahl@gmail.com>2018-04-16 13:28:03 +0200
commit84e575be775c49f1e13c5c99842f89ed2378b091 (patch)
treec5609dd2b8f9fcb456999f7854f85623f19f25c6
parent7945ee5bebbc84340e1a3febe969928fe47a7995 (diff)
downloadmutter-84e575be775c49f1e13c5c99842f89ed2378b091.tar.gz
x11: Allow XTest and core events to reset idletime
Now that we've removed the X11 specific backend of the idle monitor, add back a cut-down version of it for the explicit purpose of being told about idle time resets when XTest events are used. XTest events are usually used by test suites and remote display software to inject events into an X11 session. We should consider somebody moving the mouse remotely to be just as "active" as somebody moving it locally. https://bugzilla.gnome.org/show_bug.cgi?id=705942
-rw-r--r--src/backends/x11/meta-backend-x11.c102
1 files changed, 102 insertions, 0 deletions
diff --git a/src/backends/x11/meta-backend-x11.c b/src/backends/x11/meta-backend-x11.c
index 226d187c5..e3dba9913 100644
--- a/src/backends/x11/meta-backend-x11.c
+++ b/src/backends/x11/meta-backend-x11.c
@@ -46,6 +46,7 @@
#include "display-private.h"
#include "compositor/compositor-private.h"
#include "backends/meta-dnd-private.h"
+#include "backends/meta-idle-monitor-private.h"
struct _MetaBackendX11Private
{
@@ -56,6 +57,8 @@ struct _MetaBackendX11Private
int xsync_event_base;
int xsync_error_base;
+ XSyncAlarm user_active_alarm;
+ XSyncCounter counter;
int xinput_opcode;
int xinput_event_base;
@@ -82,6 +85,79 @@ G_DEFINE_TYPE_WITH_CODE (MetaBackendX11, meta_backend_x11, META_TYPE_BACKEND,
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
initable_iface_init));
+
+static void
+uint64_to_xsync_value (uint64_t value,
+ XSyncValue *xsync_value)
+{
+ XSyncIntsToValue (xsync_value, value & 0xffffffff, value >> 32);
+}
+
+static XSyncAlarm
+xsync_user_active_alarm_set (MetaBackendX11Private *priv)
+{
+ XSyncAlarmAttributes attr;
+ XSyncValue delta;
+ unsigned long flags;
+
+ flags = (XSyncCACounter | XSyncCAValueType | XSyncCATestType |
+ XSyncCAValue | XSyncCADelta | XSyncCAEvents);
+
+ XSyncIntToValue (&delta, 0);
+ attr.trigger.counter = priv->counter;
+ attr.trigger.value_type = XSyncAbsolute;
+ attr.delta = delta;
+ attr.events = TRUE;
+
+ uint64_to_xsync_value (1, &attr.trigger.wait_value);
+
+ attr.trigger.test_type = XSyncNegativeTransition;
+ return XSyncCreateAlarm (priv->xdisplay, flags, &attr);
+}
+
+static XSyncCounter
+find_idletime_counter (MetaBackendX11Private *priv)
+{
+ int i;
+ int n_counters;
+ XSyncSystemCounter *counters;
+ XSyncCounter counter = None;
+
+ counters = XSyncListSystemCounters (priv->xdisplay, &n_counters);
+ for (i = 0; i < n_counters; i++)
+ {
+ if (g_strcmp0 (counters[i].name, "IDLETIME") == 0)
+ {
+ counter = counters[i].counter;
+ break;
+ }
+ }
+ XSyncFreeSystemCounterList (counters);
+
+ return counter;
+}
+
+static void
+handle_alarm_notify (MetaBackend *backend,
+ XSyncAlarmNotifyEvent *alarm_event)
+{
+ MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
+ MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
+ MetaIdleMonitor *idle_monitor;
+ XSyncAlarmAttributes attr;
+
+ if (alarm_event->state != XSyncAlarmActive ||
+ alarm_event->alarm != priv->user_active_alarm)
+ return;
+
+ attr.events = TRUE;
+ XSyncChangeAlarm (priv->xdisplay, priv->user_active_alarm,
+ XSyncCAEvents, &attr);
+
+ idle_monitor = meta_backend_get_idle_monitor (backend, 0);
+ meta_idle_monitor_reset_idletime (idle_monitor);
+}
+
static void
meta_backend_x11_translate_device_event (MetaBackendX11 *x11,
XIDeviceEvent *device_event)
@@ -264,6 +340,9 @@ handle_host_xevent (MetaBackend *backend,
bypass_clutter = (meta_backend_x11_handle_host_xevent (x11, event) ||
bypass_clutter);
+ if (event->type == (priv->xsync_event_base + XSyncAlarmNotify))
+ handle_alarm_notify (backend, (XSyncAlarmNotifyEvent *) event);
+
if (event->type == priv->xkb_event_base)
{
XkbEvent *xkb_ev = (XkbEvent *) event;
@@ -410,6 +489,12 @@ meta_backend_x11_post_init (MetaBackend *backend)
!XSyncInitialize (priv->xdisplay, &major, &minor))
meta_fatal ("Could not initialize XSync");
+ priv->counter = find_idletime_counter (priv);
+ if (priv->counter == None)
+ meta_fatal ("Could not initialize XSync counter");
+
+ priv->user_active_alarm = xsync_user_active_alarm_set (priv);
+
if (XQueryExtension (priv->xdisplay,
"XInputExtension",
&priv->xinput_opcode,
@@ -658,10 +743,27 @@ initable_iface_init (GInitableIface *initable_iface)
}
static void
+meta_backend_x11_finalize (GObject *object)
+{
+ MetaBackendX11 *x11 = META_BACKEND_X11 (object);
+ MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
+
+ if (priv->user_active_alarm != None)
+ {
+ XSyncDestroyAlarm (priv->xdisplay, priv->user_active_alarm);
+ priv->user_active_alarm = None;
+ }
+
+ G_OBJECT_CLASS (meta_backend_x11_parent_class)->finalize (object);
+}
+
+static void
meta_backend_x11_class_init (MetaBackendX11Class *klass)
{
MetaBackendClass *backend_class = META_BACKEND_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = meta_backend_x11_finalize;
backend_class->create_clutter_backend = meta_backend_x11_create_clutter_backend;
backend_class->post_init = meta_backend_x11_post_init;
backend_class->grab_device = meta_backend_x11_grab_device;