diff options
author | Brian Tarricone <brian@tarricone.org> | 2009-07-19 21:51:54 +0000 |
---|---|---|
committer | Brian Tarricone <brian@tarricone.org> | 2009-07-19 21:51:54 +0000 |
commit | 1bfeae1b8103302d57abbfe586929e5812cd181c (patch) | |
tree | f75eb8773f30cfb6ac2782b4dbc32746db92511b | |
parent | 7a4c721c618bcda92c33d21128186909b6a323d1 (diff) | |
download | xfce4-session-1bfeae1b8103302d57abbfe586929e5812cd181c.tar.gz |
add org.freedesktop.PowerManagement support for logout actions
(Old svn revision: 30356)
-rw-r--r-- | xfce4-session/shutdown.c | 38 | ||||
-rw-r--r-- | xfce4-session/xfsm-shutdown-helper.c | 315 |
2 files changed, 273 insertions, 80 deletions
diff --git a/xfce4-session/shutdown.c b/xfce4-session/shutdown.c index 49f72fdf..cbb3b7bf 100644 --- a/xfce4-session/shutdown.c +++ b/xfce4-session/shutdown.c @@ -252,6 +252,10 @@ shutdownDialog(const gchar *sessionName, XfsmShutdownType *shutdownType, gboolea return TRUE; } + /* spawn the helper early so we know what it supports when + * constructing the dialog */ + shutdown_helper = xfsm_shutdown_helper_spawn (NULL); + /* It's really bad here if someone else has the pointer * grabbed, so we first grab the pointer and keyboard * to an offscreen window, and then once we have the @@ -426,6 +430,9 @@ shutdownDialog(const gchar *sessionName, XfsmShutdownType *shutdownType, gboolea label = gtk_label_new (_("Restart")); gtk_widget_show (label); gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, FALSE, 0); + + if (!kiosk_can_shutdown || !xfsm_shutdown_helper_supports (shutdown_helper, XFSM_SHUTDOWN_REBOOT)) + gtk_widget_set_sensitive (reboot_button, FALSE); /* halt */ halt_button = gtk_button_new (); @@ -451,8 +458,16 @@ shutdownDialog(const gchar *sessionName, XfsmShutdownType *shutdownType, gboolea label = gtk_label_new (_("Shut Down")); gtk_widget_show (label); gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, FALSE, 0); + + if (!kiosk_can_shutdown || !xfsm_shutdown_helper_supports (shutdown_helper, XFSM_SHUTDOWN_HALT)) + gtk_widget_set_sensitive (halt_button, FALSE); + + if (show_suspend) + show_suspend = xfsm_shutdown_helper_supports (shutdown_helper, XFSM_SHUTDOWN_SUSPEND); + if (show_hibernate) + show_hibernate = xfsm_shutdown_helper_supports (shutdown_helper, XFSM_SHUTDOWN_HIBERNATE); - if (show_suspend || show_hibernate) + if (kiosk_can_shutdown && (show_suspend || show_hibernate)) { hbox = gtk_hbox_new (FALSE, BORDER); gtk_widget_show (hbox); @@ -460,7 +475,7 @@ shutdownDialog(const gchar *sessionName, XfsmShutdownType *shutdownType, gboolea } /* suspend */ - if (show_suspend) + if (kiosk_can_shutdown && show_suspend) { suspend_button = gtk_button_new (); gtk_widget_show (suspend_button); @@ -488,7 +503,7 @@ shutdownDialog(const gchar *sessionName, XfsmShutdownType *shutdownType, gboolea } /* hibernate */ - if (show_hibernate) + if (kiosk_can_shutdown && show_hibernate) { hibernate_button = gtk_button_new (); gtk_widget_show (hibernate_button); @@ -536,23 +551,6 @@ shutdownDialog(const gchar *sessionName, XfsmShutdownType *shutdownType, gboolea /* center dialog on target monitor */ xfce_gtk_window_center_on_monitor (GTK_WINDOW (dialog), screen, monitor); - /* connect to the shutdown helper */ - if (!kiosk_can_shutdown || - (shutdown_helper = xfsm_shutdown_helper_spawn (NULL)) == NULL) - { - gtk_widget_set_sensitive (reboot_button, FALSE); - gtk_widget_set_sensitive (halt_button, FALSE); - if (suspend_button) - gtk_widget_set_sensitive (suspend_button, FALSE); - if (hibernate_button) - gtk_widget_set_sensitive (hibernate_button, FALSE); - } - - if (suspend_button && !xfsm_shutdown_helper_supports (shutdown_helper, XFSM_SHUTDOWN_SUSPEND)) - gtk_widget_hide (suspend_button); - if (hibernate_button && !xfsm_shutdown_helper_supports (shutdown_helper, XFSM_SHUTDOWN_HIBERNATE)) - gtk_widget_hide (hibernate_button); - /* save portion of the root window covered by the dialog */ if (!accessibility && shutdown_helper != NULL) { diff --git a/xfce4-session/xfsm-shutdown-helper.c b/xfce4-session/xfsm-shutdown-helper.c index bcb99404..ce319e27 100644 --- a/xfce4-session/xfsm-shutdown-helper.c +++ b/xfce4-session/xfsm-shutdown-helper.c @@ -65,6 +65,14 @@ #include "shutdown.h" #include "xfsm-shutdown-helper.h" +typedef enum +{ + XFSM_SHUTDOWN_SUDO = 0, + XFSM_SHUTDOWN_HAL, + XFSM_SHUTDOWN_POWER_MANAGER, +} XfsmShutdownBackend; + + static struct { XfsmShutdownType command; @@ -79,17 +87,19 @@ static struct struct _XfsmShutdownHelper { - gchar *sudo; - pid_t pid; - FILE *infile; - FILE *outfile; - gboolean use_hal; - gboolean need_password; + XfsmShutdownBackend backend; + + gchar *sudo; + pid_t pid; + FILE *infile; + FILE *outfile; + gboolean need_password; }; static DBusConnection * -xfsm_shutdown_helper_dbus_connect (GError **error) +xfsm_shutdown_helper_dbus_connect (DBusBusType bus_type, + GError **error) { DBusConnection *connection; DBusError derror; @@ -98,7 +108,7 @@ xfsm_shutdown_helper_dbus_connect (GError **error) dbus_error_init (&derror); /* connect to the system message bus */ - connection = dbus_bus_get (DBUS_BUS_SYSTEM, &derror); + connection = dbus_bus_get (bus_type, &derror); if (G_UNLIKELY (connection == NULL)) { g_warning (G_STRLOC ": Failed to connect to the system message bus: %s", derror.message); @@ -112,18 +122,189 @@ xfsm_shutdown_helper_dbus_connect (GError **error) } + static gboolean -xfsm_shutdown_helper_hal_check (XfsmShutdownHelper *helper, - GError **error) +xfsm_shutdown_helper_pm_check (XfsmShutdownHelper *helper) { DBusConnection *connection; DBusMessage *message; DBusMessage *result; DBusError derror; - g_return_val_if_fail (helper && (!error || !*error), FALSE); + connection = xfsm_shutdown_helper_dbus_connect (DBUS_BUS_SESSION, NULL); + if (!connection) + return FALSE; + + /* older versions of xfce4-power-manager didn't have the 'CanReboot' + * method, so we'll key off that one to check for support. */ + message = dbus_message_new_method_call ("org.freedesktop.PowerManagement", + "/org/freedesktop/PowerManagement", + "org.freedesktop.PowerManagement", + "CanReboot"); + + dbus_error_init(&derror); + result = dbus_connection_send_with_reply_and_block (connection, message, -1, &derror); + dbus_message_unref (message); - connection = xfsm_shutdown_helper_dbus_connect (error); + if (result == NULL) + { + g_debug (G_STRLOC ": Failed to contact PM: %s", derror.message); + dbus_error_free (&derror); + return FALSE; + } + else if (dbus_set_error_from_message (&derror, result)) + { + g_debug (G_STRLOC ": Error talking to PM: %s", derror.message); + dbus_message_unref (result); + dbus_error_free (&derror); + /* PM running, but is broken */ + return FALSE; + } + else + { + /* it doesn't matter what the response is, but it's valid, so + * we can use the PM */ + dbus_message_unref (result); + return TRUE; + } +} + + + +static gboolean +xfsm_shutdown_helper_pm_send (XfsmShutdownHelper *helper, + XfsmShutdownType command, + GError **error) +{ + DBusConnection *connection; + const char *methodname; + DBusMessage *message; + DBusMessage *result; + DBusError derror; + guint i; + + for (i = 0; i < G_N_ELEMENTS (command_name_map); i++) + { + if (command_name_map[i].command == command) + { + methodname = command_name_map[i].name; + break; + } + } + + if (!methodname) + { + if (error) + { + g_set_error (error, DBUS_GERROR, DBUS_GERROR_INVALID_ARGS, + "%s", _("Invalid shutdown type")); + } + return FALSE; + } + + connection = xfsm_shutdown_helper_dbus_connect (DBUS_BUS_SESSION, error); + if (G_UNLIKELY (!connection)) + return FALSE; + + message = dbus_message_new_method_call ("org.freedesktop.PowerManagement", + "/org/freedesktop/PowerManagement", + "org.freedesktop.PowerManagement", + methodname); + + dbus_error_init (&derror); + result = dbus_connection_send_with_reply_and_block (connection, message, -1, &derror); + dbus_message_unref (message); + + if (!result) + { + if (error) + dbus_set_g_error (error, &derror); + dbus_error_free (&derror); + return FALSE; + } + else if (dbus_set_error_from_message (&derror, result)) + { + dbus_message_unref (result); + if (error) + { + dbus_set_g_error (error, &derror); + } + dbus_error_free (&derror); + return FALSE; + } + + return TRUE; +} + + + +static gboolean +xfsm_shutdown_helper_check_pm_cap (const char *capability) +{ + DBusConnection *connection; + char method[64]; + DBusMessage *message; + DBusMessage *result; + DBusError derror; + dbus_bool_t response = FALSE; + + connection = xfsm_shutdown_helper_dbus_connect (DBUS_BUS_SESSION, NULL); + if (!connection) + return FALSE; + + g_strlcpy (method, "Can", sizeof (method)); + g_strlcat (method, capability, sizeof (method)); + + message = dbus_message_new_method_call ("org.freedesktop.PowerManagement", + "/org/freedesktop/PowerManagement", + "org.freedesktop.PowerManagement", + method); + + dbus_error_init(&derror); + result = dbus_connection_send_with_reply_and_block (connection, message, -1, &derror); + dbus_message_unref (message); + + if (G_UNLIKELY (result == NULL)) + { + g_warning (G_STRLOC ": Failed to contact PM: %s", derror.message); + dbus_error_free (&derror); + return FALSE; + } + + if (!result) + return FALSE; + + if (dbus_set_error_from_message (&derror, result)) + { + dbus_error_free (&derror); + response = FALSE; + } + else if (!dbus_message_get_args (result, &derror, + DBUS_TYPE_BOOLEAN, &response, + DBUS_TYPE_INVALID)) + { + dbus_error_free (&derror); + response = FALSE; + } + + dbus_message_unref (result); + + return response; +} + + + +static gboolean +xfsm_shutdown_helper_hal_check (XfsmShutdownHelper *helper) +{ + DBusConnection *connection; + DBusMessage *message; + DBusMessage *result; + DBusError derror; + + g_return_val_if_fail (helper, FALSE); + + connection = xfsm_shutdown_helper_dbus_connect (DBUS_BUS_SYSTEM, NULL); if (!connection) return FALSE; @@ -152,11 +333,6 @@ xfsm_shutdown_helper_hal_check (XfsmShutdownHelper *helper, { /* we received a valid message return?! HAL must be on crack! */ dbus_message_unref (result); - if (error) - { - g_set_error (error, DBUS_GERROR, DBUS_GERROR_FAILED, - _("Unexpected error from HAL")); - } return FALSE; } @@ -171,8 +347,6 @@ xfsm_shutdown_helper_hal_check (XfsmShutdownHelper *helper, /* otherwise, we failed for some reason */ g_warning (G_STRLOC ": Failed to contact HAL: %s", derror.message); - if (error) - dbus_set_g_error (error, &derror); dbus_error_free (&derror); return FALSE; @@ -193,11 +367,6 @@ xfsm_shutdown_helper_hal_send (XfsmShutdownHelper *helper, dbus_int32_t wakeup = 0; guint i; - /* FIXME: would rather not call this here, but it's nice to be able - * to get a correct error message */ - if (!xfsm_shutdown_helper_hal_check (helper, error)) - return FALSE; - for (i = 0; i < G_N_ELEMENTS (command_name_map); i++) { if (command_name_map[i].command == command) @@ -217,7 +386,7 @@ xfsm_shutdown_helper_hal_send (XfsmShutdownHelper *helper, return FALSE; } - connection = xfsm_shutdown_helper_dbus_connect (error); + connection = xfsm_shutdown_helper_dbus_connect (DBUS_BUS_SYSTEM, error); if(!connection) return FALSE; @@ -264,7 +433,7 @@ xfsm_shutdown_helper_check_hal_property (const gchar *object_path, DBusError derror; dbus_bool_t response = FALSE; - connection = xfsm_shutdown_helper_dbus_connect (NULL); + connection = xfsm_shutdown_helper_dbus_connect (DBUS_BUS_SYSTEM, NULL); if (!connection) return FALSE; @@ -329,12 +498,20 @@ xfsm_shutdown_helper_spawn (GError **error) /* allocate a new helper */ helper = g_new0 (XfsmShutdownHelper, 1); + /* first choice is the power manager */ + if (xfsm_shutdown_helper_pm_check (helper)) + { + g_message (G_STRLOC ": Using PM to shutdown/reboot the computer."); + helper->backend = XFSM_SHUTDOWN_POWER_MANAGER; + return helper; + } + /* check if we can use HAL to shutdown the computer */ - if (xfsm_shutdown_helper_hal_check (helper, NULL)) + if (xfsm_shutdown_helper_hal_check (helper)) { /* well that's it then */ g_message (G_STRLOC ": Using HAL to shutdown/reboot the computer."); - helper->use_hal = TRUE; + helper->backend = XFSM_SHUTDOWN_HAL; return helper; } @@ -517,7 +694,7 @@ xfsm_shutdown_helper_send_password (XfsmShutdownHelper *helper, g_return_val_if_fail (helper != NULL, FALSE); g_return_val_if_fail (password != NULL, FALSE); - g_return_val_if_fail (!helper->use_hal, FALSE); + g_return_val_if_fail (helper->backend == XFSM_SHUTDOWN_SUDO, FALSE); g_return_val_if_fail (helper->need_password, FALSE); g_snprintf (buffer, 1024, "%s\n", password); @@ -596,8 +773,11 @@ xfsm_shutdown_helper_send_command (XfsmShutdownHelper *helper, g_return_val_if_fail (!error || !*error, FALSE); g_return_val_if_fail (command != XFSM_SHUTDOWN_ASK, FALSE); - /* check if we can use HAL to perform the requested action */ - if (G_LIKELY (helper->use_hal)) + if (helper->backend == XFSM_SHUTDOWN_POWER_MANAGER) + { + return xfsm_shutdown_helper_pm_send (helper, command, error); + } + else if (helper->backend == XFSM_SHUTDOWN_HAL) { /* well, send the command to HAL then */ return xfsm_shutdown_helper_hal_send (helper, command, error); @@ -673,41 +853,56 @@ gboolean xfsm_shutdown_helper_supports (XfsmShutdownHelper *helper, XfsmShutdownType shutdown_type) { - if (helper->use_hal) + const char *method_name = NULL; + guint i; + + if (!helper) + return FALSE; + + switch (helper->backend) { - switch (shutdown_type) - { - case XFSM_SHUTDOWN_SUSPEND: - if (xfsm_shutdown_helper_check_hal_property ("/org/freedesktop/Hal/devices/computer", - "power_management.can_suspend")) + case XFSM_SHUTDOWN_POWER_MANAGER: + for (i = 0; i < G_N_ELEMENTS (command_name_map); i++) + { + if (command_name_map[i].command == shutdown_type) { - return TRUE; + method_name = command_name_map[i].name; + break; } - return FALSE; + } - case XFSM_SHUTDOWN_HIBERNATE: - if (xfsm_shutdown_helper_check_hal_property ("/org/freedesktop/Hal/devices/computer", - "power_management.can_hibernate")) - { - return TRUE; - } - return FALSE; + if (G_UNLIKELY (!method_name)) + return FALSE; - default: - return TRUE; - } - } - else - { - switch (shutdown_type) - { - case XFSM_SHUTDOWN_SUSPEND: - case XFSM_SHUTDOWN_HIBERNATE: - return FALSE; + return xfsm_shutdown_helper_check_pm_cap (method_name); + + case XFSM_SHUTDOWN_HAL: + switch (shutdown_type) + { + case XFSM_SHUTDOWN_SUSPEND: + return xfsm_shutdown_helper_check_hal_property ("/org/freedesktop/Hal/devices/computer", + "power_management.can_suspend"); + + case XFSM_SHUTDOWN_HIBERNATE: + return xfsm_shutdown_helper_check_hal_property ("/org/freedesktop/Hal/devices/computer", + "power_management.can_hibernate"); + + default: + return TRUE; + } + break; + + case XFSM_SHUTDOWN_SUDO: + switch (shutdown_type) + { + case XFSM_SHUTDOWN_SUSPEND: + case XFSM_SHUTDOWN_HIBERNATE: + return FALSE; - default: - return TRUE; - } + default: + return TRUE; + } + break; } g_assert_not_reached(); |