[gnome-flashback] idle-monitor: merge MetaIdleMonitorXSync into MetaIdleMonitor
- From: Alberts Muktupāvels <muktupavels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-flashback] idle-monitor: merge MetaIdleMonitorXSync into MetaIdleMonitor
- Date: Tue, 24 May 2022 10:10:07 +0000 (UTC)
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]