[gnome-power-manager] Go back to the original IDLETIME code to fix backlight bugs



commit d5d78515f7d59da54056124d835223f1b625abc4
Author: Richard Hughes <richard hughsie com>
Date:   Fri May 29 12:20:38 2009 +0100

    Go back to the original IDLETIME code to fix backlight bugs
    
    The new IDLETIME code from gnome-session is very buggy, and the old code
    was much easier to understand. This should fix random DPMS off blanking
    and the fade-up-down-up on session resume.
---
 src/egg-idletime.c  |  759 +++++++++++++++++++++++++++++----------------------
 src/egg-idletime.h  |   42 ++--
 src/gpm-idle.c      |  283 +++++++++++++++++---
 src/gpm-idle.h      |    1 +
 src/gpm-self-test.c |    2 +
 5 files changed, 702 insertions(+), 385 deletions(-)

diff --git a/src/egg-idletime.c b/src/egg-idletime.c
index 4d684f7..8f9d971 100644
--- a/src/egg-idletime.c
+++ b/src/egg-idletime.c
@@ -1,7 +1,6 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
  *
- * Copyright (C) 2007 Richard Hughes <richard hughsie com>
- * Copyright (C) 2007-2009 William Jon McCann <mccann jhu edu>
+ * Copyright (C) 2007-2009 Richard Hughes <richard hughsie com>
  *
  * Licensed under the GNU General Public License Version 2
  *
@@ -20,39 +19,42 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
-#include "config.h"
-
-#include <time.h>
-#include <string.h>
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
 
+#include <glib.h>
 #include <X11/Xlib.h>
 #include <X11/extensions/sync.h>
-
-#include <glib.h>
 #include <gdk/gdkx.h>
 #include <gdk/gdk.h>
 
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
 #include "egg-idletime.h"
-#include "egg-debug.h"
 
-static void egg_idletime_finalize	(GObject		*object);
+static void     egg_idletime_finalize   (GObject       *object);
 
