[Xfce4-commits] <xfce4-power-manager:master> Query notification server capabilities for adding actions to notification, if server supports actions use them to show a notification warning about the low power level if not use gtk.

Ali Abdallah noreply at xfce.org
Sat Jan 30 02:18:03 CET 2010


Updating branch refs/heads/master
         to 14d0c8e0da97157b3acf127086c7a79be73961c3 (commit)
       from 44f74bccaf9cedbf1e245d372152055f487e52ad (commit)

commit 14d0c8e0da97157b3acf127086c7a79be73961c3
Author: Ali Abdallah <ali at ali-xfce.org>
Date:   Thu Nov 5 10:04:22 2009 +0100

    Query notification server capabilities for adding actions to
    notification, if server supports actions use them to show a
    notification warning about the low power level if not use gtk.
    
    Re-Enable suspend/hibernate/lid actions.

 TODO                        |   13 +-
 libdbus/xfpm-dbus-monitor.c |   34 -----
 libdbus/xfpm-dbus-monitor.h |    9 --
 src/xfpm-battery.c          |   61 ++++++++-
 src/xfpm-battery.h          |   18 +++-
 src/xfpm-dkp.c              |  311 ++++++++++++++++++++++++++++++++++++++-----
 src/xfpm-dkp.h              |    2 +
 src/xfpm-manager.c          |   17 ++-
 src/xfpm-notify.c           |  108 ++++++++++++++--
 src/xfpm-xfconf.c           |    2 +-
 10 files changed, 477 insertions(+), 98 deletions(-)

diff --git a/TODO b/TODO
index 00e9a83..dd1ba55 100644
--- a/TODO
+++ b/TODO
@@ -1,5 +1,8 @@
-* : Solve the problem of possible multiple sleep requests between us and the session manager.
-
-* : Probably provide a PermissionDenied error on the inhibit interface?
-
-* : Updating the documentations.
+* Reimplement critical battery action
+* Make xrandr brightness control working.
+* Reimplement the org.freedesktop.PowerManagement interface.
+* Battery information.
+* Hard drive spinning.
+* Survive D-Bus restarts.
+* Probably provide a PermissionDenied error on the inhibit interface?
+* Update the documentations.
diff --git a/libdbus/xfpm-dbus-monitor.c b/libdbus/xfpm-dbus-monitor.c
index 16fa406..1721901 100644
--- a/libdbus/xfpm-dbus-monitor.c
+++ b/libdbus/xfpm-dbus-monitor.c
@@ -53,8 +53,6 @@ struct XfpmDBusMonitorPrivate
     
     GPtrArray       *names_array;
     GPtrArray 	    *services_array;
-    
-    gboolean	     hal_connected;
 };
 
 typedef struct
@@ -68,7 +66,6 @@ enum
 {
     UNIQUE_NAME_LOST,
     SERVICE_CONNECTION_CHANGED,
-    HAL_CONNECTION_CHANGED,
     SYSTEM_BUS_CONNECTION_CHANGED,
     LAST_SIGNAL
 };
@@ -126,14 +123,6 @@ xfpm_dbus_monitor_service_connection_changed (XfpmDBusMonitor *monitor, DBusBusT
     XfpmWatchData *watch;
     guint i;
     
-    /* Simplify things for HAL */
-    if ( !g_strcmp0 (name, "org.freedesktop.Hal") && bus_type == DBUS_BUS_SYSTEM )
-    {
-	monitor->priv->hal_connected = connected;
-	g_signal_emit (G_OBJECT (monitor), signals [HAL_CONNECTION_CHANGED], 0, connected);
-	return;
-    }
-    
     for ( i = 0; i < monitor->priv->services_array->len; i++)
     {
 	watch = g_ptr_array_index (monitor->priv->services_array, i);
@@ -196,10 +185,6 @@ xfpm_dbus_monitor_query_system_bus_idle (gpointer data)
 	return TRUE;
     }
     
-    /*
-     * This message is catched by xfpm manager then it simply
-     * restarts all the power manager
-     */
     monitor = XFPM_DBUS_MONITOR (data);
     g_signal_emit (G_OBJECT (monitor), signals [SYSTEM_BUS_CONNECTION_CHANGED], 0, TRUE);
     
@@ -288,15 +273,6 @@ xfpm_dbus_monitor_class_init (XfpmDBusMonitorClass *klass)
 		      G_TYPE_NONE, 2, 
 		      G_TYPE_STRING, G_TYPE_BOOLEAN);
 		     
-    signals [HAL_CONNECTION_CHANGED] =
-    	g_signal_new ("hal-connection-changed",
-		      XFPM_TYPE_DBUS_MONITOR,
-		      G_SIGNAL_RUN_LAST,
-		      G_STRUCT_OFFSET (XfpmDBusMonitorClass, hal_connection_changed),
-		      NULL, NULL,
-		      g_cclosure_marshal_VOID__BOOLEAN,
-		      G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
-		      
     signals [SERVICE_CONNECTION_CHANGED] =
     	g_signal_new ("service-connection-changed",
 		      XFPM_TYPE_DBUS_MONITOR,
@@ -345,11 +321,6 @@ xfpm_dbus_monitor_init (XfpmDBusMonitor *monitor)
 			        xfpm_dbus_monitor_system_bus_filter,
 				monitor, 
 				NULL);
-				
-    monitor->priv->hal_connected  = xfpm_dbus_name_has_owner (dbus_g_connection_get_connection (monitor->priv->system_bus), 
-							      "org.freedesktop.Hal");
-							      
-    xfpm_dbus_monitor_add_service (monitor, DBUS_BUS_SESSION, "org.freedesktop.Hal");
 }
 
 static void
