Index: src/Makefile.am
===================================================================
RCS file: /cvs/gnome/gnome-power-manager/src/Makefile.am,v
retrieving revision 1.38
diff -p -u -r1.38 Makefile.am
--- src/Makefile.am	6 Jan 2006 11:22:31 -0000	1.38
+++ src/Makefile.am	7 Jan 2006 00:06:01 -0000
@@ -73,6 +73,10 @@ gnome_power_manager_SOURCES =				\
 	gpm-libnotify.c					\
 	gpm-idle.h					\
 	gpm-idle.c					\
+	gpm-hal-monitor.h				\
+	gpm-hal-monitor.c				\
+	gpm-manager.h					\
+	gpm-manager.c					\
 	gpm-notification.h				\
 	gpm-notification.c				\
 	gpm-core.h					\
Index: src/gpm-dbus-server.c
===================================================================
RCS file: /cvs/gnome/gnome-power-manager/src/gpm-dbus-server.c,v
retrieving revision 1.25
diff -p -u -r1.25 gpm-dbus-server.c
--- src/gpm-dbus-server.c	27 Dec 2005 20:27:57 -0000	1.25
+++ src/gpm-dbus-server.c	7 Jan 2006 00:06:01 -0000
@@ -33,14 +33,24 @@
  */
 
 #include <glib.h>
-#include <gnome.h>
 #include <dbus/dbus-glib.h>
+
 #include "gpm-dbus-server.h"
 #include "gpm-common.h"
 #include "gpm-dbus-common.h"
 #include "gpm-hal.h"
 
-G_DEFINE_TYPE(GPMObject, gpm_object, G_TYPE_OBJECT)
+G_DEFINE_TYPE (GPMObject, gpm_object, G_TYPE_OBJECT)
+
+/** The dbus signal type
+ */
+enum
+{
+	MAINS_CHANGED,		/**< Signal mainsStatusChanged		*/
+	ACTION_ABOUT_TO_HAPPEN,	/**< Signal actionAboutToHappen		*/
+	PERFORMING_ACTION,	/**< Signal performingAction		*/
+	LAST_SIGNAL		/**< The last signal...			*/
+};
 
 guint signals[LAST_SIGNAL] = { 0 };
 
Index: src/gpm-dbus-server.h
===================================================================
RCS file: /cvs/gnome/gnome-power-manager/src/gpm-dbus-server.h,v
retrieving revision 1.13
diff -p -u -r1.13 gpm-dbus-server.h
--- src/gpm-dbus-server.h	23 Dec 2005 18:43:17 -0000	1.13
+++ src/gpm-dbus-server.h	7 Jan 2006 00:06:01 -0000
@@ -29,15 +29,11 @@
 #ifndef _GPMDBUSSERVER_H
 #define _GPMDBUSSERVER_H
 
-/** The dbus signal type
- */
-enum
-{
-	MAINS_CHANGED,		/**< Signal mainsStatusChanged		*/
-	ACTION_ABOUT_TO_HAPPEN,	/**< Signal actionAboutToHappen		*/
-	PERFORMING_ACTION,	/**< Signal performingAction		*/
-	LAST_SIGNAL		/**< The last signal...			*/
-};
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+G_BEGIN_DECLS
 
 typedef struct GPMObject GPMObject;
 typedef struct GPMObjectClass GPMObjectClass;
@@ -47,10 +43,15 @@ GType gpm_object_get_type (void);
 
 /** The dbus GPM GObject type
  */
-struct GPMObject {GObject parent;};
+struct GPMObject {
+  GObject parent;
+};
+
 /** The dbus GPM GObject class type
  */
-struct GPMObjectClass {GObjectClass parent;};
+struct GPMObjectClass {
+  GObjectClass parent;
+};
 
 gboolean gpm_object_register (DBusGConnection *connection);
 gboolean gpm_emit_about_to_happen (const gint value);
