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
This commit is contained in:
Bastien Nocera 2018-04-12 17:36:58 +02:00 committed by Jonas Ådahl
parent 7945ee5beb
commit 84e575be77

View File

@ -46,6 +46,7 @@
#include "display-private.h" #include "display-private.h"
#include "compositor/compositor-private.h" #include "compositor/compositor-private.h"
#include "backends/meta-dnd-private.h" #include "backends/meta-dnd-private.h"
#include "backends/meta-idle-monitor-private.h"
struct _MetaBackendX11Private struct _MetaBackendX11Private
{ {
@ -56,6 +57,8 @@ struct _MetaBackendX11Private
int xsync_event_base; int xsync_event_base;
int xsync_error_base; int xsync_error_base;
XSyncAlarm user_active_alarm;
XSyncCounter counter;
int xinput_opcode; int xinput_opcode;
int xinput_event_base; 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, G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
initable_iface_init)); 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 static void
meta_backend_x11_translate_device_event (MetaBackendX11 *x11, meta_backend_x11_translate_device_event (MetaBackendX11 *x11,
XIDeviceEvent *device_event) XIDeviceEvent *device_event)
@ -264,6 +340,9 @@ handle_host_xevent (MetaBackend *backend,
bypass_clutter = (meta_backend_x11_handle_host_xevent (x11, event) || bypass_clutter = (meta_backend_x11_handle_host_xevent (x11, event) ||
bypass_clutter); bypass_clutter);
if (event->type == (priv->xsync_event_base + XSyncAlarmNotify))
handle_alarm_notify (backend, (XSyncAlarmNotifyEvent *) event);
if (event->type == priv->xkb_event_base) if (event->type == priv->xkb_event_base)
{ {
XkbEvent *xkb_ev = (XkbEvent *) event; XkbEvent *xkb_ev = (XkbEvent *) event;
@ -410,6 +489,12 @@ meta_backend_x11_post_init (MetaBackend *backend)
!XSyncInitialize (priv->xdisplay, &major, &minor)) !XSyncInitialize (priv->xdisplay, &major, &minor))
meta_fatal ("Could not initialize XSync"); 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, if (XQueryExtension (priv->xdisplay,
"XInputExtension", "XInputExtension",
&priv->xinput_opcode, &priv->xinput_opcode,
@ -657,11 +742,28 @@ initable_iface_init (GInitableIface *initable_iface)
initable_iface->init = meta_backend_x11_initable_init; 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 static void
meta_backend_x11_class_init (MetaBackendX11Class *klass) meta_backend_x11_class_init (MetaBackendX11Class *klass)
{ {
MetaBackendClass *backend_class = META_BACKEND_CLASS (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->create_clutter_backend = meta_backend_x11_create_clutter_backend;
backend_class->post_init = meta_backend_x11_post_init; backend_class->post_init = meta_backend_x11_post_init;
backend_class->grab_device = meta_backend_x11_grab_device; backend_class->grab_device = meta_backend_x11_grab_device;