@@ -473,8 +444,3 @@ void xfpm_dbus_monitor_remove_service (XfpmDBusMonitor *monitor, DBusBusType bus
 	xfpm_dbus_monitor_free_watch_data (watch);
     }
 }
-
-gboolean xfpm_dbus_monitor_hal_connected (XfpmDBusMonitor *monitor)
-{
-    return monitor->priv->hal_connected;
-}
diff --git a/libdbus/xfpm-dbus-monitor.h b/libdbus/xfpm-dbus-monitor.h
index 8488990..cc78002 100644
--- a/libdbus/xfpm-dbus-monitor.h
+++ b/libdbus/xfpm-dbus-monitor.h
@@ -59,12 +59,6 @@ typedef struct
 								 gboolean on_session);
 								 
     /*
-     * Hal Connection
-     */
-    void		(*hal_connection_changed)		(XfpmDBusMonitor *monitor,
-								 gboolean connected);
-      
-    /*
      * DBus: system bus disconnected
      */
     void		(*system_bus_connection_changed)  	(XfpmDBusMonitor *monitor,
@@ -91,9 +85,6 @@ gboolean		xfpm_dbus_monitor_add_service	  	(XfpmDBusMonitor *monitor,
 void			xfpm_dbus_monitor_remove_service  	(XfpmDBusMonitor *monitor,
 								 DBusBusType bus_type,
 								 const gchar *service_name);
-
-gboolean		xfpm_dbus_monitor_hal_connected		(XfpmDBusMonitor *monitor);
-
 G_END_DECLS
 
 #endif /* __XFPM_DBUS_MONITOR_H */
diff --git a/src/xfpm-battery.c b/src/xfpm-battery.c
index e66d14c..29b6cdd 100644
--- a/src/xfpm-battery.c
+++ b/src/xfpm-battery.c
@@ -55,11 +55,12 @@ struct XfpmBatteryPrivate
     
     gchar		   *icon_prefix;
     
+    XfpmBatteryCharge       charge;
     XfpmDkpDeviceState      state;
     XfpmDkpDeviceType       type;
     gboolean		    ac_online;
     gboolean                present;
-    gint 		    percentage;
+    guint 		    percentage;
     gint64		    time_to_full;
     gint64		    time_to_empty;
     
@@ -72,6 +73,14 @@ enum
     PROP_AC_ONLINE
 };
     
+enum
+{
+    BATTERY_CHARGE_CHANGED,
+    LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0 };
+
 G_DEFINE_TYPE (XfpmBattery, xfpm_battery, GTK_TYPE_STATUS_ICON)
 
 static const gchar * G_GNUC_CONST
@@ -219,7 +228,6 @@ xfpm_battery_notify_idle (gpointer data)
 				   FALSE,
 				   XFPM_NOTIFY_NORMAL,
 				   GTK_STATUS_ICON (battery));
-    
     return FALSE;
 }
 
@@ -389,6 +397,32 @@ xfpm_battery_set_tooltip_primary (XfpmBattery *battery, GtkTooltip *tooltip)
 }
 
 static void
+xfpm_battery_check_charge (XfpmBattery *battery)
+{
+    XfpmBatteryCharge charge;
+    guint critical_level, low_level;
+    
+    g_object_get (G_OBJECT (battery->priv->conf),
+		  CRITICAL_POWER_LEVEL, &critical_level,
+		  NULL);
+		  
+    low_level = critical_level + 10;
+    
+    if ( battery->priv->percentage > low_level )
+	charge = XFPM_BATTERY_CHARGE_OK;
+    else if ( battery->priv->percentage <= low_level && battery->priv->percentage > critical_level )
+	charge = XFPM_BATTERY_CHARGE_LOW;
+    else if ( battery->priv->percentage <= critical_level )
+	charge = XFPM_BATTERY_CHARGE_CRITICAL;
+	
+    if ( charge != battery->priv->charge )
+    {
+	battery->priv->charge = charge;
+	g_signal_emit (G_OBJECT (battery), signals [BATTERY_CHARGE_CHANGED], 0);
+    }
+}
+
+static void
 xfpm_battery_refresh (XfpmBattery *battery, GHashTable *props)
 {
     GValue *value;
@@ -427,7 +461,9 @@ xfpm_battery_refresh (XfpmBattery *battery, GHashTable *props)
 	goto out;
     }
     
-    battery->priv->percentage = (gint) g_value_get_double (value);
+    battery->priv->percentage = (guint) g_value_get_double (value);
+    
+    xfpm_battery_check_charge (battery);
     
     xfpm_battery_refresh_icon (battery);
     
@@ -551,6 +587,15 @@ xfpm_battery_class_init (XfpmBatteryClass *klass)
 
     status_icon_class->query_tooltip = xfpm_battery_query_tooltip;
     
