[gnome-flashback] idle-monitor: merge MetaIdleMonitorXSync into MetaIdleMonitor



commit f0ace308d4c22a0c24b40f11dc3830f26ff72fb5
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date:   Tue May 24 13:01:23 2022 +0300

    idle-monitor: merge MetaIdleMonitorXSync into MetaIdleMonitor

 daemons/idle-monitor/Makefile.am               |   2 -
 daemons/idle-monitor/flashback-idle-monitor.c  |   8 +-
 daemons/idle-monitor/meta-idle-monitor-xsync.c | 356 -------------------------
 daemons/idle-monitor/meta-idle-monitor-xsync.h |  45 ----
 daemons/idle-monitor/meta-idle-monitor.c       | 276 ++++++++++++++++++-
 daemons/idle-monitor/meta-idle-monitor.h       |  20 +-
 6 files changed, 279 insertions(+), 428 deletions(-)
---
diff --git a/daemons/idle-monitor/Makefile.am b/daemons/idle-monitor/Makefile.am
index 3330a94..7bac978 100644
--- a/daemons/idle-monitor/Makefile.am
+++ b/daemons/idle-monitor/Makefile.am
@@ -25,8 +25,6 @@ gnome_flashback_idle_monitor_SOURCES = \
        meta-dbus-idle-monitor.h \
        meta-idle-monitor.c \
        meta-idle-monitor.h \
-       meta-idle-monitor-xsync.c \
-       meta-idle-monitor-xsync.h \
        $(NULL)
 
 gnome_flashback_idle_monitor_LDFLAGS = \
diff --git a/daemons/idle-monitor/flashback-idle-monitor.c b/daemons/idle-monitor/flashback-idle-monitor.c
index f9f0165..c726004 100644
--- a/daemons/idle-monitor/flashback-idle-monitor.c
+++ b/daemons/idle-monitor/flashback-idle-monitor.c
@@ -27,7 +27,6 @@
 
 #include "flashback-idle-monitor.h"
 #include "meta-idle-monitor.h"
-#include "meta-idle-monitor-xsync.h"
 #include "meta-dbus-idle-monitor.h"
 
 struct _FlashbackIdleMonitor