-#define EGG_IDLETIME_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), EGG_TYPE_IDLETIME, EggIdletimePrivate))
+#define EGG_IDLETIME_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), EGG_IDLETIME_TYPE, EggIdletimePrivate))
 
 struct EggIdletimePrivate
 {
-	GHashTable	*watches;
-	int		 sync_event_base;
-	XSyncCounter	 counter;
+	int			 sync_event;
+	guint			 last_event;
+	gboolean		 reset_set;
+	XSyncCounter		 idle_counter;
+	GPtrArray		*array;
+	Display			*dpy;
 };
 
 typedef struct
 {
-	guint		 id;
-	XSyncValue	 interval;
-	XSyncAlarm	 xalarm_positive;
-	XSyncAlarm	 xalarm_negative;
-} EggIdletimeWatch;
+	guint			 id;
+	XSyncValue		 timeout;
+	XSyncAlarm		 xalarm;
+} EggIdletimeAlarm;
 
 enum {
 	SIGNAL_ALARM_EXPIRED,
@@ -60,346 +62,259 @@ enum {
 	LAST_SIGNAL
 };
 
-static guint32 watch_serial = 1;
+typedef enum {
+	EGG_IDLETIME_ALARM_TYPE_POSITIVE,
+	EGG_IDLETIME_ALARM_TYPE_NEGATIVE,
+	EGG_IDLETIME_ALARM_TYPE_DISABLED
+} EggIdletimeAlarmType;
+
 static guint signals [LAST_SIGNAL] = { 0 };
+static gpointer egg_idletime_object = NULL;
 
 G_DEFINE_TYPE (EggIdletime, egg_idletime, G_TYPE_OBJECT)
 
 /**
- * egg_idletime_xsyncvalue_to_int64:
- */
-static gint64
-egg_idletime_xsyncvalue_to_int64 (XSyncValue value)
-{
-	return ((guint64) XSyncValueHigh32 (value)) << 32
-		| (guint64) XSyncValueLow32 (value);
-}
-
-/**
- * egg_idletime_int64_to_xsyncvalue:
- */
-static XSyncValue
-egg_idletime_int64_to_xsyncvalue (gint64 value)
-{
-	XSyncValue ret;
-	XSyncIntsToValue (&ret, value, ((guint64)value) >> 32);
-	return ret;
-}
-
-/**
- * egg_idletime_find_alarm:
- */
-static gboolean
-egg_idletime_find_alarm (gpointer key, EggIdletimeWatch *watch, XSyncAlarm *alarm)
-{
-	egg_debug ("Searching for %d in %d,%d", (int)*alarm, (int)watch->xalarm_positive, (int)watch->xalarm_negative);
-	if (watch->xalarm_positive == *alarm ||
-	    watch->xalarm_negative == *alarm) {
-		return TRUE;
-	}
-	return FALSE;
-}
-
-/**
- * egg_idletime_find_watch_for_alarm:
- */
-static EggIdletimeWatch *
-egg_idletime_find_watch_for_alarm (EggIdletime *idletime, XSyncAlarm alarm)
-{
-	EggIdletimeWatch *watch;
-	watch = g_hash_table_find (idletime->priv->watches,
-				   (GHRFunc)egg_idletime_find_alarm, &alarm);
-	return watch;
-}
-
-/**
- * egg_idletime_handle_alarm_notify_event:
+ * egg_idletime_xsync_alarm_set:
  */
 static void
-egg_idletime_handle_alarm_notify_event (EggIdletime *idletime, XSyncAlarmNotifyEvent *alarm_event)
+egg_idletime_xsync_alarm_set (EggIdletime *idletime, EggIdletimeAlarm *alarm, EggIdletimeAlarmType alarm_type)
 {
-	EggIdletimeWatch *watch;
-
-	if (alarm_event->state == XSyncAlarmDestroyed)
-		return;
-
-	watch = egg_idletime_find_watch_for_alarm (idletime, alarm_event->alarm);
-
-	if (watch == NULL) {
-		egg_warning ("Unable to find watch for alarm %d", (int)alarm_event->alarm);
+	XSyncAlarmAttributes attr;
+	XSyncValue delta;
+	unsigned int flags;
+	XSyncTestType test;
+
+	/* just remove it */
+	if (alarm_type == EGG_IDLETIME_ALARM_TYPE_DISABLED) {
+		if (alarm->xalarm) {
+			XSyncDestroyAlarm (idletime->priv->dpy, alarm->xalarm);
+			alarm->xalarm = None;
+		}
 		return;
 	}
 
-	egg_debug ("Watch %d fired, idle time = %" G_GINT64_FORMAT,
-		   watch->id, egg_idletime_xsyncvalue_to_int64 (alarm_event->counter_value));
+	/* which way do we do the test? */
+	if (alarm_type == EGG_IDLETIME_ALARM_TYPE_POSITIVE)
+		test = XSyncPositiveTransition;
+	else
+		test = XSyncNegativeTransition;
 
-	if (alarm_event->alarm == watch->xalarm_positive) {
-		g_signal_emit (idletime, signals [SIGNAL_ALARM_EXPIRED], 0, watch->id);
-	} else {
-		g_signal_emit (idletime, signals [SIGNAL_RESET], 0);
-	}
-}
-
-/**
- * egg_idletime_xevent_filter:
- */
-static GdkFilterReturn
-egg_idletime_xevent_filter (GdkXEvent *xevent, GdkEvent *event, EggIdletime *idletime)
-{
-	XEvent *ev;
-	XSyncAlarmNotifyEvent *alarm_event;
+	XSyncIntToValue (&delta, 0);
 
-	ev = xevent;
-	if (ev->xany.type != idletime->priv->sync_event_base + XSyncAlarmNotify)
-		return GDK_FILTER_CONTINUE;
+	attr.trigger.counter = idletime->priv->idle_counter;
+	attr.trigger.value_type = XSyncAbsolute;
+	attr.trigger.test_type = test;
+	attr.trigger.wait_value = alarm->timeout;
+	attr.delta = delta;
 
-	alarm_event = xevent;
-	egg_idletime_handle_alarm_notify_event (idletime, alarm_event);
+	flags = XSyncCACounter | XSyncCAValueType | XSyncCATestType | XSyncCAValue | XSyncCADelta;
 
-	return GDK_FILTER_CONTINUE;
+	if (alarm->xalarm)
+		XSyncChangeAlarm (idletime->priv->dpy, alarm->xalarm, flags, &attr);
+	else
+		alarm->xalarm = XSyncCreateAlarm (idletime->priv->dpy, flags, &attr);
 }
 
 /**
- * egg_idletime_init_xsync:
+ * egg_idletime_alarm_reset_all:
  */
-static gboolean
-egg_idletime_init_xsync (EggIdletime *idletime)
+void
+egg_idletime_alarm_reset_all (EggIdletime *idletime)
 {
-	int sync_error_base;
-	int res;
-	int major;
-	int minor;
-	int i;
-	int ncounters;
-	XSyncSystemCounter *counters;
-
-	res = XSyncQueryExtension (GDK_DISPLAY (),
-				   &idletime->priv->sync_event_base,
-				   &sync_error_base);
-	if (res == 0) {
-		egg_warning ("EggIdletime: Sync extension not present");
-		return FALSE;
-	}
+	guint i;
+	EggIdletimeAlarm *alarm;
 
-	res = XSyncInitialize (GDK_DISPLAY (), &major, &minor);
-	if (res == 0) {
-		egg_warning ("EggIdletime: Unable to initialize Sync extension");
-		return FALSE;
-	}
+	g_return_if_fail (EGG_IS_IDLETIME (idletime));
 
-	counters = XSyncListSystemCounters (GDK_DISPLAY (), &ncounters);
-	for (i = 0; i < ncounters; i++) {
-		if (counters[i].name != NULL &&
-		    g_strcmp0 (counters[i].name, "IDLETIME") == 0) {
-			idletime->priv->counter = counters[i].counter;
-			break;
-		}
+	/* reset all the alarms (except the reset alarm) to their timeouts */
+	for (i=1; i<idletime->priv->array->len; i++) {
+		alarm = g_ptr_array_index (idletime->priv->array, i);
+		egg_idletime_xsync_alarm_set (idletime, alarm, EGG_IDLETIME_ALARM_TYPE_POSITIVE);
 	}
-	XSyncFreeSystemCounterList (counters);
 
-	if (idletime->priv->counter == None) {
-		egg_warning ("EggIdletime: IDLETIME counter not found");
-		return FALSE;
-	}
+	/* set the reset alarm to be disabled */
+	alarm = g_ptr_array_index (idletime->priv->array, 0);
+	egg_idletime_xsync_alarm_set (idletime, alarm, EGG_IDLETIME_ALARM_TYPE_DISABLED);
 
-	gdk_window_add_filter (NULL, (GdkFilterFunc) egg_idletime_xevent_filter, idletime);
+	/* emit signal so say we've reset all timers */
+	g_signal_emit (idletime, signals [SIGNAL_RESET], 0);
 
-	return TRUE;
+	/* we need to be reset again on the next event */
+	idletime->priv->reset_set = FALSE;
 }
 
 /**
- * egg_idletime_get_next_watch_serial:
+ * egg_idletime_alarm_find_id:
  */
-static guint32
-egg_idletime_get_next_watch_serial (void)
+static EggIdletimeAlarm *
+egg_idletime_alarm_find_id (EggIdletime *idletime, guint id)
 {
-	guint32 serial;
-
-	serial = watch_serial++;
-	/* cope with overflow */
-	if ((gint32)watch_serial < 0)
-		watch_serial = 1;
-	return serial;
+	guint i;
+	EggIdletimeAlarm *alarm;
+	for (i=0; i<idletime->priv->array->len; i++) {
+		alarm = g_ptr_array_index (idletime->priv->array, i);
+		if (alarm->id == id)
+			return alarm;
+	}
+	return NULL;
 }
 
 /**
- * egg_idletime_watch_new:
+ * egg_idletime_set_reset_alarm:
  */
-static EggIdletimeWatch *
-egg_idletime_watch_new (guint interval)
+static void
+egg_idletime_set_reset_alarm (EggIdletime *idletime, XSyncAlarmNotifyEvent *alarm_event)
 {
-	EggIdletimeWatch *watch;
+	EggIdletimeAlarm *alarm;
+	int overflow;
+	XSyncValue add;
 
-	watch = g_slice_new0 (EggIdletimeWatch);
-	watch->interval = egg_idletime_int64_to_xsyncvalue ((gint64)interval);
-	watch->id = egg_idletime_get_next_watch_serial ();
-	watch->xalarm_positive = None;
-	watch->xalarm_negative = None;
+	alarm = egg_idletime_alarm_find_id (idletime, 0);
 
-	return watch;
+	if (!idletime->priv->reset_set) {
+		/* don't match on the current value because
+		 * XSyncNegativeComparison means less or equal. */
+		XSyncIntToValue (&add, -1);
+		XSyncValueAdd (&alarm->timeout, alarm_event->counter_value, add, &overflow);
+
+		/* set the reset alarm to fire the next time
+		 * idletime->priv->idle_counter < the current counter value */
+		egg_idletime_xsync_alarm_set (idletime, alarm, EGG_IDLETIME_ALARM_TYPE_NEGATIVE);
+
+		/* don't try to set this again if multiple timers are doing off in sequence */
+		idletime->priv->reset_set = TRUE;
+	}
 }
 
 /**
- * egg_idletime_watch_free:
+ * egg_idletime_alarm_find_event:
  */
-static void
-egg_idletime_watch_free (EggIdletimeWatch *watch)
+static EggIdletimeAlarm *
+egg_idletime_alarm_find_event (EggIdletime *idletime, XSyncAlarmNotifyEvent *alarm_event)
 {
-	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 (EggIdletimeWatch, watch);
+	guint i;
+	EggIdletimeAlarm *alarm;
+	for (i=0; i<idletime->priv->array->len; i++) {
+		alarm = g_ptr_array_index (idletime->priv->array, i);
+		if (alarm_event->alarm == alarm->xalarm)
+			return alarm;
+	}
+	return NULL;
 }
 
 /**
- * egg_idletime_xsync_alarm_set:
+ * egg_idletime_event_filter_cb:
  */
-static gboolean
-egg_idletime_xsync_alarm_set (EggIdletime *idletime, EggIdletimeWatch *watch)
+static GdkFilterReturn
+egg_idletime_event_filter_cb (GdkXEvent *gdkxevent, GdkEvent *event, gpointer data)
 {
-	XSyncAlarmAttributes attr;
-	XSyncValue delta;
-	guint flags;
-
-	flags = XSyncCACounter
-		| XSyncCAValueType
-		| XSyncCATestType
-		| XSyncCAValue
-		| XSyncCADelta
-		| XSyncCAEvents;
-
-	XSyncIntToValue (&delta, 0);
-	attr.trigger.counter = idletime->priv->counter;
-	attr.trigger.value_type = XSyncAbsolute;
-	attr.trigger.wait_value = watch->interval;
-	attr.delta = delta;
-	attr.events = TRUE;
-
-	attr.trigger.test_type = XSyncPositiveTransition;
-	if (watch->xalarm_positive != None) {
-		egg_debug ("EggIdletime: updating alarm for positive transition wait=%" G_GINT64_FORMAT,
-			   egg_idletime_xsyncvalue_to_int64 (attr.trigger.wait_value));
-		XSyncChangeAlarm (GDK_DISPLAY (), watch->xalarm_positive, flags, &attr);
-	} else {
-		egg_debug ("EggIdletime: creating new alarm for positive transition wait=%" G_GINT64_FORMAT,
-			   egg_idletime_xsyncvalue_to_int64 (attr.trigger.wait_value));
-		watch->xalarm_positive = XSyncCreateAlarm (GDK_DISPLAY (), flags, &attr);
-	}
+	EggIdletimeAlarm *alarm;
+	XEvent *xevent = (XEvent *) gdkxevent;
+	EggIdletime *idletime = (EggIdletime *) data;
+	XSyncAlarmNotifyEvent *alarm_event;
 
-	attr.trigger.test_type = XSyncNegativeTransition;
-	if (watch->xalarm_negative != None) {
-		egg_debug ("EggIdletime: updating alarm for negative transition wait=%" G_GINT64_FORMAT,
-			   egg_idletime_xsyncvalue_to_int64 (attr.trigger.wait_value));
-		XSyncChangeAlarm (GDK_DISPLAY (), watch->xalarm_negative, flags, &attr);
-	} else {
-		egg_debug ("EggIdletime: creating new alarm for negative transition wait=%" G_GINT64_FORMAT,
-			   egg_idletime_xsyncvalue_to_int64 (attr.trigger.wait_value));
-		watch->xalarm_negative = XSyncCreateAlarm (GDK_DISPLAY (), flags, &attr);
-	}
+	/* no point continuing */
+	if (xevent->type != idletime->priv->sync_event + XSyncAlarmNotify)
+		return GDK_FILTER_CONTINUE;
 
-	return TRUE;
-}
+	alarm_event = (XSyncAlarmNotifyEvent *) xevent;
 
-/**
- * egg_idletime_add_watch:
- */
-guint
-egg_idletime_add_watch (EggIdletime *idletime, guint interval)
-{
-	EggIdletimeWatch *watch;
+	/* did we match one of our alarms? */
+	alarm = egg_idletime_alarm_find_event (idletime, alarm_event);
+	if (alarm != NULL) {
+		/* save the last state we triggered */
+		idletime->priv->last_event = alarm->id;
 
-	g_return_val_if_fail (EGG_IS_IDLETIME (idletime), 0);
+		/* are we not the reset symbol */
+		if (alarm->id != 0) {
+			/* emit signal */
+			g_signal_emit (idletime, signals [SIGNAL_ALARM_EXPIRED], 0, alarm->id);
 
-	watch = egg_idletime_watch_new (interval);
+			/* we need the first alarm to go off to set the reset alarm */
+			egg_idletime_set_reset_alarm (idletime, alarm_event);
+			return GDK_FILTER_CONTINUE;
+		}
 
-	egg_idletime_xsync_alarm_set (idletime, watch);
+		/* do the reset callback */
+		egg_idletime_alarm_reset_all (idletime);
+	}
 
-	g_hash_table_insert (idletime->priv->watches,
-			     GUINT_TO_POINTER (watch->id), watch);
-	return watch->id;
+	return GDK_FILTER_CONTINUE;
 }
 
 /**
- * egg_idletime_remove_watch:
+ * egg_idletime_alarm_set:
  */
-void
-egg_idletime_remove_watch (EggIdletime *idletime, guint id)
+gboolean
+egg_idletime_alarm_set (EggIdletime *idletime, guint id, guint timeout)
 {
-	g_return_if_fail (EGG_IS_IDLETIME (idletime));
+	EggIdletimeAlarm *alarm;
 
-	g_hash_table_remove (idletime->priv->watches, GUINT_TO_POINTER (id));
-}
+	g_return_val_if_fail (EGG_IS_IDLETIME (idletime), FALSE);
+	g_return_val_if_fail (id != 0, FALSE);
+	g_return_val_if_fail (timeout != 0, FALSE);
 
-/**
- * egg_idletime_finalize:
- */
-static void
-egg_idletime_finalize (GObject *object)
-{
-	EggIdletime *idletime;
+	/* see if we already created an alarm with this ID */
+	alarm = egg_idletime_alarm_find_id (idletime, id);
+	if (alarm == NULL) {
+		/* create a new alarm */
+		alarm = g_new0 (EggIdletimeAlarm, 1);
 
-	g_return_if_fail (object != NULL);
-	g_return_if_fail (EGG_IS_IDLETIME (object));
+		/* set the default values */
+		alarm->id = id;
+		alarm->xalarm = None;
 
-	idletime = EGG_IDLETIME (object);
+		/* add to array */
+		g_ptr_array_add (idletime->priv->array, alarm);
+	}
 
-	g_return_if_fail (idletime->priv != NULL);
+	/* set the timeout */
+	XSyncIntToValue (&alarm->timeout, (gint)timeout);
 
-	G_OBJECT_CLASS (egg_idletime_parent_class)->finalize (object);
+	/* set, and start the timer */
+	egg_idletime_xsync_alarm_set (idletime, alarm, EGG_IDLETIME_ALARM_TYPE_POSITIVE);
+	return TRUE;
 }
 
 /**
- * egg_idletime_constructor:
+ * egg_idletime_alarm_free:
  */
-static GObject *
-egg_idletime_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties)
+static gboolean
+egg_idletime_alarm_free (EggIdletime *idletime, EggIdletimeAlarm *alarm)
 {
-	EggIdletime *idletime;
-
-	idletime = EGG_IDLETIME (G_OBJECT_CLASS (egg_idletime_parent_class)->constructor (type, n_construct_properties, construct_properties));
-
-	if (!egg_idletime_init_xsync (idletime)) {
-		g_object_unref (idletime);
-		return NULL;
-	}
-
-	return G_OBJECT (idletime);
+	if (alarm->xalarm)
+		XSyncDestroyAlarm (idletime->priv->dpy, alarm->xalarm);
+	g_free (alarm);
+	g_ptr_array_remove (idletime->priv->array, alarm);
+	return TRUE;
 }
 
 /**
- * egg_idletime_dispose:
+ * egg_idletime_alarm_free:
  */
-static void
-egg_idletime_dispose (GObject *object)
+gboolean
+egg_idletime_alarm_remove (EggIdletime *idletime, guint id)
 {
-	EggIdletime *idletime;
-
-	g_return_if_fail (EGG_IS_IDLETIME (object));
+	EggIdletimeAlarm *alarm;
 
-	idletime = EGG_IDLETIME (object);
+	g_return_val_if_fail (EGG_IS_IDLETIME (idletime), FALSE);
 
-	if (idletime->priv->watches != NULL) {
-		g_hash_table_destroy (idletime->priv->watches);
-		idletime->priv->watches = NULL;
-	}
-
-	G_OBJECT_CLASS (egg_idletime_parent_class)->dispose (object);
+	alarm = egg_idletime_alarm_find_id (idletime, id);
+	if (alarm == NULL)
+		return FALSE;
+	egg_idletime_alarm_free (idletime, alarm);
+	return TRUE;
 }
 
 /**
  * egg_idletime_class_init:
- */
+ **/
 static void
 egg_idletime_class_init (EggIdletimeClass *klass)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
 	object_class->finalize = egg_idletime_finalize;
-	object_class->dispose = egg_idletime_dispose;
-	object_class->constructor = egg_idletime_constructor;
+	g_type_class_add_private (klass, sizeof (EggIdletimePrivate));
 
 	signals [SIGNAL_ALARM_EXPIRED] =
 		g_signal_new ("alarm-expired",
@@ -415,31 +330,100 @@ egg_idletime_class_init (EggIdletimeClass *klass)
 			      G_STRUCT_OFFSET (EggIdletimeClass, reset),
 			      NULL, NULL, g_cclosure_marshal_VOID__VOID,
 			      G_TYPE_NONE, 0);
-
-	g_type_class_add_private (klass, sizeof (EggIdletimePrivate));
 }
 
 /**
  * egg_idletime_init:
- */
+ **/
 static void
 egg_idletime_init (EggIdletime *idletime)
 {
+	int sync_error;
+	int ncounters;
+	XSyncSystemCounter *counters;
+	EggIdletimeAlarm *alarm;
+	guint i;
+
 	idletime->priv = EGG_IDLETIME_GET_PRIVATE (idletime);
-	idletime->priv->counter = None;
-	idletime->priv->watches = g_hash_table_new_full (NULL, NULL, NULL,
-							(GDestroyNotify) egg_idletime_watch_free);
+
+	idletime->priv->array = g_ptr_array_new ();
+
+	idletime->priv->idle_counter = None;
+	idletime->priv->last_event = 0;
+	idletime->priv->sync_event = 0;
+	idletime->priv->dpy = GDK_DISPLAY ();
+
+	/* get the sync event */
+	if (!XSyncQueryExtension (idletime->priv->dpy, &idletime->priv->sync_event, &sync_error)) {
+		g_warning ("No Sync extension.");
+		return;
+	}
+
+	/* gtk_init should do XSyncInitialize for us */
+	counters = XSyncListSystemCounters (idletime->priv->dpy, &ncounters);
+	for (i=0; i < ncounters && !idletime->priv->idle_counter; i++) {
+		if (strcmp(counters[i].name, "IDLETIME") == 0)
+			idletime->priv->idle_counter = counters[i].counter;
+	}
+	XSyncFreeSystemCounterList (counters);
+
+	/* arh. we don't have IDLETIME support */
+	if (!idletime->priv->idle_counter) {
+		g_warning ("No idle counter.");
+		return;
+	}
+
+	idletime->priv->reset_set = FALSE;
+
+	/* catch the timer alarm */
+	gdk_window_add_filter (NULL, egg_idletime_event_filter_cb, idletime);
+
+	/* create a reset alarm */
+	alarm = g_new0 (EggIdletimeAlarm, 1);
+	alarm->id = 0;
+	alarm->xalarm = None;
+	g_ptr_array_add (idletime->priv->array, alarm);
+}
+
+/**
+ * egg_idletime_finalize:
+ **/
+static void
+egg_idletime_finalize (GObject *object)
+{
+	guint i;
+	EggIdletime *idletime;
+	EggIdletimeAlarm *alarm;
+
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (EGG_IS_IDLETIME (object));
+
+	idletime = EGG_IDLETIME (object);
+	idletime->priv = EGG_IDLETIME_GET_PRIVATE (idletime);
+
+	/* free all counters, including reset counter */
+	for (i=0; i<idletime->priv->array->len; i++) {
+		alarm = g_ptr_array_index (idletime->priv->array, i);
+		egg_idletime_alarm_free (idletime, alarm);
+	}
+	g_ptr_array_free (idletime->priv->array, TRUE);
+
+	G_OBJECT_CLASS (egg_idletime_parent_class)->finalize (object);
 }
 
 /**
  * egg_idletime_new:
- */
+ **/
 EggIdletime *
 egg_idletime_new (void)
 {
-	GObject *idletime;
-	idletime = g_object_new (EGG_TYPE_IDLETIME, NULL);
-	return EGG_IDLETIME (idletime);
+	if (egg_idletime_object != NULL) {
+		g_object_ref (egg_idletime_object);
+	} else {
+		egg_idletime_object = g_object_new (EGG_IDLETIME_TYPE, NULL);
+		g_object_add_weak_pointer (egg_idletime_object, &egg_idletime_object);
+	}
+	return EGG_IDLETIME (egg_idletime_object);
 }
 
 /***************************************************************************
@@ -448,94 +432,211 @@ egg_idletime_new (void)
 #ifdef EGG_TEST
 #include "egg-test.h"
 
-static guint _last_alarm = 0;
+static void
+egg_test_egg_idletime_wait (guint time_ms)
+{
+	GTimer *ltimer = g_timer_new ();
+	gfloat goal = time_ms / (gfloat) 1000.0f;
+	do {
+		g_main_context_iteration (NULL, FALSE);
+	} while (g_timer_elapsed (ltimer, NULL) < goal);
+	g_timer_destroy (ltimer);
+}
+
+static guint last_alarm = 0;
+static guint event_time;
+GTimer *timer;
 
 static void
-egg_idletime_test_alarm_expired_cb (EggIdletime *idletime, guint alarm, EggTest *test)
+gpm_alarm_expired_cb (EggIdletime *idletime, guint alarm, gpointer data)
 {
-	_last_alarm = alarm;
-	egg_debug ("alarm %i", alarm);
-	egg_test_loop_quit (test);
+	last_alarm = alarm;
+	event_time = g_timer_elapsed (timer, NULL) * (gfloat) 1000.0f;
+//	g_print ("[evt %i in %ims]\n", alarm, event_time);
 }
 
 static void
-egg_idletime_test_reset_cb (EggIdletime *idletime, EggTest *test)
+wait_until_alarm (void)
 {
-	_last_alarm = 0;
-	egg_debug ("reset");
-	egg_test_loop_quit (test);
+	g_print ("*****************************\n");
+	g_print ("*** DO NOT MOVE THE MOUSE ***\n");
+	g_print ("*****************************\n");
+	while (last_alarm == 0)
+		g_main_context_iteration (NULL, FALSE);
+}
+
+static void
+wait_until_reset (void)
+{
+	if (last_alarm == 0)
+		return;
+	g_print ("*****************************\n");
+	g_print ("***     MOVE THE MOUSE    ***\n");
+	g_print ("*****************************\n");
+	while (last_alarm != 0)
+		g_main_context_iteration (NULL, FALSE);
+	egg_test_egg_idletime_wait (1000);
 }
 
 void
 egg_idletime_test (gpointer data)
 {
 	EggIdletime *idletime;
+	gboolean ret;
+	guint i;
 	EggTest *test = (EggTest *) data;
-	guint id;
 
 	if (egg_test_start (test, "EggIdletime") == FALSE)
 		return;
 
+	timer = g_timer_new ();
 	gdk_init (NULL, NULL);
 
+	/* warn */
+
+	g_timer_start (timer);
 	/************************************************************/
-	egg_test_title (test, "make sure we get an object");
+	egg_test_title (test, "check to see if delay works as expected");
+	egg_test_egg_idletime_wait (2000);
+	event_time = g_timer_elapsed (timer, NULL) * (gfloat) 1000.0f;
+	if (event_time > 1800 && event_time < 2200) {
+		egg_test_success (test, "time %i~=%i", 2000, event_time);
+	} else {
+		egg_test_failed (test, "time not the same! %i != %i", event_time, 2000);
+	}
+
+	/************************************************************/
+	egg_test_title (test, "make sure we get a non null device");
 	idletime = egg_idletime_new ();
-	egg_test_assert (test, (idletime != NULL));
+	if (idletime != NULL) {
+		egg_test_success (test, "got EggIdletime");
+	} else {
+		egg_test_failed (test, "could not get EggIdletime");
+	}
 	g_signal_connect (idletime, "alarm-expired",
-			  G_CALLBACK (egg_idletime_test_alarm_expired_cb), test);
-	g_signal_connect (idletime, "reset",
-			  G_CALLBACK (egg_idletime_test_reset_cb), test);
+			  G_CALLBACK (gpm_alarm_expired_cb), NULL);
 
 	/************************************************************/
