gnome-screensaver r1559 - in trunk: . src



Author: mccann
Date: Fri Nov 14 03:17:07 2008
New Revision: 1559
URL: http://svn.gnome.org/viewvc/gnome-screensaver?rev=1559&view=rev

Log:
2008-11-13  William Jon McCann  <jmccann redhat com>

	* configure.ac:
	* src/Makefile.am:
	* src/gs-idle-monitor.c (_xsyncvalue_to_int64),
	(_int64_to_xsyncvalue), (gs_idle_monitor_dispose), (_find_alarm),
	(find_watch_for_alarm), (send_fake_event), (gs_idle_monitor_reset),
	(handle_alarm_notify_event), (xevent_filter), (init_xsync),
	(_init_xtest), (gs_idle_monitor_constructor),
	(gs_idle_monitor_class_init), (get_next_watch_serial),
	(idle_monitor_watch_new), (idle_monitor_watch_free),
	(gs_idle_monitor_init), (gs_idle_monitor_finalize),
	(gs_idle_monitor_new), (_xsync_alarm_set),
	(gs_idle_monitor_add_watch), (gs_idle_monitor_remove_watch):
	* src/gs-idle-monitor.h:
	* src/gs-monitor.c (connect_watcher_signals):
	* src/gs-watcher-x11.c (remove_watchdog_timer),
	(add_watchdog_timer), (gs_watcher_reset), (gs_watcher_class_init),
	(on_power_timeout), (on_notice_timeout), (on_idle_timeout),
	(start_idle_watcher), (stop_idle_watcher), (gs_watcher_init),
	(gs_watcher_finalize), (disable_builtin_screensaver),
	(gs_watcher_new):
	* src/test-idle-monitor.c (on_less_idle), (on_idle),
	(on_very_idle), (test_idle_monitor), (main):
	* src/test-watcher.c (watcher_idle_notice_cb),
	(connect_watcher_signals), (test_watcher):
	Create a new class that can use IDLETIME counter to
	get idle times.  Rip out all the old code that
	selects for events on windows.
	Fixes #444927



Added:
   trunk/src/gs-idle-monitor.c
   trunk/src/gs-idle-monitor.h
   trunk/src/test-idle-monitor.c
Modified:
   trunk/ChangeLog
   trunk/configure.ac
   trunk/src/Makefile.am
   trunk/src/gs-monitor.c
   trunk/src/gs-watcher-x11.c
   trunk/src/test-watcher.c

Modified: trunk/configure.ac
==============================================================================
--- trunk/configure.ac	(original)
+++ trunk/configure.ac	Fri Nov 14 03:17:07 2008
@@ -319,6 +319,28 @@
   ])
 
 dnl ---------------------------------------------------------------------------
