[mutter/wayland] MetaIdleMonitor: add wayland support



commit 9affbf10a6ae675107a6295af7d38cc9abefa2a4
Author: Giovanni Campagna <gcampagn redhat com>
Date:   Fri Aug 23 15:07:57 2013 +0200

    MetaIdleMonitor: add wayland support
    
    Keep a timer source that we reset when we capture an event in
    MetaWayland, and fire watches accordingly.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=706005

 src/core/meta-idle-monitor-private.h |    1 +
 src/core/meta-idle-monitor.c         |  127 +++++++++++++++++++++++++++++++---
 src/wayland/meta-wayland.c           |   28 ++++++++
 3 files changed, 146 insertions(+), 10 deletions(-)
---
diff --git a/src/core/meta-idle-monitor-private.h b/src/core/meta-idle-monitor-private.h
index f301e4f..40608ff 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 568e6db..cc3e8f7 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_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);
 
-      g_hash_table_add (monitor->alarms, (gpointer) watch->xalarm);
+          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);
+
+          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);
+          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);
+    }
+}
+
+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);
 
-  return _xsyncvalue_to_int64 (value);
+  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 600db93..0452bc6 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -49,6 +49,7 @@
 #include <meta/types.h>
 #include <meta/main.h>
 #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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]