-	egg_test_title (test, "add a watch");
-	id = egg_idletime_add_watch (idletime, 3000);
-	egg_test_assert (test, (id != 0));
+	egg_test_title (test, "check if we are alarm zero with no alarms");
+	if (idletime->priv->last_event == 0) {
+		egg_test_success (test, NULL);
+	} else {
+		egg_test_failed (test, "alarm %i set!", idletime->priv->last_event);
+	}
 
 	/************************************************************/
-	g_print ("*****************************\n");
-	g_print ("*** DO NOT MOVE THE MOUSE ***\n");
-	g_print ("*****************************\n");
-	egg_test_loop_wait (test, 4500);
-	egg_test_loop_check (test);
+	egg_test_title (test, "check if we can set an reset alarm");
+	ret = egg_idletime_alarm_set (idletime, 0, 100);
+	if (!ret) {
+		egg_test_success (test, "ignored reset alarm");
+	} else {
+		egg_test_failed (test, "did not ignore reset alarm");
+	}
 
 	/************************************************************/
-	egg_test_title (test, "check condition");
-	egg_test_assert (test, (_last_alarm == 1));
+	egg_test_title (test, "check if we can set an alarm timeout of zero");
+	ret = egg_idletime_alarm_set (idletime, 999, 0);
+	if (!ret) {
+		egg_test_success (test, "ignored invalid alarm");
+	} else {
+		egg_test_failed (test, "did not ignore invalid alarm");
+	}
 
 	/************************************************************/
