Author: kelnos Date: 2009-07-19 21:51:54 +0000 (Sun, 19 Jul 2009) New Revision: 30356
Modified: xfce4-session/trunk/xfce4-session/shutdown.c xfce4-session/trunk/xfce4-session/xfsm-shutdown-helper.c Log: add org.freedesktop.PowerManagement support for logout actions Modified: xfce4-session/trunk/xfce4-session/shutdown.c =================================================================== --- xfce4-session/trunk/xfce4-session/shutdown.c 2009-07-19 19:00:59 UTC (rev 30355) +++ xfce4-session/trunk/xfce4-session/shutdown.c 2009-07-19 21:51:54 UTC (rev 30356) @@ -252,6 +252,10 @@ 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 @@ 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 @@ 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 @@ } /* suspend */ - if (show_suspend) + if (kiosk_can_shutdown && show_suspend) { suspend_button = gtk_button_new (); gtk_widget_show (suspend_button); @@ -488,7 +503,7 @@ } /* hibernate */ - if (show_hibernate) + if (kiosk_can_shutdown && show_hibernate) { hibernate_button = gtk_button_new (); gtk_widget_show (hibernate_button); @@ -536,23 +551,6 @@ /* 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) { Modified: xfce4-session/trunk/xfce4-session/xfsm-shutdown-helper.c =================================================================== --- xfce4-session/trunk/xfce4-session/xfsm-shutdown-helper.c 2009-07-19 19:00:59 UTC (rev 30355) +++ xfce4-session/trunk/xfce4-session/xfsm-shutdown-helper.c 2009-07-19 21:51:54 UTC (rev 30356) @@ -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 @@ 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 @@ 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,21 +122,192 @@ } + 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; - connection = xfsm_shutdown_helper_dbus_connect (error); + /* 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); + + 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; + /* initialize the error */ dbus_error_init (&derror); @@ -152,11 +333,6 @@ { /* 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 @@ /* 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 @@ 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 @@ 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 @@ 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 @@ /* 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 @@ 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,9 +773,12 @@ 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 @@ 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); - default: - return TRUE; - } + 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; + } + break; } g_assert_not_reached(); _______________________________________________ Xfce4-commits mailing list Xfce4-commits@xfce.org http://foo-projects.org/mailman/listinfo/xfce4-commits