@@ -60,6 +61,8 @@ gboolean gpm_emit_mains_changed (const g
 gboolean gpm_object_is_on_battery (GPMObject *obj, gboolean *ret, GError **error);
 gboolean gpm_object_is_on_ups (GPMObject *obj, gboolean *ret, GError **error);
 gboolean gpm_object_is_on_ac (GPMObject *obj, gboolean *ret, GError **error);
+
+G_END_DECLS
 
 #endif	/* _GPMDBUSSERVER_H */
 /** @} */
Index: src/gpm-hal-callback.c
===================================================================
RCS file: /cvs/gnome/gnome-power-manager/src/gpm-hal-callback.c,v
retrieving revision 1.2
diff -p -u -r1.2 gpm-hal-callback.c
--- src/gpm-hal-callback.c	27 Dec 2005 20:18:54 -0000	1.2
+++ src/gpm-hal-callback.c	7 Jan 2006 00:06:01 -0000
@@ -45,6 +45,7 @@
 HalFunctions function;
 HalRegistered reg;
 HalConnections proxy;
+gpointer cb_user_data;
 
 /** PropertyModified signal handler
  *
@@ -78,7 +79,7 @@ signal_handler_PropertyModified (DBusGPr
 		key = g_value_get_string (g_value_array_get_nth (array, 0));
 		removed = g_value_get_boolean (g_value_array_get_nth (array, 1));
 		added = g_value_get_boolean (g_value_array_get_nth (array, 2));
-		function.device_property_modified (udi, key, removed, added);
+		function.device_property_modified (udi, key, removed, added, cb_user_data);
 	}
 }
 
@@ -95,7 +96,7 @@ signal_handler_DeviceRemoved (DBusGProxy
 		return;
 	}
 	g_debug ("gpm_hal: device removed '%s'", udi);
-	function.device_removed (udi);
+	function.device_removed (udi, cb_user_data);
 }
 
 /** NewCapability signal handler
@@ -112,7 +113,7 @@ signal_handler_NewCapability (DBusGProxy
 		return;
 	}
 	g_debug ("gpm_hal: new capability '%s'", udi);
-	function.device_new_capability (udi, capability);
+	function.device_new_capability (udi, capability, cb_user_data);
 }
 
 /** Condition signal handler
@@ -131,7 +132,7 @@ signal_handler_Condition (DBusGProxy *pr
 	}
 	udi = dbus_g_proxy_get_path (proxy);
 	g_debug ("gpm_hal: condition '%s'", udi);
-	function.device_condition (udi, name, details);
+	function.device_condition (udi, name, details, cb_user_data);
 }
 
 /** Removed watch removal 
@@ -489,7 +490,7 @@ gpm_hal_method_device_condition (HalDevi
  *  @return			If we initialised callbacks okay
  */
 gboolean
-gpm_hal_callback_init (void)
+gpm_hal_callback_init (gpointer data)
 {
 	g_debug ("gpm_hal_callback: init");
 	function.device_added = NULL;
@@ -513,6 +514,8 @@ gpm_hal_callback_init (void)
 	/* array types */
 	proxy.device_condition = g_ptr_array_new ();
 	proxy.device_property_modified = g_ptr_array_new ();
+
+        cb_user_data = data;
 
 	return TRUE;
 }
Index: src/gpm-hal-callback.h
===================================================================
RCS file: /cvs/gnome/gnome-power-manager/src/gpm-hal-callback.h,v
retrieving revision 1.1
diff -p -u -r1.1 gpm-hal-callback.h
--- src/gpm-hal-callback.h	23 Dec 2005 23:45:15 -0000	1.1
+++ src/gpm-hal-callback.h	7 Jan 2006 00:06:01 -0000
@@ -31,12 +31,12 @@
 
 #include <dbus/dbus-glib.h>
 
-typedef void (*HalDeviceAdded) (const gchar *udi);
-typedef void (*HalDeviceRemoved) (const gchar *udi);
-typedef void (*HalDeviceNewCapability) (const gchar *udi, const gchar *capability);
-typedef void (*HalDeviceLostCapability) (const gchar *udi, const gchar *capability);
-typedef void (*HalDevicePropertyModified) (const gchar *udi, const gchar *key, gboolean removed, gboolean added);
-typedef void (*HalDeviceCondition) (const gchar *udi, const gchar *name, const gchar *detail);
+typedef void (*HalDeviceAdded) (const gchar *udi, gpointer user_data);
+typedef void (*HalDeviceRemoved) (const gchar *udi, gpointer user_data);
+typedef void (*HalDeviceNewCapability) (const gchar *udi, const gchar *capability, gpointer user_data);
+typedef void (*HalDeviceLostCapability) (const gchar *udi, const gchar *capability, gpointer user_data);
+typedef void (*HalDevicePropertyModified) (const gchar *udi, const gchar *key, gboolean removed, gboolean added, gpointer user_data);
+typedef void (*HalDeviceCondition) (const gchar *udi, const gchar *name, const gchar *detail, gpointer user_data);
 
 typedef void (*HalNameOwnerChanged) (const gchar *name, gboolean connected);
 
@@ -75,7 +75,7 @@ typedef struct {
 	DBusGProxy			*proxy;
 } UdiProxy;
 
-gboolean gpm_hal_callback_init (void);
+gboolean gpm_hal_callback_init (gpointer user_data);
 gboolean gpm_hal_callback_shutdown (void);
 
 gboolean gpm_hal_method_device_removed (HalDeviceRemoved callback);
Index: src/gpm-hal.h
===================================================================
RCS file: /cvs/gnome/gnome-power-manager/src/gpm-hal.h,v
retrieving revision 1.5
diff -p -u -r1.5 gpm-hal.h
--- src/gpm-hal.h	24 Dec 2005 18:00:30 -0000	1.5
+++ src/gpm-hal.h	7 Jan 2006 00:06:01 -0000
@@ -29,6 +29,10 @@
 #ifndef _GPMHAL_H
 #define _GPMHAL_H
 
+#include <glib.h>
+
+G_BEGIN_DECLS
+
 gboolean gpm_hal_has_power_management (void);
 
 gboolean gpm_hal_is_running (void);
@@ -57,6 +61,8 @@ gboolean gpm_hal_find_device_capability 
 gint gpm_hal_num_devices_of_capability (const gchar *capability);
 gint gpm_hal_num_devices_of_capability_with_value (const gchar *capability, const gchar *key, const gchar *value);
 void gpm_hal_free_capability (gchar **value);
+
+G_END_DECLS
 
 #endif	/* _GPMHAL_H */
 /** @} */
Index: src/gpm-idle.c
===================================================================
RCS file: /cvs/gnome/gnome-power-manager/src/gpm-idle.c,v
retrieving revision 1.17
diff -p -u -r1.17 gpm-idle.c
--- src/gpm-idle.c	21 Dec 2005 21:54:00 -0000	1.17
+++ src/gpm-idle.c	7 Jan 2006 00:06:01 -0000
@@ -1,23 +1,11 @@
-/** @file	gpm-idle.c
- *  @brief	Idle calculation routines
- *  @author	Richard Hughes <richard@hughsie.com>
- *  @date	2005-10-02
- *
- * This module handles all the idle and load checking for g-p-m. It
- * uses the functionality of gnome-screensaver, and it's own load
- * calculator to call a user specified callback on user idle.
- *
- *  @note	gpm_idle_set_callback (x) and gpm_idle_set_timeout (x)
- *		must be called before a g_timeout is added to the main loop.
- *    		e.g. g_timeout_add (POLL_FREQ * 1000, gpm_idle_update, NULL);
- */
-/*
- * Licensed under the GNU General Public License Version 2
+/* -*- 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 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
@@ -26,34 +14,477 @@
  *
  * 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., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-/**
- * @addtogroup	idle		Idle checking for CPU load
- * @brief			Uses the functionality of gnome-screensaver
- *				and custom (quick) checking routines.
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ *          William Jon McCann <mccann@jhu.edu>
+ *          Richard Hughes <richard@hughsie.com>
  *
- * @{
  */
 
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
+#include "config.h"
 
+#include <stdlib.h>
 #include <stdio.h>
+#include <time.h>
+#include <errno.h>
+
+#include <string.h>
 #include <sys/time.h>
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
 
 #include <glib.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include "gpm-dbus-common.h"
+
 #include "gpm-idle.h"
-#include "gpm-screensaver.h"
 
-/* global in this file */
-cpudata		old;
-gboolean	init;
-double		loadpercentage;
-gint		time_idle_callback = 0;
-IdleCallback	callbackfunction;
+static void     gpm_idle_class_init (GpmIdleClass *klass);
+static void     gpm_idle_init       (GpmIdle      *idle);
+static void     gpm_idle_finalize   (GObject      *object);
+
+static gdouble  cpu_update_data     (GpmIdle      *idle);
+
+#define GPM_IDLE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GPM_TYPE_IDLE, GpmIdlePrivate))
+
+/*  How many seconds between polling? */
+#define POLL_FREQUENCY	5
+
+/*
+ * Sets the idle percent limit, i.e. how hard the computer can work 
+ * while considered "at idle"
+ */
+#define IDLE_LIMIT	5
+
+/* The cached cpu statistics used to work out the difference */
+typedef struct {
+	long unsigned user;	/**< The CPU user time			*/
+	long unsigned nice;	/**< The CPU nice time			*/
+	long unsigned system;	/**< The CPU system time		*/
+	long unsigned idle;	/**< The CPU idle time			*/
+	long unsigned total;	/**< The CPU total time (uptime)	*/
+} cpudata;
+
+struct GpmIdlePrivate
+{
+        DBusGConnection *connection;
+        DBusGProxy      *screensaver_object;
+
+        GpmIdleMode      mode;
+
+        guint            session_timeout;
+        guint            system_timeout;
+
+        guint            session_timer_id;
+        guint            system_timer_id;
+
+        guint            system_idle_timer_id;
+
+        gboolean         init;
+        cpudata	         cpu_old;
+};
+
+enum {
+        CHANGED,
+        LAST_SIGNAL
+};
+
+enum {
+        PROP_0,
+        PROP_MODE,
+        PROP_SESSION_TIMEOUT,
+        PROP_SYSTEM_TIMEOUT
+};
+
+#define GS_DBUS_SERVICE   "org.gnome.screensaver"
+#define GS_DBUS_PATH      "/org/gnome/screensaver"
+#define GS_DBUS_INTERFACE "org.gnome.screensaver"
+
+static GObjectClass *parent_class = NULL;
+static guint         signals [LAST_SIGNAL] = { 0, };
+
+G_DEFINE_TYPE (GpmIdle, gpm_idle, G_TYPE_OBJECT)
+
+static gboolean
+poll_system_timer (GpmIdle *idle)
+{
+	gdouble load;
+
+	/* get our computed load value */
+	load = cpu_update_data (idle);
+
+	/* check if system is "idle" enough */
+
+        /* FIXME: should this stay below this level for a certain time? */
+        /* FIXME: check that we are on console? */
+
+	if (load < IDLE_LIMIT) {
+                g_debug ("Detected that the CPU is quiet\n");
+
+                gpm_idle_set_mode (idle, GPM_IDLE_MODE_SYSTEM);
+
+                idle->priv->system_idle_timer_id = 0;
+                return FALSE;
+	}
+
+        return TRUE;
+}
+
+static void
+add_poll_system_timer (GpmIdle *idle,
+                       glong    timeout)
+{
+        idle->priv->system_idle_timer_id = g_timeout_add (timeout, (GSourceFunc)poll_system_timer, idle);
+}
+
+static void
+remove_poll_system_timer (GpmIdle *idle)
+{
+        if (idle->priv->system_idle_timer_id != 0) {
+                g_source_remove (idle->priv->system_idle_timer_id);
+                idle->priv->system_idle_timer_id = 0;
+        }
+}
+
+static gboolean
+system_timer (GpmIdle *idle)
+{
+        g_debug ("System idle timeout\n");
+
+        /* instead of doing the state transition directly
+         * we wait until the system is quiet */
+        remove_poll_system_timer (idle);
+        add_poll_system_timer (idle, POLL_FREQUENCY * 1000);
+
+        idle->priv->system_timer_id = 0;
+        return FALSE;
+}
+
+static gboolean
+session_timer (GpmIdle *idle)
+{
+        g_debug ("Session idle timeout\n");
+
+        gpm_idle_set_mode (idle, GPM_IDLE_MODE_SESSION);
+        idle->priv->session_timer_id = 0;
+        return FALSE;
+}
+
+static void
+remove_system_timer (GpmIdle *idle)
+{
+        if (idle->priv->system_timer_id != 0) {
+                g_source_remove (idle->priv->system_timer_id);
+                idle->priv->system_timer_id = 0;
+        }
+}
+
+static void
+remove_session_timer (GpmIdle *idle)
+{
+        if (idle->priv->session_timer_id != 0) {
+                g_source_remove (idle->priv->session_timer_id);
+                idle->priv->session_timer_id = 0;
+        }
+}
+
+static void
+remove_all_timers (GpmIdle *idle)
+{
+        remove_poll_system_timer (idle); 
+        remove_session_timer (idle);
+        remove_system_timer (idle);
+}
+
+static void
+add_system_timer (GpmIdle *idle)
+{
+        guint64 msecs;
+
+        msecs = idle->priv->system_timeout * 60000;
+
+        if (idle->priv->system_timeout > 0) {
+                idle->priv->system_timer_id = g_timeout_add (msecs,
+                                                             (GSourceFunc)system_timer, idle);
+        }
+}
+
+static void
+add_session_timer (GpmIdle *idle)
+{
+        guint64 msecs;
+
+        msecs = idle->priv->session_timeout * 60000;
+
+        if (idle->priv->session_timeout > 0) {
+                idle->priv->session_timer_id = g_timeout_add (msecs,
+                                                              (GSourceFunc)session_timer, idle);
+        }
+}
+
+void
+gpm_idle_set_mode (GpmIdle    *idle,
+                   GpmIdleMode mode)
+{
+        g_return_if_fail (GPM_IS_IDLE (idle));
+
+        if (mode != idle->priv->mode) {
+                idle->priv->mode = mode;
+
+                gpm_idle_reset (idle);
+
+                g_debug ("Doing a state transition: %d\n", mode);
+
+                g_signal_emit (idle,
+                               signals [CHANGED],
+                               0,
+                               mode);
+        }
+}
+
+GpmIdleMode
+gpm_idle_get_mode (GpmIdle *idle)
+{
+        GpmIdleMode mode;
+
+        mode = idle->priv->mode;
+
+        return mode;
+}
+
+void
+gpm_idle_reset (GpmIdle *idle)
+{
+        g_return_if_fail (GPM_IS_IDLE (idle));
+
+        remove_all_timers (idle);
+
+        switch (idle->priv->mode) {
+        case GPM_IDLE_MODE_NORMAL:
+                /* restart session idle timer */
+                add_session_timer (idle);
+
+                break;
+        case GPM_IDLE_MODE_SESSION:
+                /* restart system idle timer */
+                add_system_timer (idle);
+
+                break;
+        case GPM_IDLE_MODE_SYSTEM:
+                /* nothing? */
+                break;
+        default:
+                g_assert_not_reached ();
+                break;
+        }
+}
+
+/* session idle timeout is ignored when using gnome-screensaver */
+void
+gpm_idle_set_session_timeout (GpmIdle    *idle,
+                              guint       timeout)
+{
+        g_return_if_fail (GPM_IS_IDLE (idle));
+
+        g_debug ("Setting session idle timeout: %d\n", timeout);
+
+        if (idle->priv->session_timeout != timeout) {
+                idle->priv->session_timeout = timeout;
+
+                /* restart the timers if necessary */
+                gpm_idle_reset (idle);
+        }
+}
+
+void
+gpm_idle_set_system_timeout (GpmIdle    *idle,
+                             guint       timeout)
+{
+        g_return_if_fail (GPM_IS_IDLE (idle));
+
+        g_debug ("Setting system idle timeout: %d\n", timeout);
+
+        if (idle->priv->system_timeout != timeout) {
+                idle->priv->system_timeout = timeout;
+
+                /* restart the timers if necessary */
+                gpm_idle_reset (idle);
+        }
+}
+
+static void
+gpm_idle_set_property (GObject            *object,
+                       guint               prop_id,
+                       const GValue       *value,
+                       GParamSpec         *pspec)
+{
+        GpmIdle *idle;
+
+        idle = GPM_IDLE (object);
+
+        switch (prop_id) {
+        case PROP_SESSION_TIMEOUT:
+                gpm_idle_set_session_timeout (idle, g_value_get_uint (value));
+                break;
+        case PROP_SYSTEM_TIMEOUT:
+                gpm_idle_set_system_timeout (idle, g_value_get_uint (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gpm_idle_get_property (GObject            *object,
+                       guint               prop_id,
+                       GValue             *value,
+                       GParamSpec         *pspec)
+{
+        GpmIdle *idle;
+
+        idle = GPM_IDLE (object);
+
+        switch (prop_id) {
+        case PROP_SESSION_TIMEOUT:
+                g_value_set_uint (value, idle->priv->session_timeout);
+                break;
+        case PROP_SYSTEM_TIMEOUT:
+                g_value_set_uint (value, idle->priv->system_timeout);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gpm_idle_class_init (GpmIdleClass *klass)
+{
+        GObjectClass   *object_class = G_OBJECT_CLASS (klass);
+
+        parent_class = g_type_class_peek_parent (klass);
+
+        object_class->finalize     = gpm_idle_finalize;
+        object_class->get_property = gpm_idle_get_property;
+        object_class->set_property = gpm_idle_set_property;
+
+        signals [CHANGED] =
+                g_signal_new ("changed",
+                              G_TYPE_FROM_CLASS (object_class),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GpmIdleClass, changed),
+                              NULL,
+                              NULL,
+                              g_cclosure_marshal_VOID__INT,
+                              G_TYPE_NONE,
+                              1, G_TYPE_INT);
+
+        g_object_class_install_property (object_class,
+                                         PROP_MODE,
+                                         g_param_spec_uint ("mode",
+                                                            NULL,
+                                                            NULL,
+                                                            0,
+                                                            G_MAXUINT,
+                                                            GPM_IDLE_MODE_NORMAL,
+                                                            G_PARAM_READWRITE));
+        g_object_class_install_property (object_class,
+                                         PROP_SESSION_TIMEOUT,
+                                         g_param_spec_uint ("session-timeout",
+                                                            NULL,
+                                                            NULL,
+                                                            0,
+                                                            G_MAXUINT,
+                                                            0,
+                                                            G_PARAM_READWRITE));
+        g_object_class_install_property (object_class,
+                                         PROP_SYSTEM_TIMEOUT,
+                                         g_param_spec_uint ("system-timeout",
+                                                            NULL,
+                                                            NULL,
+                                                            0,
+                                                            G_MAXUINT,
+                                                            0,
+                                                            G_PARAM_READWRITE));
+
+        g_type_class_add_private (klass, sizeof (GpmIdlePrivate));
+}
+
+static void
+session_idle_changed_handler (DBusGProxy *proxy,
+                              gboolean    is_idle,
+                              GpmIdle    *idle)
+{
+        GpmIdleMode mode;
+
+        g_debug ("Received GS idle changed: %d\n", is_idle);
+
+        if (is_idle) {
+                mode = GPM_IDLE_MODE_SESSION;
+        } else {
+                mode = GPM_IDLE_MODE_NORMAL;
+        }
+
+        gpm_idle_set_mode (idle, mode);
+}
+
+static void
+gpm_idle_init (GpmIdle *idle)
+{
+        idle->priv = GPM_IDLE_GET_PRIVATE (idle);
+
+	gpm_dbus_get_session_connection (&idle->priv->connection);
+
+        idle->priv->screensaver_object = dbus_g_proxy_new_for_name (idle->priv->connection,
+                                                                    GS_DBUS_SERVICE,
+                                                                    GS_DBUS_PATH,
+                                                                    GS_DBUS_INTERFACE);
+        if (! idle->priv->screensaver_object) {
+                g_warning ("Could not connect to screensaver");
+        } else {
+                dbus_g_proxy_add_signal (idle->priv->screensaver_object,
+                                         "SessionIdleChanged", G_TYPE_BOOLEAN, G_TYPE_INVALID);
+                dbus_g_proxy_connect_signal (idle->priv->screensaver_object,
+                                             "SessionIdleChanged",
+                                             G_CALLBACK (session_idle_changed_handler),
+                                             idle,
+                                             NULL);
+        }
+}
+
+static void
+gpm_idle_finalize (GObject *object)
+{
+        GpmIdle *idle;
+
+        g_return_if_fail (object != NULL);
+        g_return_if_fail (GPM_IS_IDLE (object));
+
+        idle = GPM_IDLE (object);
+
+        g_return_if_fail (idle->priv != NULL);
+
+        remove_all_timers (idle);
+
+        G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+GpmIdle *
+gpm_idle_new (void)
+{
+        GpmIdle *idle;
+
+        idle = g_object_new (GPM_TYPE_IDLE, NULL);
+
+        return GPM_IDLE (idle);
+}
+
 
 /** Gets the raw CPU values from /proc/stat
  *
@@ -161,113 +592,32 @@ cpudata_normalize (cpudata *data)
  *
  *  @return			The CPU load
  */
-static gint
-cpu_update_data (void)
+static gdouble
+cpu_update_data (GpmIdle *idle)
 {
 	cpudata new;
 	cpudata diff;
+        double  loadpercentage;
 
 	/* fill "old" value manually */
-	if (!init) {
-		init = TRUE;
-		cpudata_get_values (&old);
+	if (! idle->priv->init) {
+		idle->priv->init = TRUE;
+		cpudata_get_values (&idle->priv->cpu_old);
 		return 0;
 	}
 
 	/* work out the differences */
 	cpudata_get_values (&new);
-	cpudata_diff (&old, &new, &diff);
+	cpudata_diff (&idle->priv->cpu_old, &new, &diff);
 
 	/* Copy into old */
-	cpudata_copy (&old, &new);
+	cpudata_copy (&idle->priv->cpu_old, &new);
 
 	/* If we divide the total time by idle time we get the load. */
 	if (diff.idle > 0)
 		loadpercentage = (double) diff.total / (double) diff.idle;
 	else
 		loadpercentage = 100;
-	return loadpercentage;
-}
-
-/** Sets the idle timeout
- *
- *  @param	timeout		The idle timeout to set before calling our
- *				assigned Callback function.
- *  @return			If timeout was valid
- */
-gboolean
-gpm_idle_set_timeout (gint timeout)
-{
-	if (timeout <= 0 || timeout > 10 * 60 * 60) {
-		g_warning ("gpm_idle_set_timeout was called with value = %i", timeout);
-		return FALSE;
-	}
-	g_debug ("gpm_idle_set_timeout = %i", timeout);
-	time_idle_callback = timeout;
-	return TRUE;
-}
-
-/** Sets the idle callback
- *
- *  @param	callback	The assigned Callback function.
- *  @return			Success.
- */
-gboolean
-gpm_idle_set_callback (IdleCallback callback)
-{
-	callbackfunction = callback;
-	return TRUE;
-}
-
-/** Find out if we should call out callback.
- *
- *  @param	data		Unused
- *  @return			If we should continue to poll
- *
- *  @note	The load has to be less than IDLE_LIMIT so we do not suspend
- *		or shutdown halfway thru a heavy CPU utility, e.g. disk update, 
- *		rpm transaction, or kernel compile.
- */
-gboolean
-gpm_idle_update (gpointer data)
-{
-	gint gstime = 0;
-	gint load;
-
-	if (!callbackfunction) {
-		g_warning ("gpm_idle_set_callback has not been called so no"
-			   "function set!");
-		/* will stop polling */
-		return FALSE;
-	}
-
-	if (time_idle_callback == 0) {
-		static gboolean has_warned = FALSE;
-		if (!has_warned) {
-			g_debug ("gpm_idle_set_timeout has not been called with "
-				 "a valid timeout so no idle processing done");
-			has_warned = TRUE;
-		}
-		/*
-		 * Will not stop polling, as user could increase value by
-		 * changing g-conf value using g-p-p
-		 */
-		return TRUE;
-	}
 
-	/* get our computed load value */
-	load = cpu_update_data ();
-
-	/* get idle time from g-s */
-	if (!gpm_screensaver_get_idle (&gstime)) {
-		g_warning ("getIdleTime polling disabled");
-		return FALSE; /* will stop polling */
-	}
-	/* check if "idle" enough */
-	if (gstime > time_idle_callback && load < IDLE_LIMIT) {
-		g_debug ("running callback function");
-		callbackfunction (gstime);
-	}
-	return TRUE;
+	return loadpercentage;
 }
-/** @} */
Index: src/gpm-idle.h
===================================================================
RCS file: /cvs/gnome/gnome-power-manager/src/gpm-idle.h,v
retrieving revision 1.5
diff -p -u -r1.5 gpm-idle.h
--- src/gpm-idle.h	17 Oct 2005 12:47:10 -0000	1.5
+++ src/gpm-idle.h	7 Jan 2006 00:06:01 -0000
@@ -1,15 +1,11 @@
-/** @file	gpm-idle.h
- *  @brief	Idle calculation routines
- *  @author	Richard Hughes <richard@hughsie.com>
- *  @date	2005-10-02
- */
-/*
- * Licensed under the GNU General Public License Version 2
+/* -*- 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 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
@@ -18,43 +14,62 @@
  *
  * 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., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-/**
- * @addtogroup	idle
- * @{
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors: William Jon McCann <mccann@jhu.edu>
+ *
  */
 
-#ifndef _GPMIDLE_H
-#define _GPMIDLE_H
+#ifndef __GPM_IDLE_H
+#define __GPM_IDLE_H
 
-/*
- * How many seconds between polling?
- */
-#define POLL_FREQUENCY	5
-/*
- * Sets the idle percent limit, i.e. how hard the computer can work 
- * while considered "at idle"
- */
-#define IDLE_LIMIT	5
+#include <glib-object.h>
 
-/** The cached cpu statistics used to work out the difference
- *
- */
-typedef struct {
-	long unsigned user;	/**< The CPU user time			*/
-	long unsigned nice;	/**< The CPU nice time			*/
-	long unsigned system;	/**< The CPU system time		*/
-	long unsigned idle;	/**< The CPU idle time			*/
-	long unsigned total;	/**< The CPU total time (uptime)	*/
-} cpudata;
-
-typedef void (*IdleCallback) (const gint timeout);
-
-gboolean gpm_idle_set_callback (IdleCallback callback);
-gboolean gpm_idle_update (gpointer data);
-gboolean gpm_idle_set_timeout (gint timeout);
+G_BEGIN_DECLS
+
+#define GPM_TYPE_IDLE          (gpm_idle_get_type ())
+#define GPM_IDLE(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GPM_TYPE_IDLE, GpmIdle))
+#define GPM_IDLE_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), GPM_TYPE_IDLE, GpmIdleClass))
+#define GPM_IS_IDLE(o)         (G_TYPE_CHECK_INSTANCE_TYPE ((o), GPM_TYPE_IDLE))
+#define GPM_IS_IDLE_CLASS(k)   (G_TYPE_CHECK_CLASS_TYPE ((k), GPM_TYPE_IDLE))
+#define GPM_IDLE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GPM_TYPE_IDLE, GpmIdleClass))
+
+typedef enum {
+        GPM_IDLE_MODE_NORMAL,
+        GPM_IDLE_MODE_SESSION,
+        GPM_IDLE_MODE_SYSTEM
+} GpmIdleMode;
+
+typedef struct GpmIdlePrivate GpmIdlePrivate;
+
+typedef struct
+{
+        GObject         parent;
+        GpmIdlePrivate *priv;
+} GpmIdle;
+
+typedef struct
+{
+        GObjectClass      parent_class;
+
+        void              (* changed)        (GpmIdle    *idle,
+                                              GpmIdleMode mode);
+} GpmIdleClass;
+
+GType       gpm_idle_get_type         (void);
+
+GpmIdle   * gpm_idle_new                 (void);
+
+void        gpm_idle_reset               (GpmIdle    *idle);
+GpmIdleMode gpm_idle_get_mode            (GpmIdle    *idle);
+void        gpm_idle_set_mode            (GpmIdle    *idle,
+                                          GpmIdleMode mode);
+
+void        gpm_idle_set_session_timeout (GpmIdle    *idle,
+                                          guint       timeout);
+void        gpm_idle_set_system_timeout  (GpmIdle    *idle,
+                                          guint       timeout);
+
+G_END_DECLS
 
-#endif	/* _GPMIDLE_H */
-/** @} */
+#endif /* __GPM_IDLE_H */
Index: src/gpm-main.c
===================================================================
RCS file: /cvs/gnome/gnome-power-manager/src/gpm-main.c,v
retrieving revision 1.138
diff -p -u -r1.138 gpm-main.c
--- src/gpm-main.c	5 Jan 2006 16:19:58 -0000	1.138
+++ src/gpm-main.c	7 Jan 2006 00:06:01 -0000
@@ -1,3 +1,4 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /** @file	gpm-main.c
  *  @brief	GNOME Power Manager session daemon
  *  @author	Richard Hughes <richard@hughsie.com>
@@ -54,227 +55,34 @@
  *  desktop parts are fairly lightweight and straightforward.
  */
 
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
+#include "config.h"
+
+#include <string.h>
+#include <unistd.h>
+#include <popt.h>
 
 #include <glib.h>
 #include <dbus/dbus-glib.h>
 #include <dbus/dbus-glib-lowlevel.h>
 
-#include <gdk/gdkx.h>
 #include <libgnome/libgnome.h>
+#include <libgnomeui/libgnomeui.h>
 #include <glade/glade.h>
-#include <gconf/gconf-client.h>
-#include <popt.h>
-#include <unistd.h>
 
-#include "gpm-prefs.h"
-#include "gpm-common.h"
-#include "gpm-core.h"
-#include "gpm-main.h"
-#include "gpm-notification.h"
-#include "gpm-idle.h"
-#include "gpm-screensaver.h"
-#include "gpm-networkmanager.h"
-#include "gpm-libnotify.h"
 #include "gpm-dbus-server.h"
 #include "gpm-dbus-common.h"
 #include "gpm-dbus-signal-handler.h"
-#include "gpm-hal.h"
-#include "gpm-hal-callback.h"
 #include "gpm-stock-icons.h"
-#include "gpm-sysdev.h"
+#include "gpm-hal.h"
 
 #include "gnome-power-glue.h"
 
-static void
-gpm_main_log_dummy (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data)
-{
-}
-
-/** Callback for gconf modified keys (that we are watching).
- *
- * @param	client		A valid GConfClient
- * @param	cnxn_id		Unknown
- * @param	entry		The key that was modified
- * @param	user_data	user_data pointer. No function.
- */
-static void
-callback_gconf_key_changed (GConfClient *client,
-	guint cnxn_id,
-	GConfEntry *entry,
-	gpointer user_data)
-{
-	gint value = 0;
-	gboolean on_ac = gpm_hal_is_on_ac ();
-
-	g_debug ("callback_gconf_key_changed (%s)", entry->key);
-
-	if (gconf_entry_get_value (entry) == NULL)
-		return;
-
-	if (strcmp (entry->key, GPM_PREF_ICON_POLICY) == 0) {
-		gpm_notification_icon_update ();
-	} else if (strcmp (entry->key, GPM_PREF_BATTERY_SLEEP_COMPUTER) == 0) {
-		/* set new suspend timeouts */
-		value = gconf_client_get_int (client, entry->key, NULL);
-		if (!on_ac)
-			gpm_idle_set_timeout (value);
-	} else if (strcmp (entry->key, GPM_PREF_AC_SLEEP_COMPUTER) == 0) {
-		/* set new suspend timeouts */
-		value = gconf_client_get_int (client, entry->key, NULL);
-		if (on_ac)
-			gpm_idle_set_timeout (value);
-	} else if (strcmp (entry->key, GPM_PREF_BATTERY_SLEEP_DISPLAY) == 0) {
-		/* set new suspend timeouts */
-		if (!on_ac) {
-			value = gconf_client_get_int (client, entry->key, NULL);
-			gpm_screensaver_set_dpms_timeout (value);
-		}
-	} else if (strcmp (entry->key, GPM_PREF_AC_SLEEP_DISPLAY) == 0) {
-		/* set new suspend timeouts */
-		if (on_ac) {
-			value = gconf_client_get_int (client, entry->key, NULL);
-			gpm_screensaver_set_dpms_timeout (value);
-		}
-	}
-
-}
-
-/** Do all the action when we go from batt to ac, or ac to batt (or coldplug)
- *
- *  @param	on_ac		If we are on AC power
- *
- *  @note
- *	- Sets the brightness level
- *	- Sets HAL to be in LaptopMode if !AC
- *	- Sets DPMS timeout to be our policy value
- *	- Sets GNOME Screensaver to [not] run fancy screensavers
- *	- Sets our inactivity sleep timeout to policy value
- */
-void
-perform_power_policy (gboolean on_ac)
-{
-	gint brightness, sleep_display, sleep_computer;
-	GConfClient *client = gconf_client_get_default ();
-
-	if (on_ac) {
-		brightness = gconf_client_get_int (client, GPM_PREF_AC_BRIGHTNESS, NULL);
-		sleep_display = gconf_client_get_int (client, GPM_PREF_AC_SLEEP_DISPLAY, NULL);
-		sleep_computer = gconf_client_get_int (client, GPM_PREF_AC_SLEEP_COMPUTER, NULL);
-	} else {
-		brightness = gconf_client_get_int (client, GPM_PREF_BATTERY_BRIGHTNESS, NULL);
-		sleep_computer = gconf_client_get_int (client, GPM_PREF_BATTERY_SLEEP_COMPUTER, NULL);
-		sleep_display = gconf_client_get_int (client, GPM_PREF_BATTERY_SLEEP_DISPLAY, NULL);
-	}
-
-	gpm_hal_set_brightness_dim (brightness);
-	gpm_hal_enable_power_save (!on_ac);
-
-	gpm_screensaver_set_dpms_timeout (sleep_display);
-
-	/*
-	 * make sure gnome-screensaver disables screensaving,
-	 * and enables monitor shut-off instead when on batteries
-	 */
-	gpm_screensaver_enable_throttle (!on_ac);
-
-	/* set the new sleep (inactivity) value */
-	gpm_idle_set_timeout (sleep_computer);
-}
-
-/** Do a hibernate with all the associated callbacks and methods.
- *
- *  @note
- *	- Locks the screen (if required)
- *	- Sets NetworkManager to sleep
- *	- Does the hibernate...
- *	- Sets NetworkManager to wake
- *	- Pokes g-s so we get the unlock screen (if required)
- */
-static void
-gpm_hibernate (void)
-{
-	gboolean should_lock = gpm_screensaver_lock_enabled ();
-
-	if (!gpm_hal_can_hibernate ()) {
-		g_warning ("Cannot hibernate as disabled in HAL");
-		return;
-	}
-
-	if (should_lock)
-		gpm_screensaver_lock ();
-
-	gpm_networkmanager_sleep ();
-	gpm_hal_hibernate ();
-	gpm_networkmanager_wake ();
-
-	/* Poke GNOME ScreenSaver so the dialogue is displayed */
-	if (should_lock)
-		gpm_screensaver_poke ();
-}
+#include "gpm-manager.h"
+#include "gpm-main.h"
 
-/** Do a suspend with all the associated callbacks and methods.
- *
- *  @note
- *	- Locks the screen (if required)
- *	- Sets NetworkManager to sleep
- *	- Does the suspend...
- *	- Sets NetworkManager to wake
- *	- Pokes g-s so we get the unlock screen (if required)
- */
 static void
-gpm_suspend (void)
-{
-	gboolean should_lock = gpm_screensaver_lock_enabled ();
-
-	if (!gpm_hal_can_suspend ()) {
-		g_warning ("Cannot suspend as disabled in HAL");
-		return;
-	}
-
-	if (should_lock)
-		gpm_screensaver_lock ();
-
-	gpm_networkmanager_sleep ();
-	gpm_hal_suspend (0);
-	gpm_networkmanager_wake ();
-
-	/* Poke GNOME ScreenSaver so the dialogue is displayed */
-	if (should_lock)
-		gpm_screensaver_poke ();
-}
-
-/** Do the action dictated by policy from gconf
- *
- *  @param	action	string
- *
- *  @todo	Add the actions to doxygen.
- */
-void
-action_policy_do (gchar* action)
+gpm_main_log_dummy (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data)
 {
-	if (!action)
-		return;
-
-	if (strcmp (action, ACTION_NOTHING) == 0) {
-		g_debug ("*ACTION* Doing nothing");
-	} else if (strcmp (action, ACTION_SUSPEND) == 0) {
-		g_debug ("*ACTION* Suspend");
-		gpm_suspend ();
-	} else if (strcmp (action, ACTION_HIBERNATE) == 0) {
-		g_debug ("*ACTION* Hibernate");
-		gpm_hibernate ();
-	} else if (strcmp (action, ACTION_SHUTDOWN) == 0) {
-		g_debug ("*ACTION* Shutdown");
-		/* Save current session */
-		gnome_client_request_save (gnome_master_client (), GNOME_SAVE_GLOBAL,
-					   FALSE, GNOME_INTERACT_NONE, FALSE,  TRUE);
-		gpm_hal_shutdown ();
-	} else {
-		g_warning ("action_policy_do called with unknown action %s", action);
-	}
 }
 
 /** Generic exit
@@ -284,354 +92,14 @@ static void
 gpm_exit (void)
 {
 	g_debug ("Quitting!");
-	gpm_hal_callback_shutdown ();
+
 	gpm_stock_icons_shutdown ();
 	gpm_dbus_remove_noc ();
 	gpm_dbus_remove_nlost ();
 
-	/* cleanup all system devices */
-	gpm_sysdev_free_all ();
-
-	gpm_notification_icon_destroy ();
 	exit (0);
 }
 
-/** When we have a device removed
- *
- *  @param	udi		The HAL UDI
- */
-static void
-hal_device_removed (const gchar *udi)
-{
-	if (gpm_device_removed (udi))
-		gpm_notification_icon_update ();
-}
-
-/** When we have a new device hot-plugged
- *
- *  @param	udi		UDI
- *  @param	capability	Name of capability
- */
-static void
-hal_device_new_capability (const gchar *udi, const gchar *capability)
-{
-	if (gpm_device_new_capability (udi, capability))
-		gpm_notification_icon_update ();
-}
-
-/** Notifies user of a low battery
- *
- *  @param	sds		Data structure
- *  @param	new_charge	New charge value (%)
- *  @return			If a warning was sent
- */
-static gboolean
-notify_user_low_batt (sysDevStruct *sds, gint new_charge)
-{
-	GConfClient *client;
-	gint low_threshold;
-	gint critical_threshold;
-	gchar *message;
-	gchar *remaining;
-	gchar *action;
-
-	if (!sds->is_discharging) {
-		g_debug ("battery is not discharging!");
-		return FALSE;
-	}
-
-	client = gconf_client_get_default ();
-	low_threshold = gconf_client_get_int (client, GPM_PREF_THRESHOLD_LOW, NULL);
-	critical_threshold = gconf_client_get_int (client, GPM_PREF_THRESHOLD_CRITICAL, NULL);
-	g_debug ("low_threshold = %i, critical_threshold = %i",
-		 low_threshold, critical_threshold);
-
-	/* less than critical, do action */
-	if (new_charge < critical_threshold) {
-		g_debug ("battery is below critical limit!");
-		action = gconf_client_get_string (client, GPM_PREF_BATTERY_CRITICAL, NULL);
-		action_policy_do (action);
-		g_free (action);
-		return TRUE;
-	}
-
-	/* critical warning */
-	if (new_charge == critical_threshold) {
-		g_debug ("battery is critical limit!");
-		remaining = get_timestring_from_minutes (sds->minutes_remaining);
-		message = g_strdup_printf (_("You have approximately <b>%s</b> "
-					   "of remaining battery life (%i%%). "
-			  		   "Plug in your AC Adapter to avoid losing data."),
-					   remaining, new_charge);
-		gpm_libnotify_event (_("Battery Critically Low"),
-				     message,
-				     LIBNOTIFY_URGENCY_CRITICAL,
-				     gpm_notification_get_icon ());
-		g_free (message);
-		g_free (remaining);
-		return TRUE;
-	}
-
-	/* low warning */
-	if (new_charge < low_threshold) {
-		g_debug ("battery is low!");
-		remaining = get_timestring_from_minutes (sds->minutes_remaining);
-		g_assert (remaining);
-		message = g_strdup_printf (
-			_("You have approximately <b>%s</b> of remaining battery life (%i%%). "
-			  "Plug in your AC Adapter to avoid losing data."),
-			remaining, new_charge);
-		gpm_libnotify_event (_("Battery Low"),
-				     message,
-				     LIBNOTIFY_URGENCY_CRITICAL,
-				     gpm_notification_get_icon ());
-		g_free (message);
-		g_free (remaining);
-		return TRUE;
-	}
-	return FALSE;
-}
-
-/** Invoked when a property of a device in the Global Device List is
- *  changed, and we have we have subscribed to changes for that device.
- *
- *  @param	udi		The HAL UDI
- *  @param	key		Property key
- *  @param	is_added	If the key was added
- *  @param	is_removed	If the key was removed
- */
-static void
-hal_device_property_modified (const gchar *udi,
-	const gchar *key,
-	gboolean is_added,
-	gboolean is_removed)
-{
-	sysDev *sd = NULL;
-	sysDevStruct *sds = NULL;
-	gchar *type;
-
-	gint old_charge;
-	gint new_charge;
-
-	g_debug ("hal_device_property_modified: udi=%s, key=%s, added=%i, removed=%i",
-		udi, key, is_added, is_removed);
-
-	/* only process modified entries, not added or removed keys */
-	if (is_removed||is_added)
-		return;
-
-	if (strcmp (key, "ac_adapter.present") == 0) {
-		if (!gpm_hal_is_on_ac ()) {
-			gboolean show_notify;
-			show_notify = gconf_client_get_bool (gconf_client_get_default (),
-							     GPM_PREF_NOTIFY_ACADAPTER, NULL);
-			if (show_notify) {
-				gpm_libnotify_event (_("AC Power Unplugged"),
-						     _("The AC Power has been unplugged. "
-						     "The system is now using battery power."),
-						     LIBNOTIFY_URGENCY_NORMAL,
-						     gpm_notification_get_icon ());
-			}
-			perform_power_policy (FALSE);
-			gpm_emit_mains_changed (FALSE);
-
-		} else {
-			/*
-			 * for where we add back the ac_adapter before
-			 * the "AC Power unplugged" message times out.
-			 */
-			gpm_libnotify_clear ();
-			/* do all our powersaving stuff */
-			perform_power_policy (TRUE);
-			gpm_emit_mains_changed (TRUE);
-		}
-		/* update all states */
-		gpm_sysdev_update_all ();
-		/* update icon */
-		gpm_notification_icon_update ();
-		return;
-	}
-
-	/* no point continuing any further if we are never going to match ...*/
-	if (strncmp (key, "battery", 7) != 0)
-		return;
-
-	sds = gpm_sysdev_find_all (udi);
-	/*
-	 * if we BUG here then *HAL* has a problem where key modification is
-	 * done before capability is present
-	 */
-	if (!sds) {
-		g_warning ("sds is NULL! udi=%s\n"
-			   "This is probably a bug in HAL where we are getting "
-			   "is_removed=false, is_added=false before the capability "
-			   "had been added. In addon-hid-ups this is likely to happen.",
-			   udi);
-		return;
-	}
-
-	/* get battery type so we know what to process */
-	gpm_hal_device_get_string (udi, "battery.type", &type);
-	if (!type) {
-		g_warning ("Battery %s has no type!", udi);
-		return;
-	}
-	DeviceType dev = hal_to_device_type (type);
-	g_free (type);
-
-	/* find old percentage_charge */
-	sd = gpm_sysdev_get (dev);
-	old_charge = sd->percentage_charge;
-
-	/* update values in the struct */
-	if (strcmp (key, "battery.present") == 0) {
-		gpm_hal_device_get_bool (udi, key, &sds->is_present);
-		/* read in values */
-		gpm_read_battery_data (sds);
-		/* update icon if required */
-		gpm_notification_icon_update ();
-	} else if (strcmp (key, "battery.rechargeable.is_charging") == 0) {
-		gpm_hal_device_get_bool (udi, key, &sds->is_charging);
-		/*
-		 * invalidate the remaining time, as we need to wait for
-		 * the next HAL update. This is a HAL bug I think.
-		 */
-		sds->minutes_remaining = 0;
-	} else if (strcmp (key, "battery.rechargeable.is_discharging") == 0) {
-		gpm_hal_device_get_bool (udi, key, &sds->is_discharging);
-		/* invalidate the remaining time */
-		sds->minutes_remaining = 0;
-	} else if (strcmp (key, "battery.charge_level.percentage") == 0) {
-		gpm_hal_device_get_int (udi, key, &sds->percentage_charge);
-		/* give notification @100% */
-		if (sd->type == BATT_PRIMARY && sds->percentage_charge == 100) {
-			gboolean show_notify;
-			show_notify = gconf_client_get_bool (gconf_client_get_default (),
-							     GPM_PREF_NOTIFY_BATTCHARGED, NULL);
-			if (show_notify)
-				gpm_libnotify_event (_("Battery Charged"),
-						     _("Your battery is now fully charged"),
-						     LIBNOTIFY_URGENCY_LOW,
-					             gpm_notification_get_icon ());
-		}
-	} else if (strcmp (key, "battery.remaining_time") == 0) {
-		gint tempval;
-		gpm_hal_device_get_int (udi, key, &tempval);
-		if (tempval > 0)
-			sds->minutes_remaining = tempval / 60;
-	} else {
-		/* ignore */
-		return;
-	}
-
-	gpm_sysdev_update (dev);
-	gpm_sysdev_debug_print (dev);
-
-	/* find new percentage_charge  */
-	new_charge = sd->percentage_charge;
-
-	g_debug ("new_charge = %i, old_charge = %i", new_charge, old_charge);
-
-	gpm_notification_icon_update ();
-
-	/* do we need to notify the user we are getting low ? */
-	if (old_charge != new_charge) {
-		g_debug ("percentage change %i -> %i", old_charge, new_charge);
-		notify_user_low_batt (sds, new_charge);
-	}
-}
-
-/** Invoked when a property of a device in the Global Device List is
- *  changed, and we have we have subscribed to changes for that device.
- *
- *  @param	udi			Univerisal Device Id
- *  @param	name		Name of condition
- *  @param	details	D-BUS message with parameters
- */
-static void
-hal_device_condition (const gchar *udi, const gchar *name, const gchar *details)
-{
-	gchar *type = NULL;
-	gchar* action;
-	gboolean value;
-	GConfClient *client = gconf_client_get_default ();
-
-	g_assert (udi);
-	g_assert (name);
-	g_assert (details);
-
-	g_debug ("hal_device_condition: udi=%s, name=%s, details=%s",
-		 udi, name, details);
-
-	if (strcmp (name, "ButtonPressed") == 0) {
-		gpm_hal_device_get_string (udi, "button.type", &type);
-		if (!type) {
-			g_warning ("You must have a button type for %s!", udi);
-			return;
-		}
-		g_debug ("ButtonPressed : %s", type);
-		if (strcmp (type, "power") == 0) {
-			/* Log out interactively */
-			gnome_client_request_save (gnome_master_client (), GNOME_SAVE_GLOBAL,
-						   TRUE, GNOME_INTERACT_ANY, FALSE,  TRUE);
-		} else if (strcmp (type, "sleep") == 0) {
-			action = gconf_client_get_string (client, GPM_PREF_BUTTON_SUSPEND, NULL);
-			action_policy_do (action);
-			g_free (action);
-		} else if (strcmp (type, "lid") == 0) {
-			gpm_hal_device_get_bool (udi, "button.state.value", &value);
-			/*
-			 * We enable/disable DPMS because some laptops do
-			 * not turn off the LCD backlight when the lid
-			 * is closed. See
-			 * http://bugzilla.gnome.org/show_bug.cgi?id=321313
-			 */
-			if (value) {
-				/* we only do a policy event when the lid is CLOSED */
-				action = gconf_client_get_string (client, GPM_PREF_BUTTON_LID, NULL);
-				action_policy_do (action);
-				g_free (action);
-				gpm_screensaver_enable_dpms (FALSE);
-			} else {
-				gpm_screensaver_enable_dpms (TRUE);
-			}
-		} else if (strcmp (type, "virtual") == 0) {
-			if (!details) {
-				g_warning ("Virtual buttons must have details for %s!", udi);
-				return;
-			}
-			if (strcmp (details, "BrightnessUp") == 0)
-				gpm_hal_set_brightness_up ();
-			else if (strcmp (details, "BrightnessDown") == 0)
-				gpm_hal_set_brightness_down ();
-			else if (strcmp (details, "Suspend") == 0)
-				action_policy_do (ACTION_SUSPEND);
-			else if (strcmp (details, "Hibernate") == 0)
-				action_policy_do (ACTION_HIBERNATE);
-			else if (strcmp (details, "Lock") == 0)
-				gpm_screensaver_lock ();
-		} else {
-			g_warning ("Button '%s' unrecognised", type);
-		}
-		g_free (type);
-	}
-}
-
-/** Callback for the idle function.
- *
- *  @param	timeout		Time in minutes that computer has been idle
- */
-void
-gpm_idle_callback (gint timeout)
-{
-	gchar *action;
-	action = gconf_client_get_string (gconf_client_get_default (), GPM_PREF_BATTERY_CRITICAL, NULL); /* @todo! */
-
-	/* can only be hibernate or suspend */
-	action_policy_do (action);
-	g_free (action);
-}
-
 /** Callback for the DBUS NameOwnerChanged function.
  *
  *  @param	name		The DBUS name, e.g. org.freedesktop.Hal
@@ -685,13 +153,13 @@ main (int argc, char *argv[])
 {
 	gint i;
 	GMainLoop *loop;
-	GConfClient *client;
 	GnomeClient *master;
 	GnomeClientFlags flags;
 	DBusGConnection *system_connection;
 	DBusGConnection *session_connection;
 	gboolean verbose = FALSE;
 	gboolean no_daemon;
+	GpmManager *manager;
 
 	struct poptOption options[] = {
 		{ "no-daemon", '\0', POPT_ARG_NONE, NULL, 0,
@@ -732,10 +200,6 @@ main (int argc, char *argv[])
 		g_thread_init (NULL);
 	dbus_g_thread_init ();
 
-	client = gconf_client_get_default ();
-	gconf_client_add_dir (client, GPM_PREF_DIR, GCONF_CLIENT_PRELOAD_NONE, NULL);
-	gconf_client_notify_add (client, GPM_PREF_DIR, callback_gconf_key_changed, NULL, NULL, NULL);
-
 	bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
 	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
 	textdomain (GETTEXT_PACKAGE);
@@ -746,15 +210,9 @@ main (int argc, char *argv[])
 	if (!gpm_dbus_get_session_connection (&session_connection))
 		g_error ("Unable to get session dbus connection");
 
-	if (!gpm_libnotify_init (NICENAME))
-		g_error ("Cannot initialise libnotify!");
-
 	if (!gpm_stock_icons_init())
 		g_error ("Cannot continue without stock icons");
 
-	/* initialise all system devices */
-	gpm_sysdev_init_all ();
-
 	if (!no_daemon && daemon (0, 0))
 		g_error ("Could not daemonize: %s", g_strerror (errno));
 
@@ -779,44 +237,15 @@ main (int argc, char *argv[])
 	gpm_dbus_init_nlost (system_connection, signalhandler_nlost);
 
 	loop = g_main_loop_new (NULL, FALSE);
-	if (!gpm_hal_is_running ()) {
-		g_critical ("GNOME Power Manager cannot connect to HAL!");
-		return 0;
-	}
-
-	if (!gpm_hal_has_power_management ()) {
-		g_warning ("HAL does not have modern PowerManagement capability");
-		return 0;
-	}
-
-	gpm_hal_callback_init ();
-	/* assign the callback functions */
-	gpm_hal_method_device_removed (hal_device_removed);
-	gpm_hal_method_device_new_capability (hal_device_new_capability);
-	gpm_hal_method_device_property_modified (hal_device_property_modified);
-	gpm_hal_method_device_condition (hal_device_condition);
-
-	/* sets up these devices and adds watches */
-	gpm_coldplug_batteries ();
-	gpm_coldplug_acadapter ();
-	gpm_coldplug_buttons ();
-
-	gpm_sysdev_update_all ();
-	gpm_sysdev_debug_print_all ();
-
-	gpm_notification_icon_update ();
 
-	/* do all the actions as we have to set initial state */
-	perform_power_policy (gpm_hal_is_on_ac ());
-
-	gpm_idle_set_callback (gpm_idle_callback);
-
-	/* set up idle calculation function */
-	g_timeout_add (POLL_FREQUENCY * 1000, gpm_idle_update, NULL);
+	manager = gpm_manager_new ();
 
 	g_main_loop_run (loop);
 
+	g_object_unref (manager);
+
 	gpm_exit ();
+
 	return 0;
 }
 /** @} */
Index: src/gpm-marshal.list
===================================================================
RCS file: /cvs/gnome/gnome-power-manager/src/gpm-marshal.list,v
retrieving revision 1.1
diff -p -u -r1.1 gpm-marshal.list
--- src/gpm-marshal.list	27 Dec 2005 20:18:54 -0000	1.1
+++ src/gpm-marshal.list	7 Jan 2006 00:06:01 -0000
@@ -1,3 +1,4 @@
 NONE:INT,BOXED
 NONE:STRING,STRING
 NONE:STRING
+NONE:INT,LONG,BOOLEAN,BOOLEAN
Index: src/gpm-notification.c
===================================================================
RCS file: /cvs/gnome/gnome-power-manager/src/gpm-notification.c,v
retrieving revision 1.84
diff -p -u -r1.84 gpm-notification.c
--- src/gpm-notification.c	3 Jan 2006 18:27:47 -0000	1.84
+++ src/gpm-notification.c	7 Jan 2006 00:06:01 -0000
@@ -1,3 +1,4 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
 /** @file	gpm-notification.c
  *  @brief	GNOME Power Notification
  *  @author	Richard Hughes <richard@hughsie.com>
@@ -410,9 +411,15 @@ callback_actions_activated (GtkMenuItem 
 
 	g_debug ("action = '%s'", action);
 	if (strcmp (action, "suspend") == 0) {
-		action_policy_do (ACTION_SUSPEND);
+
+                /* FIXME: Emit a signal instead */
+		/* action_policy_do (ACTION_SUSPEND); */
+
 	} else if (strcmp (action, "hibernate") == 0) {
-		action_policy_do (ACTION_HIBERNATE);
+
+                /* FIXME: Emit a signal instead */
+		/*action_policy_do (ACTION_HIBERNATE);*/
+
 	} else if (strcmp (action, "about") == 0) {
 		callback_about_activated ();
 	} else if (strcmp (action, "preferences") == 0) {
Index: src/gpm-notification.h
===================================================================
RCS file: /cvs/gnome/gnome-power-manager/src/gpm-notification.h,v
retrieving revision 1.18
diff -p -u -r1.18 gpm-notification.h
--- src/gpm-notification.h	24 Dec 2005 18:00:30 -0000	1.18
+++ src/gpm-notification.h	7 Jan 2006 00:06:01 -0000
@@ -25,9 +25,15 @@
 #ifndef _GPM_NOTIFICATION_H
 #define _GPM_NOTIFICATION_H
 
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
 GtkWidget *gpm_notification_get_icon (void);
 
 void gpm_notification_icon_destroy (void);
 void gpm_notification_icon_update (void);
+
+G_END_DECLS
 
 #endif	/* _GPM_NOTIFICATION_H */
Index: src/gpm-screensaver.h
===================================================================
RCS file: /cvs/gnome/gnome-power-manager/src/gpm-screensaver.h,v
retrieving revision 1.13
diff -p -u -r1.13 gpm-screensaver.h
--- src/gpm-screensaver.h	28 Dec 2005 19:58:37 -0000	1.13
+++ src/gpm-screensaver.h	7 Jan 2006 00:06:01 -0000
@@ -29,6 +29,10 @@
 #ifndef _GPM_SCREENSAVER_H
 #define _GPM_SCREENSAVER_H
 
+#include <glib.h>
+
+G_BEGIN_DECLS
+
 #define GS_PREF_DIR		"/apps/gnome-screensaver"
 #define GS_PREF_DPMS_SUSPEND	GS_PREF_DIR "/dpms_suspend"
 #define GS_PREF_DPMS_ENABLED	GS_PREF_DIR "/dpms_enabled"
@@ -43,6 +47,8 @@ gboolean gpm_screensaver_poke (void);
 gboolean gpm_screensaver_get_idle (gint *time);
 gboolean gpm_screensaver_set_dpms_timeout (gint timeout);
 gboolean gpm_screensaver_enable_dpms (gboolean enable);
+
+G_END_DECLS
 
 #endif	/* _GPMSCREENSAVER_H */
 /** @} */
--- /dev/null	2006-01-06 11:54:16.656529500 -0500
+++ src/gpm-hal-monitor.c	2006-01-06 19:02:14.000000000 -0500
@@ -0,0 +1,579 @@
+/* -*- 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>
+ *          Richard Hughes <richard@hughsie.com>
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <errno.h>
+
+#include <string.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#include "gpm-common.h"
+#include "gpm-core.h"
+#include "gpm-prefs.h"
+#include "gpm-hal.h"
+#include "gpm-hal-callback.h"
+#include "gpm-sysdev.h"
+#include "gpm-marshal.h"
+
+#include "gpm-hal-monitor.h"
+
+static void     gpm_hal_monitor_class_init (GpmHalMonitorClass *klass);
+static void     gpm_hal_monitor_init       (GpmHalMonitor      *hal_monitor);
+static void     gpm_hal_monitor_finalize   (GObject      *object);
+
+#define GPM_HAL_MONITOR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GPM_TYPE_HAL_MONITOR, GpmHalMonitorPrivate))
+
+struct GpmHalMonitorPrivate
+{
+        gboolean enabled;
+        gboolean has_power_management;
+
+};
+
+enum {
+        POWER_BUTTON,
+        SUSPEND_BUTTON,
+        LID_BUTTON,
+        HIBERNATE,
+        SUSPEND,
+        LOCK,
+        AC_POWER_CHANGED,
+        BATTERY_POWER_CHANGED,
+        DEVICE_ADDED,
+        DEVICE_REMOVED,
+        LAST_SIGNAL
+};
+
+enum {
+        PROP_0,
+        PROP_MODE
+};
+
+static GObjectClass *parent_class = NULL;
+static guint         signals [LAST_SIGNAL] = { 0, };
+
+G_DEFINE_TYPE (GpmHalMonitor, gpm_hal_monitor, G_TYPE_OBJECT)
+
+static void
+gpm_hal_monitor_set_property (GObject            *object,
+                              guint               prop_id,
+                              const GValue       *value,
+                              GParamSpec         *pspec)
+{
+        switch (prop_id) {
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gpm_hal_monitor_get_property (GObject            *object,
+                              guint               prop_id,
+                              GValue             *value,
+                              GParamSpec         *pspec)
+{
+        switch (prop_id) {
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gpm_hal_monitor_class_init (GpmHalMonitorClass *klass)
+{
+        GObjectClass   *object_class = G_OBJECT_CLASS (klass);
+
+        parent_class = g_type_class_peek_parent (klass);
+
+        object_class->finalize     = gpm_hal_monitor_finalize;
+        object_class->get_property = gpm_hal_monitor_get_property;
+        object_class->set_property = gpm_hal_monitor_set_property;
+
+        g_type_class_add_private (klass, sizeof (GpmHalMonitorPrivate));
+
+        signals [DEVICE_ADDED] =
+                g_signal_new ("device-added",
+                              G_TYPE_FROM_CLASS (object_class),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GpmHalMonitorClass, device_added),
+                              NULL,
+                              NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE,
+                              0);
+        signals [DEVICE_REMOVED] =
+                g_signal_new ("device-removed",
+                              G_TYPE_FROM_CLASS (object_class),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GpmHalMonitorClass, device_removed),
+                              NULL,
+                              NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE,
+                              0);
+        signals [SUSPEND_BUTTON] =
+                g_signal_new ("suspend-button",
+                              G_TYPE_FROM_CLASS (object_class),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GpmHalMonitorClass, suspend_button),
+                              NULL,
+                              NULL,
+                              g_cclosure_marshal_VOID__BOOLEAN,
+                              G_TYPE_NONE,
+                              1, G_TYPE_BOOLEAN);
+        signals [POWER_BUTTON] =
+                g_signal_new ("power-button",
+                              G_TYPE_FROM_CLASS (object_class),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GpmHalMonitorClass, power_button),
+                              NULL,
+                              NULL,
+                              g_cclosure_marshal_VOID__BOOLEAN,
+                              G_TYPE_NONE,
+                              1, G_TYPE_BOOLEAN);
+        signals [LID_BUTTON] =
+                g_signal_new ("lid-button",
+                              G_TYPE_FROM_CLASS (object_class),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GpmHalMonitorClass, lid_button),
+                              NULL,
+                              NULL,
+                              g_cclosure_marshal_VOID__BOOLEAN,
+                              G_TYPE_NONE,
+                              1, G_TYPE_BOOLEAN);
+        signals [HIBERNATE] =
+                g_signal_new ("hibernate",
+                              G_TYPE_FROM_CLASS (object_class),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GpmHalMonitorClass, hibernate),
+                              NULL,
+                              NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE,
+                              0);
+        signals [LOCK] =
+                g_signal_new ("lock",
+                              G_TYPE_FROM_CLASS (object_class),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GpmHalMonitorClass, lock),
+                              NULL,
+                              NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE,
+                              0);
+        signals [SUSPEND] =
+                g_signal_new ("suspend",
+                              G_TYPE_FROM_CLASS (object_class),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GpmHalMonitorClass, suspend),
+                              NULL,
+                              NULL,
+                              g_cclosure_marshal_VOID__VOID,
+                              G_TYPE_NONE,
+                              0);
+        signals [AC_POWER_CHANGED] =
+                g_signal_new ("ac-power-changed",
+                              G_TYPE_FROM_CLASS (object_class),
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GpmHalMonitorClass, ac_power_changed),
+                              NULL,
+                              NULL,
+                              g_cclosure_marshal_VOID__BOOLEAN,
+                              G_TYPE_NONE,
+                              1,
+                              G_TYPE_BOOLEAN);
+	signals [BATTERY_POWER_CHANGED] =
+		g_signal_new ("battery-power-changed",
+			      G_TYPE_FROM_CLASS (object_class),
+			      G_SIGNAL_RUN_LAST,
+			      G_STRUCT_OFFSET (GpmHalMonitorClass, battery_power_changed),
+			      NULL,
+                              NULL,
+			      gpm_marshal_VOID__INT_LONG_BOOLEAN_BOOLEAN,
+			      G_TYPE_NONE, 4, G_TYPE_INT, G_TYPE_LONG, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN);
+
+
+}
+
+
+/** When we have a device removed
+ *
+ *  @param	udi		The HAL UDI
+ */
+static void
+hal_device_removed (const gchar *udi,
+                    gpointer     user_data)
+{
+        GpmHalMonitor *monitor;
+
+        monitor = GPM_HAL_MONITOR (user_data);
+
+	if (gpm_device_removed (udi)) {
+                g_signal_emit (monitor, signals [DEVICE_REMOVED], 0);
+        }
+}
+
+/** When we have a new device hot-plugged
+ *
+ *  @param	udi		UDI
+ *  @param	capability	Name of capability
+ */
+static void
+hal_device_new_capability (const gchar *udi,
+                           const gchar *capability,
+                           gpointer     user_data)
+{
+        GpmHalMonitor *monitor;
+
+        monitor = GPM_HAL_MONITOR (user_data);
+
+	if (gpm_device_new_capability (udi, capability)) {
+                g_signal_emit (monitor, signals [DEVICE_ADDED], 0);
+        }
+}
+
+static void
+monitor_change_on_ac (GpmHalMonitor *monitor,
+                      gboolean       on_ac)
+{
+        g_signal_emit (monitor, signals [AC_POWER_CHANGED], 0, on_ac);
+}
+
+/** Invoked when a property of a device in the Global Device List is
+ *  changed, and we have we have subscribed to changes for that device.
+ *
+ *  @param	udi		The HAL UDI
+ *  @param	key		Property key
+ *  @param	is_added	If the key was added
+ *  @param	is_removed	If the key was removed
+ */
+static void
+hal_device_property_modified (const gchar *udi,
+                              const gchar *key,
+                              gboolean     is_added,
+                              gboolean     is_removed,
+                              gpointer     user_data)
+{
+	sysDev *sd = NULL;
+	sysDevStruct *sds = NULL;
+	gchar *type;
+	gint old_charge;
+	gint new_charge;
+        GpmHalMonitor *monitor;
+        DeviceType dev;
+
+        monitor = GPM_HAL_MONITOR (user_data);
+
+	g_debug ("hal_device_property_modified: udi=%s, key=%s, added=%i, removed=%i",
+                 udi, key, is_added, is_removed);
+
+	/* only process modified entries, not added or removed keys */
+	if (is_removed || is_added)
+		return;
+
+	if (strcmp (key, "ac_adapter.present") == 0) {
+                gboolean on_ac = gpm_hal_is_on_ac ();
+
+                monitor_change_on_ac (monitor, on_ac);
+
+		/* update all states */
+		gpm_sysdev_update_all ();
+
+		return;
+	}
+
+	/* no point continuing any further if we are never going to match ...*/
+	if (strncmp (key, "battery", 7) != 0)
+		return;
+
+	sds = gpm_sysdev_find_all (udi);
+	/*
+	 * if we BUG here then *HAL* has a problem where key modification is
+	 * done before capability is present
+	 */
+	if (!sds) {
+		g_warning ("sds is NULL! udi=%s\n"
+			   "This is probably a bug in HAL where we are getting "
+			   "is_removed=false, is_added=false before the capability "
+			   "had been added. In addon-hid-ups this is likely to happen.",
+			   udi);
+		return;
+	}
+
+	/* get battery type so we know what to process */
+	gpm_hal_device_get_string (udi, "battery.type", &type);
+	if (!type) {
+		g_warning ("Battery %s has no type!", udi);
+		return;
+	}
+
+	dev = hal_to_device_type (type);
+	g_free (type);
+
+	/* find old percentage_charge */
+	sd = gpm_sysdev_get (dev);
+	old_charge = sd->percentage_charge;
+
+	/* update values in the struct */
+	if (strcmp (key, "battery.present") == 0) {
+		gpm_hal_device_get_bool (udi, key, &sds->is_present);
+		/* read in values */
+		gpm_read_battery_data (sds);
+
+	} else if (strcmp (key, "battery.rechargeable.is_charging") == 0) {
+		gpm_hal_device_get_bool (udi, key, &sds->is_charging);
+		/*
+		 * invalidate the remaining time, as we need to wait for
+		 * the next HAL update. This is a HAL bug I think.
+		 */
+		sds->minutes_remaining = 0;
+	} else if (strcmp (key, "battery.rechargeable.is_discharging") == 0) {
+		gpm_hal_device_get_bool (udi, key, &sds->is_discharging);
+		/* invalidate the remaining time */
+		sds->minutes_remaining = 0;
+	} else if (strcmp (key, "battery.charge_level.percentage") == 0) {
+		gpm_hal_device_get_int (udi, key, &sds->percentage_charge);
+
+	} else if (strcmp (key, "battery.remaining_time") == 0) {
+		gint tempval;
+		gpm_hal_device_get_int (udi, key, &tempval);
+		if (tempval > 0)
+			sds->minutes_remaining = tempval / 60;
+	} else {
+		/* ignore */
+		return;
+	}
+
+	gpm_sysdev_update (dev);
+	gpm_sysdev_debug_print (dev);
+
+	/* find new percentage_charge  */
+	new_charge = sd->percentage_charge;
+
+	g_debug ("new_charge = %i, old_charge = %i", new_charge, old_charge);
+
+	/* do we need to notify the user we are getting low ? */
+	if (old_charge != new_charge) {
+                gboolean is_primary;
+
+		g_debug ("percentage change %i -> %i", old_charge, new_charge);
+
+                is_primary = (sd->type == BATT_PRIMARY);
+                g_signal_emit (monitor,
+                               signals [BATTERY_POWER_CHANGED], 0,
+                               sd->percentage_charge,
+                               sds->minutes_remaining,
+                               sds->is_discharging,
+                               is_primary);
+	}
+}
+
+/** Invoked when a property of a device in the Global Device List is
+ *  changed, and we have we have subscribed to changes for that device.
+ *
+ *  @param	udi			Univerisal Device Id
+ *  @param	name		Name of condition
+ *  @param	details	D-BUS message with parameters
+ */
+static void
+hal_device_condition (const gchar *udi,
+                      const gchar *name,
+                      const gchar *details,
+                      gpointer     user_data)
+{
+	gchar   *type = NULL;
+	gboolean value;
+        GpmHalMonitor *monitor;
+
+        monitor = GPM_HAL_MONITOR (user_data);
+
+	g_assert (udi);
+	g_assert (name);
+	g_assert (details);
+
+	g_debug ("hal_device_condition: udi=%s, name=%s, details=%s",
+		 udi, name, details);
+
+	if (strcmp (name, "ButtonPressed") == 0) {
+		gpm_hal_device_get_string (udi, "button.type", &type);
+
+		if (!type) {
+			g_warning ("You must have a button type for %s!", udi);
+			return;
+		}
+
+		g_debug ("ButtonPressed : %s", type);
+		if (strcmp (type, "power") == 0) {
+                        gboolean state = TRUE;
+
+                        g_signal_emit (monitor, signals [POWER_BUTTON], 0, state);
+
+		} else if (strcmp (type, "sleep") == 0) {
+                        gboolean state = TRUE;
+                        g_signal_emit (monitor, signals [SUSPEND_BUTTON], 0, state);
+
+		} else if (strcmp (type, "lid") == 0) {
+			gpm_hal_device_get_bool (udi, "button.state.value", &value);
+
+                        g_signal_emit (monitor, signals [LID_BUTTON], 0, value);
+
+		} else if (strcmp (type, "virtual") == 0) {
+
+			if (!details) {
+				g_warning ("Virtual buttons must have details for %s!", udi);
+				return;
+			}
+
+			if (strcmp (details, "BrightnessUp") == 0) {
+
+				gpm_hal_set_brightness_up ();
+
+                        } else if (strcmp (details, "BrightnessDown") == 0) {
+
+				gpm_hal_set_brightness_down ();
+
+                        } else if (strcmp (details, "Suspend") == 0) {
+
+                                g_signal_emit (monitor, signals [SUSPEND], 0);
+
+                        } else if (strcmp (details, "Hibernate") == 0) {
+
+                                g_signal_emit (monitor, signals [HIBERNATE], 0);
+
+                        } else if (strcmp (details, "Lock") == 0) {
+
+                                g_signal_emit (monitor, signals [LOCK], 0);
+
+                        }
+
+		} else {
+			g_warning ("Button '%s' unrecognised", type);
+		}
+
+		g_free (type);
+	}
+}
+
+static void
+hal_monitor_start (GpmHalMonitor *monitor)
+{
+	/* initialise all system devices */
+	gpm_sysdev_init_all ();
+
+	gpm_hal_callback_init (monitor);
+	/* assign the callback functions */
+	gpm_hal_method_device_removed (hal_device_removed);
+	gpm_hal_method_device_new_capability (hal_device_new_capability);
+	gpm_hal_method_device_property_modified (hal_device_property_modified);
+	gpm_hal_method_device_condition (hal_device_condition);
+
+	/* sets up these devices and adds watches */
+	gpm_coldplug_batteries ();
+	gpm_coldplug_acadapter ();
+	gpm_coldplug_buttons ();
+
+	gpm_sysdev_update_all ();
+	gpm_sysdev_debug_print_all ();
+}
+
+static void
+hal_monitor_stop (GpmHalMonitor *monitor)
+{
+	gpm_hal_callback_shutdown ();
+	/* cleanup all system devices */
+	gpm_sysdev_free_all ();
+}
+
+gboolean
+gpm_hal_monitor_get_on_ac (GpmHalMonitor *monitor)
+{
+        gboolean on_ac;
+
+        g_return_val_if_fail (GS_IS_HAL_MONITOR (monitor), FALSE);
+
+        on_ac = gpm_hal_is_on_ac ();
+
+        return on_ac;
+}
+
+
+static void
+gpm_hal_monitor_init (GpmHalMonitor *monitor)
+{
+        monitor->priv = GPM_HAL_MONITOR_GET_PRIVATE (monitor);
+
+        monitor->priv->enabled = gpm_hal_is_running ();
+
+	if (! monitor->priv->enabled) {
+		g_warning ("GNOME Power Manager cannot connect to HAL!");
+	}
+
+        monitor->priv->has_power_management = gpm_hal_has_power_management ();
+
+	if (! monitor->priv->has_power_management) {
+                g_warning ("HAL does not have modern PowerManagement capability");
+	}
+
+        if (monitor->priv->enabled
+            && monitor->priv->has_power_management) {
+                hal_monitor_start (monitor);
+        }
+}
+
+static void
+gpm_hal_monitor_finalize (GObject *object)
+{
+        GpmHalMonitor *monitor;
+
+        g_return_if_fail (object != NULL);
+        g_return_if_fail (GS_IS_HAL_MONITOR (object));
+
+        monitor = GPM_HAL_MONITOR (object);
+
+        g_return_if_fail (monitor->priv != NULL);
+
+        hal_monitor_stop (monitor);
+
+        G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+GpmHalMonitor *
+gpm_hal_monitor_new (void)
+{
+        GpmHalMonitor *monitor;
+
+        monitor = g_object_new (GPM_TYPE_HAL_MONITOR, NULL);
+
+        return GPM_HAL_MONITOR (monitor);
+}
--- /dev/null	2006-01-06 11:54:16.656529500 -0500
+++ src/gpm-hal-monitor.h	2006-01-06 17:13:06.000000000 -0500
@@ -0,0 +1,81 @@
+/* -*- 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>
+ *
+ */
+
+#ifndef __GPM_HAL_MONITOR_H
+#define __GPM_HAL_MONITOR_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GPM_TYPE_HAL_MONITOR          (gpm_hal_monitor_get_type ())
+#define GPM_HAL_MONITOR(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GPM_TYPE_HAL_MONITOR, GpmHalMonitor))
+#define GPM_HAL_MONITOR_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), GPM_TYPE_HAL_MONITOR, GpmHalMonitorClass))
+#define GS_IS_HAL_MONITOR(o)         (G_TYPE_CHECK_INSTANCE_TYPE ((o), GPM_TYPE_HAL_MONITOR))
+#define GS_IS_HAL_MONITOR_CLASS(k)   (G_TYPE_CHECK_CLASS_TYPE ((k), GPM_TYPE_HAL_MONITOR))
+#define GPM_HAL_MONITOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GPM_TYPE_HAL_MONITOR, GpmHalMonitorClass))
+
+typedef struct GpmHalMonitorPrivate GpmHalMonitorPrivate;
+
+typedef struct
+{
+        GObject               parent;
+        GpmHalMonitorPrivate *priv;
+} GpmHalMonitor;
+
+typedef struct
+{
+        GObjectClass      parent_class;
+
+        void              (* device_added)          (GpmHalMonitor    *monitor);
+        void              (* device_removed)        (GpmHalMonitor    *monitor);
+
+        void              (* power_button)          (GpmHalMonitor    *monitor,
+                                                     gboolean          state);
+        void              (* suspend_button)        (GpmHalMonitor    *monitor,
+                                                     gboolean          state);
+        void              (* lid_button)            (GpmHalMonitor    *monitor,
+                                                     gboolean          state);
+
+        void              (* suspend)               (GpmHalMonitor    *monitor);
+        void              (* hibernate)             (GpmHalMonitor    *monitor);
+        void              (* lock)                  (GpmHalMonitor    *lock);
+        void              (* ac_power_changed)      (GpmHalMonitor    *monitor,
+                                                     gboolean          on_ac);
+        void              (* battery_power_changed) (GpmHalMonitor    *monitor,
+                                                     gint              percentage,
+                                                     gint64            minutes,
+                                                     gboolean          discharging,
+                                                     gboolean          primary);
+                                                     
+
+} GpmHalMonitorClass;
+
+GType             gpm_hal_monitor_get_type         (void);
+
+GpmHalMonitor   * gpm_hal_monitor_new              (void);
+
+gboolean          gpm_hal_monitor_get_on_ac        (GpmHalMonitor *monitor);
+
+G_END_DECLS
+
+#endif /* __GPM_HAL_MONITOR_H */
--- /dev/null	2006-01-06 11:54:16.656529500 -0500
+++ src/gpm-manager.c	2006-01-06 18:58:29.000000000 -0500
@@ -0,0 +1,737 @@
+/* -*- 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>
+ *          Richard Hughes <richard@hughsie.com>
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <errno.h>
+
+#include <string.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#include <glib/gi18n.h>
+#include <gconf/gconf-client.h>
+
+#include "gpm-common.h"
+#include "gpm-prefs.h"
+#include "gpm-notification.h"
+#include "gpm-screensaver.h"
+#include "gpm-networkmanager.h"
+#include "gpm-libnotify.h"
+
+#include "gpm-dbus-server.h"
+
+/* FIXME: we should abstract the HAL stuff */
+#include "gpm-hal.h"
+
+#include "gpm-idle.h"
+#include "gpm-hal-monitor.h"
+#include "gpm-manager.h"
+
+static void     gpm_manager_class_init (GpmManagerClass *klass);
+static void     gpm_manager_init       (GpmManager      *manager);
+static void     gpm_manager_finalize   (GObject         *object);
+
+#define GPM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GPM_TYPE_MANAGER, GpmManagerPrivate))
+
+struct GpmManagerPrivate
+{
+        gboolean       on_ac;
+
+        GConfClient   *gconf_client;
+
+        GpmIdle       *idle;
+        GpmHalMonitor *hal_monitor;
+};
+
+enum {
+        PROP_0,
+        PROP_ON_AC
+};
+
+static GObjectClass *parent_class = NULL;
+
+G_DEFINE_TYPE (GpmManager, gpm_manager, G_TYPE_OBJECT)
+
+#define DISABLE_SHUTDOWN_FOR_TESTING 1
+
+/** Do all the action when we go from batt to ac, or ac to batt (or coldplug)
+ *
+ *  @param	on_ac		If we are on AC power
+ *
+ *  @note
+ *	- Sets the brightness level
+ *	- Sets HAL to be in LaptopMode if !AC
+ *	- Sets DPMS timeout to be our policy value
+ *	- Sets GNOME Screensaver to [not] run fancy screensavers
+ *	- Sets our inactivity sleep timeout to policy value
+ */
+static void
+change_power_policy (GpmManager *manager,
+                     gboolean    on_ac)
+{
+	int          brightness;
+        int          sleep_display;
+        int          sleep_computer;
+        GConfClient *client;
+
+        client = manager->priv->gconf_client;
+
+	if (on_ac) {
+		brightness = gconf_client_get_int (client, GPM_PREF_AC_BRIGHTNESS, NULL);
+		sleep_computer = gconf_client_get_int (client, GPM_PREF_AC_SLEEP_COMPUTER, NULL);
+		sleep_display = gconf_client_get_int (client, GPM_PREF_AC_SLEEP_DISPLAY, NULL);
+	} else {
+		brightness = gconf_client_get_int (client, GPM_PREF_BATTERY_BRIGHTNESS, NULL);
+		sleep_computer = gconf_client_get_int (client, GPM_PREF_BATTERY_SLEEP_COMPUTER, NULL);
+		sleep_display = gconf_client_get_int (client, GPM_PREF_BATTERY_SLEEP_DISPLAY, NULL);
+	}
+
+	gpm_hal_set_brightness_dim (brightness);
+	gpm_hal_enable_power_save (!on_ac);
+
+	/*
+	 * make sure gnome-screensaver disables screensaving,
+	 * and enables monitor shut-off instead when on batteries
+	 */
+	gpm_screensaver_enable_throttle (!on_ac);
+
+	/* set the new sleep (inactivity) value */
+	gpm_idle_set_session_timeout (manager->priv->idle, sleep_display);
+        gpm_idle_set_system_timeout (manager->priv->idle, sleep_computer);
+}
+
+static void
+maybe_notify_on_ac_changed (GpmManager *manager,
+                            gboolean    on_ac)
+{
+        gboolean show_notify;
+
+        show_notify = gconf_client_get_bool (manager->priv->gconf_client,
+                                             GPM_PREF_NOTIFY_ACADAPTER, NULL);
+
+        if (! on_ac) {
+                if (show_notify) {
+                        gpm_libnotify_event (_("AC Power Unplugged"),
+                                             _("The AC Power has been unplugged. "
+                                               "The system is now using battery power."),
+                                             LIBNOTIFY_URGENCY_NORMAL,
+                                             gpm_notification_get_icon ());
+                }
+        } else {
+
+                /*
+                 * for where we add back the ac_adapter before
+                 * the "AC Power unplugged" message times out.
+                 */
+                gpm_libnotify_clear ();
+        }
+
+        /* update icon */
+        gpm_notification_icon_update ();
+}
+
+/** Do the action dictated by policy from gconf
+ *
+ *  @param	action	string
+ *
+ *  @todo	Add the actions to doxygen.
+ */
+static void
+manager_policy_do (GpmManager *manager,
+                   const char *policy)
+{
+        char *action;
+
+        action = gconf_client_get_string (manager->priv->gconf_client, policy, NULL);
+
+	if (! action)
+		return;
+
+	if (strcmp (action, ACTION_NOTHING) == 0) {
+		g_debug ("*ACTION* Doing nothing");
+
+	} else if (strcmp (action, ACTION_SUSPEND) == 0) {
+		g_debug ("*ACTION* Suspend");
+
+                gpm_manager_suspend (manager);
+
+	} else if (strcmp (action, ACTION_HIBERNATE) == 0) {
+		g_debug ("*ACTION* Hibernate");
+
+                gpm_manager_hibernate (manager);
+
+	} else if (strcmp (action, ACTION_SHUTDOWN) == 0) {
+		g_debug ("*ACTION* Shutdown");
+
+                gpm_manager_shutdown (manager);
+
+	} else {
+		g_warning ("manager_policy_do called with unknown action %s", action);
+	}
+
+        g_free (action);
+
+}
+
+static void
+maybe_notify_battery_power_changed (GpmManager *manager,
+                                    int         percentage,
+                                    glong       minutes,
+                                    gboolean    discharging,
+                                    gboolean    primary)
+{
+        gboolean show_notify;
+	gint     low_threshold;
+	gint     critical_threshold;
+	gchar   *message;
+	gchar   *remaining;
+
+	g_debug ("percentage = %d, minutes = %ld, discharging = %d, primary = %d",
+		 percentage, minutes, discharging, primary);
+
+        /* give notification @100% */
+        if (primary && percentage >= 100) {
+                show_notify = gconf_client_get_bool (gconf_client_get_default (),
+                                                     GPM_PREF_NOTIFY_BATTCHARGED, NULL);
+                if (show_notify)
+                        gpm_libnotify_event (_("Battery Charged"),
+                                             _("Your battery is now fully charged"),
+                                             LIBNOTIFY_URGENCY_LOW,
+                                             gpm_notification_get_icon ());
+                return;
+        }
+
+        if (! discharging) {
+		g_debug ("battery is not discharging!");
+		return;
+	}
+
+	low_threshold = gconf_client_get_int (manager->priv->gconf_client,
+                                              GPM_PREF_THRESHOLD_LOW, NULL);
+	critical_threshold = gconf_client_get_int (manager->priv->gconf_client,
+                                                   GPM_PREF_THRESHOLD_CRITICAL, NULL);
+
+	g_debug ("percentage = %d, low_threshold = %i, critical_threshold = %i",
+		 percentage, low_threshold, critical_threshold);
+
+	/* less than critical, do action */
+	if (percentage < critical_threshold) {
+		g_debug ("battery is below critical limit!");
+		manager_policy_do (manager, GPM_PREF_BATTERY_CRITICAL);
+
+		return;
+	}
+
+	/* critical warning */
+	if (percentage == critical_threshold) {
+		g_debug ("battery is critical limit!");
+		remaining = get_timestring_from_minutes (minutes);
+
+		message = g_strdup_printf (_("You have approximately <b>%s</b> "
+                                             "of remaining battery life (%d%%). "
+                                             "Plug in your AC Adapter to avoid losing data."),
+					   remaining, percentage);
+		gpm_libnotify_event (_("Battery Critically Low"),
+				     message,
+				     LIBNOTIFY_URGENCY_CRITICAL,
+				     gpm_notification_get_icon ());
+		g_free (message);
+		g_free (remaining);
+
+		return;
+	}
+
+	/* low warning */
+	if (percentage < low_threshold) {
+		g_debug ("battery is low!");
+		remaining = get_timestring_from_minutes (minutes);
+		g_assert (remaining);
+
+		message = g_strdup_printf (_("You have approximately <b>%s</b> of remaining battery life (%d%%). "
+                                             "Plug in your AC Adapter to avoid losing data."),
+                                           remaining, percentage);
+
+		gpm_libnotify_event (_("Battery Low"),
+				     message,
+				     LIBNOTIFY_URGENCY_CRITICAL,
+				     gpm_notification_get_icon ());
+		g_free (message);
+		g_free (remaining);
+
+		return;
+	}
+
+        /* update icon */
+        gpm_notification_icon_update ();
+}
+
+void
+gpm_manager_set_on_ac (GpmManager *manager,
+                       gboolean    on_ac)
+{
+        g_return_if_fail (GS_IS_MANAGER (manager));
+
+        if (on_ac != manager->priv->on_ac) {
+                manager->priv->on_ac = on_ac;
+
+		g_debug ("Setting on-ac: %d", on_ac);
+
+                maybe_notify_on_ac_changed (manager, on_ac);
+                gpm_emit_mains_changed (on_ac);
+
+                change_power_policy (manager, on_ac);
+        }
+}
+
+gboolean
+gpm_manager_get_on_ac (GpmManager *manager)
+{
+        gboolean on_ac;
+
+        g_return_val_if_fail (GS_IS_MANAGER (manager), FALSE);
+
+        on_ac = manager->priv->on_ac;
+
+        return on_ac;
+}
+
+void
+gpm_manager_shutdown (GpmManager *manager)
+{
+#ifndef DISABLE_SHUTDOWN_FOR_TESTING
+        gnome_client_request_save (gnome_master_client (),
+                                   GNOME_SAVE_GLOBAL,
+                                   FALSE, GNOME_INTERACT_NONE, FALSE,  TRUE);
+        gpm_hal_shutdown ();
+#else
+        g_debug ("Shutdown disabled for testing\n");
+#endif
+}
+
+/** Do a hibernate with all the associated callbacks and methods.
+ *
+ *  @note
+ *	- Locks the screen (if required)
+ *	- Sets NetworkManager to sleep
+ *	- Does the hibernate...
+ *	- Sets NetworkManager to wake
+ *	- Pokes g-s so we get the unlock screen (if required)
+ */
+void
+gpm_manager_hibernate (GpmManager *manager)
+{
+#ifndef DISABLE_SHUTDOWN_FOR_TESTING
+	gboolean should_lock = gpm_screensaver_lock_enabled ();
+
+	if (!gpm_hal_can_hibernate ()) {
+		g_warning ("Cannot hibernate as disabled in HAL");
+		return;
+	}
+
+	if (should_lock)
+		gpm_screensaver_lock ();
+
+	gpm_networkmanager_sleep ();
+	gpm_hal_hibernate ();
+	gpm_networkmanager_wake ();
+
+	/* Poke GNOME ScreenSaver so the dialogue is displayed */
+	if (should_lock)
+		gpm_screensaver_poke ();
+
+#else
+        g_debug ("Hibernate disabled for testing\n");
+#endif
+}
+
+/** Do a suspend with all the associated callbacks and methods.
+ *
+ *  @note
+ *	- Locks the screen (if required)
+ *	- Sets NetworkManager to sleep
+ *	- Does the suspend...
+ *	- Sets NetworkManager to wake
+ *	- Pokes g-s so we get the unlock screen (if required)
+ */
+void
+gpm_manager_suspend (GpmManager *manager)
+{
+#ifndef DISABLE_SHUTDOWN_FOR_TESTING
+	gboolean should_lock = gpm_screensaver_lock_enabled ();
+
+	if (! gpm_hal_can_suspend ()) {
+		g_warning ("Cannot suspend as disabled in HAL");
+		return;
+	}
+
+	if (should_lock)
+		gpm_screensaver_lock ();
+
+	gpm_networkmanager_sleep ();
+	gpm_hal_suspend (0);
+	gpm_networkmanager_wake ();
+
+	/* Poke GNOME ScreenSaver so the dialogue is displayed */
+	if (should_lock)
+		gpm_screensaver_poke ();
+#else
+        g_debug ("Suspend disabled for testing\n");
+#endif
+}
+
+/** Callback for the idle function.
+ */
+static void
+idle_changed_cb (GpmIdle    *idle,
+                 GpmIdleMode mode,
+                 GpmManager *manager)
+{
+
+        switch (mode) {
+	case GPM_IDLE_MODE_NORMAL:
+                /* FIXME: Disable DPMS */
+                g_debug ("Idle state changed: NORMAL\n");
+
+		break;
+	case GPM_IDLE_MODE_SESSION:
+                /* FIXME: Enable DPMS */
+                g_debug ("Idle state changed: SESSION\n");
+
+		break;
+	case GPM_IDLE_MODE_SYSTEM:
+                g_debug ("Idle state changed: SYSTEM\n");
+
+                /* can only be hibernate or suspend */
+                manager_policy_do (manager, GPM_PREF_BATTERY_CRITICAL);
+
+		break;
+	default:
+                g_assert_not_reached ();
+		break;
+        }
+
+}
+
+static void
+hal_power_button_cb (GpmHalMonitor *monitor,
+                     gboolean       state,
+                     GpmManager    *manager)
+{
+        /* Log out interactively */
+        gnome_client_request_save (gnome_master_client (),
+                                   GNOME_SAVE_GLOBAL,
+                                   TRUE, GNOME_INTERACT_ANY, FALSE,  TRUE);
+}
+
+static void
+hal_lid_button_cb (GpmHalMonitor *monitor,
+                   gboolean       state,
+                   GpmManager    *manager)
+{
+        /*
+         * We enable/disable DPMS because some laptops do
+         * not turn off the LCD backlight when the lid
+         * is closed. See
+         * http://bugzilla.gnome.org/show_bug.cgi?id=321313
+         */
+        if (state) {
+                /* we only do a policy event when the lid is CLOSED */
+                manager_policy_do (manager, GPM_PREF_BUTTON_LID);
+        }
+
+        gpm_screensaver_enable_dpms (! state);
+
+}
+
+static void
+hal_suspend_button_cb (GpmHalMonitor *monitor,
+                       gboolean       state,
+                       GpmManager    *manager)
+{
+        manager_policy_do (manager, GPM_PREF_BUTTON_SUSPEND);
+}
+
+static void
+hal_suspend_cb (GpmHalMonitor *monitor,
+                GpmManager    *manager)
+{
+        gpm_manager_suspend (manager);
+}
+
+static void
+hal_hibernate_cb (GpmHalMonitor *monitor,
+                  GpmManager    *manager)
+{
+        gpm_manager_hibernate (manager);
+}
+
+static void
+hal_lock_cb (GpmHalMonitor *monitor,
+             GpmManager    *manager)
+{
+        gpm_screensaver_lock ();
+}
+
+static void
+hal_on_ac_changed_cb (GpmHalMonitor *monitor,
+                      gboolean       on_ac,
+                      GpmManager    *manager)
+{
+        gpm_manager_set_on_ac (manager, on_ac);
+}
+
+static void
+hal_battery_power_changed_cb (GpmHalMonitor *monitor,
+                              int            percentage,
+                              glong          minutes,
+                              gboolean       discharging,
+                              gboolean       primary,
+                              GpmManager    *manager)
+{
+        maybe_notify_battery_power_changed (manager,
+                                            percentage,
+                                            minutes,
+                                            discharging,
+                                            primary);
+}
+
+static void
+gpm_manager_set_property (GObject            *object,
+                          guint               prop_id,
+                          const GValue       *value,
+                          GParamSpec         *pspec)
+{
+	GpmManager *manager = GPM_MANAGER (object);
+
+        switch (prop_id) {
+        case PROP_ON_AC:
+		gpm_manager_set_on_ac (manager, g_value_get_boolean (value));
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gpm_manager_get_property (GObject            *object,
+                          guint               prop_id,
+                          GValue             *value,
+                          GParamSpec         *pspec)
+{
+	GpmManager *manager = GPM_MANAGER (object);
+
+        switch (prop_id) {
+        case PROP_ON_AC:
+		g_value_set_boolean (value, manager->priv->on_ac);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gpm_manager_class_init (GpmManagerClass *klass)
+{
+        GObjectClass   *object_class = G_OBJECT_CLASS (klass);
+
+        parent_class = g_type_class_peek_parent (klass);
+
+        object_class->finalize     = gpm_manager_finalize;
+        object_class->get_property = gpm_manager_get_property;
+        object_class->set_property = gpm_manager_set_property;
+
+        g_object_class_install_property (object_class,
+                                         PROP_ON_AC,
+                                         g_param_spec_boolean ("on_ac",
+                                                               NULL,
+                                                               NULL,
+                                                               TRUE,
+                                                               G_PARAM_READWRITE));
+
+        g_type_class_add_private (klass, sizeof (GpmManagerPrivate));
+}
+
+/** Callback for gconf modified keys (that we are watching).
+ *
+ * @param	client		A valid GConfClient
+ * @param	cnxn_id		Unknown
+ * @param	entry		The key that was modified
+ * @param	user_data	user_data pointer. No function.
+ */
+static void
+callback_gconf_key_changed (GConfClient *client,
+                            guint        cnxn_id,
+                            GConfEntry  *entry,
+                            gpointer     user_data)
+{
+	gint        value = 0;
+        GpmManager *manager = GPM_MANAGER (user_data);
+	gboolean    on_ac;
+
+        on_ac = manager->priv->on_ac;
+
+	g_debug ("callback_gconf_key_changed (%s)", entry->key);
+
+	if (gconf_entry_get_value (entry) == NULL) {
+		return;
+        }
+
+	if (strcmp (entry->key, GPM_PREF_ICON_POLICY) == 0) {
+		gpm_notification_icon_update ();
+	} else if (strcmp (entry->key, GPM_PREF_BATTERY_SLEEP_COMPUTER) == 0) {
+		/* set new suspend timeouts */
+		value = gconf_client_get_int (client, entry->key, NULL);
+                
+		if (! on_ac) {
+			gpm_idle_set_system_timeout (manager->priv->idle, value);
+                }
+
+	} else if (strcmp (entry->key, GPM_PREF_AC_SLEEP_COMPUTER) == 0) {
+
+		/* set new suspend timeouts */
+		value = gconf_client_get_int (client, entry->key, NULL);
+
+		if (on_ac) {
+			gpm_idle_set_system_timeout (manager->priv->idle,
+                                                     value);
+                }
+
+	} else if (strcmp (entry->key, GPM_PREF_BATTERY_SLEEP_DISPLAY) == 0) {
+		/* set new suspend timeouts */
+                value = gconf_client_get_int (client, entry->key, NULL);
+
+		if (! on_ac) {
+			/*gpm_dpms_set_timeout (manager->priv->dpms, value); */
+			gpm_screensaver_set_dpms_timeout (value);
+		}
+	} else if (strcmp (entry->key, GPM_PREF_AC_SLEEP_DISPLAY) == 0) {
+		/* set new suspend timeouts */
+                value = gconf_client_get_int (client, entry->key, NULL);
+
+		if (on_ac) {
+			/*gpm_dpms_set_timeout (manager->priv->idle, value); */
+			gpm_screensaver_set_dpms_timeout (value);
+		}
+	}
+}
+
+static void
+gpm_manager_init (GpmManager *manager)
+{
+        manager->priv = GPM_MANAGER_GET_PRIVATE (manager);
+
+	manager->priv->gconf_client = gconf_client_get_default ();
+
+	gconf_client_add_dir (manager->priv->gconf_client,
+                              GPM_PREF_DIR,
+                              GCONF_CLIENT_PRELOAD_NONE,
+                              NULL);
+
+	gconf_client_notify_add (manager->priv->gconf_client,
+                                 GPM_PREF_DIR,
+                                 callback_gconf_key_changed,
+                                 manager,
+                                 NULL,
+                                 NULL);
+
+	if (! gpm_libnotify_init (NICENAME))
+		g_error ("Cannot initialise libnotify!");
+
+        manager->priv->idle = gpm_idle_new ();
+        g_signal_connect (manager->priv->idle, "changed",
+                          G_CALLBACK (idle_changed_cb), manager);
+
+	manager->priv->hal_monitor = gpm_hal_monitor_new ();
+        g_signal_connect (manager->priv->hal_monitor, "ac-power-changed",
+                          G_CALLBACK (hal_on_ac_changed_cb), manager);
+        g_signal_connect (manager->priv->hal_monitor, "battery-power-changed",
+                          G_CALLBACK (hal_battery_power_changed_cb), manager);
+        g_signal_connect (manager->priv->hal_monitor, "power-button",
+                          G_CALLBACK (hal_power_button_cb), manager);
+        g_signal_connect (manager->priv->hal_monitor, "suspend-button",
+                          G_CALLBACK (hal_suspend_button_cb), manager);
+        g_signal_connect (manager->priv->hal_monitor, "lid-button",
+                          G_CALLBACK (hal_lid_button_cb), manager);
+        g_signal_connect (manager->priv->hal_monitor, "suspend",
+                          G_CALLBACK (hal_suspend_cb), manager);
+        g_signal_connect (manager->priv->hal_monitor, "hibernate",
+                          G_CALLBACK (hal_hibernate_cb), manager);
+        g_signal_connect (manager->priv->hal_monitor, "lock",
+                          G_CALLBACK (hal_lock_cb), manager);
+
+	/* do all the actions as we have to set initial state */
+	gpm_manager_set_on_ac (manager,
+                               gpm_hal_monitor_get_on_ac (manager->priv->hal_monitor));
+
+	gpm_notification_icon_update ();
+
+}
+
+static void
+gpm_manager_finalize (GObject *object)
+{
+        GpmManager *manager;
+
+        g_return_if_fail (object != NULL);
+        g_return_if_fail (GS_IS_MANAGER (object));
+
+        manager = GPM_MANAGER (object);
+
+        g_return_if_fail (manager->priv != NULL);
+
+        if (manager->priv->gconf_client != NULL) {
+                g_object_unref (manager->priv->gconf_client);
+        }
+
+        if (manager->priv->idle != NULL) {
+                g_object_unref (manager->priv->idle);
+        }
+
+        if (manager->priv->hal_monitor != NULL) {
+                g_object_unref (manager->priv->hal_monitor);
+        }
+
+	gpm_notification_icon_destroy ();
+
+        G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+GpmManager *
+gpm_manager_new (void)
+{
+        GpmManager *manager;
+
+        manager = g_object_new (GPM_TYPE_MANAGER, NULL);
+
+        return GPM_MANAGER (manager);
+}
--- /dev/null	2006-01-06 11:54:16.656529500 -0500
+++ src/gpm-manager.h	2006-01-06 16:31:51.000000000 -0500
@@ -0,0 +1,64 @@
+/* -*- 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>
+ *
+ */
+
+#ifndef __GPM_MANAGER_H
+#define __GPM_MANAGER_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GPM_TYPE_MANAGER          (gpm_manager_get_type ())
+#define GPM_MANAGER(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GPM_TYPE_MANAGER, GpmManager))
+#define GPM_MANAGER_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), GPM_TYPE_MANAGER, GpmManagerClass))
+#define GS_IS_MANAGER(o)         (G_TYPE_CHECK_INSTANCE_TYPE ((o), GPM_TYPE_MANAGER))
+#define GS_IS_MANAGER_CLASS(k)   (G_TYPE_CHECK_CLASS_TYPE ((k), GPM_TYPE_MANAGER))
+#define GPM_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GPM_TYPE_MANAGER, GpmManagerClass))
+
+typedef struct GpmManagerPrivate GpmManagerPrivate;
+
+typedef struct
+{
+        GObject         parent;
+        GpmManagerPrivate *priv;
+} GpmManager;
+
+typedef struct
+{
+        GObjectClass      parent_class;
+} GpmManagerClass;
+
+GType          gpm_manager_get_type         (void);
+
+GpmManager   * gpm_manager_new              (void);
+
+gboolean       gpm_manager_get_on_ac        (GpmManager    *manager);
+void           gpm_manager_set_on_ac        (GpmManager    *manager,
+                                             gboolean       on_ac);
+
+void           gpm_manager_suspend          (GpmManager    *manager);
+void           gpm_manager_hibernate        (GpmManager    *manager);
+void           gpm_manager_shutdown         (GpmManager    *manager);
+
+G_END_DECLS
+
+#endif /* __GPM_MANAGER_H */