-	g_print ("*****************************\n");
-	g_print ("***    MOVE THE MOUSE     ***\n");
-	g_print ("*****************************\n");
-	egg_test_loop_wait (test, 10000);
-	egg_test_loop_check (test);
+	g_timer_start (timer);
+	egg_test_title (test, "check if we can set an alarm");
+	ret = egg_idletime_alarm_set (idletime, 101, 5000);
+	if (ret) {
+		egg_test_success (test, "set alarm okay");
+	} else {
+		egg_test_failed (test, "could not set alarm");
+	}
 
-	/************************************************************/
-	egg_test_title (test, "check condition");
-	egg_test_assert (test, (_last_alarm == 0));
+	egg_idletime_alarm_set (idletime, 101, 5000);
+	wait_until_alarm ();
+
+	/* loop this two times */
+	for (i=0; i<2; i++) {
+		/* just let it time out, and wait for human input */
+		wait_until_reset ();
+		g_timer_start (timer);
+
+		/************************************************************/
+		g_timer_start (timer);
+		egg_test_title (test, "check if we can set an alarm");
+		ret = egg_idletime_alarm_set (idletime, 101, 5000);
+		if (ret) {
+			egg_test_success (test, "set alarm 5000ms okay");
+		} else {
+			egg_test_failed (test, "could not set alarm 5000ms");
+		}
+
+		/* wait for alarm to go off */
+		wait_until_alarm ();
+		g_timer_start (timer);
+
+		/************************************************************/
+		egg_test_title (test, "check if correct alarm has gone off");
+		if (idletime->priv->last_event == 101) {
+			egg_test_success (test, "correct alarm");
+		} else {
+			egg_test_failed (test, "alarm %i set!", idletime->priv->last_event);
+		}
+
+		/************************************************************/
+		egg_test_title (test, "check if alarm has gone off in correct time");
+		if (event_time > 3000 && event_time < 6000) {
+			egg_test_success (test, "correct, timeout ideally %ims (we did after %ims)", 5000, event_time);
+		} else {
+			egg_test_failed (test, "alarm %i did not timeout correctly !", idletime->priv->last_event);
+		}
+	}
+
+	/* just let it time out, and wait for human input */
+	wait_until_reset ();
+	g_timer_start (timer);
 
 	/************************************************************/