@@ -266,8 +265,8 @@ filter_func (GdkXEvent *xevent,
 
   if (xev->type == (monitor->xsync_event_base + XSyncAlarmNotify))
     {
-      meta_idle_monitor_xsync_handle_xevent (monitor->monitor,
-                                             (XSyncAlarmNotifyEvent*) xev);
+      meta_idle_monitor_handle_xevent (monitor->monitor,
+                                       (XSyncAlarmNotifyEvent*) xev);
     }
 
   return GDK_FILTER_CONTINUE;
@@ -319,7 +318,8 @@ flashback_idle_monitor_init (FlashbackIdleMonitor *monitor)
   gint major;
   gint minor;
 
-  monitor->monitor = g_object_new (META_TYPE_IDLE_MONITOR_XSYNC, NULL);
+  monitor->monitor = g_object_new (META_TYPE_IDLE_MONITOR,
+                                   NULL);
 
   monitor->dbus_name_id = g_bus_own_name (G_BUS_TYPE_SESSION,
                                           "org.gnome.Mutter.IdleMonitor",
diff --git a/daemons/idle-monitor/meta-idle-monitor.c b/daemons/idle-monitor/meta-idle-monitor.c
index 5479e91..8934461 100644
--- a/daemons/idle-monitor/meta-idle-monitor.c
+++ b/daemons/idle-monitor/meta-idle-monitor.c
@@ -26,10 +26,22 @@
 
 #include "config.h"
 
+#include <gdk/gdkx.h>
 #include <string.h>
 
 #include "meta-idle-monitor.h"
-#include "meta-idle-monitor-xsync.h"
+
+struct _MetaIdleMonitor
+{
+  GObject       parent;
+
+  GHashTable   *watches;
+
+  GHashTable   *alarms;
+  Display      *display;
+  XSyncCounter  counter;
+  XSyncAlarm    user_active_alarm;
+};
 
 G_STATIC_ASSERT(sizeof(unsigned long) == sizeof(gpointer));
 
@@ -63,6 +75,119 @@ _meta_idle_monitor_watch_fire (MetaIdleMonitorWatch *watch)
   g_object_unref (monitor);
 }
 
+static gint64
+_xsyncvalue_to_int64 (XSyncValue value)
+{
+  return ((guint64) XSyncValueHigh32 (value)) << 32 |
+         (guint64) XSyncValueLow32 (value);
+}
+
+static void
+free_watch (gpointer data)
+{
+  MetaIdleMonitorWatch *watch = data;
+  MetaIdleMonitor *monitor = watch->monitor;
+
+  g_object_ref (monitor);
+
+  if (watch->idle_source_id)
+    {
+      g_source_remove (watch->idle_source_id);
+      watch->idle_source_id = 0;
+    }
+
+  if (watch->notify != NULL)
+    watch->notify (watch->user_data);
+
+  if (watch->xalarm != monitor->user_active_alarm &&
+      watch->xalarm != None)
+    {
+      XSyncDestroyAlarm (monitor->display, watch->xalarm);
+      g_hash_table_remove (monitor->alarms, (gpointer) watch->xalarm);
+    }
+
+  g_object_unref (monitor);
+  g_free (watch);
+}
+
+#define GUINT64_TO_XSYNCVALUE(value, ret) XSyncIntsToValue (ret, (value) & 0xFFFFFFFF, ((guint64)(value)) >> 
32)
+
+static XSyncAlarm
+_xsync_alarm_set (MetaIdleMonitor *self,
+                  XSyncTestType    test_type,
+                  guint64          interval,
+                  gboolean         want_events)
+{
+  XSyncAlarmAttributes attr;
+  XSyncValue delta;
+  guint flags;
+
+  flags = XSyncCACounter | XSyncCAValueType | XSyncCATestType |
+          XSyncCAValue | XSyncCADelta | XSyncCAEvents;
+
+  XSyncIntToValue (&delta, 0);
+  attr.trigger.counter = self->counter;
+  attr.trigger.value_type = XSyncAbsolute;
+  attr.delta = delta;
+  attr.events = want_events;
+
+  GUINT64_TO_XSYNCVALUE (interval, &attr.trigger.wait_value);
+  attr.trigger.test_type = test_type;
+  return XSyncCreateAlarm (self->display, flags, &attr);
+}
+
+static XSyncCounter
+find_idletime_counter (MetaIdleMonitor *self)
+{
+  int i;
+  int ncounters;
+  XSyncSystemCounter *counters;
+  XSyncCounter counter = None;
+
+  counters = XSyncListSystemCounters (self->display, &ncounters);
+  for (i = 0; i < ncounters; i++)
+    {
+      if (counters[i].name != NULL && strcmp (counters[i].name, "IDLETIME") == 0)
+        {
+          counter = counters[i].counter;
+          break;
+        }
+    }
+  XSyncFreeSystemCounterList (counters);
+
+  return counter;
+}
+
+static void
+init_xsync (MetaIdleMonitor *self)
+{
+  self->counter = find_idletime_counter (self);
+
+  /* IDLETIME counter not found? */
+  if (self->counter == None)
+    {
+      g_warning ("IDLETIME counter not found\n");
+      return;
+    }
+
+  self->user_active_alarm = _xsync_alarm_set (self, XSyncNegativeTransition, 1, FALSE);
+}
+
+static void
+meta_idle_monitor_constructed (GObject *object)
+{
+  MetaIdleMonitor *self;
+  GdkDisplay *display;
+
+  self = META_IDLE_MONITOR (object);
+
+  G_OBJECT_CLASS (meta_idle_monitor_parent_class)->constructed (object);
+
+  display = gdk_display_get_default ();
+  self->display = gdk_x11_display_get_xdisplay (display);
+  init_xsync (self);
+}
+
 static void
 meta_idle_monitor_dispose (GObject *object)
 {
@@ -70,6 +195,14 @@ meta_idle_monitor_dispose (GObject *object)
 
   g_clear_pointer (&monitor->watches, g_hash_table_destroy);
 
+  if (monitor->user_active_alarm != None)
+    {
+      XSyncDestroyAlarm (monitor->display, monitor->user_active_alarm);
+      monitor->user_active_alarm = None;
+    }
+
+  g_clear_pointer (&monitor->alarms, g_hash_table_destroy);
+
   G_OBJECT_CLASS (meta_idle_monitor_parent_class)->dispose (object);
 }
 
