[mutter/wayland] MetaIdleMonitor: fire immediately watches that are already expired



commit 389e04c715b290f8e8fab58dc8a2669e9329e3b7
Author: Giovanni Campagna <gcampagn redhat com>
Date:   Mon Sep 16 14:27:08 2013 +0200

    MetaIdleMonitor: fire immediately watches that are already expired
    
    The XSync semantics mandate that alarms already expired will not
    fire until the counter is reset and the alarm triggered again, so
    clients traditionally called get_idle_time() first to see if they
    should install the alarm.
    This is inherently racy, as by the time the call is handled by
    mutter and the reply received the idle time could be different.
    Instead, if we see that the watch would have fired in the past,
    fire it immediately.
    
    This is a behavior change, but it's a compatible one, as all legacy
    clients are calling get_idle_time() first, and it was perfectly
    possible for the idle time counter to trigger the alarm right
    after the get_idle_time() call.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=707302

 src/core/meta-idle-monitor.c |   29 ++++++++++++++++++++++++++++-
 1 files changed, 28 insertions(+), 1 deletions(-)
---
diff --git a/src/core/meta-idle-monitor.c b/src/core/meta-idle-monitor.c
index 01c4cb3..3c0d31e 100644
--- a/src/core/meta-idle-monitor.c
+++ b/src/core/meta-idle-monitor.c
@@ -77,7 +77,8 @@ typedef struct
   guint64                   timeout_msec;
 
   /* x11 */
-  XSyncAlarm               xalarm;
+  XSyncAlarm                xalarm;
+  int                       idle_source_id;
 
   /* wayland */
   GSource                  *timeout_source;
@@ -116,6 +117,12 @@ fire_watch (MetaIdleMonitorWatch *watch)
   monitor = watch->monitor;
   g_object_ref (monitor);
 
+  if (watch->idle_source_id)
+    {
+      g_source_remove (watch->idle_source_id);
+      watch->idle_source_id = 0;
+    }
+
   id = watch->id;
   is_user_active_watch = (watch->timeout_msec == 0);
 
@@ -287,6 +294,12 @@ idle_monitor_watch_free (MetaIdleMonitorWatch *watch)
 
   monitor = watch->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);
 
@@ -480,6 +493,17 @@ static GSourceFuncs wayland_source_funcs = {
   NULL, /* finalize */
 };
 
+static gboolean
+fire_watch_idle (gpointer data)
+{
+  MetaIdleMonitorWatch *watch = data;
+
+  watch->idle_source_id = 0;
+  fire_watch (watch);
+
+  return FALSE;
+}
+
 static MetaIdleMonitorWatch *
 make_watch (MetaIdleMonitor           *monitor,
             guint64                    timeout_msec,
@@ -518,6 +542,9 @@ make_watch (MetaIdleMonitor           *monitor,
           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);
         }
       else
         {


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