-	g_print ("*****************************\n");
-	g_print ("*** DO NOT MOVE THE MOUSE ***\n");
-	g_print ("*****************************\n");
-	egg_test_loop_wait (test, 4500);
-	egg_test_loop_check (test);
+	g_timer_start (timer);
+	egg_test_title (test, "check if we can set an existing alarm");
+	ret = egg_idletime_alarm_set (idletime, 101, 10000);
+	if (ret) {
+		egg_test_success (test, "set alarm 10000ms okay");
+	} else {
+		egg_test_failed (test, "could not set alarm 10000ms");
+	}
+
+	/* wait for alarm to go off */
+	wait_until_alarm ();
+	g_timer_start (timer);
 
 	/************************************************************/
-	egg_test_title (test, "check condition");
-	egg_test_assert (test, (_last_alarm == 1));
+	egg_test_title (test, "check if alarm has gone off in the old time");
+	if (event_time > 5000) {
+		egg_test_success (test, "last timeout value used");
+	} else {
+		egg_test_failed (test, "incorrect timeout used %ims", event_time);
+	}
 
 	/************************************************************/
-	g_print ("*****************************\n");
-	g_print ("***    MOVE THE MOUSE     ***\n");
-	g_print ("*****************************\n");
-	egg_test_loop_wait (test, 10000);
-	egg_test_loop_check (test);
+	egg_test_title (test, "check if we can remove an invalid alarm");
+	ret = egg_idletime_alarm_remove (idletime, 202);
+	if (!ret) {
+		egg_test_success (test, "ignored invalid alarm");
+	} else {
+		egg_test_failed (test, "removed invalid alarm");
+	}
 
 	/************************************************************/
-	egg_test_title (test, "check condition");
-	egg_test_assert (test, (_last_alarm == 0));
+	egg_test_title (test, "check if we can remove an valid alarm");
+	ret = egg_idletime_alarm_remove (idletime, 101);
+	if (ret) {
+		egg_test_success (test, "removed valid alarm");
+	} else {
+		egg_test_failed (test, "failed to remove valid alarm");
+	}
 