@@ -78,12 +211,111 @@ meta_idle_monitor_class_init (MetaIdleMonitorClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
+  object_class->constructed = meta_idle_monitor_constructed;
   object_class->dispose = meta_idle_monitor_dispose;
 }
 
 static void
 meta_idle_monitor_init (MetaIdleMonitor *monitor)
 {
+  monitor->watches = g_hash_table_new_full (NULL, NULL, NULL, free_watch);
+  monitor->alarms = g_hash_table_new (NULL, NULL);
+}
+
+static void
+check_x11_watches (MetaIdleMonitor *self,
+                   XSyncAlarm       alarm)
+{
+  GList *node, *watch_ids;
+
+  /* we get the keys and do explicit look ups in case
+   * an early iteration of the loop ends up leading
+   * to watches from later iterations getting invalidated
+   */
+  watch_ids = g_hash_table_get_keys (self->watches);
+
+  for (node = watch_ids; node != NULL; node = node->next)
+    {
+      guint watch_id = GPOINTER_TO_UINT (node->data);
+      MetaIdleMonitorWatch *watch;
+
+      watch = g_hash_table_lookup (self->watches, GUINT_TO_POINTER (watch_id));
+
+      if (watch && watch->xalarm == alarm)
+        _meta_idle_monitor_watch_fire (watch);
+    }
+
+  g_list_free (watch_ids);
+}
+
+static void
+ensure_alarm_rescheduled (Display    *dpy,
+                          XSyncAlarm  alarm)
+{
+  XSyncAlarmAttributes attr;
+
+  /* Some versions of Xorg have an issue where alarms aren't
+   * always rescheduled. Calling XSyncChangeAlarm, even
+   * without any attributes, will reschedule the alarm. */
+  XSyncChangeAlarm (dpy, alarm, 0, &attr);
+}
+
+static void
+set_alarm_enabled (Display    *dpy,
+                   XSyncAlarm  alarm,
+                   gboolean    enabled)
+{
+  XSyncAlarmAttributes attr;
+  attr.events = enabled;
+  XSyncChangeAlarm (dpy, alarm, XSyncCAEvents, &attr);
+}
+
+void
+meta_idle_monitor_handle_xevent (MetaIdleMonitor       *self,
+                                 XSyncAlarmNotifyEvent *alarm_event)
+{
+  XSyncAlarm alarm;
+  gboolean has_alarm;
+
+  if (alarm_event->state != XSyncAlarmActive)
+    return;
+
+  alarm = alarm_event->alarm;
+
+  has_alarm = FALSE;
+
+  if (alarm == self->user_active_alarm)
+    {
+      set_alarm_enabled (self->display, alarm, FALSE);
+      has_alarm = TRUE;
+    }
+  else if (g_hash_table_contains (self->alarms, (gpointer) alarm))
+    {
+      ensure_alarm_rescheduled (self->display, alarm);
+      has_alarm = TRUE;
+    }
+
+  if (has_alarm)
+    check_x11_watches (self, alarm);
+}
+
+static guint32
+get_next_watch_serial (void)
+{
+  static guint32 serial = 0;
+  g_atomic_int_inc (&serial);
+  return serial;
+}
+
+static gboolean
+fire_watch_idle (gpointer data)
+{
+  MetaIdleMonitorWatch *watch = data;
+
+  watch->idle_source_id = 0;
+  _meta_idle_monitor_watch_fire (watch);
+
+  return FALSE;
 }
 
 static MetaIdleMonitorWatch *