+    signals [BATTERY_CHARGE_CHANGED] = 
+        g_signal_new ("battery-charge-changed",
+                      XFPM_TYPE_BATTERY,
+                      G_SIGNAL_RUN_LAST,
+                      G_STRUCT_OFFSET(XfpmBatteryClass, battery_charge_changed),
+                      NULL, NULL,
+                      g_cclosure_marshal_VOID__VOID,
+                      G_TYPE_NONE, 0, G_TYPE_NONE);
+    
     g_object_class_install_property (object_class,
                                      PROP_AC_ONLINE,
                                      g_param_spec_boolean("ac-online",
@@ -571,6 +616,7 @@ xfpm_battery_init (XfpmBattery *battery)
     battery->priv->proxy_prop    = NULL;
     battery->priv->state         = XFPM_DKP_DEVICE_STATE_UNKNOWN;
     battery->priv->type          = XFPM_DKP_DEVICE_TYPE_UNKNOWN;
+    battery->priv->charge        = XFPM_BATTERY_CHARGE_UNKNOWN;
     battery->priv->icon_prefix   = NULL;
     battery->priv->time_to_full  = 0;
     battery->priv->time_to_empty = 0;
@@ -661,9 +707,16 @@ void xfpm_battery_monitor_device (XfpmBattery *battery,
     xfpm_battery_changed_cb (proxy, battery);
 }
 
-XfpmDkpDeviceType	    xfpm_battery_get_device_type (XfpmBattery *battery)
+XfpmDkpDeviceType xfpm_battery_get_device_type (XfpmBattery *battery)
 {
     g_return_val_if_fail (XFPM_IS_BATTERY (battery), XFPM_DKP_DEVICE_TYPE_UNKNOWN );
     
     return battery->priv->type;
 }
+
+XfpmBatteryCharge xfpm_battery_get_charge (XfpmBattery *battery)
+{
+    g_return_val_if_fail (XFPM_IS_BATTERY (battery), XFPM_BATTERY_CHARGE_UNKNOWN);
+    
+    return battery->priv->charge;
+}
diff --git a/src/xfpm-battery.h b/src/xfpm-battery.h
index 2cd4399..9194517 100644
--- a/src/xfpm-battery.h
+++ b/src/xfpm-battery.h
@@ -33,6 +33,18 @@ G_BEGIN_DECLS
 #define XFPM_BATTERY(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), XFPM_TYPE_BATTERY, XfpmBattery))
 #define XFPM_IS_BATTERY(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), XFPM_TYPE_BATTERY))
 
+/*
+ * Order matters
+ */
+typedef enum
+{
+    XFPM_BATTERY_CHARGE_UNKNOWN,
+    XFPM_BATTERY_CHARGE_CRITICAL,
+    XFPM_BATTERY_CHARGE_LOW,
+    XFPM_BATTERY_CHARGE_OK
+    
+} XfpmBatteryCharge;
+
 typedef struct XfpmBatteryPrivate XfpmBatteryPrivate;
 
 typedef struct
@@ -47,6 +59,8 @@ typedef struct
 {
     GtkStatusIconClass 	    parent_class;
     
+    void		    (*battery_charge_changed)	 (XfpmBattery *battery);
+    
 } XfpmBatteryClass;
 
 GType        		    xfpm_battery_get_type        (void) G_GNUC_CONST;
@@ -57,9 +71,11 @@ void			    xfpm_battery_monitor_device  (XfpmBattery *battery,
 							  DBusGProxy *proxy,
 							  DBusGProxy *proxy_prop,
 							  XfpmDkpDeviceType device_type);
-
+//FIXME, make these as properties
 XfpmDkpDeviceType	    xfpm_battery_get_device_type (XfpmBattery *battery);
 
+XfpmBatteryCharge	    xfpm_battery_get_charge      (XfpmBattery *battery);
+
 G_END_DECLS
 
 #endif /* __XFPM_BATTERY_H */
diff --git a/src/xfpm-dkp.c b/src/xfpm-dkp.c
index 1a7a0b5..1e59d65 100644
--- a/src/xfpm-dkp.c
+++ b/src/xfpm-dkp.c
@@ -43,14 +43,12 @@
 #include "xfpm-icons.h"
 #include "xfpm-common.h"
 #include "xfpm-config.h"
+#include "xfpm-enum-glib.h"
+#include "xfpm-debug.h"
+#include "xfpm-enum-types.h"
 
 static void xfpm_dkp_finalize     (GObject *object);
 
-static void xfpm_dkp_set_property (GObject *object,
-				   guint prop_id,
-				   const GValue *value,
-				   GParamSpec *pspec);
-				   
 static void xfpm_dkp_get_property (GObject *object,
 				   guint prop_id,
 				   GValue *value,
@@ -89,6 +87,8 @@ struct XfpmDkpPrivate
     gchar           *daemon_version;
     gboolean	     can_suspend;
     gboolean         can_hibernate;
+    
+    GtkWidget 	    *dialog;
 };
 
 enum
@@ -109,6 +109,7 @@ enum
     LID_CHANGED,
     WAKING_UP,
     SLEEPING,
+    ASK_SHUTDOWN,
     LAST_SIGNAL
 };
 
@@ -326,6 +327,7 @@ xfpm_dkp_sleep (XfpmDkp *dkp, const gchar *sleep, gboolean force)
 	    return;
     }
     