+	g_timer_destroy (timer);
 	g_object_unref (idletime);
 
 	egg_test_end (test);
diff --git a/src/egg-idletime.h b/src/egg-idletime.h
index 9616710..9e54bc3 100644
--- a/src/egg-idletime.h
+++ b/src/egg-idletime.h
@@ -1,7 +1,6 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
  *
- * Copyright (C) 2007-2009 Richard Hughes <richard hughsie com>
- * Copyright (C) 2007-2009 William Jon McCann <mccann jhu edu>
+ * Copyright (C) 2007 Richard Hughes <richard hughsie com>
  *
  * Licensed under the GNU General Public License Version 2
  *
@@ -27,12 +26,12 @@
 
 G_BEGIN_DECLS
 
-#define EGG_TYPE_IDLETIME		(egg_idletime_get_type ())
-#define EGG_IDLETIME(o)			(G_TYPE_CHECK_INSTANCE_CAST ((o), EGG_TYPE_IDLETIME, EggIdletime))
-#define EGG_IDLETIME_CLASS(k)		(G_TYPE_CHECK_CLASS_CAST((k), EGG_TYPE_IDLETIME, EggIdletimeClass))
-#define EGG_IS_IDLETIME(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), EGG_TYPE_IDLETIME))
-#define EGG_IS_IDLETIME_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), EGG_TYPE_IDLETIME))
-#define EGG_IDLETIME_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), EGG_TYPE_IDLETIME, EggIdletimeClass))
+#define EGG_IDLETIME_TYPE		(egg_idletime_get_type ())
+#define EGG_IDLETIME(o)			(G_TYPE_CHECK_INSTANCE_CAST ((o), EGG_IDLETIME_TYPE, EggIdletime))
+#define EGG_IDLETIME_CLASS(k)		(G_TYPE_CHECK_CLASS_CAST((k), EGG_IDLETIME_TYPE, EggIdletimeClass))
+#define EGG_IS_IDLETIME(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), EGG_IDLETIME_TYPE))
+#define EGG_IS_IDLETIME_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), EGG_IDLETIME_TYPE))
+#define EGG_IDLETIME_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), EGG_IDLETIME_TYPE, EggIdletimeClass))
 
 typedef struct EggIdletimePrivate EggIdletimePrivate;
 
@@ -44,22 +43,25 @@ typedef struct
 
 typedef struct
 {
-	GObjectClass	 parent_class;
-	void		(* alarm_expired)	(EggIdletime	*idletime,
-						 guint		 timer_id);
-	void		(* reset)		(EggIdletime	*idletime);
+	GObjectClass	parent_class;
+	void		(* alarm_expired)		(EggIdletime	*idletime,
+							 guint		 timer_id);
+	void		(* reset)			(EggIdletime	*idletime);
 } EggIdletimeClass;
 
-GType		 egg_idletime_get_type		(void);
-EggIdletime	*egg_idletime_new		(void);
-guint		 egg_idletime_add_watch		(EggIdletime	*idletime,
-						 guint		 interval);
-void		 egg_idletime_remove_watch	(EggIdletime	*idletime,
-						 guint		 id);
+GType		 egg_idletime_get_type			(void);
+EggIdletime	*egg_idletime_new			(void);
+
+void		 egg_idletime_alarm_reset_all		(EggIdletime	*idletime);
+gboolean	 egg_idletime_alarm_set			(EggIdletime	*idletime,
+							 guint		 alarm_id,
+							 guint		 timeout);
+gboolean	 egg_idletime_alarm_remove		(EggIdletime	*idletime,
+							 guint		 alarm_id);
 #ifdef EGG_TEST
-void		 egg_idletime_test		(gpointer	 data);
+void		 egg_idletime_test			(gpointer	 data);
 #endif
 
 G_END_DECLS
 
-#endif /* __EGG_IDLETIME_H */
+#endif	/* __EGG_IDLETIME_H */
diff --git a/src/gpm-idle.c b/src/gpm-idle.c
index dbbd637..b0a0f03 100644
--- a/src/gpm-idle.c
+++ b/src/gpm-idle.c
@@ -49,6 +49,7 @@
    while considered "at idle" */
 #define GPM_IDLE_CPU_LIMIT			5
 #define GPM_IDLE_TIMEOUT_IGNORE_DPMS_CHANGE	1.0f /* seconds */