+dnl - Check for XSync extension
+dnl ---------------------------------------------------------------------------
+
+have_xsync=no
+AC_CHECK_X_HEADER(X11/extensions/sync.h, [have_xsync=yes],,
+                    [#include <X11/Xlib.h>])
+if test "$have_xsync" = yes; then
+  AC_DEFINE(HAVE_XSYNC, 1, [Have the SYNC extension library])
+fi
+
+dnl ---------------------------------------------------------------------------
+dnl - Check for XTest extension
+dnl ---------------------------------------------------------------------------
+
+have_xtest=no
+AC_CHECK_X_LIB(Xtst, XTestFakeKeyEvent, [have_xtest=yes], [have_xtest=no], -lX11 -lXext)
+if test "$have_xtest" = yes; then
+    AC_DEFINE(HAVE_XTEST, 1, [Have the XTest extension library])
+    SAVER_LIBS="$SAVER_LIBS -lXtst"
+fi
+
+dnl ---------------------------------------------------------------------------
 dnl - Check for shaped window extension
 dnl ---------------------------------------------------------------------------
 
@@ -1092,6 +1114,8 @@
         Extension libs:           ${SAVER_LIBS}
         Maintainer mode:          ${USE_MAINTAINER_MODE}
         Docs enabled:             ${enable_docbook_docs}
+	Have XSync:               ${have_xsync}
+	Have XTest:               ${have_xtest}
 
 	GL:                       ${have_libgl}
 

Modified: trunk/src/Makefile.am
==============================================================================
--- trunk/src/Makefile.am	(original)
+++ trunk/src/Makefile.am	Fri Nov 14 03:17:07 2008
@@ -48,6 +48,7 @@
 	test-fade	\
 	test-passwd	\
 	test-watcher	\
+	test-idle-monitor	\
 	test-window	\
 	$(NULL)
 
@@ -95,6 +96,8 @@
 	test-watcher.c			\
 	gs-watcher.h			\
 	gs-watcher-x11.c		\
+	gs-idle-monitor.h		\
+	gs-idle-monitor.c		\
 	gs-marshal.c 			\
 	gs-marshal.h			\
 	gs-debug.c			\
@@ -106,6 +109,19 @@
 	$(SAVER_LIBS)			\
 	$(NULL)
 
+test_idle_monitor_SOURCES =		\
+	test-idle-monitor.c		\
+	gs-idle-monitor.h		\
+	gs-idle-monitor.c		\
+	gs-debug.c			\
+	gs-debug.h			\
+	$(NULL)
+
+test_idle_monitor_LDADD =		\
+	$(GNOME_SCREENSAVER_LIBS)	\
+	$(SAVER_LIBS)			\
+	$(NULL)
+
 test_window_SOURCES =			\
 	test-window.c			\
 	gs-window.h			\
@@ -171,6 +187,8 @@
 	gs-monitor.h		\
 	gs-watcher-x11.c	\
 	gs-watcher.h		\
+	gs-idle-monitor.h	\
+	gs-idle-monitor.c	\
 	gs-listener-dbus.c	\
 	gs-listener-dbus.h	\
 	gs-manager.c		\

Added: trunk/src/gs-idle-monitor.c
==============================================================================
--- (empty file)
+++ trunk/src/gs-idle-monitor.c	Fri Nov 14 03:17:07 2008
@@ -0,0 +1,494 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors: William Jon McCann <mccann jhu edu>
+ *
+ */
+
+#include "config.h"
+
+#include <time.h>
+#include <string.h>
+
+#include <X11/Xlib.h>
+#include <X11/extensions/sync.h>
+
+#ifdef HAVE_XTEST
+#include <X11/extensions/XTest.h>
+#endif /* HAVE_XTEST */
+
+#include <glib.h>
+#include <gdk/gdkx.h>
+#include <gdk/gdk.h>
+
+#include "gs-idle-monitor.h"
+
+static void gs_idle_monitor_class_init (GSIdleMonitorClass *klass);
+static void gs_idle_monitor_init       (GSIdleMonitor      *idle_monitor);
+static void gs_idle_monitor_finalize   (GObject             *object);
+
+#define GS_IDLE_MONITOR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GS_TYPE_IDLE_MONITOR, GSIdleMonitorPrivate))
+
+struct GSIdleMonitorPrivate
+{
+        GHashTable  *watches;
+        int          sync_event_base;
+        XSyncCounter counter;
+
+        /* For use with XTest */
+        int         *keycode;
+        int          keycode1;
+        int          keycode2;
+        gboolean     have_xtest;
+};
+
+typedef struct
+{
+        guint                  id;
+        XSyncValue             interval;
+        GSIdleMonitorWatchFunc callback;
+        gpointer               user_data;
+        XSyncAlarm             xalarm_positive;
+        XSyncAlarm             xalarm_negative;
+} GSIdleMonitorWatch;
+
+static guint32 watch_serial = 1;
+
+G_DEFINE_TYPE (GSIdleMonitor, gs_idle_monitor, G_TYPE_OBJECT)
+
+static gint64
+_xsyncvalue_to_int64 (XSyncValue value)
+{
+        return ((guint64) XSyncValueHigh32 (value)) << 32
+                | (guint64) XSyncValueLow32 (value);
+}
+
+static XSyncValue
+_int64_to_xsyncvalue (gint64 value)
+{
+        XSyncValue ret;
+
+        XSyncIntsToValue (&ret, value, ((guint64)value) >> 32);
+
+        return ret;
+}
+
+static void
+gs_idle_monitor_dispose (GObject *object)
+{
+        GSIdleMonitor *monitor;
+
+        g_return_if_fail (GS_IS_IDLE_MONITOR (object));
+
+        monitor = GS_IDLE_MONITOR (object);
+
+        if (monitor->priv->watches != NULL) {
+                g_hash_table_destroy (monitor->priv->watches);
+                monitor->priv->watches = NULL;
+        }
+
+        G_OBJECT_CLASS (gs_idle_monitor_parent_class)->dispose (object);
+}
+
+static gboolean
+_find_alarm (gpointer            key,
+             GSIdleMonitorWatch *watch,
+             XSyncAlarm         *alarm)
+{
+        if (watch->xalarm_positive == *alarm
+            || watch->xalarm_negative == *alarm) {
+                return TRUE;
+        }
+        return FALSE;
+}
+
+static GSIdleMonitorWatch *
+find_watch_for_alarm (GSIdleMonitor *monitor,
+                      XSyncAlarm     alarm)
+{
+        GSIdleMonitorWatch *watch;
+
+        watch = g_hash_table_find (monitor->priv->watches,
+                                   (GHRFunc)_find_alarm,
+                                   &alarm);
+        return watch;
+}
+
+#ifdef HAVE_XTEST
+static gboolean
+send_fake_event (GSIdleMonitor *monitor)
+{
+        if (! monitor->priv->have_xtest) {
+                return FALSE;
+        }
+
+        XLockDisplay (GDK_DISPLAY());
+        XTestFakeKeyEvent (GDK_DISPLAY(),
+                           *monitor->priv->keycode,
+                           True,
+                           CurrentTime);
+        XTestFakeKeyEvent (GDK_DISPLAY(),
+                           *monitor->priv->keycode,
+                           False,
+                           CurrentTime);
+        XUnlockDisplay (GDK_DISPLAY());
+
+        /* Swap the keycode */
+        if (monitor->priv->keycode == &monitor->priv->keycode1) {
+                monitor->priv->keycode = &monitor->priv->keycode2;
+        } else {
+                monitor->priv->keycode = &monitor->priv->keycode1;
+        }
+
+        return TRUE;
+}
+#endif /* HAVE_XTEST */
+
+void
+gs_idle_monitor_reset (GSIdleMonitor *monitor)
+{
+        g_return_if_fail (GS_IS_IDLE_MONITOR (monitor));
+
+        /* FIXME: is there a better way to reset the IDLETIME? */
+        send_fake_event (monitor);
+}
+
+static void
+handle_alarm_notify_event (GSIdleMonitor         *monitor,
+                           XSyncAlarmNotifyEvent *alarm_event)
+{
+        GSIdleMonitorWatch *watch;
+        gboolean            res;
+        gboolean            condition;
+
+        watch = find_watch_for_alarm (monitor, alarm_event->alarm);
+
+        if (watch == NULL) {
+                g_warning ("Unable to find watch for alarm");
+                return;
+        }
+
+        g_debug ("Watch %d fired, idle time = %lld",
+                 watch->id,
+                 _xsyncvalue_to_int64 (alarm_event->counter_value));
+
+        if (alarm_event->alarm == watch->xalarm_positive) {
+                condition = TRUE;
+        } else {
+                condition = FALSE;
+        }
+
+        res = TRUE;
+        if (watch->callback != NULL) {
+                res = watch->callback (monitor,
+                                       watch->id,
+                                       condition,
+                                       watch->user_data);
+        }
+
+        if (! res) {
+                /* reset all timers */
+                g_debug ("GSIdleMonitor: callback returned FALSE; resetting idle time");
+                gs_idle_monitor_reset (monitor);
+        }
+}
+
+static GdkFilterReturn
+xevent_filter (GdkXEvent     *xevent,
+               GdkEvent      *event,
+               GSIdleMonitor *monitor)
+{
+        XEvent                *ev;
+        XSyncAlarmNotifyEvent *alarm_event;
+
+        ev = xevent;
+        if (ev->xany.type != monitor->priv->sync_event_base + XSyncAlarmNotify) {
+                return GDK_FILTER_CONTINUE;
+        }
+
+        alarm_event = xevent;
+
+        handle_alarm_notify_event (monitor, alarm_event);
+
+        return GDK_FILTER_CONTINUE;
+}
+
+static gboolean
+init_xsync (GSIdleMonitor *monitor)
+{
+        int                 sync_error_base;
+        int                 res;
+        int                 major;
+        int                 minor;
+        int                 i;
+        int                 ncounters;
+        XSyncSystemCounter *counters;
+
+        res = XSyncQueryExtension (GDK_DISPLAY (),
+                                   &monitor->priv->sync_event_base,
+                                   &sync_error_base);
+        if (! res) {
+                g_warning ("GSIdleMonitor: Sync extension not present");
+                return FALSE;
+        }
+
+        res = XSyncInitialize (GDK_DISPLAY (), &major, &minor);
+        if (! res) {
+                g_warning ("GSIdleMonitor: Unable to initialize Sync extension");
+                return FALSE;
+        }
+
+        counters = XSyncListSystemCounters (GDK_DISPLAY (), &ncounters);
+        for (i = 0; i < ncounters; i++) {
+                if (counters[i].name != NULL
+                    && strcmp (counters[i].name, "IDLETIME") == 0) {
+                        monitor->priv->counter = counters[i].counter;
+                        break;
+                }
+        }
+        XSyncFreeSystemCounterList (counters);
+
+        if (monitor->priv->counter == None) {
+                g_warning ("GSIdleMonitor: IDLETIME counter not found");
+                return FALSE;
+        }
+
+        /* select for sync events */
+        gdk_error_trap_push ();
+        XSelectInput (GDK_DISPLAY (), GDK_ROOT_WINDOW (), XSyncAlarmNotifyMask);
+        if (gdk_error_trap_pop ()) {
+                g_warning ("XSelectInput failed");
+        }
+
+        gdk_window_add_filter (NULL, (GdkFilterFunc)xevent_filter, monitor);
+
+        return TRUE;
+}
+
+static void
+_init_xtest (GSIdleMonitor *monitor)
+{
+#ifdef HAVE_XTEST
+        int a, b, c, d;
+
+        XLockDisplay (GDK_DISPLAY());
+        monitor->priv->have_xtest = (XTestQueryExtension (GDK_DISPLAY(), &a, &b, &c, &d) == True);
+        if (monitor->priv->have_xtest) {
+                monitor->priv->keycode1 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_L);
+                if (monitor->priv->keycode1 == 0) {
+                        g_warning ("keycode1 not existant");
+                }
+                monitor->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_R);
+                if (monitor->priv->keycode2 == 0) {
+                        monitor->priv->keycode2 = XKeysymToKeycode (GDK_DISPLAY(), XK_Alt_L);
+                        if (monitor->priv->keycode2 == 0) {
+                                g_warning ("keycode2 not existant");
+                        }
+                }
+                monitor->priv->keycode = &monitor->priv->keycode1;
+        }
+        XUnlockDisplay (GDK_DISPLAY());
+#endif /* HAVE_XTEST */
+}
+
+static GObject *
+gs_idle_monitor_constructor (GType                  type,
+                             guint                  n_construct_properties,
+                             GObjectConstructParam *construct_properties)
+{
+        GSIdleMonitor *monitor;
+
+        monitor = GS_IDLE_MONITOR (G_OBJECT_CLASS (gs_idle_monitor_parent_class)->constructor (type,
+                                                                                               n_construct_properties,
+                                                                                               construct_properties));
+
+        _init_xtest (monitor);
+
+        if (! init_xsync (monitor)) {
+                g_object_unref (monitor);
+                return NULL;
+        }
+
+        return G_OBJECT (monitor);
+}
+
+static void
+gs_idle_monitor_class_init (GSIdleMonitorClass *klass)
+{
+        GObjectClass   *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->finalize = gs_idle_monitor_finalize;
+        object_class->dispose = gs_idle_monitor_dispose;
+        object_class->constructor = gs_idle_monitor_constructor;
+
+        g_type_class_add_private (klass, sizeof (GSIdleMonitorPrivate));
+}
+
+static guint32
+get_next_watch_serial (void)
+{
+        guint32 serial;
+
+        serial = watch_serial++;
+
+        if ((gint32)watch_serial < 0) {
+                watch_serial = 1;
+        }
+
+        /* FIXME: make sure it isn't in the hash */
+
+        return serial;
+}
+
+static GSIdleMonitorWatch *
+idle_monitor_watch_new (guint interval)
+{
+        GSIdleMonitorWatch *watch;
+
+        watch = g_slice_new0 (GSIdleMonitorWatch);
+        watch->interval = _int64_to_xsyncvalue ((gint64)interval);
+        watch->id = get_next_watch_serial ();
+        watch->xalarm_positive = None;
+        watch->xalarm_negative = None;
+
+        return watch;
+}
+
+static void
+idle_monitor_watch_free (GSIdleMonitorWatch *watch)
+{
+        if (watch == NULL) {
+                return;
+        }
+        if (watch->xalarm_positive != None) {
+                XSyncDestroyAlarm (GDK_DISPLAY (), watch->xalarm_positive);
+        }
+        if (watch->xalarm_negative != None) {
+                XSyncDestroyAlarm (GDK_DISPLAY (), watch->xalarm_negative);
+        }
+        g_slice_free (GSIdleMonitorWatch, watch);
+}
+
+static void
+gs_idle_monitor_init (GSIdleMonitor *monitor)
+{
+        monitor->priv = GS_IDLE_MONITOR_GET_PRIVATE (monitor);
+
+        monitor->priv->watches = g_hash_table_new_full (NULL,
+                                                        NULL,
+                                                        NULL,
+                                                        (GDestroyNotify)idle_monitor_watch_free);
+
+        monitor->priv->counter = None;
+}
+
+static void
+gs_idle_monitor_finalize (GObject *object)
+{
+        GSIdleMonitor *idle_monitor;
+
+        g_return_if_fail (object != NULL);
+        g_return_if_fail (GS_IS_IDLE_MONITOR (object));
+
+        idle_monitor = GS_IDLE_MONITOR (object);
+
+        g_return_if_fail (idle_monitor->priv != NULL);
+
+        G_OBJECT_CLASS (gs_idle_monitor_parent_class)->finalize (object);
+}
+
+GSIdleMonitor *
+gs_idle_monitor_new (void)
+{
+        GObject *idle_monitor;
+
+        idle_monitor = g_object_new (GS_TYPE_IDLE_MONITOR,
+                                     NULL);
+
+        return GS_IDLE_MONITOR (idle_monitor);
+}
+
+static gboolean
+_xsync_alarm_set (GSIdleMonitor      *monitor,
+                  GSIdleMonitorWatch *watch)
+{
+        XSyncAlarmAttributes attr;
+        XSyncValue           delta;
+        guint                flags;
+
+        flags = XSyncCACounter
+                | XSyncCAValueType
+                | XSyncCATestType
+                | XSyncCAValue
+                | XSyncCADelta;
+
+        XSyncIntToValue (&delta, 0);
+        attr.trigger.counter = monitor->priv->counter;
+        attr.trigger.value_type = XSyncAbsolute;
+        attr.trigger.wait_value = watch->interval;
+        attr.delta = delta;
+
+        attr.trigger.test_type = XSyncPositiveTransition;
+        if (watch->xalarm_positive != None) {
+                XSyncChangeAlarm (GDK_DISPLAY (), watch->xalarm_positive, flags, &attr);
+        } else {
+                watch->xalarm_positive = XSyncCreateAlarm (GDK_DISPLAY (), flags, &attr);
+        }
+
+        attr.trigger.test_type = XSyncNegativeTransition;
+        if (watch->xalarm_negative != None) {
+                XSyncChangeAlarm (GDK_DISPLAY (), watch->xalarm_negative, flags, &attr);
+        } else {
+                watch->xalarm_negative = XSyncCreateAlarm (GDK_DISPLAY (), flags, &attr);
+        }
+
+        return TRUE;
+}
+
+guint
+gs_idle_monitor_add_watch (GSIdleMonitor         *monitor,
+                           guint                  interval,
+                           GSIdleMonitorWatchFunc callback,
+                           gpointer               user_data)
+{
+        GSIdleMonitorWatch *watch;
+
+        g_return_val_if_fail (GS_IS_IDLE_MONITOR (monitor), 0);
+        g_return_val_if_fail (callback != NULL, 0);
+
+        watch = idle_monitor_watch_new (interval);
+        watch->callback = callback;
+        watch->user_data = user_data;
+
+        _xsync_alarm_set (monitor, watch);
+
+        g_hash_table_insert (monitor->priv->watches,
+                             GUINT_TO_POINTER (watch->id),
+                             watch);
+        return watch->id;
+}
+
+void
+gs_idle_monitor_remove_watch (GSIdleMonitor *monitor,
+                              guint          id)
+{
+        g_return_if_fail (GS_IS_IDLE_MONITOR (monitor));
+
+        g_hash_table_remove (monitor->priv->watches,
+                             GUINT_TO_POINTER (id));
+}