@@ -95,11 +327,36 @@ make_watch (MetaIdleMonitor           *monitor,
 {
   MetaIdleMonitorWatch *watch;
 
-  watch = META_IDLE_MONITOR_GET_CLASS (monitor)->make_watch (monitor,
-                                                             timeout_msec,
-                                                             callback,
-                                                             user_data,
-                                                             notify);
+  watch = g_new0 (MetaIdleMonitorWatch, 1);
+
+  watch->monitor = monitor;
+  watch->id = get_next_watch_serial ();
+  watch->callback = callback;
+  watch->user_data = user_data;
+  watch->notify = notify;
+  watch->timeout_msec = timeout_msec;
+
+  if (monitor->user_active_alarm != None)
+    {
+      if (timeout_msec != 0)
+        {
+          watch->xalarm = _xsync_alarm_set (monitor, XSyncPositiveTransition, timeout_msec, TRUE);
+
+          g_hash_table_add (monitor->alarms, (gpointer) watch->xalarm);
+
+          if (meta_idle_monitor_get_idletime (monitor) > (gint64) timeout_msec)
+            {
+              watch->idle_source_id = g_idle_add (fire_watch_idle, watch);
+              g_source_set_name_by_id (watch->idle_source_id, "[mutter] fire_watch_idle");
+            }
+        }
+      else
+        {
+          watch->xalarm = monitor->user_active_alarm;
+
+          set_alarm_enabled (monitor->display, monitor->user_active_alarm, TRUE);
+        }
+    }
 
   g_hash_table_insert (monitor->watches,
                        GUINT_TO_POINTER (watch->id),
@@ -215,5 +472,10 @@ meta_idle_monitor_remove_watch (MetaIdleMonitor *monitor,
 gint64
 meta_idle_monitor_get_idletime (MetaIdleMonitor *monitor)
 {
-  return META_IDLE_MONITOR_GET_CLASS (monitor)->get_idletime (monitor);
+  XSyncValue value;
+
+  if (!XSyncQueryCounter (monitor->display, monitor->counter, &value))
+    return -1;
+
+  return _xsyncvalue_to_int64 (value);
 }
diff --git a/daemons/idle-monitor/meta-idle-monitor.h b/daemons/idle-monitor/meta-idle-monitor.h
index 7c9dbbe..83c73c4 100644
--- a/daemons/idle-monitor/meta-idle-monitor.h
+++ b/daemons/idle-monitor/meta-idle-monitor.h
@@ -19,6 +19,8 @@
 #define META_IDLE_MONITOR_H
 
 #include <glib-object.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/sync.h>
 
 #define META_TYPE_IDLE_MONITOR            (meta_idle_monitor_get_type ())
 #define META_IDLE_MONITOR(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_IDLE_MONITOR, 
MetaIdleMonitor))
@@ -43,31 +45,21 @@ typedef struct
   GDestroyNotify            notify;
   guint64                   timeout_msec;
   int                       idle_source_id;
+  XSyncAlarm                xalarm;
 } MetaIdleMonitorWatch;
 
 void _meta_idle_monitor_watch_fire (MetaIdleMonitorWatch *watch);
 
-struct _MetaIdleMonitor
-{
-  GObject parent_instance;
-
-  GHashTable *watches;
-};
-
 struct _MetaIdleMonitorClass
 {
   GObjectClass parent_class;
-
-  gint64 (*get_idletime) (MetaIdleMonitor *monitor);
-  MetaIdleMonitorWatch * (*make_watch) (MetaIdleMonitor           *monitor,
-                                        guint64                    timeout_msec,
-                                        MetaIdleMonitorWatchFunc   callback,
-                                        gpointer                   user_data,
-                                        GDestroyNotify             notify);
 };
 
 GType meta_idle_monitor_get_type (void);
 
+void          meta_idle_monitor_handle_xevent         (MetaIdleMonitor          *self,
+                                                       XSyncAlarmNotifyEvent    *xevent);
+
 guint         meta_idle_monitor_add_idle_watch        (MetaIdleMonitor          *monitor,
                                                       guint64                   interval_msec,
                                                       MetaIdleMonitorWatchFunc  callback,


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