From 89261be556a53efef05545c9d79fd855b4a81838 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Thu, 12 Apr 2018 17:36:58 +0200 Subject: [PATCH] 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 --- src/backends/x11/meta-backend-x11.c | 102 ++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) 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, @@ -657,11 +742,28 @@ initable_iface_init (GInitableIface *initable_iface) initable_iface->init = meta_backend_x11_initable_init; } +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;