Added: trunk/src/gs-idle-monitor.h
==============================================================================
--- (empty file)
+++ trunk/src/gs-idle-monitor.h	Fri Nov 14 03:17:07 2008
@@ -0,0 +1,71 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors: William Jon McCann <mccann jhu edu>
+ *
+ */
+
+#ifndef __GS_IDLE_MONITOR_H
+#define __GS_IDLE_MONITOR_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GS_TYPE_IDLE_MONITOR         (gs_idle_monitor_get_type ())
+#define GS_IDLE_MONITOR(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GS_TYPE_IDLE_MONITOR, GSIdleMonitor))
+#define GS_IDLE_MONITOR_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), GS_TYPE_IDLE_MONITOR, GSIdleMonitorClass))
+#define GS_IS_IDLE_MONITOR(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), GS_TYPE_IDLE_MONITOR))
+#define GS_IS_IDLE_MONITOR_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), GS_TYPE_IDLE_MONITOR))
+#define GS_IDLE_MONITOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GS_TYPE_IDLE_MONITOR, GSIdleMonitorClass))
+
+typedef struct GSIdleMonitorPrivate GSIdleMonitorPrivate;
+
+typedef struct
+{
+        GObject               parent;
+        GSIdleMonitorPrivate *priv;
+} GSIdleMonitor;
+
+typedef struct
+{
+        GObjectClass          parent_class;
+} GSIdleMonitorClass;
+
+typedef gboolean (*GSIdleMonitorWatchFunc) (GSIdleMonitor *monitor,
+                                            guint          id,
+                                            gboolean       condition,
+                                            gpointer       user_data);
+
+GType           gs_idle_monitor_get_type       (void);
+
+GSIdleMonitor * gs_idle_monitor_new            (void);
+
+guint           gs_idle_monitor_add_watch      (GSIdleMonitor         *monitor,
+                                                guint                  interval,
+                                                GSIdleMonitorWatchFunc callback,
+                                                gpointer               user_data);
+
+void            gs_idle_monitor_remove_watch   (GSIdleMonitor         *monitor,
+                                                guint                  id);
+void            gs_idle_monitor_reset          (GSIdleMonitor         *monitor);
+
+
+G_END_DECLS
+
+#endif /* __GS_IDLE_MONITOR_H */