+#define	GPM_IDLE_IDLETIME_ID			1
 
 struct GpmIdlePrivate
 {
@@ -61,8 +62,6 @@ struct GpmIdlePrivate
 	guint		 timeout_sleep;		/* in seconds */
 	guint		 timeout_blank_id;
 	guint		 timeout_sleep_id;
-	guint		 idletime_id;
-	guint		 idletime_ignore_id;
 	gboolean	 x_idle;
 	gboolean	 check_type_cpu;
 	GTimer		*timer;
@@ -97,7 +96,6 @@ gpm_idle_mode_to_text (GpmIdleMode mode)
 
 /**
  * gpm_idle_set_mode:
- * @idle: This class instance
  * @mode: The new mode, e.g. GPM_IDLE_MODE_SLEEP
  **/
 static void
@@ -119,7 +117,6 @@ gpm_idle_set_mode (GpmIdle *idle, GpmIdleMode mode)
 
 /**
  * gpm_idle_set_check_cpu:
- * @idle: This class instance
  * @check_type_cpu: If we should check the CPU before mode becomes
  *		    GPM_IDLE_MODE_SLEEP and the event is done.
  **/
@@ -133,7 +130,6 @@ gpm_idle_set_check_cpu (GpmIdle *idle, gboolean check_type_cpu)
 
 /**
  * gpm_idle_get_mode:
- * @idle: This class instance
  * Return value: The current mode, e.g. GPM_IDLE_MODE_SLEEP
  **/
 GpmIdleMode
@@ -168,7 +164,6 @@ gpm_idle_sleep_cb (GpmIdle *idle)
 	/* get our computed load value */
 	if (idle->priv->check_type_cpu) {
 		load = gpm_load_get_current (idle->priv->load);
-		/* FIXME: should this stay below this level for a certain time? */
 		if (load > GPM_IDLE_CPU_LIMIT) {
 			/* check if system is "idle" enough */
 			egg_debug ("Detected that the CPU is busy");
@@ -252,7 +247,6 @@ out:
 
 /**
  * gpm_idle_set_timeout_dim:
- * @idle: This class instance
  * @timeout: The new timeout we want to set, in seconds
  **/
 gboolean
@@ -264,18 +258,16 @@ gpm_idle_set_timeout_dim (GpmIdle *idle, guint timeout)
 	if (idle->priv->timeout_dim != timeout) {
 		idle->priv->timeout_dim = timeout;
 
-		/* remove old id */
-		if (idle->priv->idletime_id != 0)
-			egg_idletime_remove_watch (idle->priv->idletime, idle->priv->idletime_id);
-		idle->priv->idletime_id =
-			egg_idletime_add_watch (idle->priv->idletime, timeout * 1000);
+		if (timeout > 0)
+			egg_idletime_alarm_set (idle->priv->idletime, GPM_IDLE_IDLETIME_ID, timeout * 1000);
+		else
+			egg_idletime_alarm_remove (idle->priv->idletime, GPM_IDLE_IDLETIME_ID);
 	}
 	return TRUE;
 }
 
 /**
  * gpm_idle_set_timeout_blank:
- * @idle: This class instance
  * @timeout: The new timeout we want to set, in seconds
  **/
 gboolean
@@ -293,7 +285,6 @@ gpm_idle_set_timeout_blank (GpmIdle *idle, guint timeout)
 
 /**
  * gpm_idle_set_timeout_sleep:
- * @idle: This class instance
  * @timeout: The new timeout we want to set, in seconds
  **/
 gboolean
@@ -312,7 +303,6 @@ gpm_idle_set_timeout_sleep (GpmIdle *idle, guint timeout)
 /**
  * gpm_idle_session_idle_changed_cb:
  * @is_idle: If the session is idle
- * @idle: This class instance
  *
  * The SessionIdleChanged callback from gnome-session.
  **/
@@ -341,10 +331,10 @@ gpm_idle_session_inhibited_changed_cb (GpmSession *session, gboolean is_inhibite
 static void
 gpm_idle_idletime_alarm_expired_cb (EggIdletime *idletime, guint alarm_id, GpmIdle *idle)
 {
-	egg_debug ("idletime alarm: %i", alarm_id);
+	egg_warning ("idletime alarm: %i", alarm_id);
 
-	if (alarm_id == idle->priv->idletime_ignore_id)
-		egg_debug ("expired 1ms timeout");
+	/* reset time to dim default (could be 1ms) */
+	egg_idletime_alarm_set (idle->priv->idletime, GPM_IDLE_IDLETIME_ID, idle->priv->timeout_dim * 1000);
 
 	/* set again */
 	idle->priv->x_idle = TRUE;
@@ -362,25 +352,17 @@ gpm_idle_idletime_reset_cb (EggIdletime *idletime, GpmIdle *idle)
 	gdouble elapsed;
 	elapsed = g_timer_elapsed (idle->priv->timer, NULL);
 
+	egg_warning ("idletime reset");
+
 	/* have we just chaged state? */
 	if (idle->priv->mode == GPM_IDLE_MODE_BLANK &&
 	    elapsed < GPM_IDLE_TIMEOUT_IGNORE_DPMS_CHANGE) {
 		egg_debug ("ignoring reset, as we've just done a state change");
 		/* make sure we trigger a short 1ms timeout so we can get the expired signal */
-		if (idle->priv->idletime_ignore_id != 0)
-			egg_idletime_remove_watch (idle->priv->idletime, idle->priv->idletime_ignore_id);
-		idle->priv->idletime_ignore_id =
-			egg_idletime_add_watch (idle->priv->idletime, 1);
+		egg_idletime_alarm_set (idle->priv->idletime, GPM_IDLE_IDLETIME_ID, 1);
 		return;
 	}
 
-	/* remove 1ms timeout */
-	if (idle->priv->idletime_ignore_id != 0) {
-		egg_debug ("removing 1ms timeout");
-		egg_idletime_remove_watch (idle->priv->idletime, idle->priv->idletime_ignore_id);
-		idle->priv->idletime_ignore_id = 0;
-	}
-
 	idle->priv->x_idle = FALSE;
 	gpm_idle_evaluate (idle);
 }
@@ -410,10 +392,7 @@ gpm_idle_finalize (GObject *object)
 	g_object_unref (idle->priv->load);
 	g_object_unref (idle->priv->session);
 
-	if (idle->priv->idletime_id != 0)
-		egg_idletime_remove_watch (idle->priv->idletime, idle->priv->idletime_id);
-	if (idle->priv->idletime_ignore_id != 0)
-		egg_idletime_remove_watch (idle->priv->idletime, idle->priv->idletime_ignore_id);
+	egg_idletime_alarm_remove (idle->priv->idletime, GPM_IDLE_IDLETIME_ID);
 	g_object_unref (idle->priv->idletime);
 
 	G_OBJECT_CLASS (gpm_idle_parent_class)->finalize (object);
@@ -443,7 +422,6 @@ gpm_idle_class_init (GpmIdleClass *klass)
 
 /**
  * gpm_idle_init:
- * @idle: This class instance
  *
  * Gets a DBUS connection, and aquires the session connection so we can
  * get session changed events.
@@ -459,8 +437,6 @@ gpm_idle_init (GpmIdle *idle)
 	idle->priv->timeout_sleep = G_MAXUINT;
 	idle->priv->timeout_blank_id = 0;
 	idle->priv->timeout_sleep_id = 0;
-	idle->priv->idletime_id = 0;
-	idle->priv->idletime_ignore_id = 0;
 	idle->priv->x_idle = FALSE;
 	idle->priv->timer = g_timer_new ();
 	idle->priv->load = gpm_load_new ();
@@ -491,3 +467,238 @@ gpm_idle_new (void)
 	return GPM_IDLE (gpm_idle_object);
 }
 
+/***************************************************************************
+ ***                          MAKE CHECK TESTS                           ***
+ ***************************************************************************/
+#ifdef EGG_TEST
+#include "egg-test.h"
+#include "gpm-dpms.h"
+
+static GpmIdleMode _mode = 0;
+
+static void
+gpm_idle_test_idle_changed_cb (GpmIdle *idle, GpmIdleMode mode, EggTest *test)
+{
+	_mode = mode;
+	egg_debug ("idle-changed %s", gpm_idle_mode_to_text (mode));
+	egg_test_loop_quit (test);
+}
+
+static gboolean
+gpm_idle_test_delay_cb (EggTest *test)
+{
+	egg_warning ("timing out");
+	egg_test_loop_quit (test);
+	return FALSE;
+}
+
+void
+gpm_idle_test (gpointer data)
+{
+	GpmIdle *idle;
+	gboolean ret;
+	EggTest *test = (EggTest *) data;
+	GpmIdleMode mode;
+	GpmDpms *dpms;
+
+	if (!egg_test_start (test, "GpmIdle"))
+		return;
+
+	/************************************************************/
+	egg_test_title (test, "get object");
+	idle = gpm_idle_new ();
+	if (idle != NULL)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "got no object");
+
+	/* set up defaults */
+	gpm_idle_set_check_cpu (idle, FALSE);
+	gpm_idle_set_timeout_dim (idle, 4);
+	gpm_idle_set_timeout_blank (idle, 5);
+	gpm_idle_set_timeout_sleep (idle, 15);
+	g_signal_connect (idle, "idle-changed",
+			  G_CALLBACK (gpm_idle_test_idle_changed_cb), test);
+
+	/************************************************************/
+	egg_test_title (test, "check cpu type");
+	egg_test_assert (test, (idle->priv->check_type_cpu == FALSE));
+
+	/************************************************************/
+	egg_test_title (test, "check timeout dim");
+	egg_test_assert (test, (idle->priv->timeout_dim == 4));
+
+	/************************************************************/
+	egg_test_title (test, "check timeout blank");
+	egg_test_assert (test, (idle->priv->timeout_blank == 5));
+
+	/************************************************************/
+	egg_test_title (test, "check timeout sleep");
+	egg_test_assert (test, (idle->priv->timeout_sleep == 15));
+
+	/************************************************************/
+	egg_test_title (test, "check x_idle");
+	egg_test_assert (test, (idle->priv->x_idle == FALSE));
+
+	/************************************************************/
+	egg_test_title (test, "check blank id");
+	egg_test_assert (test, (idle->priv->timeout_blank_id == 0));
+
+	/************************************************************/
+	egg_test_title (test, "check sleep id");
+	egg_test_assert (test, (idle->priv->timeout_sleep_id == 0));
+
+	/************************************************************/
+	egg_test_title (test, "check normal at startup");
+	mode = gpm_idle_get_mode (idle);
+	if (mode == GPM_IDLE_MODE_NORMAL)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "mode: %s", gpm_idle_mode_to_text (mode));
+
+	/************************************************************/
+	g_print ("*****************************\n");
+	g_print ("*** DO NOT MOVE THE MOUSE ***\n");
+	g_print ("*****************************\n");
+	egg_test_loop_wait (test, 2000 + 10000);
+	egg_test_loop_check (test);
+
+	/************************************************************/
+	egg_test_title (test, "check callback mode");
+	if (_mode == GPM_IDLE_MODE_DIM)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "mode: %s", gpm_idle_mode_to_text (mode));
+
+	/************************************************************/
+	egg_test_title (test, "check current mode");
+	mode = gpm_idle_get_mode (idle);
+	if (mode == GPM_IDLE_MODE_DIM)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "mode: %s", gpm_idle_mode_to_text (mode));
+
+	/************************************************************/
+	egg_test_title (test, "check x_idle");
+	egg_test_assert (test, (idle->priv->x_idle == TRUE));
+
+	/************************************************************/
+	egg_test_title (test, "check blank id");
+	egg_test_assert (test, (idle->priv->timeout_blank_id != 0));
+
+	/************************************************************/
+	egg_test_title (test, "check sleep id");
+	egg_test_assert (test, (idle->priv->timeout_sleep_id == 0));
+
+	/************************************************************/
+	egg_test_loop_wait (test, 5000 + 1000);
+	egg_test_loop_check (test);
+
+	/************************************************************/
+	egg_test_title (test, "check callback mode");
+	if (_mode == GPM_IDLE_MODE_BLANK)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "mode: %s", gpm_idle_mode_to_text (mode));
+
+	/************************************************************/
+	egg_test_title (test, "check current mode");
+	mode = gpm_idle_get_mode (idle);
+	if (mode == GPM_IDLE_MODE_BLANK)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "mode: %s", gpm_idle_mode_to_text (mode));
+
+	/************************************************************/
+	g_print ("**********************\n");
+	g_print ("*** MOVE THE MOUSE ***\n");
+	g_print ("**********************\n");
+	egg_test_loop_wait (test, G_MAXUINT);
+	egg_test_loop_check (test);
+
+	/************************************************************/
+	egg_test_title (test, "check callback mode");
+	if (_mode == GPM_IDLE_MODE_NORMAL)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "mode: %s", gpm_idle_mode_to_text (mode));
+
+	/************************************************************/
+	egg_test_title (test, "check current mode");
+	mode = gpm_idle_get_mode (idle);
+	if (mode == GPM_IDLE_MODE_NORMAL)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "mode: %s", gpm_idle_mode_to_text (mode));
+
+	/************************************************************/
+	egg_test_title (test, "check x_idle");
+	egg_test_assert (test, (idle->priv->x_idle == FALSE));
+
+	/************************************************************/
+	egg_test_title (test, "check blank id");
+	egg_test_assert (test, (idle->priv->timeout_blank_id == 0));
+
+	/************************************************************/
+	g_print ("*****************************\n");
+	g_print ("*** DO NOT MOVE THE MOUSE ***\n");
+	g_print ("*****************************\n");
+	egg_test_loop_wait (test, 4000 + 1500);
+	egg_test_loop_check (test);
+
+	/************************************************************/
+	egg_test_title (test, "check current mode");
+	mode = gpm_idle_get_mode (idle);
+	if (mode == GPM_IDLE_MODE_DIM)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "mode: %s", gpm_idle_mode_to_text (mode));
+
+	/************************************************************/
+	egg_test_title (test, "check x_idle");
+	egg_test_assert (test, (idle->priv->x_idle == TRUE));
+
+	egg_test_loop_wait (test, 15000);
+	egg_test_loop_check (test);
+
+	/************************************************************/
+	egg_test_title (test, "check current mode");
+	mode = gpm_idle_get_mode (idle);
+	if (mode == GPM_IDLE_MODE_BLANK)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "mode: %s", gpm_idle_mode_to_text (mode));
+
+	/************************************************************/
+	egg_test_title (test, "set dpms off");
+	dpms = gpm_dpms_new ();
+	ret = gpm_dpms_set_mode (dpms, GPM_DPMS_MODE_OFF, NULL);
+	egg_test_assert (test, ret);
+
+	/* wait for normal event to be suppressed */
+	g_timeout_add (2000, (GSourceFunc) gpm_idle_test_delay_cb, test);
+	egg_test_loop_wait (test, G_MAXUINT);
+	egg_test_loop_check (test);
+
+	/************************************************************/
+	egg_test_title (test, "check current mode");
+	mode = gpm_idle_get_mode (idle);
+	if (mode == GPM_IDLE_MODE_BLANK)
+		egg_test_success (test, NULL);
+	else
+		egg_test_failed (test, "mode: %s", gpm_idle_mode_to_text (mode));
+
+	/************************************************************/
+	egg_test_title (test, "check x_idle");
+	egg_test_assert (test, (idle->priv->x_idle == TRUE));
+
+	gpm_dpms_set_mode (dpms, GPM_DPMS_MODE_ON, NULL);
+
+	g_object_unref (idle);
+	g_object_unref (dpms);
+
+	egg_test_end (test);
+}
+
+#endif
+
diff --git a/src/gpm-idle.h b/src/gpm-idle.h
index e720768..51d62ce 100644
--- a/src/gpm-idle.h
+++ b/src/gpm-idle.h
@@ -67,6 +67,7 @@ gboolean	 gpm_idle_set_timeout_blank		(GpmIdle	*idle,
 							 guint		 timeout);
 gboolean	 gpm_idle_set_timeout_sleep		(GpmIdle	*idle,
 							 guint		 timeout);
+void		 gpm_idle_test				(gpointer	 data);
 
 G_END_DECLS
 
diff --git a/src/gpm-self-test.c b/src/gpm-self-test.c
index 2610ce7..d13cf45 100644
--- a/src/gpm-self-test.c
+++ b/src/gpm-self-test.c
@@ -35,6 +35,7 @@ void egg_array_float_test (EggTest *test);
 void egg_idletime_test (EggTest *test);
 
 void gpm_common_test (EggTest *test);
+void gpm_idle_test (EggTest *test);
 void gpm_phone_test (EggTest *test);
 void gpm_dpms_test (EggTest *test);
 void gpm_graph_widget_test (EggTest *test);
@@ -63,6 +64,7 @@ main (int argc, char **argv)
 //	egg_idletime_test (test);
 
 	gpm_common_test (test);
+	gpm_idle_test (test);
 	gpm_phone_test (test);
 //	gpm_dpms_test (test);
 //	gpm_graph_widget_test (test);



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