diff --git a/src/core/meta-idle-monitor-private.h b/src/core/meta-idle-monitor-private.h index f301e4fd6..40608ffd9 100644 --- a/src/core/meta-idle-monitor-private.h +++ b/src/core/meta-idle-monitor-private.h @@ -26,5 +26,6 @@ void meta_idle_monitor_handle_xevent_all (XEvent *xevent); +void meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor); void meta_idle_monitor_init_dbus (void); diff --git a/src/core/meta-idle-monitor.c b/src/core/meta-idle-monitor.c index 568e6db72..cc3e8f707 100644 --- a/src/core/meta-idle-monitor.c +++ b/src/core/meta-idle-monitor.c @@ -57,6 +57,9 @@ struct _MetaIdleMonitor int sync_event_base; XSyncCounter counter; XSyncAlarm user_active_alarm; + + /* Wayland implementation */ + guint64 last_event_time; }; struct _MetaIdleMonitorClass @@ -75,6 +78,9 @@ typedef struct /* x11 */ XSyncAlarm xalarm; + + /* wayland */ + GSource *timeout_source; } MetaIdleMonitorWatch; enum @@ -290,6 +296,9 @@ idle_monitor_watch_free (MetaIdleMonitorWatch *watch) g_hash_table_remove (monitor->alarms, (gpointer) watch->xalarm); } + if (watch->timeout_source != NULL) + g_source_destroy (watch->timeout_source); + g_slice_free (MetaIdleMonitorWatch, watch); } @@ -368,8 +377,11 @@ meta_idle_monitor_constructed (GObject *object) { MetaIdleMonitor *monitor = META_IDLE_MONITOR (object); - monitor->display = meta_get_display ()->xdisplay; - init_xsync (monitor); + if (!meta_is_wayland_compositor ()) + { + monitor->display = meta_get_display ()->xdisplay; + init_xsync (monitor); + } } static void @@ -448,6 +460,25 @@ meta_idle_monitor_get_for_device (int device_id) return device_monitors[device_id]; } +static gboolean +wayland_dispatch_timeout (GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + MetaIdleMonitorWatch *watch = user_data; + + fire_watch (watch); + g_source_set_ready_time (watch->timeout_source, -1); + return TRUE; +} + +static GSourceFuncs wayland_source_funcs = { + NULL, /* prepare */ + NULL, /* check */ + wayland_dispatch_timeout, + NULL, /* finalize */ +}; + static MetaIdleMonitorWatch * make_watch (MetaIdleMonitor *monitor, guint64 timeout_msec, @@ -465,17 +496,34 @@ make_watch (MetaIdleMonitor *monitor, watch->notify = notify; watch->timeout_msec = timeout_msec; - if (timeout_msec != 0) + if (meta_is_wayland_compositor ()) { - watch->xalarm = _xsync_alarm_set (monitor, XSyncPositiveTransition, timeout_msec, TRUE); + if (timeout_msec != 0) + { + GSource *source = g_source_new (&wayland_source_funcs, sizeof (GSource)); - g_hash_table_add (monitor->alarms, (gpointer) watch->xalarm); + g_source_set_callback (source, NULL, watch, NULL); + g_source_set_ready_time (source, monitor->last_event_time + timeout_msec * 1000); + g_source_attach (source, NULL); + g_source_unref (source); + + watch->timeout_source = source; + } } else { - watch->xalarm = monitor->user_active_alarm; + if (timeout_msec != 0) + { + watch->xalarm = _xsync_alarm_set (monitor, XSyncPositiveTransition, timeout_msec, TRUE); - set_alarm_enabled (monitor->display, monitor->user_active_alarm, TRUE); + g_hash_table_add (monitor->alarms, (gpointer) watch->xalarm); + } + else + { + watch->xalarm = monitor->user_active_alarm; + + set_alarm_enabled (monitor->display, monitor->user_active_alarm, TRUE); + } } g_hash_table_insert (monitor->watches, @@ -592,10 +640,69 @@ meta_idle_monitor_get_idletime (MetaIdleMonitor *monitor) { XSyncValue value; - if (!XSyncQueryCounter (monitor->display, monitor->counter, &value)) - return -1; + if (meta_is_wayland_compositor ()) + { + return (g_get_monotonic_time () - monitor->last_event_time) / 1000; + } + else + { + if (!XSyncQueryCounter (monitor->display, monitor->counter, &value)) + return -1; - return _xsyncvalue_to_int64 (value); + return _xsyncvalue_to_int64 (value); + } +} + +typedef struct { + MetaIdleMonitor *monitor; + GList *fired_watches; +} CheckWaylandClosure; + +static gboolean +check_wayland_watch (gpointer key, + gpointer value, + gpointer user_data) +{ + MetaIdleMonitorWatch *watch = value; + CheckWaylandClosure *closure = user_data; + gboolean steal; + + if (watch->timeout_msec == 0) + { + closure->fired_watches = g_list_prepend (closure->fired_watches, watch); + steal = TRUE; + } + else + { + g_source_set_ready_time (watch->timeout_source, + closure->monitor->last_event_time + + watch->timeout_msec * 1000); + steal = FALSE; + } + + return steal; +} + +static void +fire_wayland_watch (gpointer watch, + gpointer data) +{ + fire_watch (watch); +} + +void +meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor) +{ + CheckWaylandClosure closure; + + monitor->last_event_time = g_get_monotonic_time (); + + closure.monitor = monitor; + closure.fired_watches = NULL; + g_hash_table_foreach_steal (monitor->watches, check_wayland_watch, &closure); + + g_list_foreach (closure.fired_watches, fire_wayland_watch, NULL); + g_list_free (closure.fired_watches); } static gboolean diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c index 600db9368..0452bc601 100644 --- a/src/wayland/meta-wayland.c +++ b/src/wayland/meta-wayland.c @@ -49,6 +49,7 @@ #include #include #include "frame.h" +#include "meta-idle-monitor-private.h" static MetaWaylandCompositor _meta_wayland_compositor; @@ -1260,6 +1261,31 @@ synthesize_motion_event (MetaWaylandCompositor *compositor, meta_display_handle_event (display, (XEvent *) &generic_event); } +static void +reset_idletimes (const ClutterEvent *event) +{ + ClutterInputDevice *device, *source_device; + MetaIdleMonitor *core_monitor, *device_monitor; + int device_id; + + device = clutter_event_get_device (event); + device_id = clutter_input_device_get_device_id (device); + + core_monitor = meta_idle_monitor_get_core (); + device_monitor = meta_idle_monitor_get_for_device (device_id); + + meta_idle_monitor_reset_idletime (core_monitor); + meta_idle_monitor_reset_idletime (device_monitor); + + source_device = clutter_event_get_source_device (event); + if (source_device != device) + { + device_id = clutter_input_device_get_device_id (device); + device_monitor = meta_idle_monitor_get_for_device (device_id); + meta_idle_monitor_reset_idletime (device_monitor); + } +} + static gboolean event_cb (ClutterActor *stage, const ClutterEvent *event, @@ -1270,6 +1296,8 @@ event_cb (ClutterActor *stage, MetaWaylandSurface *surface; MetaDisplay *display; + reset_idletimes (event); + meta_wayland_seat_handle_event (compositor->seat, event); /* HACK: for now, the surfaces from Wayland clients aren't