Modified: trunk/src/gs-monitor.c
==============================================================================
--- trunk/src/gs-monitor.c	(original)
+++ trunk/src/gs-monitor.c	Fri Nov 14 03:17:07 2008
@@ -403,11 +403,11 @@
 static void
 connect_watcher_signals (GSMonitor *monitor)
 {
-        g_signal_connect (monitor->priv->watcher, "idle_changed",
+        g_signal_connect (monitor->priv->watcher, "idle-changed",
                           G_CALLBACK (watcher_idle_cb), monitor);
-        g_signal_connect (monitor->priv->watcher, "idle_notice_changed",
+        g_signal_connect (monitor->priv->watcher, "idle-notice-changed",
                           G_CALLBACK (watcher_idle_notice_cb), monitor);
-        g_signal_connect (monitor->priv->watcher, "power_notice_changed",
+        g_signal_connect (monitor->priv->watcher, "power-notice-changed",
                           G_CALLBACK (watcher_power_notice_cb), monitor);
 }
 

Modified: trunk/src/gs-watcher-x11.c
==============================================================================
--- trunk/src/gs-watcher-x11.c	(original)
+++ trunk/src/gs-watcher-x11.c	Fri Nov 14 03:17:07 2008
@@ -1,9 +1,7 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
  *
- * Portions derived from xscreensaver,
- * Copyright (c) 1991-2004 Jamie Zawinski <jwz jwz org>
- *
  * Copyright (C) 2004-2006 William Jon McCann <mccann jhu edu>
+ * Copyright (C) 2008      Red Hat, Inc.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -30,18 +28,9 @@
 #include <errno.h>
 
 #include <string.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif /* HAVE_SYS_SELECT_H */
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-
-#include <gdk/gdk.h>
 #include <gdk/gdkx.h>
 
+#include "gs-idle-monitor.h"
 #include "gs-watcher.h"
 #include "gs-marshal.h"
 #include "gs-debug.h"
@@ -50,15 +39,7 @@
 static void     gs_watcher_init       (GSWatcher      *watcher);
 static void     gs_watcher_finalize   (GObject        *object);
 
-static void     initialize_server_extensions (GSWatcher *watcher);
-
-static void     schedule_wakeup_event        (GSWatcher      *watcher,
-                                              int             when);
-static void     schedule_power_wakeup_event  (GSWatcher      *watcher,
-                                              int             when);
-static gboolean watchdog_timer               (GSWatcher      *watcher);
-static gboolean idle_timer                   (GSWatcher      *watcher);
-static gboolean power_timer                  (GSWatcher      *watcher);
+static gboolean watchdog_timer        (GSWatcher      *watcher);
 
 #define GS_WATCHER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GS_TYPE_WATCHER, GSWatcherPrivate))
 
@@ -68,28 +49,21 @@
         guint           enabled : 1;
         guint           timeout;
         guint           power_timeout;
-
-        guint           notice_timeout;
+        guint           delta_notice_timeout;
 
         /* state */
-        guint            active : 1;
-        guint            idle : 1;
-        guint            idle_notice : 1;
-        guint            power_notice : 1;
-
-        GTimer         *idle_timer;
-        guint           emergency_lock : 1;
+        guint           active : 1;
+        guint           idle : 1;
+        guint           idle_notice : 1;
+        guint           power_notice : 1;
+
+        GSIdleMonitor  *idle_monitor;
+        guint           power_id;
+        guint           notice_id;
+        guint           idle_id;
 
-        guint           timer_id;
-        guint           power_timer_id;
         guint           watchdog_timer_id;
 
-        guint           using_mit_saver_extension : 1;
-
-# ifdef HAVE_MIT_SAVER_EXTENSION
-        int             mit_saver_ext_event_number;
-        int             mit_saver_ext_error_number;
-# endif
 };
 
 enum {
@@ -105,18 +79,35 @@
         PROP_POWER_TIMEOUT
 };
 
-static guint         signals [LAST_SIGNAL] = { 0, };
+static guint signals [LAST_SIGNAL] = { 0, };
 
 G_DEFINE_TYPE (GSWatcher, gs_watcher, G_TYPE_OBJECT)
 
+static void
+remove_watchdog_timer (GSWatcher *watcher)
+{
+        if (watcher->priv->watchdog_timer_id != 0) {
+                g_source_remove (watcher->priv->watchdog_timer_id);
+                watcher->priv->watchdog_timer_id = 0;
+        }
+}
+
+static void
+add_watchdog_timer (GSWatcher *watcher,
+                    glong      timeout)
+{
+        watcher->priv->watchdog_timer_id = g_timeout_add (timeout,
+                                                          (GSourceFunc)watchdog_timer,
+                                                          watcher);
+}
+
 void
 gs_watcher_reset (GSWatcher *watcher)
 {
         g_return_if_fail (GS_IS_WATCHER (watcher));
 
-        /* just return quietly if not enabled */
-        if (! watcher->priv->enabled) {
-                return;
+        if (watcher->priv->idle_monitor != NULL) {
+                gs_idle_monitor_reset (watcher->priv->idle_monitor);
         }
 
         /* restart if necessary */
@@ -210,7 +201,7 @@
         object_class->set_property = gs_watcher_set_property;
 
         signals [IDLE_CHANGED] =
-                g_signal_new ("idle_changed",
+                g_signal_new ("idle-changed",
                               G_TYPE_FROM_CLASS (object_class),
                               G_SIGNAL_RUN_LAST,
                               G_STRUCT_OFFSET (GSWatcherClass, idle_changed),
@@ -220,7 +211,7 @@
                               G_TYPE_BOOLEAN,
                               1, G_TYPE_BOOLEAN);
         signals [IDLE_NOTICE_CHANGED] =
-                g_signal_new ("idle_notice_changed",
+                g_signal_new ("idle-notice-changed",
                               G_TYPE_FROM_CLASS (object_class),
                               G_SIGNAL_RUN_LAST,
                               G_STRUCT_OFFSET (GSWatcherClass, idle_notice_changed),
@@ -230,7 +221,7 @@
                               G_TYPE_BOOLEAN,
                               1, G_TYPE_BOOLEAN);
         signals [POWER_NOTICE_CHANGED] =
-                g_signal_new ("power_notice_changed",
+                g_signal_new ("power-notice-changed",
                               G_TYPE_FROM_CLASS (object_class),
                               G_SIGNAL_RUN_LAST,
                               G_STRUCT_OFFSET (GSWatcherClass, power_notice_changed),
@@ -248,221 +239,20 @@
                                                             10000,
                                                             G_MAXUINT,
                                                             600000,
-                                                            G_PARAM_READWRITE));
+                                                            G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
         g_object_class_install_property (object_class,
-                                         PROP_TIMEOUT,
+                                         PROP_POWER_TIMEOUT,
                                          g_param_spec_uint ("power-timeout",
                                                             NULL,
                                                             NULL,
                                                             10000,
                                                             G_MAXUINT,
                                                             60000,
-                                                            G_PARAM_READWRITE));
+                                                            G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
 
         g_type_class_add_private (klass, sizeof (GSWatcherPrivate));
 }
 
-static void
-notice_events_inner (Window   window,
-                     gboolean enable,
-                     gboolean top)
-{
-        XWindowAttributes attrs;
-        unsigned long     events;
-        Window            root;
-        Window            parent;
-        Window           *kids;
-        unsigned int      nkids;
-        int               status;
-        GdkWindow        *gwindow;
-
-        gwindow = gdk_window_lookup (window);
-        if (gwindow != NULL
-            && (window != GDK_ROOT_WINDOW ())) {
-                /* If it's one of ours, don't mess up its event mask. */
-                return;
-        }
-
-        kids = NULL;
-        status = XQueryTree (GDK_DISPLAY (), window, &root, &parent, &kids, &nkids);
-
-        if (status == 0) {
-                if (kids != NULL) {
-                        XFree (kids);
-                }
-                return;
-        }
-
-        if (window == root) {
-                top = FALSE;
-        }
-
-        memset (&attrs, 0, sizeof (attrs));
-        XGetWindowAttributes (GDK_DISPLAY (), window, &attrs);
-
-        if (enable) {
-                /* Select for KeyPress on all windows that already have it selected */
-                events = ((attrs.all_event_masks | attrs.do_not_propagate_mask) & KeyPressMask);
-
-                /* Keep already selected events.  This is important when the
-                   window == GDK_ROOT_WINDOW () since the mask will contain
-                   StructureNotifyMask that is essential for RANDR support */
-                events |= attrs.your_event_mask;
-
-                /* Select for SubstructureNotify on all windows */
-                events |= SubstructureNotifyMask;
-
-                /* Select for PropertyNotify events to get user time changes */
-                events |= PropertyChangeMask;
-
-                /* As with keypress events, only select mouse motion events
-                   for windows which already have them selected. */
-                events |= ((attrs.all_event_masks | attrs.do_not_propagate_mask) & (PointerMotionMask | PointerMotionHintMask));
-        } else {
-                /* We want to disable all events */
-
-                /* Don't mess up the root window */
-                if (window == GDK_ROOT_WINDOW ()) {
-                        events = attrs.your_event_mask;
-                } else {
-                        events = 0;
-                }
-        }
-
-        /* Select for SubstructureNotify on all windows.
-           Select for KeyPress on all windows that already have it selected.
-
-           Note that we can't select for ButtonPress, because of X braindamage:
-           only one client at a time may select for ButtonPress on a given
-           window, though any number can select for KeyPress.  Someone explain
-           *that* to me.
-
-           So, if the user spends a while clicking the mouse without ever moving
-           the mouse or touching the keyboard, we won't know that they've been
-           active, and the screensaver will come on.  That sucks, but I don't
-           know how to get around it.
-
-           Since X presents mouse wheels as clicks, this applies to those, too:
-           scrolling through a document using only the mouse wheel doesn't
-           count as activity...  Fortunately, /proc/interrupts helps, on
-           systems that have it.  Oh, if it's a PS/2 mouse, not serial or USB.
-           This sucks!
-        */
-
-        XSelectInput (GDK_DISPLAY (), window, events);
-
-        if (top && (events & KeyPressMask)) {
-                /* Only mention one window per tree */
-                top = FALSE;
-                if (enable) {
-                        gs_debug ("Adding events for 0x%lX", (unsigned long)window);
-                } else {
-                        gs_debug ("Removing events for 0x%lX", (unsigned long)window);
-                }
-        }
-
-        if (kids != NULL) {
-                while (nkids > 0) {
-                        notice_events_inner (kids [--nkids], enable, top);
-                }
-
-                XFree (kids);
-        }
-}
-
-static void
-notice_events (Window   window,
-               gboolean enable,
-               gboolean top)
-{
-        gdk_error_trap_push ();
-
-        notice_events_inner (window, enable, top);
-
-        gdk_display_sync (gdk_display_get_default ());
-        gdk_error_trap_pop ();
-}
-
-static void
-stop_notice_events (GSWatcher *watcher,
-                    Window     window)
-{
-        gboolean is_top = TRUE;
-        notice_events (window, FALSE, is_top);
-}
-
-static void
-start_notice_events (GSWatcher *watcher,
-                     Window     window)
-{
-        gboolean is_top = TRUE;
-        notice_events (window, TRUE, is_top);
-}
-
-static void
-remove_power_timer (GSWatcher *watcher)
-{
-        if (watcher->priv->power_timer_id != 0) {
-                g_source_remove (watcher->priv->power_timer_id);
-                watcher->priv->power_timer_id = 0;
-        }
-}
-
-static void
-add_power_timer (GSWatcher *watcher,
-                 glong      timeout)
-{
-        watcher->priv->power_timer_id = g_timeout_add (timeout, (GSourceFunc)power_timer, watcher);
-}
-
-static void
-remove_idle_timer (GSWatcher *watcher)
-{
-        if (watcher->priv->timer_id != 0) {
-                g_source_remove (watcher->priv->timer_id);
-                watcher->priv->timer_id = 0;
-        }
-}
-
-static void
-add_idle_timer (GSWatcher *watcher,
-                glong      timeout)
-{
-        watcher->priv->timer_id = g_timeout_add (timeout, (GSourceFunc)idle_timer, watcher);
-}
-
-static void
-remove_watchdog_timer (GSWatcher *watcher)
-{
-        if (watcher->priv->watchdog_timer_id != 0) {
-                g_source_remove (watcher->priv->watchdog_timer_id);
-                watcher->priv->watchdog_timer_id = 0;
-        }
-}
-
-static void
-add_watchdog_timer (GSWatcher *watcher,
-                    glong      timeout)
-{
-        watcher->priv->watchdog_timer_id = g_timeout_add (timeout,
-                                                          (GSourceFunc)watchdog_timer,
-                                                          watcher);
-}
-
-/* Call this when user activity (or "simulated" activity) has been noticed.
- */
-static void
-reset_timers (GSWatcher *watcher)
-{
-        remove_power_timer (watcher);
-        remove_idle_timer (watcher);
-
-        schedule_wakeup_event (watcher, watcher->priv->timeout);
-        schedule_power_wakeup_event (watcher, watcher->priv->power_timeout);
-
-        g_timer_start (watcher->priv->idle_timer);
-}
-
 static gboolean
 _gs_watcher_set_session_power_notice (GSWatcher *watcher,
                                       gboolean   in_effect)
@@ -532,132 +322,76 @@
         return res;
 }
 
-static void
-_gs_watcher_notice_activity (GSWatcher *watcher)
-{
-        if (! watcher->priv->active) {
-                gs_debug ("Noticed activity but watcher is inactive");
-                return;
-        }
-
-        /* if a power notice was sent, cancel it */
-        if (watcher->priv->power_notice) {
-                gboolean in_effect = FALSE;
-                _gs_watcher_set_session_power_notice (watcher, in_effect);
-        }
-
-        /* if an idle notice was sent, cancel it */
-        if (watcher->priv->idle_notice) {
-                gboolean in_effect = FALSE;
-                _gs_watcher_set_session_idle_notice (watcher, in_effect);
-        }
-
-        /* if idle signal was sent, cancel it */
-        if (watcher->priv->idle) {
-                gboolean is_idle = FALSE;
-                _gs_watcher_set_session_idle (watcher, is_idle);
-        }
-
-        reset_timers (watcher);
-}
-
-static void
-_gs_watcher_notice_window_created (GSWatcher *watcher,
-                                   Window     window)
+static gboolean
+on_power_timeout (GSIdleMonitor *monitor,
+                  guint          id,
+                  gboolean       condition,
+                  GSWatcher     *watcher)
 {
-        gs_debug ("Window created: noticing activity on 0x%lX", (unsigned long)window);
-
-        start_notice_events (watcher, window);
+        gboolean res;
+        res = _gs_watcher_set_session_power_notice (watcher, condition);
+        return res;
 }
 
 static gboolean
-query_pointer_timeout (Window window)
+on_notice_timeout (GSIdleMonitor *monitor,
+                   guint          id,
+                   gboolean       condition,
+                   GSWatcher     *watcher)
 {
-        Window       root;
-        Window       child;
-        int          root_x;
-        int          root_y;
-        int          win_x;
-        int          win_y;
-        unsigned int mask;
-
-        gdk_error_trap_push ();
-        XQueryPointer (GDK_DISPLAY (),
-                       window,
-                       &root, &child, &root_x, &root_y, &win_x, &win_y, &mask);
-        gdk_display_sync (gdk_display_get_default ());
-        gdk_error_trap_pop ();
-
-        return FALSE;
+        gboolean res;
+        res = _gs_watcher_set_session_idle_notice (watcher, condition);
+        return res;
 }
 
-static void
-gs_watcher_xevent (GSWatcher *watcher,
-                   GdkXEvent *xevent)
+static gboolean
+on_idle_timeout (GSIdleMonitor *monitor,
+                 guint          id,
+                 gboolean       condition,
+                 GSWatcher     *watcher)
 {
-        XEvent *ev;
-
-        /* do nothing if we aren't watching */
-        if (! watcher->priv->active) {
-                return;
-        }
-
-        ev = xevent;
-
-        switch (ev->xany.type) {
-        case KeyPress:
-        case KeyRelease:
-        case ButtonPress:
-        case ButtonRelease:
-                _gs_watcher_notice_activity (watcher);
-                break;
-        case PropertyNotify:
-                if (ev->xproperty.atom == gdk_x11_get_xatom_by_name ("_NET_WM_USER_TIME")) {
-                        _gs_watcher_notice_activity (watcher);
-                }
-                break;
-        case CreateNotify:
-                {
-                        Window window = ev->xcreatewindow.window;
-                        _gs_watcher_notice_window_created (watcher,
-                                                           window);
-                }
-                break;
-        case MotionNotify:
-                if (ev->xmotion.is_hint) {
-                        /* need to respond to hints so we continue to get events */
-                        g_timeout_add (1000, (GSourceFunc)query_pointer_timeout, GINT_TO_POINTER (ev->xmotion.window));
-                }
+        gboolean res;
 
-                _gs_watcher_notice_activity (watcher);
+        res = _gs_watcher_set_session_idle (watcher, condition);
+        _gs_watcher_set_session_idle_notice (watcher, !condition);
 
-                break;
-        default:
-                break;
+        /* if the event wasn't handled then schedule another timer */
+        if (! res) {
+                gs_debug ("Idle signal was not handled, restarting watcher");
         }
 
-}
-
-static GdkFilterReturn
-xevent_filter (GdkXEvent *xevent,
-               GdkEvent  *event,
-               GSWatcher *watcher)
-{
-        gs_watcher_xevent (watcher, xevent);
-
-        return GDK_FILTER_CONTINUE;
+        return res;
 }
 
 static gboolean
 start_idle_watcher (GSWatcher *watcher)
 {
+        guint notice_timeout;
+
         g_return_val_if_fail (watcher != NULL, FALSE);
         g_return_val_if_fail (GS_IS_WATCHER (watcher), FALSE);
 
-        gdk_window_add_filter (NULL, (GdkFilterFunc)xevent_filter, watcher);
-        start_notice_events (watcher, DefaultRootWindow (GDK_DISPLAY ()));
-
-        reset_timers (watcher);
+        g_debug ("GSWatcher: adding power watch %d", watcher->priv->power_timeout);
+        watcher->priv->power_id
+                = gs_idle_monitor_add_watch (watcher->priv->idle_monitor,
+                                             watcher->priv->power_timeout,
+                                             (GSIdleMonitorWatchFunc)on_power_timeout,
+                                             watcher);
+
+        notice_timeout = watcher->priv->timeout - watcher->priv->delta_notice_timeout;
+        g_debug ("GSWatcher: adding notice watch %d", notice_timeout);
+        watcher->priv->notice_id
+                = gs_idle_monitor_add_watch (watcher->priv->idle_monitor,
+                                             notice_timeout,
+                                             (GSIdleMonitorWatchFunc)on_notice_timeout,
+                                             watcher);
+
+        g_debug ("GSWatcher: adding idle watch %d", watcher->priv->timeout);
+        watcher->priv->idle_id
+                = gs_idle_monitor_add_watch (watcher->priv->idle_monitor,
+                                             watcher->priv->timeout,
+                                             (GSIdleMonitorWatchFunc)on_idle_timeout,
+                                             watcher);
 
         watchdog_timer (watcher);
 
@@ -670,13 +404,18 @@
         g_return_val_if_fail (watcher != NULL, FALSE);
         g_return_val_if_fail (GS_IS_WATCHER (watcher), FALSE);
 
-        g_timer_stop (watcher->priv->idle_timer);
-
-        remove_idle_timer (watcher);
-        remove_power_timer (watcher);
-
-        stop_notice_events (watcher, DefaultRootWindow (GDK_DISPLAY ()));
-        gdk_window_remove_filter (NULL, (GdkFilterFunc)xevent_filter, watcher);
+        if (watcher->priv->notice_id > 0) {
+                gs_idle_monitor_remove_watch (watcher->priv->idle_monitor,
+                                              watcher->priv->notice_id);
+        }
+        if (watcher->priv->power_id > 0) {
+                gs_idle_monitor_remove_watch (watcher->priv->idle_monitor,
+                                              watcher->priv->power_id);
+        }
+        if (watcher->priv->idle_id > 0) {
+                gs_idle_monitor_remove_watch (watcher->priv->idle_monitor,
+                                              watcher->priv->idle_id);
+        }
 
         return FALSE;
 }
@@ -721,7 +460,6 @@
         return TRUE;
 }
 
-
 gboolean
 gs_watcher_set_active (GSWatcher *watcher,
                        gboolean   active)
@@ -786,12 +524,10 @@
         watcher->priv->active = FALSE;
         watcher->priv->timeout = 600000;
 
-        /* time before idle signal to send notice signal */
-        watcher->priv->notice_timeout = 10000;
-
-        watcher->priv->idle_timer = g_timer_new ();
+        watcher->priv->idle_monitor = gs_idle_monitor_new ();
 
-        initialize_server_extensions (watcher);
+        /* time before idle signal to send notice signal */
+        watcher->priv->delta_notice_timeout = 10000;
 
         add_watchdog_timer (watcher, 600000);
 }
@@ -813,102 +549,12 @@
         watcher->priv->active = FALSE;
         stop_idle_watcher (watcher);
 
-        g_timer_destroy (watcher->priv->idle_timer);
-        watcher->priv->idle_timer = NULL;
-
         G_OBJECT_CLASS (gs_watcher_parent_class)->finalize (object);
 }
 
-#ifdef HAVE_MIT_SAVER_EXTENSION
-
-# include <X11/extensions/scrnsaver.h>
-
-static gboolean
-query_mit_saver_extension (int *event_number,
-                           int *error_number)
-{
-        return XScreenSaverQueryExtension (GDK_DISPLAY (),
-                                           event_number,
-                                           error_number);
-}
-
-/* MIT SCREEN-SAVER server extension hackery.
- */
-static gboolean
-init_mit_saver_extension (void)
-{
-        int         i;
-        GdkDisplay *display   = gdk_display_get_default ();
-        int         n_screens = gdk_display_get_n_screens (display);
-        Pixmap     *blank_pix = (Pixmap *) calloc (sizeof (Pixmap), n_screens);
-
-        for (i = 0; i < n_screens; i++) {
-                XID        kill_id   = 0;
-                Atom       kill_type = 0;
-                GdkScreen *screen    = gdk_display_get_screen (display, i);
-                Window     root      = RootWindowOfScreen (GDK_SCREEN_XSCREEN (screen));
-
-                blank_pix[i] = XCreatePixmap (GDK_DISPLAY (), root, 1, 1, 1);
-
-                /* Kill off the old MIT-SCREEN-SAVER client if there is one.
-                   This tends to generate X errors, though (possibly due to a bug
-                   in the server extension itself?) so just ignore errors here. */
-                if (XScreenSaverGetRegistered (GDK_DISPLAY (),
-                                               XScreenNumberOfScreen (GDK_SCREEN_XSCREEN (screen)),
-                                               &kill_id, &kill_type)
-                    && kill_id != blank_pix[i]) {
-                        gdk_error_trap_push ();
-
-                        XKillClient (GDK_DISPLAY (), kill_id);
-
-                        gdk_display_sync (gdk_display_get_default ());
-                        gdk_error_trap_pop ();
-                }
-
-                XScreenSaverSelectInput (GDK_DISPLAY (), root, ScreenSaverNotifyMask);
-                XScreenSaverRegister (GDK_DISPLAY (),
-                                      XScreenNumberOfScreen (GDK_SCREEN_XSCREEN (screen)),
-                                      (XID) blank_pix [i],
-                                      gdk_x11_get_xatom_by_name_for_display (display, "XA_PIXMAP"));
-        }
-
-        free (blank_pix);
-
-        return TRUE;
-}
-#endif /* HAVE_MIT_SAVER_EXTENSION */
-
-
-/* If any server extensions have been requested, try and initialize them.
-   Issue warnings if requests can't be honored.
-*/
-static void
-initialize_server_extensions (GSWatcher *watcher)
-{
-        gboolean server_has_mit_saver_extension = FALSE;
-
-        watcher->priv->using_mit_saver_extension = FALSE;
-
-#ifdef HAVE_MIT_SAVER_EXTENSION
-        server_has_mit_saver_extension = query_mit_saver_extension (&watcher->priv->mit_saver_ext_event_number,
-                                                                    &watcher->priv->mit_saver_ext_error_number);
-#endif
-
-        if (! server_has_mit_saver_extension) {
-                watcher->priv->using_mit_saver_extension = FALSE;
-        } else {
-                if (watcher->priv->using_mit_saver_extension) {
-                        gs_debug ("Using MIT-SCREEN-SAVER extension.");
-                } else {
-                        gs_debug ("Not using server's MIT-SCREEN-SAVER extension.");
-                }
-        }
-}
-
 /* Figuring out what the appropriate XSetScreenSaver() parameters are
    (one wouldn't expect this to be rocket science.)
 */
-
 static void
 disable_builtin_screensaver (GSWatcher *watcher,
                              gboolean   unblank_screen)
@@ -936,21 +582,13 @@
            on some systems that don't support XDPMS?  Who know... */
         desired_allow_exp = AllowExposures;
 
-        if (watcher->priv->using_mit_saver_extension) {
-
-                desired_server_timeout = (watcher->priv->timeout / 1000);
-
-                desired_prefer_blank = DontPreferBlanking;
-        } else {
-                /* When we're not using an extension, set the server-side timeout to 0,
-                   so that the server never gets involved with screen blanking, and we
-                   do it all ourselves.  (However, when we *are* using an extension,
-                   we tell the server when to notify us, and rather than blanking the
-                   screen, the server will send us an X event telling us to blank.)
-                */
-
-                desired_server_timeout = 0;
-        }
+        /* When we're not using an extension, set the server-side timeout to 0,
+           so that the server never gets involved with screen blanking, and we
+           do it all ourselves.  (However, when we *are* using an extension,
+           we tell the server when to notify us, and rather than blanking the
+           screen, the server will send us an X event telling us to blank.)
+        */
+        desired_server_timeout = 0;
 
         if (desired_server_timeout     != current_server_timeout
             || desired_server_interval != current_server_interval
@@ -973,191 +611,12 @@
                 XSync (GDK_DISPLAY (), FALSE);
         }
 
-
-#if defined(HAVE_MIT_SAVER_EXTENSION)
-        {
-                static gboolean extension_initted = FALSE;
-
-                if (! extension_initted) {
-
-                        extension_initted = TRUE;
-
-# ifdef HAVE_MIT_SAVER_EXTENSION
-                        if (watcher->priv->using_mit_saver_extension) {
-                                init_mit_saver_extension ();
-                        }
-# endif
-
-                }
-        }
-#endif /* HAVE_MIT_SAVER_EXTENSION */
-
         if (unblank_screen) {
                 /* Turn off the server builtin saver if it is now running. */
                 XForceScreenSaver (GDK_DISPLAY (), ScreenSaverReset);
         }
 }
 
-static void
-maybe_send_signal (GSWatcher *watcher)
-{
-        gboolean polling_for_idleness = TRUE;
-        gint64   elapsed;
-        gboolean do_idle_signal = FALSE;
-        gboolean do_notice_signal = FALSE;
-
-        if (! watcher->priv->active) {
-                gs_debug ("Checking for idleness but watcher is inactive");
-                return;
-        }
-
-        if (watcher->priv->idle) {
-                /* already idle, do nothing */
-                gs_debug ("Checking for idleness but already idle");
-                return;
-        }
-
-        elapsed = 1000 * g_timer_elapsed (watcher->priv->idle_timer, NULL);
-
-        if (elapsed >= watcher->priv->timeout) {
-                /* Look, we've been idle long enough.  We're done. */
-                do_idle_signal = TRUE;
-        } else if (watcher->priv->emergency_lock) {
-                /* Oops, the wall clock has jumped far into the future, so
-                   we need to lock down in a hurry! */
-                gs_debug ("Doing emergency lock");
-                do_idle_signal = TRUE;
-        } else {
-                /* The event went off, but it turns out that the user has not
-                   yet been idle for long enough.  So re-signal the event.
-                   Be economical: if we should blank after 5 minutes, and the
-                   user has been idle for 2 minutes, then set this timer to
-                   go off in 3 minutes.
-                */
-
-                if (polling_for_idleness) {
-                        guint time_left;
-
-                        time_left = watcher->priv->timeout - elapsed;
-
-                        if (time_left <= watcher->priv->notice_timeout) {
-                                do_notice_signal = TRUE;
-                        }
-
-                        schedule_wakeup_event (watcher, time_left);
-                }
-
-                do_idle_signal = FALSE;
-        }
-
-        if (do_notice_signal && ! watcher->priv->idle_notice) {
-                gboolean res = FALSE;
-                gboolean in_effect = TRUE;
-
-                res = _gs_watcher_set_session_idle_notice (watcher, in_effect);
-        }
-
-        if (do_idle_signal) {
-                gboolean res = FALSE;
-                gboolean is_idle = TRUE;
-
-                res = _gs_watcher_set_session_idle (watcher, is_idle);
-                _gs_watcher_set_session_idle_notice (watcher, !is_idle);
-
-                /* if the event wasn't handled then schedule another timer */
-                if (! res) {
-                        gs_debug ("Idle signal was not handled, restarting watcher");
-                        gs_watcher_reset (watcher);
-                }
-        }
-}
-
-static gboolean
-power_timer (GSWatcher *watcher)
-{
-        gint64   elapsed;
-
-        gs_debug ("in power timer");
-
-        watcher->priv->power_timer_id = 0;
-
-        if (! watcher->priv->active) {
-                gs_debug ("Checking for power idleness but watcher is inactive");
-                return FALSE;
-        }
-
-        if (watcher->priv->power_notice) {
-                gs_debug ("Power notice already sent");
-                return FALSE;
-        }
-
-        elapsed = 1000 * g_timer_elapsed (watcher->priv->idle_timer, NULL);
-
-        if (elapsed >= watcher->priv->power_timeout) {
-                gboolean in_effect = TRUE;
-                gs_debug ("Setting power notice elapsed: %ld", (long int)elapsed);
-
-                _gs_watcher_set_session_power_notice (watcher, in_effect);
-        } else {
-                guint time_left;
-
-                time_left = watcher->priv->power_timeout - elapsed;
-                gs_debug ("Scheduling power notice in: %u", time_left);
-                schedule_power_wakeup_event (watcher, time_left);
-        }
-
-        return FALSE;
-}
-
-static gboolean
-idle_timer (GSWatcher *watcher)
-{
-        gs_debug ("in idle timer");
-
-        watcher->priv->timer_id = 0;
-
-        maybe_send_signal (watcher);
-
-        return FALSE;
-}
-
-static void
-schedule_power_wakeup_event (GSWatcher *watcher,
-                             int        when)
-{
-        guint timeout;
-
-        if (watcher->priv->power_timer_id) {
-                gs_debug ("power_timer already running");
-                return;
-        }
-
-        timeout = when;
-
-        add_power_timer (watcher, timeout);
-}
-
-static void
-schedule_wakeup_event (GSWatcher *watcher,
-                       int        when)
-{
-        guint timeout;
-
-        if (watcher->priv->timer_id) {
-                gs_debug ("idle_timer already running");
-                return;
-        }
-
-        timeout = when;
-
-        /* Wake up before idle so we can send a notice signal */
-        if (timeout > watcher->priv->notice_timeout) {
-                timeout -= watcher->priv->notice_timeout;
-        }
-
-        /* Wake up periodically to ask the server if we are idle. */
-        add_idle_timer (watcher, timeout);
-}
 
 /* This timer goes off every few minutes, whether the user is idle or not,
    to try and clean up anything that has gone wrong.
@@ -1186,7 +645,8 @@
         GSWatcher *watcher;
 
         watcher = g_object_new (GS_TYPE_WATCHER,
-                                "timeout", timeout, NULL);
+                                "timeout", timeout,
+                                NULL);
 
         return GS_WATCHER (watcher);
 }

Added: trunk/src/test-idle-monitor.c
==============================================================================
--- (empty file)
+++ trunk/src/test-idle-monitor.c	Fri Nov 14 03:17:07 2008
@@ -0,0 +1,127 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2005 William Jon McCann <mccann jhu edu>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Authors: William Jon McCann <mccann jhu edu>
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include "gs-idle-monitor.h"
+#include "gs-debug.h"
+
+static gboolean
+on_less_idle (GSIdleMonitor *monitor,
+              guint          id,
+              gboolean       condition,
+              gpointer       data)
+{
+        g_debug ("Less idle callback condition=%d", condition);
+
+        /* return TRUE so that the idle monitor is not reset */
+        return TRUE;
+}
+
+
+static gboolean
+on_idle (GSIdleMonitor *monitor,
+         guint          id,
+         gboolean       condition,
+         gpointer       data)
+{
+        g_debug ("Idle callback condition=%d", condition);
+
+        /* return FALSE to reset monitor
+         * means that very idle callback sound never fire */
+
+        /* this is how we implement inhibit */
+        return FALSE;
+}
+
+static gboolean
+on_very_idle (GSIdleMonitor *monitor,
+              guint          id,
+              gboolean       condition,
+              gpointer       data)
+{
+        g_debug ("Very idle callback");
+
+        /* return TRUE so that the idle monitor is not reset */
+        return TRUE;
+}
+
+static void
+test_idle_monitor (void)
+{
+        GSIdleMonitor *monitor;
+        guint          timeout;
+        guint          id;
+
+        timeout = 5000;
+
+        monitor = gs_idle_monitor_new ();
+        id = gs_idle_monitor_add_watch (monitor,
+                                        timeout / 2,
+                                        on_less_idle,
+                                        NULL);
+        id = gs_idle_monitor_add_watch (monitor,
+                                        timeout,
+                                        on_idle,
+                                        NULL);
+        id = gs_idle_monitor_add_watch (monitor,
+                                        timeout * 2,
+                                        on_very_idle,
+                                        NULL);
+}
+
+int
+main (int    argc,
+      char **argv)
+{
+        GError *error = NULL;
+
+#ifdef ENABLE_NLS
+        bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
+# ifdef HAVE_BIND_TEXTDOMAIN_CODESET
+        bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+# endif
+        textdomain (GETTEXT_PACKAGE);
+#endif
+
+        if (! gtk_init_with_args (&argc, &argv, NULL, NULL, NULL, &error)) {
+                fprintf (stderr, "%s", error->message);
+                g_error_free (error);
+                exit (1);
+        }
+
+        gs_debug_init (TRUE, FALSE);
+
+        test_idle_monitor ();
+
+        gtk_main ();
+
+        gs_debug_shutdown ();
+
+        return 0;
+}