+    g_signal_emit (G_OBJECT (dkp), signals [SLEEPING], 0);
     xfpm_send_message_to_network_manager ("sleep");
         
     g_object_get (G_OBJECT (dkp->priv->conf),
@@ -366,18 +368,34 @@ xfpm_dkp_sleep (XfpmDkp *dkp, const gchar *sleep, gboolean force)
 }
 
 static void
-xfpm_dkp_hibernate_cb (GtkStatusIcon *icon, XfpmDkp *dkp)
+xfpm_dkp_hibernate_cb (XfpmDkp *dkp)
 {
     xfpm_dkp_sleep (dkp, "Hibernate", FALSE);
 }
 
 static void
-xfpm_dkp_suspend_cb (GtkStatusIcon *icon, XfpmDkp *dkp)
+xfpm_dkp_suspend_cb (XfpmDkp *dkp)
 {
     xfpm_dkp_sleep (dkp, "Suspend", FALSE);
 }
 
 static void
+xfpm_dkp_hibernate_clicked (XfpmDkp *dkp)
+{
+    gtk_widget_destroy (dkp->priv->dialog );
+    dkp->priv->dialog = NULL;
+    xfpm_dkp_sleep (dkp, "Hibernate", TRUE);
+}
+
+static void
+xfpm_dkp_suspend_clicked (XfpmDkp *dkp)
+{
+    gtk_widget_destroy (dkp->priv->dialog );
+    dkp->priv->dialog = NULL;
+    xfpm_dkp_sleep (dkp, "Suspend", TRUE);
+}
+
+static void
 xfpm_dkp_battery_info_cb (GtkStatusIcon *icon)
 {
     
@@ -420,8 +438,8 @@ xfpm_dkp_show_tray_menu (XfpmDkp *dkp,
     if ( dkp->priv->can_hibernate && dkp->priv->auth_hibernate)
     {
 	gtk_widget_set_sensitive (mi, TRUE);
-	g_signal_connect (G_OBJECT (mi), "activate",
-			 G_CALLBACK (xfpm_dkp_hibernate_cb), dkp);
+	g_signal_connect_swapped (G_OBJECT (mi), "activate",
+				  G_CALLBACK (xfpm_dkp_hibernate_cb), dkp);
     }
     gtk_widget_show (mi);
     gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
@@ -436,8 +454,8 @@ xfpm_dkp_show_tray_menu (XfpmDkp *dkp,
     if ( dkp->priv->can_suspend && dkp->priv->auth_hibernate)
     {
 	gtk_widget_set_sensitive (mi, TRUE);
-	g_signal_connect (mi, "activate",
-			  G_CALLBACK (xfpm_dkp_suspend_cb), dkp);
+	g_signal_connect_swapped (mi, "activate",
+				  G_CALLBACK (xfpm_dkp_suspend_cb), dkp);
     }
     
     gtk_widget_show (mi);
@@ -530,6 +548,242 @@ xfpm_dkp_show_tray_menu_battery (GtkStatusIcon *icon, guint button,
     xfpm_dkp_show_tray_menu (dkp, icon, button, activate_time, TRUE);
 }
 
+static XfpmBatteryCharge
+xfpm_dkp_get_current_charge_state (XfpmDkp *dkp)
+{
+    GList *list;
+    XfpmBatteryCharge charge = XFPM_BATTERY_CHARGE_UNKNOWN;
+    guint len, i;
+    
+    list = g_hash_table_get_values (dkp->priv->hash);
+    len = g_list_length (list);
+    
+    for ( i = 0; i < len; i++)
+    {
+	charge = MAX (charge, xfpm_battery_get_charge (XFPM_BATTERY (g_list_nth_data (list, i))));
+    }
+    
+    return charge;
+}
+
+static void
+xfpm_dkp_notify_action_callback (NotifyNotification *n, gchar *action, XfpmDkp *dkp)
+{
+    if ( !g_strcmp0 (action, "Shutdown") )
+	;
+    else
+	xfpm_dkp_sleep (dkp, action, TRUE);
+}
+
+
+static void
+xfpm_dkp_add_actions_to_notification (XfpmDkp *dkp, NotifyNotification *n)
+{
+    if (  dkp->priv->can_hibernate && dkp->priv->auth_hibernate )
+    {
+        xfpm_notify_add_action_to_notification(
+			       dkp->priv->notify,
+			       n,
+                               "Hibernate",
+                               _("Hibernate the system"),
+                               (NotifyActionCallback)xfpm_dkp_notify_action_callback,
+                               dkp);      
+    }
+    
+    if (  dkp->priv->can_suspend && dkp->priv->auth_suspend )
+    {
+        xfpm_notify_add_action_to_notification(
+			       dkp->priv->notify,
+			       n,
+                               "Suspend",
+                               _("Suspend the system"),
+                               (NotifyActionCallback)xfpm_dkp_notify_action_callback,
+                               dkp);      
+    }
+    //FIXME, Shutdown
+}
+
+static void
+xfpm_dkp_show_critical_action_notification (XfpmDkp *dkp, XfpmBattery *battery)
+{
+    const gchar *message;
+    NotifyNotification *n;
+    
+    message = _("System is running on low power. "\
+               "Save your work to avoid losing data");
+	      
+    n = 
+	xfpm_notify_new_notification (dkp->priv->notify, 
+				      _("Xfce power manager"), 
+				      message, 
+				      gtk_status_icon_get_icon_name (GTK_STATUS_ICON (battery)),
+				      20000,
+				      XFPM_NOTIFY_CRITICAL,
+				      GTK_STATUS_ICON (battery));
+    
+    xfpm_dkp_add_actions_to_notification (dkp, n);
+    xfpm_notify_critical (dkp->priv->notify, n);
+
+}
+
+static void
+xfpm_dkp_close_critical_dialog (XfpmDkp *dkp)
+{
+    gtk_widget_destroy (dkp->priv->dialog);
+    dkp->priv->dialog = NULL;
+}
+
+static void
+xfpm_dkp_show_critical_action_gtk (XfpmDkp *dkp)
+{
+    GtkWidget *dialog;
+    GtkWidget *content_area;
+    GtkWidget *img;
+    GtkWidget *cancel;
+    const gchar *message;
+    
+    message = _("System is running on low power. "\
+               "Save your work to avoid losing data");
+    
+    dialog = gtk_dialog_new_with_buttons (_("Xfce Power Manager"), NULL, GTK_DIALOG_MODAL,
+                                          NULL);
+    
+    gtk_dialog_set_default_response (GTK_DIALOG (dialog),
+                                     GTK_RESPONSE_CANCEL);
+    
+    content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+
+    gtk_box_pack_start_defaults (GTK_BOX (content_area), gtk_label_new (message));
+    
+    if ( dkp->priv->can_hibernate && dkp->priv->auth_hibernate )
+    {
+	GtkWidget *hibernate;
+	hibernate = gtk_button_new_with_label (_("Hibernate"));
+	img = gtk_image_new_from_icon_name (XFPM_HIBERNATE_ICON, GTK_ICON_SIZE_BUTTON);
+	gtk_button_set_image (GTK_BUTTON (hibernate), img);
+	gtk_dialog_add_action_widget (GTK_DIALOG (dialog), hibernate, GTK_RESPONSE_NONE);
+	
+	g_signal_connect_swapped (hibernate, "clicked",
+			          G_CALLBACK (xfpm_dkp_hibernate_clicked), dkp);
+    }
+    
+    if ( dkp->priv->can_suspend && dkp->priv->auth_suspend )
+    {
+	GtkWidget *suspend;
+	
+	suspend = gtk_button_new_with_label (_("Suspend"));
+	img = gtk_image_new_from_icon_name (XFPM_SUSPEND_ICON, GTK_ICON_SIZE_BUTTON);
+	gtk_button_set_image (GTK_BUTTON (suspend), img);
+	gtk_dialog_add_action_widget (GTK_DIALOG (dialog), suspend, GTK_RESPONSE_NONE);
+	
+	g_signal_connect_swapped (suspend, "clicked",
+			          G_CALLBACK (xfpm_dkp_suspend_clicked), dkp);
+    }
+    
+    cancel = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
+    gtk_dialog_add_action_widget (GTK_DIALOG (dialog), cancel, GTK_RESPONSE_NONE);
+    
+    g_signal_connect_swapped (cancel, "clicked",
+			      G_CALLBACK (xfpm_dkp_close_critical_dialog), dkp);
+    
+    g_signal_connect_swapped (dialog, "destroy",
+			      G_CALLBACK (xfpm_dkp_close_critical_dialog), dkp);
+    
+    dkp->priv->dialog = dialog;
+    gtk_widget_show_all (dialog);
+}
+
+static void
+xfpm_dkp_show_critical_action (XfpmDkp *dkp, XfpmBattery *battery)
+{
+    gboolean supports_actions;
+    
+    g_object_get (G_OBJECT (dkp->priv->notify),
+		  "actions", &supports_actions,
+		  NULL);
+		  
+    if ( supports_actions )
+	xfpm_dkp_show_critical_action_notification (dkp, battery);
+    else
+	xfpm_dkp_show_critical_action_gtk (dkp);
+}
+
+static void
+xfpm_dkp_process_critical_action (XfpmDkp *dkp, XfpmShutdownRequest req)
+{
+    if ( req == XFPM_ASK )
+	g_signal_emit (G_OBJECT (dkp), signals [ASK_SHUTDOWN], 0);
+    else if ( req == XFPM_DO_SUSPEND )
+	xfpm_dkp_sleep (dkp, "Suspend", TRUE);
+    else if ( req == XFPM_DO_HIBERNATE )
+	xfpm_dkp_sleep (dkp, "Hibernate", TRUE);
+    //FIXME, Shutdown also.
+    
+}
+
+static void
+xfpm_dkp_system_on_low_power (XfpmDkp *dkp, XfpmBattery *battery)
+{
+    XfpmShutdownRequest critical_action;
+    
+    g_object_get (G_OBJECT (dkp->priv->conf),
+	          CRITICAL_BATT_ACTION_CFG, &critical_action,
+		  NULL);
+
+    TRACE ("System is running on low power");
+    XFPM_DEBUG_ENUM ("Critical battery action", critical_action, XFPM_TYPE_SHUTDOWN_REQUEST);
+
+    if ( critical_action == XFPM_DO_NOTHING )
+    {
+	xfpm_dkp_show_critical_action (dkp, battery);
+    }
+    else
+    {
+	xfpm_dkp_process_critical_action (dkp, critical_action);
+    }
+}
+
+static void
+xfpm_dkp_battery_charge_changed_cb (XfpmBattery *battery, XfpmDkp *dkp)
+{
+    XfpmBatteryCharge battery_charge;
+    XfpmBatteryCharge current_charge;
+    
+    battery_charge = xfpm_battery_get_charge (battery);
+    current_charge = xfpm_dkp_get_current_charge_state (dkp);
+    
+    if ( current_charge == XFPM_BATTERY_CHARGE_CRITICAL )
+    {
+	xfpm_dkp_system_on_low_power (dkp, battery);
+	return;
+    }
+    
+    if ( battery_charge == XFPM_BATTERY_CHARGE_LOW )
+    {
+	gboolean notify;
+	
+	g_object_get (G_OBJECT (dkp->priv->conf),
+		      GENERAL_NOTIFICATION_CFG, &notify,
+		      NULL);
+	if ( notify )
+	    xfpm_notify_show_notification (dkp->priv->notify, 
+					   _("Xfce power manager"), 
+					   _("Battery charge level is low"), 
+					   gtk_status_icon_get_icon_name (GTK_STATUS_ICON (battery)),
+					   10000,
+					   FALSE,
+					   XFPM_NOTIFY_NORMAL,
+					   GTK_STATUS_ICON (battery));
+    }
+    
+    /*Current charge is okay now, then close the dialog*/
+    if ( dkp->priv->dialog )
+    {
+	gtk_widget_destroy (dkp->priv->dialog);
+	dkp->priv->dialog = NULL;
+    }
+}
+
 static void
 xfpm_dkp_add_device (XfpmDkp *dkp, const gchar *object_path)
 {
@@ -554,7 +808,7 @@ xfpm_dkp_add_device (XfpmDkp *dkp, const gchar *object_path)
     
     if ( device_type == XFPM_DKP_DEVICE_TYPE_LINE_POWER )
     {
-	
+	//FIXME: Handel adaptor.
     }
     else if ( device_type == XFPM_DKP_DEVICE_TYPE_BATTERY || 
 	      device_type == XFPM_DKP_DEVICE_TYPE_UPS     ||
@@ -576,6 +830,8 @@ xfpm_dkp_add_device (XfpmDkp *dkp, const gchar *object_path)
 	g_signal_connect (battery, "popup-menu",
 			  G_CALLBACK (xfpm_dkp_show_tray_menu_battery), dkp);
 	
+	g_signal_connect (battery, "battery-charge-changed",
+			  G_CALLBACK (xfpm_dkp_battery_charge_changed_cb), dkp);
     }
     else 
     {
@@ -688,7 +944,6 @@ xfpm_dkp_class_init (XfpmDkpClass *klass)
     object_class->finalize = xfpm_dkp_finalize;
 
     object_class->get_property = xfpm_dkp_get_property;
-    object_class->set_property = xfpm_dkp_set_property;
 
     signals [ON_BATTERY_CHANGED] = 
         g_signal_new ("on-battery-changed",
@@ -735,6 +990,15 @@ xfpm_dkp_class_init (XfpmDkpClass *klass)
                       g_cclosure_marshal_VOID__VOID,
                       G_TYPE_NONE, 0, G_TYPE_NONE);
 
+    signals [ASK_SHUTDOWN] = 
+        g_signal_new ("ask-shutdown",
+                      XFPM_TYPE_DKP,
+                      G_SIGNAL_RUN_LAST,
+                      G_STRUCT_OFFSET(XfpmDkpClass, ask_shutdown),
+                      NULL, NULL,
+                      g_cclosure_marshal_VOID__VOID,
+                      G_TYPE_NONE, 0, G_TYPE_NONE);
+
     g_object_class_install_property (object_class,
                                      PROP_ON_BATTERY,
                                      g_param_spec_boolean ("on-battery",
@@ -798,6 +1062,7 @@ xfpm_dkp_init (XfpmDkp *dkp)
     dkp->priv->can_hibernate   = FALSE;
     dkp->priv->auth_hibernate  = TRUE;
     dkp->priv->auth_suspend    = TRUE;
+    dkp->priv->dialog          = NULL;
     
     dkp->priv->inhibit = xfpm_inhibit_new ();
     dkp->priv->notify  = xfpm_notify_new ();
@@ -845,7 +1110,7 @@ xfpm_dkp_init (XfpmDkp *dkp)
 #ifdef HAVE_POLKIT
     xfpm_dkp_check_polkit_auth (dkp);
 #endif
-    
+
     dbus_g_proxy_add_signal (dkp->priv->proxy, "Changed", G_TYPE_INVALID);
     dbus_g_proxy_add_signal (dkp->priv->proxy, "DeviceAdded", G_TYPE_STRING, G_TYPE_INVALID);
     dbus_g_proxy_add_signal (dkp->priv->proxy, "DeviceRemoved", G_TYPE_STRING, G_TYPE_INVALID);
@@ -864,29 +1129,13 @@ xfpm_dkp_init (XfpmDkp *dkp)
     
 out:
     xfpm_dkp_dbus_init (dkp);
-    
+
     /*
      * Emit org.freedesktop.PowerManagement session signals on startup
      */
     g_signal_emit (G_OBJECT (dkp), signals [ON_BATTERY_CHANGED], 0, dkp->priv->on_battery);
 }
 
-static void xfpm_dkp_set_property (GObject *object,
-				   guint prop_id,
-				   const GValue *value,
-				   GParamSpec *pspec)
-{
-    XfpmDkp *dkp;
-    dkp = XFPM_DKP (object);
-
-    switch (prop_id)
-    {
-         default:
-            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-            break;
-    }
-}
-
 static void xfpm_dkp_get_property (GObject *object,
 				   guint prop_id,
 				   GValue *value,
diff --git a/src/xfpm-dkp.h b/src/xfpm-dkp.h
index f99a1a9..e928831 100644
--- a/src/xfpm-dkp.h
+++ b/src/xfpm-dkp.h
@@ -87,6 +87,8 @@ typedef struct
     
     void		(*sleeping)			(XfpmDkp *dkp);
     
+    void		(*ask_shutdown)			(XfpmDkp *dkp);
+    
 } XfpmDkpClass;
 
 GType        		xfpm_dkp_get_type        	(void) G_GNUC_CONST;
diff --git a/src/xfpm-manager.c b/src/xfpm-manager.c
index d1c0720..822b8b4 100644
--- a/src/xfpm-manager.c
+++ b/src/xfpm-manager.c
@@ -170,6 +170,13 @@ xfpm_manager_reserve_names (XfpmManager *manager)
 }
 
 static void
+xfpm_manager_ask_shutdown (XfpmManager *manager)
+{
+    if ( manager->priv->session_managed )
+	xfce_sm_client_request_shutdown (manager->priv->client, XFCE_SM_CLIENT_SHUTDOWN_HINT_ASK);
+}
+
+static void
 xfpm_manager_sleep_request (XfpmManager *manager, XfpmShutdownRequest req, gboolean force)
 {
     switch (req)
@@ -186,7 +193,7 @@ xfpm_manager_sleep_request (XfpmManager *manager, XfpmShutdownRequest req, gbool
 	    /*FIXME ConsoleKit*/
 	    break;
 	case XFPM_ASK:
-	    xfce_sm_client_request_shutdown (manager->priv->client, XFCE_SM_CLIENT_SHUTDOWN_HINT_ASK);
+	    xfpm_manager_ask_shutdown (manager);
 	    break;
 	default:
 	    g_warn_if_reached ();
@@ -235,8 +242,8 @@ xfpm_manager_button_pressed_cb (XfpmButton *bt, XfpmButtonKey type, XfpmManager
 
     XFPM_DEBUG_ENUM ("Shutdown request : ", req, XFPM_TYPE_SHUTDOWN_REQUEST);
         
-    if ( req == XFPM_ASK && manager->priv->session_managed )
-        xfce_sm_client_request_shutdown (manager->priv->client, XFCE_SM_CLIENT_SHUTDOWN_HINT_ASK);
+    if ( req == XFPM_ASK )
+	xfpm_manager_ask_shutdown (manager);
     else
     {
 	if ( g_timer_elapsed (manager->priv->timer, NULL) > SLEEP_KEY_TIMEOUT )
@@ -245,7 +252,6 @@ xfpm_manager_button_pressed_cb (XfpmButton *bt, XfpmButtonKey type, XfpmManager
 	    xfpm_manager_sleep_request (manager, req, FALSE);
 	}
     }
-    
 }
 
 static void
@@ -376,6 +382,9 @@ void xfpm_manager_start (XfpmManager *manager)
     
     g_signal_connect_swapped (manager->priv->dkp, "sleeping",
 			      G_CALLBACK (xfpm_manager_reset_sleep_timer), manager);
+			      
+    g_signal_connect_swapped (manager->priv->dkp, "ask-shutdown",
+			      G_CALLBACK (xfpm_manager_ask_shutdown), manager);
 out:
 	;
 }
diff --git a/src/xfpm-notify.c b/src/xfpm-notify.c
index 89a78bb..38d5bef 100644
--- a/src/xfpm-notify.c
+++ b/src/xfpm-notify.c
@@ -44,6 +44,7 @@
 
 #include "xfpm-common.h"
 #include "xfpm-notify.h"
+#include "xfpm-dbus-monitor.h"
 
 static void xfpm_notify_finalize   (GObject *object);
 
@@ -59,45 +60,132 @@ static NotifyNotification * xfpm_notify_new_notification_internal (const gchar *
 
 struct XfpmNotifyPrivate
 {
+    XfpmDBusMonitor    *monitor;
+    
     NotifyNotification *notification;
     NotifyNotification *critical;
+    
+    gboolean	        supports_actions;
+    gboolean		supports_sync; /*For x-canonical-private-synchronous */
 };
 
-static gpointer xfpm_notify_object = NULL;
+enum
+{
+    PROP_0,
+    PROP_ACTIONS,
+    PROP_SYNC
+};
 
 G_DEFINE_TYPE(XfpmNotify, xfpm_notify, G_TYPE_OBJECT)
 
 static void
-xfpm_notify_class_init(XfpmNotifyClass *klass)
+xfpm_notify_get_server_caps (XfpmNotify *notify)
 {
-    GObjectClass *object_class = G_OBJECT_CLASS(klass);
+    GList *caps = NULL;
+    notify->priv->supports_actions = FALSE;
+    notify->priv->supports_sync    = FALSE;
+    
+    caps = notify_get_server_caps ();
+    
+    if (caps != NULL) 
+    {
+	if (g_list_find_custom (caps, "x-canonical-private-synchronous", (GCompareFunc) g_strcmp0) != NULL)
+	    notify->priv->supports_sync = TRUE;
+    
+	if (g_list_find_custom (caps, "actions", (GCompareFunc) g_strcmp0) != NULL)
+	    notify->priv->supports_actions = TRUE;
 
-    object_class->finalize = xfpm_notify_finalize;
+	g_list_foreach(caps, (GFunc)g_free, NULL);
+	g_list_free(caps);
+    }
+}
 
+static void
+xfpm_notify_check_server (XfpmDBusMonitor *monitor, 
+			  gchar *service_name, 
+			  gboolean connected,
+			  gboolean on_session,
+			  XfpmNotify *notify)
+{
+    if ( !g_strcmp0 (service_name, "org.freedesktop.Notifications") && on_session && connected )
+	xfpm_notify_get_server_caps (notify);
+}
 
-    g_type_class_add_private(klass,sizeof(XfpmNotifyPrivate));
+static void xfpm_notify_get_property (GObject *object,
+				      guint prop_id,
+				      GValue *value,
+				      GParamSpec *pspec)
+{
+    XfpmNotify *notify;
+    
+    notify = XFPM_NOTIFY (object);
+    
+    switch (prop_id)
+    {
+	case PROP_ACTIONS:
+	    g_value_set_boolean (value, notify->priv->supports_actions);
+	    break;
+	case PROP_SYNC:
+	    g_value_set_boolean (value, notify->priv->supports_sync);
+	    break;
+	default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+            break;
+    }
+}
+
+static void
+xfpm_notify_class_init (XfpmNotifyClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+    object_class->finalize = xfpm_notify_finalize;
+    object_class->get_property = xfpm_notify_get_property;
+
+    g_object_class_install_property (object_class,
+                                     PROP_ACTIONS,
+                                     g_param_spec_boolean ("actions",
+                                                           NULL, NULL,
+                                                           FALSE,
+                                                           G_PARAM_READABLE));
+
+    g_object_class_install_property (object_class,
+                                     PROP_SYNC,
+                                     g_param_spec_boolean ("sync",
+                                                           NULL, NULL,
+                                                           FALSE,
+                                                           G_PARAM_READABLE));
+
+    g_type_class_add_private (klass, sizeof (XfpmNotifyPrivate));
 }
 
 static void
-xfpm_notify_init(XfpmNotify *notify)
+xfpm_notify_init (XfpmNotify *notify)
 {
-    notify->priv = XFPM_NOTIFY_GET_PRIVATE(notify);
+    notify->priv = XFPM_NOTIFY_GET_PRIVATE (notify);
     
     notify->priv->notification = NULL;
     notify->priv->critical = NULL;
+    
+    notify->priv->monitor = xfpm_dbus_monitor_new ();
+    xfpm_dbus_monitor_add_service (notify->priv->monitor, DBUS_BUS_SESSION, "org.freedesktop.Notifications");
+    g_signal_connect (notify->priv->monitor, "service-connection-changed",
+		      G_CALLBACK (xfpm_notify_check_server), notify);
+    
+    xfpm_notify_get_server_caps (notify);
 }
 
 static void
-xfpm_notify_finalize(GObject *object)
+xfpm_notify_finalize (GObject *object)
 {
     XfpmNotify *notify;
 
-    notify = XFPM_NOTIFY(object);
+    notify = XFPM_NOTIFY (object);
     
     xfpm_notify_close_normal (notify);
     xfpm_notify_close_critical (notify);
     
-    G_OBJECT_CLASS(xfpm_notify_parent_class)->finalize(object);
+    G_OBJECT_CLASS (xfpm_notify_parent_class)->finalize(object);
 }
 
 static void
@@ -172,6 +260,8 @@ xfpm_notify_close_notification (XfpmNotify *notify )
 XfpmNotify *
 xfpm_notify_new (void)
 {
+    static gpointer xfpm_notify_object = NULL;
+    
     if ( xfpm_notify_object != NULL )
     {
 	g_object_ref (xfpm_notify_object);
diff --git a/src/xfpm-xfconf.c b/src/xfpm-xfconf.c
index 9356269..359d0c6 100644
--- a/src/xfpm-xfconf.c
+++ b/src/xfpm-xfconf.c
@@ -234,7 +234,7 @@ xfpm_xfconf_class_init (XfpmXfconfClass *klass)
                                      PROP_CRITICAL_LEVEL,
                                      g_param_spec_uint (CRITICAL_POWER_LEVEL,
                                                         NULL, NULL,
-							5,
+							1,
 							20,
 							10,
                                                         G_PARAM_READWRITE));



More information about the Xfce4-commits mailing list