[gnome-power-manager] Update the IDLETIME code to similar to gnome-session
- From: Richard Hughes <rhughes src gnome org>
- To: svn-commits-list gnome org
- Subject: [gnome-power-manager] Update the IDLETIME code to similar to gnome-session
- Date: Sat, 18 Apr 2009 04:30:25 -0400 (EDT)
commit b499906adc7c3e1973d8885afbe729ae2647c2ef
Author: Richard Hughes <richard hughsie com>
Date: Sat Apr 18 09:29:28 2009 +0100
Update the IDLETIME code to similar to gnome-session
Our homebrewed IDLETIME code is starting to show bugs, so we should use the
same (better) code in gnome-session written by William Jon McCann.
---
src/egg-idletime.c | 760 ++++++++++++++++++++++------------------------------
src/egg-idletime.h | 43 ++--
src/gpm-idle.c | 50 ++--
3 files changed, 368 insertions(+), 485 deletions(-)
diff --git a/src/egg-idletime.c b/src/egg-idletime.c
index 6f509aa..e09ed5e 100644
--- a/src/egg-idletime.c
+++ b/src/egg-idletime.c
@@ -1,6 +1,7 @@
/* -*- 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>
*
* Licensed under the GNU General Public License Version 2
*
@@ -19,42 +20,39 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
+#include "config.h"
+
+#include <time.h>
+#include <string.h>
-#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_IDLETIME_TYPE, EggIdletimePrivate))
+#define EGG_IDLETIME_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), EGG_TYPE_IDLETIME, EggIdletimePrivate))
struct EggIdletimePrivate
{
- int sync_event;
- guint last_event;
- gboolean reset_set;
- XSyncCounter idle_counter;
- GPtrArray *array;
- Display *dpy;
+ GHashTable *watches;
+ int sync_event_base;
+ XSyncCounter counter;
};
typedef struct
{
- guint id;
- XSyncValue timeout;
- XSyncAlarm xalarm;
-} EggIdletimeAlarm;
+ guint id;
+ XSyncValue interval;
+ XSyncAlarm xalarm_positive;
+ XSyncAlarm xalarm_negative;
+} EggIdletimeWatch;
enum {
SIGNAL_ALARM_EXPIRED,
@@ -62,271 +60,346 @@ enum {
LAST_SIGNAL
};
+static guint32 watch_serial = 1;
static guint signals [LAST_SIGNAL] = { 0 };
-static gpointer egg_idletime_object = NULL;
G_DEFINE_TYPE (EggIdletime, egg_idletime, G_TYPE_OBJECT)
/**
- * egg_idletime_xsync_alarm_set:
- *
- * Gets the time remaining for the current percentage
- *
+ * egg_idletime_xsyncvalue_to_int64:
*/
-static void
-egg_idletime_xsync_alarm_set (EggIdletime *idletime, EggIdletimeAlarm *alarm, gboolean positive)
+static gint64
+egg_idletime_xsyncvalue_to_int64 (XSyncValue value)
{
- XSyncAlarmAttributes attr;
- XSyncValue delta;
- unsigned int flags;
- XSyncTestType test;
-
- /* which way do we do the test? */
- if (positive)
- test = XSyncPositiveTransition;
- else
- test = XSyncNegativeTransition;
-
- XSyncIntToValue (&delta, 0);
-
- 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;
-
- flags = XSyncCACounter | XSyncCAValueType | XSyncCATestType | XSyncCAValue | XSyncCADelta;
-
- if (alarm->xalarm)
- XSyncChangeAlarm (idletime->priv->dpy, alarm->xalarm, flags, &attr);
- else
- alarm->xalarm = XSyncCreateAlarm (idletime->priv->dpy, flags, &attr);
+ return ((guint64) XSyncValueHigh32 (value)) << 32
+ | (guint64) XSyncValueLow32 (value);
}
/**
- * egg_idletime_alarm_reset_all:
+ * egg_idletime_int64_to_xsyncvalue:
*/
-void
-egg_idletime_alarm_reset_all (EggIdletime *idletime)
+static XSyncValue
+egg_idletime_int64_to_xsyncvalue (gint64 value)
{
- guint i;
- EggIdletimeAlarm *alarm;
+ XSyncValue ret;
+ XSyncIntsToValue (&ret, value, ((guint64)value) >> 32);
+ return ret;
+}
- /* 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, TRUE);
+/**
+ * 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;
}
-
- /* emit signal */
- g_signal_emit (idletime, signals [SIGNAL_RESET], 0);
-
- /* we need to be reset again on the next event */
- idletime->priv->reset_set = FALSE;
+ return FALSE;
}
/**
- * egg_idletime_timeout:
+ * egg_idletime_find_watch_for_alarm:
*/
-static void
-egg_idletime_timeout (EggIdletime *idletime, EggIdletimeAlarm *alarm)
+static EggIdletimeWatch *
+egg_idletime_find_watch_for_alarm (EggIdletime *idletime, XSyncAlarm alarm)
{
- /* emit signal */
- g_signal_emit (idletime, signals [SIGNAL_ALARM_EXPIRED], 0, alarm->id);
+ EggIdletimeWatch *watch;
+ watch = g_hash_table_find (idletime->priv->watches,
+ (GHRFunc)egg_idletime_find_alarm, &alarm);
+ return watch;
}
/**
- * egg_idletime_xsync_value_add_one:
- *
- * Just adds one to a XSyncValue. I love X.
+ * egg_idletime_handle_alarm_notify_event:
*/
static void
-egg_idletime_xsync_value_add_one (XSyncValue *from, XSyncValue *to)
+egg_idletime_handle_alarm_notify_event (EggIdletime *idletime, XSyncAlarmNotifyEvent *alarm_event)
{
- int overflow;
- XSyncValue add;
- XSyncIntToValue (&add, -1);
- XSyncValueAdd (to, *from, add, &overflow);
+ 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);
+ return;
+ }
+
+ egg_debug ("Watch %d fired, idle time = %lld",
+ watch->id, egg_idletime_xsyncvalue_to_int64 (alarm_event->counter_value));
+
+ 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_alarm_find_id:
+ * egg_idletime_xevent_filter:
*/
-static EggIdletimeAlarm *
-egg_idletime_alarm_find_id (EggIdletime *idletime, guint id)
+static GdkFilterReturn
+egg_idletime_xevent_filter (GdkXEvent *xevent, GdkEvent *event, EggIdletime *idletime)
{
- 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;
+ XEvent *ev;
+ XSyncAlarmNotifyEvent *alarm_event;
+
+ ev = xevent;
+ if (ev->xany.type != idletime->priv->sync_event_base + XSyncAlarmNotify)
+ return GDK_FILTER_CONTINUE;
+
+ alarm_event = xevent;
+ egg_idletime_handle_alarm_notify_event (idletime, alarm_event);
+
+ return GDK_FILTER_CONTINUE;
}
/**
- * egg_idletime_x_set_reset:
+ * egg_idletime_init_xsync:
*/
-static void
-egg_idletime_x_set_reset (EggIdletime *idletime, XSyncAlarmNotifyEvent *alarm_event)
+static gboolean
+egg_idletime_init_xsync (EggIdletime *idletime)
{
- EggIdletimeAlarm *alarm;
+ int sync_error_base;
+ int res;
+ int major;
+ int minor;
+ int i;
+ int ncounters;
+ XSyncSystemCounter *counters;
- alarm = egg_idletime_alarm_find_id (idletime, 0);
+ res = XSyncQueryExtension (GDK_DISPLAY (),
+ &idletime->priv->sync_event_base,
+ &sync_error_base);
+ if (res == 0) {
+ egg_warning ("EggIdletime: Sync extension not present");
+ return FALSE;
+ }
- if (idletime->priv->reset_set == FALSE) {
- /* don't match on the current value because
- * XSyncNegativeComparison means less or equal. */
- egg_idletime_xsync_value_add_one (&alarm_event->counter_value, &alarm->timeout);
+ res = XSyncInitialize (GDK_DISPLAY (), &major, &minor);
+ if (res == 0) {
+ egg_warning ("EggIdletime: Unable to initialize Sync extension");
+ return FALSE;
+ }
- /* set the reset alarm to fire the next time
- * idletime->priv->idle_counter < the current counter value */
- egg_idletime_xsync_alarm_set (idletime, alarm, FALSE);
+ 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;
+ }
+ }
+ XSyncFreeSystemCounterList (counters);
- /* don't try to set this again */
- idletime->priv->reset_set = TRUE;
+ if (idletime->priv->counter == None) {
+ egg_warning ("EggIdletime: IDLETIME counter not found");
+ return FALSE;
}
+
+ gdk_window_add_filter (NULL, (GdkFilterFunc) egg_idletime_xevent_filter, idletime);
+
+ return TRUE;
}
/**
- * egg_idletime_alarm_find_event:
+ * egg_idletime_get_next_watch_serial:
*/
-static EggIdletimeAlarm *
-egg_idletime_alarm_find_event (EggIdletime *idletime, XSyncAlarmNotifyEvent *alarm_event)
+static guint32
+egg_idletime_get_next_watch_serial (void)
{
- 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;
+ guint32 serial;
+
+ serial = watch_serial++;
+ /* cope with overflow */
+ if ((gint32)watch_serial < 0)
+ watch_serial = 1;
+ return serial;
}
/**
- * egg_idletime_x_event_filter:
+ * egg_idletime_watch_new:
*/
-static GdkFilterReturn
-egg_idletime_x_event_filter (GdkXEvent *gdkxevent, GdkEvent *event, gpointer data)
+static EggIdletimeWatch *
+egg_idletime_watch_new (guint interval)
{
- EggIdletimeAlarm *alarm;
- XEvent *xevent = (XEvent *) gdkxevent;
- EggIdletime *idletime = (EggIdletime *) data;
- XSyncAlarmNotifyEvent *alarm_event;
+ EggIdletimeWatch *watch;
- /* no point continuing */
- if (xevent->type != idletime->priv->sync_event + XSyncAlarmNotify)
- return GDK_FILTER_CONTINUE;
+ 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_event = (XSyncAlarmNotifyEvent *) xevent;
+ return watch;
+}
- alarm = egg_idletime_alarm_find_event (idletime, alarm_event);
+/**
+ * egg_idletime_watch_free:
+ */
+static void
+egg_idletime_watch_free (EggIdletimeWatch *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 (EggIdletimeWatch, watch);
+}
- /* did we match one of our alarms? */
- if (alarm != NULL) {
- /* save the last state we triggered */
- idletime->priv->last_event = alarm->id;
+/**
+ * egg_idletime_xsync_alarm_set:
+ */
+static gboolean
+egg_idletime_xsync_alarm_set (EggIdletime *idletime, EggIdletimeWatch *watch)
+{
+ XSyncAlarmAttributes attr;
+ XSyncValue delta;
+ guint flags;
- /* do the signal */
- if (alarm->id != 0) {
- egg_idletime_timeout (idletime, alarm);
+ flags = XSyncCACounter
+ | XSyncCAValueType
+ | XSyncCATestType
+ | XSyncCAValue
+ | XSyncCADelta
+ | XSyncCAEvents;
- /* we need the first alarm to go off to set the reset alarm */
- egg_idletime_x_set_reset (idletime, alarm_event);
- return GDK_FILTER_CONTINUE;
- }
+ 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;
- /* do the reset callback */
- egg_idletime_alarm_reset_all (idletime);
+ attr.trigger.test_type = XSyncPositiveTransition;
+ if (watch->xalarm_positive != None) {
+ egg_debug ("EggIdletime: updating alarm for positive transition wait=%lld",
+ 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=%lld",
+ egg_idletime_xsyncvalue_to_int64 (attr.trigger.wait_value));
+ watch->xalarm_positive = XSyncCreateAlarm (GDK_DISPLAY (), flags, &attr);
}
- return GDK_FILTER_CONTINUE;
+ attr.trigger.test_type = XSyncNegativeTransition;
+ if (watch->xalarm_negative != None) {
+ egg_debug ("EggIdletime: updating alarm for negative transition wait=%lld",
+ 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=%lld",
+ egg_idletime_xsyncvalue_to_int64 (attr.trigger.wait_value));
+ watch->xalarm_negative = XSyncCreateAlarm (GDK_DISPLAY (), flags, &attr);
+ }
+
+ return TRUE;
}
/**
- * egg_idletime_get_idletime->priv->last_event:
+ * egg_idletime_add_watch:
*/
guint
-egg_idletime_alarm_get (EggIdletime *idletime)
+egg_idletime_add_watch (EggIdletime *idletime, guint interval)
{
- return idletime->priv->last_event;
+ EggIdletimeWatch *watch;
+
+ g_return_val_if_fail (EGG_IS_IDLETIME (idletime), 0);
+
+ watch = egg_idletime_watch_new (interval);
+
+ egg_idletime_xsync_alarm_set (idletime, watch);
+
+ g_hash_table_insert (idletime->priv->watches,
+ GUINT_TO_POINTER (watch->id), watch);
+ return watch->id;
}
/**
- * egg_idletime_alarm_set:
+ * egg_idletime_remove_watch:
*/
-gboolean
-egg_idletime_alarm_set (EggIdletime *idletime, guint id, guint timeout)
+void
+egg_idletime_remove_watch (EggIdletime *idletime, guint id)
{
- EggIdletimeAlarm *alarm;
-
- /* id cannot be zero */
- if (id == 0)
- return FALSE;
+ g_return_if_fail (EGG_IS_IDLETIME (idletime));
- /* timeout cannot be zero */
- if (timeout == 0)
- return FALSE;
+ g_hash_table_remove (idletime->priv->watches, GUINT_TO_POINTER (id));
+}
- /* 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);
+/**
+ * egg_idletime_finalize:
+ */
+static void
+egg_idletime_finalize (GObject *object)
+{
+ EggIdletime *idletime;
- /* set the id - this is just something like userdata */
- alarm->id = id;
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (EGG_IS_IDLETIME (object));
- /* add to array */
- g_ptr_array_add (idletime->priv->array, alarm);
- }
+ idletime = EGG_IDLETIME (object);
- /* set the timeout */
- XSyncIntToValue (&alarm->timeout, (gint)timeout);
+ g_return_if_fail (idletime->priv != NULL);
- /* set, and start the timer */
- egg_idletime_xsync_alarm_set (idletime, alarm, TRUE);
- return TRUE;
+ G_OBJECT_CLASS (egg_idletime_parent_class)->finalize (object);
}
/**
- * egg_idletime_alarm_free:
+ * egg_idletime_constructor:
*/
-static gboolean
-egg_idletime_alarm_free (EggIdletime *idletime, EggIdletimeAlarm *alarm)
+static GObject *
+egg_idletime_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties)
{
- XSyncDestroyAlarm (idletime->priv->dpy, alarm->xalarm);
- g_free (alarm);
- g_ptr_array_remove (idletime->priv->array, alarm);
- return TRUE;
+ 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);
}
/**
- * egg_idletime_alarm_free:
+ * egg_idletime_dispose:
*/
-gboolean
-egg_idletime_alarm_remove (EggIdletime *idletime, guint id)
+static void
+egg_idletime_dispose (GObject *object)
{
- EggIdletimeAlarm *alarm;
- alarm = egg_idletime_alarm_find_id (idletime, id);
- if (alarm == NULL)
- return FALSE;
- egg_idletime_alarm_free (idletime, alarm);
- return TRUE;
+ EggIdletime *idletime;
+
+ g_return_if_fail (EGG_IS_IDLETIME (object));
+
+ idletime = EGG_IDLETIME (object);
+
+ 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);
}
/**
* egg_idletime_class_init:
- * @klass: This class instance
- **/
+ */
static void
egg_idletime_class_init (EggIdletimeClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
object_class->finalize = egg_idletime_finalize;
- g_type_class_add_private (klass, sizeof (EggIdletimePrivate));
+ object_class->dispose = egg_idletime_dispose;
+ object_class->constructor = egg_idletime_constructor;
signals [SIGNAL_ALARM_EXPIRED] =
g_signal_new ("alarm-expired",
@@ -342,102 +415,31 @@ 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:
- *
- * @egg_idletime: This class instance
- **/
+ */
static void
egg_idletime_init (EggIdletime *idletime)
{
- int sync_error;
- int ncounters;
- XSyncSystemCounter *counters;
- EggIdletimeAlarm *alarm;
- int i;
-
idletime->priv = EGG_IDLETIME_GET_PRIVATE (idletime);
-
- 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"))
- 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_x_event_filter, idletime);
-
- /* create a reset alarm */
- alarm = g_new0 (EggIdletimeAlarm, 1);
- alarm->id = 0;
- g_ptr_array_add (idletime->priv->array, alarm);
-}
-
-/**
- * egg_idletime_finalize:
- * @object: This class instance
- **/
-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);
-
- 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);
+ idletime->priv->counter = None;
+ idletime->priv->watches = g_hash_table_new_full (NULL, NULL, NULL,
+ (GDestroyNotify) egg_idletime_watch_free);
}
/**
* egg_idletime_new:
- * Return value: new EggIdletime instance.
- **/
+ */
EggIdletime *
egg_idletime_new (void)
{
- 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);
+ GObject *idletime;
+ idletime = g_object_new (EGG_TYPE_IDLETIME, NULL);
+ return EGG_IDLETIME (idletime);
}
/***************************************************************************
@@ -446,216 +448,94 @@ egg_idletime_new (void)
#ifdef EGG_TEST
#include "egg-test.h"
-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 guint _last_alarm = 0;
static void
-gpm_alarm_expired_cb (EggIdletime *idletime, guint alarm, gpointer data)
+egg_idletime_test_alarm_expired_cb (EggIdletime *idletime, guint alarm, EggTest *test)
{
- last_alarm = alarm;
- event_time = g_timer_elapsed (timer, NULL) * (gfloat) 1000.0f;
-// g_print ("[evt %i in %ims]\n", alarm, event_time);
+ _last_alarm = alarm;
+ egg_debug ("alarm %i", alarm);
+ egg_test_loop_quit (test);
}
static void
-wait_until_alarm (void)
+egg_idletime_test_reset_cb (EggIdletime *idletime, EggTest *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);
+ _last_alarm = 0;
+ egg_debug ("reset");
+ egg_test_loop_quit (test);
}
void
egg_idletime_test (gpointer data)
{
EggIdletime *idletime;
- gboolean ret;
- guint alarm;
- 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, "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");
+ egg_test_title (test, "make sure we get an object");
idletime = egg_idletime_new ();
- if (idletime != NULL) {
- egg_test_success (test, "got EggIdletime");
- } else {
- egg_test_failed (test, "could not get EggIdletime");
- }
+ egg_test_assert (test, (idletime != NULL));
g_signal_connect (idletime, "alarm-expired",
- G_CALLBACK (gpm_alarm_expired_cb), NULL);
+ G_CALLBACK (egg_idletime_test_alarm_expired_cb), test);
+ g_signal_connect (idletime, "reset",
+ G_CALLBACK (egg_idletime_test_reset_cb), test);
/************************************************************/
- egg_test_title (test, "check if we are alarm zero with no alarms");
- alarm = egg_idletime_alarm_get (idletime);
- if (alarm == 0) {
- egg_test_success (test, NULL);
- } else {
- egg_test_failed (test, "alarm %i set!", alarm);
- }
+ 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 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");
- }
+ 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 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");
- }
+ egg_test_title (test, "check condition");
+ egg_test_assert (test, (_last_alarm == 1));
/************************************************************/
- 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_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");
- alarm = egg_idletime_alarm_get (idletime);
- if (alarm == 101) {
- egg_test_success (test, "correct alarm");
- } else {
- egg_test_failed (test, "alarm %i set!", alarm);
- }
-
- /************************************************************/
- egg_test_title (test, "check if alarm has gone off in correct time");
- alarm = egg_idletime_alarm_get (idletime);
- 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 !", alarm);
- }
- }
-
- /* just let it time out, and wait for human input */
- wait_until_reset ();
- g_timer_start (timer);
+ 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 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");
- }
+ egg_test_title (test, "check condition");
+ egg_test_assert (test, (_last_alarm == 0));
- /* wait for alarm to go off */
- wait_until_alarm ();
- 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);
/************************************************************/
- egg_test_title (test, "check if alarm has gone off in the old time");
- alarm = egg_idletime_alarm_get (idletime);
- if (event_time > 5000) {
- egg_test_success (test, "last timeout value used");
- } else {
- egg_test_failed (test, "incorrect timeout used %ims", event_time);
- }
+ egg_test_title (test, "check condition");
+ egg_test_assert (test, (_last_alarm == 1));
/************************************************************/
- 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");
- }
+ 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 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");
- }
+ egg_test_title (test, "check condition");
+ egg_test_assert (test, (_last_alarm == 0));
- 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 d67e5ec..9616710 100644
--- a/src/egg-idletime.h
+++ b/src/egg-idletime.h
@@ -1,6 +1,7 @@
/* -*- 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 Richard Hughes <richard hughsie com>
+ * Copyright (C) 2007-2009 William Jon McCann <mccann jhu edu>
*
* Licensed under the GNU General Public License Version 2
*
@@ -26,12 +27,12 @@
G_BEGIN_DECLS
-#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))
+#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))
typedef struct EggIdletimePrivate EggIdletimePrivate;
@@ -43,26 +44,22 @@ 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);
-
-void egg_idletime_alarm_reset_all (EggIdletime *idletime);
-guint egg_idletime_alarm_get (EggIdletime *idletime);
-gboolean egg_idletime_alarm_set (EggIdletime *idletime,
- guint alarm_id,
- guint timeout);
-gboolean egg_idletime_alarm_remove (EggIdletime *idletime,
- guint alarm_id);
+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);
#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 3a61264..3e515e6 100644
--- a/src/gpm-idle.c
+++ b/src/gpm-idle.c
@@ -48,8 +48,6 @@
/* Sets the idle percent limit, i.e. how hard the computer can work
while considered "at idle" */
#define GPM_IDLE_CPU_LIMIT 5
-#define GPM_IDLE_IDLETIME_ALARM_ID 1
-#define GPM_IDLE_IDLETIME_IGNORE_ID 2
#define GPM_IDLE_TIMEOUT_IGNORE_DPMS_CHANGE 1.0f /* seconds */
struct GpmIdlePrivate
@@ -63,6 +61,8 @@ 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;
@@ -260,8 +260,12 @@ gpm_idle_set_timeout_dim (GpmIdle *idle, guint timeout)
egg_debug ("Setting dim idle timeout: %ds", timeout);
if (idle->priv->timeout_dim != timeout) {
idle->priv->timeout_dim = timeout;
- egg_idletime_alarm_set (idle->priv->idletime, GPM_IDLE_IDLETIME_ALARM_ID, idle->priv->timeout_dim * 1000);
- gpm_idle_evaluate (idle);
+
+ /* 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);
}
return TRUE;
}
@@ -334,18 +338,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)
{
- gboolean ret;
-
egg_debug ("idletime alarm: %i", alarm_id);
- /* this must be out 500ms ignored timer */
- if (idle->priv->x_idle) {
- egg_debug ("removing ignored timer");
- ret = egg_idletime_alarm_remove (idle->priv->idletime, GPM_IDLE_IDLETIME_IGNORE_ID);
- if (!ret)
- egg_warning ("failed to remove timer %i", GPM_IDLE_IDLETIME_IGNORE_ID);
- return;
- }
+ if (alarm_id == idle->priv->idletime_ignore_id)
+ egg_debug ("expired 1ms timeout");
/* set again */
idle->priv->x_idle = TRUE;
@@ -360,25 +356,28 @@ gpm_idle_idletime_alarm_expired_cb (EggIdletime *idletime, guint alarm_id, GpmId
static void
gpm_idle_idletime_reset_cb (EggIdletime *idletime, GpmIdle *idle)
{
- guint id;
- gboolean ret;
gdouble elapsed;
elapsed = g_timer_elapsed (idle->priv->timer, NULL);
- id = egg_idletime_alarm_get (idle->priv->idletime);
- egg_debug ("idletime reset: %i", id);
-
/* 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 */
- ret = egg_idletime_alarm_set (idle->priv->idletime, GPM_IDLE_IDLETIME_IGNORE_ID, 500);
- if (!ret)
- egg_error ("failed to set timer %i", GPM_IDLE_IDLETIME_IGNORE_ID);
+ 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);
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);
}
@@ -407,6 +406,11 @@ gpm_idle_finalize (GObject *object)
g_timer_destroy (idle->priv->timer);
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);
g_object_unref (idle->priv->idletime);
G_OBJECT_CLASS (gpm_idle_parent_class)->finalize (object);
@@ -452,6 +456,8 @@ 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 ();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]