Modified: trunk/src/test-watcher.c
==============================================================================
--- trunk/src/test-watcher.c	(original)
+++ trunk/src/test-watcher.c	Fri Nov 14 03:17:07 2008
@@ -42,11 +42,23 @@
         return FALSE;
 }
 
+static gboolean
+watcher_idle_notice_cb (GSWatcher *watcher,
+                        gboolean   is_idle,
+                        gpointer   data)
+{
+        g_message ("Idle notice status changed: %s", is_idle ? "idle" : "not idle");
+
+        return TRUE;
+}
+
 static void
 connect_watcher_signals (GSWatcher *watcher)
 {
-        g_signal_connect (watcher, "idle_changed",
+        g_signal_connect (watcher, "idle-changed",
                           G_CALLBACK (watcher_idle_cb), NULL);
+        g_signal_connect (watcher, "idle-notice-changed",
+                          G_CALLBACK (watcher_idle_notice_cb), NULL);
 }
 
 static void
@@ -55,7 +67,7 @@
         GSWatcher *watcher;
         guint      timeout;
 
-        timeout = 60000;
+        timeout = 20000;
 
         watcher = gs_watcher_new (timeout);
         gs_watcher_set_enabled (watcher, TRUE);
@@ -92,5 +104,5 @@
 
         gs_debug_shutdown ();
 
-	return 0;
+        return 0;
 }



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