diff -up gnome-panel-2.22.0/gnome-panel/Makefile.am.ck-shutdown gnome-panel-2.22.0/gnome-panel/Makefile.am --- gnome-panel-2.22.0/gnome-panel/Makefile.am.ck-shutdown 2008-03-10 16:44:57.000000000 -0400 +++ gnome-panel-2.22.0/gnome-panel/Makefile.am 2008-04-05 20:48:37.000000000 -0400 @@ -16,6 +16,7 @@ INCLUDES = \ $(STANDARD_PROPERTIES_CFLAGS) \ $(PANEL_CFLAGS) \ $(PANELCONFIG_CFLAGS) \ + $(POLKIT_GNOME_CFLAGS) \ $(WARN_CFLAGS) \ $(NULL) @@ -98,6 +99,7 @@ panel_sources = \ panel-logout.c \ panel-gdm.c \ panel-power-manager.c \ + panel-consolekit.c \ panel-ditem-editor.c \ panel-mount-operation.c \ $(NULL) @@ -148,6 +150,7 @@ panel_headers = \ panel-logout.h \ panel-gdm.h \ panel-power-manager.h \ + panel-consolekit.h \ panel-ditem-editor.h \ panel-icon-names.h \ panel-mount-operation.h \ @@ -161,6 +164,7 @@ gnome_panel_SOURCES = \ gnome_panel_LDADD = \ $(PANEL_LIBS) \ + $(POLKIT_GNOME_LIBS) \ $(X_LIBS) gnome_panel_LDFLAGS = -export-dynamic diff -up gnome-panel-2.22.0/gnome-panel/panel-action-button.c.ck-shutdown gnome-panel-2.22.0/gnome-panel/panel-action-button.c --- gnome-panel-2.22.0/gnome-panel/panel-action-button.c.ck-shutdown 2008-04-05 20:48:37.000000000 -0400 +++ gnome-panel-2.22.0/gnome-panel/panel-action-button.c 2008-04-05 20:48:37.000000000 -0400 @@ -46,7 +46,6 @@ #include "panel-lockdown.h" #include "panel-logout.h" #include "panel-compatibility.h" -#include "panel-gdm.h" #include "panel-icon-names.h" G_DEFINE_TYPE (PanelActionButton, panel_action_button, BUTTON_TYPE_WIDGET); @@ -183,8 +182,7 @@ static gboolean panel_action_shutdown_reboot_is_disabled (void) { return (panel_lockdown_get_disable_log_out() || - (!gdm_supports_logout_action (GDM_LOGOUT_ACTION_SHUTDOWN) && - !gdm_supports_logout_action (GDM_LOGOUT_ACTION_REBOOT))); + !panel_logout_supports_shutdown_reboot); } /* Run Application diff -up /dev/null gnome-panel-2.22.0/gnome-panel/panel-consolekit.c --- /dev/null 2008-04-05 22:04:35.194004710 -0400 +++ gnome-panel-2.22.0/gnome-panel/panel-consolekit.c 2008-04-05 20:48:37.000000000 -0400 @@ -0,0 +1,682 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2008 Jon McCann + * + * 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, 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. + */ + +#include "config.h" + +#include +#include +#include + +#include +#include +#include + +#include + +#ifdef HAVE_POLKIT +#include +#endif + +#include "panel-consolekit.h" + +#define CK_NAME "org.freedesktop.ConsoleKit" +#define CK_PATH "/org/freedesktop/ConsoleKit" +#define CK_INTERFACE "org.freedesktop.ConsoleKit" + +#define CK_MANAGER_PATH "/org/freedesktop/ConsoleKit/Manager" +#define CK_MANAGER_INTERFACE "org.freedesktop.ConsoleKit.Manager" +#define CK_SEAT_INTERFACE "org.freedesktop.ConsoleKit.Seat" +#define CK_SESSION_INTERFACE "org.freedesktop.ConsoleKit.Session" + +#define PANEL_CONSOLEKIT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PANEL_TYPE_CONSOLEKIT, PanelConsolekitPrivate)) + +struct _PanelConsolekitPrivate { + DBusGConnection *dbus_connection; + DBusGProxy *bus_proxy; + DBusGProxy *ck_proxy; + guint32 is_connected : 1; +}; + +enum { + PROP_0 = 0, + PROP_IS_CONNECTED +}; + +enum { + REQUEST_COMPLETED = 0, + LAST_SIGNAL +}; + +static guint signals [LAST_SIGNAL]; + +static void panel_consolekit_class_init (PanelConsolekitClass *klass); +static void panel_consolekit_init (PanelConsolekit *ck); +static void panel_consolekit_finalize (GObject *object); +static void panel_consolekit_on_name_owner_changed (DBusGProxy *bus_proxy, + const char *name, + const char *prev_owner, + const char *new_owner, + PanelConsolekit *manager); + +G_DEFINE_TYPE (PanelConsolekit, panel_consolekit, G_TYPE_OBJECT); + +static void +panel_consolekit_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + PanelConsolekit *manager = PANEL_CONSOLEKIT (object); + + switch (prop_id) { + case PROP_IS_CONNECTED: + g_value_set_boolean (value, + manager->priv->is_connected); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, + prop_id, + pspec); + } +} + +static void +panel_consolekit_class_init (PanelConsolekitClass *manager_class) +{ + GObjectClass *object_class; + GParamSpec *param_spec; + + object_class = G_OBJECT_CLASS (manager_class); + + object_class->finalize = panel_consolekit_finalize; + object_class->get_property = panel_consolekit_get_property; + + param_spec = g_param_spec_boolean ("is-connected", + "Is connected", + "Whether the panel is connected to ConsoleKit", + FALSE, + G_PARAM_READABLE); + g_object_class_install_property (object_class, PROP_IS_CONNECTED, + param_spec); + + signals [REQUEST_COMPLETED] = + g_signal_new ("request-completed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (PanelConsolekitClass, request_completed), + NULL, + NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, + 1, G_TYPE_POINTER); + + g_type_class_add_private (manager_class, + sizeof (PanelConsolekitPrivate)); +} + +static gboolean +panel_consolekit_ensure_ck_connection (PanelConsolekit *manager, + GError **error) +{ + GError *connection_error; + gboolean is_connected; + + connection_error = NULL; + if (manager->priv->dbus_connection == NULL) { + manager->priv->dbus_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, + &connection_error); + + if (manager->priv->dbus_connection == NULL) { + g_propagate_error (error, connection_error); + is_connected = FALSE; + goto out; + } + } + + if (manager->priv->bus_proxy == NULL) { + manager->priv->bus_proxy = + dbus_g_proxy_new_for_name_owner (manager->priv->dbus_connection, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + &connection_error); + + if (manager->priv->bus_proxy == NULL) { + g_propagate_error (error, connection_error); + is_connected = FALSE; + goto out; + } + + dbus_g_proxy_add_signal (manager->priv->bus_proxy, + "NameOwnerChanged", + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_INVALID); + dbus_g_proxy_connect_signal (manager->priv->bus_proxy, + "NameOwnerChanged", + G_CALLBACK (panel_consolekit_on_name_owner_changed), + manager, NULL); + } + + if (manager->priv->ck_proxy == NULL) { + manager->priv->ck_proxy = + dbus_g_proxy_new_for_name_owner (manager->priv->dbus_connection, + "org.freedesktop.ConsoleKit", + "/org/freedesktop/ConsoleKit/Manager", + "org.freedesktop.ConsoleKit.Manager", + &connection_error); + + if (manager->priv->ck_proxy == NULL) { + g_propagate_error (error, connection_error); + is_connected = FALSE; + goto out; + } + } + is_connected = TRUE; + +out: + if (manager->priv->is_connected != is_connected) { + manager->priv->is_connected = is_connected; + g_object_notify (G_OBJECT (manager), "is-connected"); + } + + if (!is_connected) { + if (manager->priv->dbus_connection == NULL) { + if (manager->priv->bus_proxy != NULL) { + g_object_unref (manager->priv->bus_proxy); + manager->priv->bus_proxy = NULL; + } + + if (manager->priv->ck_proxy != NULL) { + g_object_unref (manager->priv->ck_proxy); + manager->priv->ck_proxy = NULL; + } + } else if (manager->priv->bus_proxy == NULL) { + if (manager->priv->ck_proxy != NULL) { + g_object_unref (manager->priv->ck_proxy); + manager->priv->ck_proxy = NULL; + } + } + } + + return is_connected; +} + +static void +panel_consolekit_on_name_owner_changed (DBusGProxy *bus_proxy, + const char *name, + const char *prev_owner, + const char *new_owner, + PanelConsolekit *manager) +{ + if (name != NULL && strcmp (name, "org.freedesktop.ConsoleKit") != 0) + return; + + if (manager->priv->ck_proxy != NULL) { + g_object_unref (manager->priv->ck_proxy); + manager->priv->ck_proxy = NULL; + } + + panel_consolekit_ensure_ck_connection (manager, NULL); +} + +static void +panel_consolekit_init (PanelConsolekit *manager) +{ + GError *error; + + manager->priv = PANEL_CONSOLEKIT_GET_PRIVATE (manager); + + error = NULL; + if (!panel_consolekit_ensure_ck_connection (manager, &error)) { + g_message ("Could not connect to ConsoleKit: %s", + error->message); + g_error_free (error); + } +} + +static void +panel_consolekit_finalize (GObject *object) +{ + PanelConsolekit *manager; + GObjectClass *parent_class; + + manager = PANEL_CONSOLEKIT (object); + + parent_class = G_OBJECT_CLASS (panel_consolekit_parent_class); + + if (manager->priv->bus_proxy != NULL) { + g_object_unref (manager->priv->bus_proxy); + } + + if (manager->priv->ck_proxy != NULL) { + g_object_unref (manager->priv->ck_proxy); + } + + if (parent_class->finalize != NULL) + parent_class->finalize (object); +} + +GQuark +panel_consolekit_error_quark (void) +{ + static GQuark error_quark = 0; + + if (error_quark == 0) + error_quark = g_quark_from_static_string ("panel-consolekit-error"); + + return error_quark; +} + +PanelConsolekit * +panel_consolekit_new (void) +{ + PanelConsolekit *manager; + + manager = g_object_new (PANEL_TYPE_CONSOLEKIT, NULL); + + return manager; +} + +static gboolean +try_system_stop (DBusGConnection *connection, + GError **error) +{ + DBusGProxy *proxy; + gboolean res; + + proxy = dbus_g_proxy_new_for_name (connection, + CK_NAME, + CK_MANAGER_PATH, + CK_MANAGER_INTERFACE); + res = dbus_g_proxy_call_with_timeout (proxy, + "Stop", + INT_MAX, + error, + /* parameters: */ + G_TYPE_INVALID, + /* return values: */ + G_TYPE_INVALID); + return res; +} + +static gboolean +try_system_restart (DBusGConnection *connection, + GError **error) +{ + DBusGProxy *proxy; + gboolean res; + + proxy = dbus_g_proxy_new_for_name (connection, + CK_NAME, + CK_MANAGER_PATH, + CK_MANAGER_INTERFACE); + res = dbus_g_proxy_call_with_timeout (proxy, + "Restart", + INT_MAX, + error, + /* parameters: */ + G_TYPE_INVALID, + /* return values: */ + G_TYPE_INVALID); + return res; +} + +static void +emit_restart_complete (PanelConsolekit *manager, + const char *error_message) +{ + GError *call_error; + + call_error = NULL; + + if (error_message != NULL) { + call_error = g_error_new_literal (PANEL_CONSOLEKIT_ERROR, + PANEL_CONSOLEKIT_ERROR_RESTARTING, + error_message); + } + + g_signal_emit (G_OBJECT (manager), + signals [REQUEST_COMPLETED], + 0, call_error); + if (call_error != NULL) { + g_error_free (call_error); + } +} + +static void +emit_stop_complete (PanelConsolekit *manager, + GError *error) +{ + GError *call_error; + + call_error = NULL; + + if (error != NULL) { + call_error = g_error_new_literal (PANEL_CONSOLEKIT_ERROR, + PANEL_CONSOLEKIT_ERROR_STOPPING, + error->message); + } + + g_signal_emit (G_OBJECT (manager), + signals [REQUEST_COMPLETED], + 0, call_error); + if (call_error != NULL) { + g_error_free (call_error); + } +} + +#ifdef HAVE_POLKIT +static void +system_restart_auth_cb (PolKitAction *action, + gboolean gained_privilege, + GError *error, + PanelConsolekit *manager) +{ + GError *local_error; + gboolean res; + + if (! gained_privilege) { + if (error != NULL) { + emit_restart_complete (manager, error->message); + } + return; + } + + local_error = NULL; + res = try_system_restart (manager->priv->dbus_connection, &local_error); + if (! res) { + g_warning ("Unable to restart system: %s", local_error->message); + emit_restart_complete (manager, local_error->message); + g_error_free (local_error); + return; + } +} + +static void +system_stop_auth_cb (PolKitAction *action, + gboolean gained_privilege, + GError *error, + PanelConsolekit *manager) +{ + GError *local_error; + gboolean res; + + if (! gained_privilege) { + if (error != NULL) { + emit_stop_complete (manager, error); + } + return; + } + + local_error = NULL; + res = try_system_stop (manager->priv->dbus_connection, &local_error); + if (! res) { + g_warning ("Unable to stop system: %s", local_error->message); + emit_stop_complete (manager, local_error); + g_error_free (local_error); + return; + } +} + +static PolKitAction * +get_action_from_error (GError *error) +{ + PolKitAction *action; + char *paction; + char *p; + + action = polkit_action_new (); + + paction = NULL; + if (g_str_has_prefix (error->message, "Not privileged for action: ")) { + paction = g_strdup (error->message + strlen ("Not privileged for action: ")); + p = strchr (paction, ' '); + if (p) + *p = '\0'; + } + polkit_action_set_action_id (action, paction); + + g_free (paction); + + return action; +} + +static PolKitResult +get_result_from_error (GError *error) +{ + PolKitResult result = POLKIT_RESULT_UNKNOWN; + const char *p; + + p = strrchr (error->message, ' '); + if (p) { + p++; + polkit_result_from_string_representation (p, &result); + } + + return result; +} + +#endif /* HAVE_POLKIT */ + +static void +request_restart_priv (PanelConsolekit *manager, + GError *error) +{ +#ifdef HAVE_POLKIT + gboolean res = FALSE; + char *error_message = NULL; + PolKitAction *action; + PolKitAction *action2; + PolKitResult result; + guint xid; + pid_t pid; + GError *local_error; + + action = get_action_from_error (error); + result = get_result_from_error (error); + + if (result == POLKIT_RESULT_NO) { + action2 = polkit_action_new (); + polkit_action_set_action_id (action2, "org.freedesktop.consolekit.system.restart-multiple-users"); + if (polkit_action_equal (action, action2)) { + emit_restart_complete (manager, _("You are not allowed to restart the computer " + "because multiple users are logged in")); + } + else { + emit_restart_complete (manager, _("You are not allowed to restart the computer")); + } + polkit_action_unref (action); + polkit_action_unref (action2); + + return; + } + + + xid = 0; + pid = getpid (); + + local_error = NULL; + res = polkit_gnome_auth_obtain (action, + xid, + pid, + (PolKitGnomeAuthCB) system_restart_auth_cb, + manager, + &local_error); + polkit_action_unref (action); + if (local_error != NULL) { + error_message = g_strdup (local_error->message); + g_error_free (local_error); + } + + if (! res) { + emit_restart_complete (manager, error_message); + g_free (error_message); + } +#else + g_assert_not_reached (); +#endif /* HAVE POLKIT */ +} + +static void +request_stop_priv (PanelConsolekit *manager, + GError *error) +{ +#ifdef HAVE_POLKIT + gboolean res = FALSE; + char *error_message = NULL; + PolKitAction *action; + PolKitAction *action2; + PolKitResult result; + guint xid; + pid_t pid; + GError *local_error; + + result = get_result_from_error (error); + action = get_action_from_error (error); + + if (result == POLKIT_RESULT_NO) { + action2 = polkit_action_new (); + polkit_action_set_action_id (action2, "org.freedesktop.consolekit.system.stop-multiple-users"); + if (polkit_action_equal (action, action2)) { + emit_restart_complete (manager, _("You are not allowed to stop the computer " + "because multiple users are logged in")); + } + else { + emit_restart_complete (manager, _("You are not allowed to stop the computer")); + } + polkit_action_unref (action); + polkit_action_unref (action2); + + return; + } + + xid = 0; + pid = getpid (); + + xid = 0; + pid = getpid (); + + local_error = NULL; + res = polkit_gnome_auth_obtain (action, + xid, + pid, + (PolKitGnomeAuthCB) system_stop_auth_cb, + manager, + &local_error); + polkit_action_unref (action); + if (local_error != NULL) { + error_message = g_strdup (local_error->message); + g_error_free (local_error); + } + if (! res) { + emit_stop_complete (manager, error_message); + g_free (error_message); + } +#else + g_assert_not_reached (); +#endif /* HAVE POLKIT */ +} + +void +panel_consolekit_attempt_restart (PanelConsolekit *manager) +{ + gboolean res; + GError *error; + + error = NULL; + + if (!panel_consolekit_ensure_ck_connection (manager, &error)) { + g_warning ("Could not connect to ConsoleKit: %s", + error->message); + g_error_free (error); + return; + } + + res = try_system_restart (manager->priv->dbus_connection, &error); + if (! res) { + if (dbus_g_error_has_name (error, "org.freedesktop.ConsoleKit.Manager.NotPrivileged")) { + request_restart_priv (manager, error); + } else { + emit_restart_complete (manager, error); + } + g_error_free (error); + } +} + +void +panel_consolekit_attempt_stop (PanelConsolekit *manager) +{ + gboolean res; + GError *error; + + error = NULL; + + if (!panel_consolekit_ensure_ck_connection (manager, &error)) { + g_warning ("Could not connect to ConsoleKit: %s", + error->message); + g_error_free (error); + return; + } + + res = try_system_stop (manager->priv->dbus_connection, &error); + if (! res) { + if (dbus_g_error_has_name (error, "org.freedesktop.ConsoleKit.Manager.NotPrivileged")) { + request_stop_priv (manager, error); + } else { + emit_stop_complete (manager, error); + } + g_error_free (error); + } +} + +gboolean +panel_consolekit_can_restart (PanelConsolekit *manager) +{ +#ifdef HAVE_POLKIT + return panel_consolekit_ensure_ck_connection (manager, NULL); +#else + return FALSE; +#endif +} + +gboolean +panel_consolekit_can_stop (PanelConsolekit *manager) +{ +#ifdef HAVE_POLKIT + return panel_consolekit_ensure_ck_connection (manager, NULL); +#else + return FALSE; +#endif +} + +PanelConsolekit * +panel_get_consolekit (void) +{ + static PanelConsolekit *manager = NULL; + + if (manager == NULL) { + manager = panel_consolekit_new (); + } + + return g_object_ref (manager); +} diff -up /dev/null gnome-panel-2.22.0/gnome-panel/panel-consolekit.h --- /dev/null 2008-04-05 22:04:35.194004710 -0400 +++ gnome-panel-2.22.0/gnome-panel/panel-consolekit.h 2008-04-05 20:48:37.000000000 -0400 @@ -0,0 +1,77 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2008 Jon McCann + * + * 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: + * Jon McCann + */ + +#ifndef PANEL_CONSOLEKIT_H +#define PANEL_CONSOLEKIT_H + +#include +#include + +G_BEGIN_DECLS + +#define PANEL_TYPE_CONSOLEKIT (panel_consolekit_get_type ()) +#define PANEL_CONSOLEKIT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PANEL_TYPE_CONSOLEKIT, PanelConsolekit)) +#define PANEL_CONSOLEKIT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANEL_TYPE_CONSOLEKIT, PanelConsolekitClass)) +#define PANEL_IS_CONSOLEKIT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PANEL_TYPE_CONSOLEKIT)) +#define PANEL_IS_CONSOLEKIT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANEL_TYPE_CONSOLEKIT)) +#define PANEL_CONSOLEKIT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PANEL_TYPE_CONSOLEKIT, PanelConsolekitClass)) +#define PANEL_CONSOLEKIT_ERROR (panel_consolekit_error_quark ()) + +typedef struct _PanelConsolekit PanelConsolekit; +typedef struct _PanelConsolekitClass PanelConsolekitClass; +typedef struct _PanelConsolekitPrivate PanelConsolekitPrivate; +typedef enum _PanelConsolekitError PanelConsolekitError; + +struct _PanelConsolekit { + GObject parent; + PanelConsolekitPrivate *priv; +}; + +struct _PanelConsolekitClass { + GObjectClass parent_class; + + void (* request_completed) (PanelConsolekit *manager, + GError *error); +}; + +enum _PanelConsolekitError { + PANEL_CONSOLEKIT_ERROR_RESTARTING = 0, + PANEL_CONSOLEKIT_ERROR_STOPPING +}; + +GType panel_consolekit_get_type (void); +GQuark panel_consolekit_error_quark (void); + +PanelConsolekit *panel_consolekit_new (void) G_GNUC_MALLOC; + +gboolean panel_consolekit_can_stop (PanelConsolekit *manager); +gboolean panel_consolekit_can_restart (PanelConsolekit *manager); + +void panel_consolekit_attempt_stop (PanelConsolekit *manager); +void panel_consolekit_attempt_restart (PanelConsolekit *manager); + +PanelConsolekit *panel_get_consolekit (void); + +G_END_DECLS + +#endif /* PANEL_CONSOLEKIT_H */ diff -up gnome-panel-2.22.0/gnome-panel/panel-logout.c.ck-shutdown gnome-panel-2.22.0/gnome-panel/panel-logout.c --- gnome-panel-2.22.0/gnome-panel/panel-logout.c.ck-shutdown 2008-04-05 20:48:37.000000000 -0400 +++ gnome-panel-2.22.0/gnome-panel/panel-logout.c 2008-04-05 22:18:24.000000000 -0400 @@ -1,4 +1,5 @@ -/* +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * * panel-logout.c: * * Copyright (C) 2006 Vincent Untz @@ -35,8 +36,10 @@ #include "panel-logout.h" #include "panel-gdm.h" #include "panel-power-manager.h" +#include "panel-consolekit.h" #include "panel-session.h" #include "panel-icon-names.h" +#include "panel-gconf.h" #define PANEL_LOGOUT_DIALOG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PANEL_TYPE_LOGOUT_DIALOG, PanelLogoutDialogPrivate)) @@ -55,6 +58,7 @@ struct _PanelLogoutDialogPrivate { PanelLogoutDialogType type; PanelPowerManager *power_manager; + PanelConsolekit *consolekit; int timeout; unsigned int timeout_id; @@ -76,7 +80,7 @@ enum { }; G_DEFINE_TYPE (PanelLogoutDialog, panel_logout, GTK_TYPE_MESSAGE_DIALOG); -static void +static void panel_logout_set_property (GObject *object, guint prop_id, const GValue *value, @@ -91,7 +95,7 @@ panel_logout_set_property (GObject } } -static void +static void panel_logout_get_property (GObject *object, guint prop_id, GValue *value, @@ -130,6 +134,57 @@ panel_logout_class_init (PanelLogoutDial } static void +ck_restart_error_window (GError *error) +{ + GtkWidget *dialog; + const char *primary; + + g_assert (error != NULL); + + switch (error->code) { + case PANEL_CONSOLEKIT_ERROR_RESTARTING: + primary = _("Unable to restart system"); + break; + case PANEL_CONSOLEKIT_ERROR_STOPPING: + primary = _("Unable to stop system"); + break; + default: + g_assert_not_reached (); + } + + dialog = gtk_message_dialog_new (NULL, 0, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_NONE, + primary); + + gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), + "%s", error->message); + + gtk_dialog_add_buttons (GTK_DIALOG (dialog), + GTK_STOCK_CLOSE, + NULL); + + gtk_dialog_set_default_response (GTK_DIALOG (dialog), + GTK_RESPONSE_CLOSE); + gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog), FALSE); + gtk_window_set_title (GTK_WINDOW (dialog), ""); + + g_signal_connect (dialog, "response", + G_CALLBACK (gtk_widget_destroy), NULL); + + gtk_widget_show (dialog); +} + +static void +on_ck_request_completed (PanelConsolekit *panel_consolekit, + GError *error) +{ + if (error) { + ck_restart_error_window (error); + } +} + +static void panel_logout_init (PanelLogoutDialog *logout_dialog) { logout_dialog->priv = PANEL_LOGOUT_DIALOG_GET_PRIVATE (logout_dialog); @@ -146,6 +201,10 @@ panel_logout_init (PanelLogoutDialog *lo GTK_WIN_POS_CENTER_ALWAYS); logout_dialog->priv->power_manager = panel_get_power_manager (); + logout_dialog->priv->consolekit = panel_get_consolekit (); + g_signal_connect (logout_dialog->priv->consolekit, + "request-completed", + G_CALLBACK (on_ck_request_completed), NULL); g_signal_connect (logout_dialog, "destroy", G_CALLBACK (panel_logout_destroy), NULL); @@ -163,37 +222,129 @@ panel_logout_destroy (PanelLogoutDialog g_object_unref (logout_dialog->priv->power_manager); logout_dialog->priv->power_manager = NULL; + g_object_unref (logout_dialog->priv->consolekit); + logout_dialog->priv->consolekit = NULL; current_dialog = NULL; } +static gboolean +panel_logout_supports_reboot (PanelLogoutDialog *logout_dialog) +{ + gboolean ret; + + ret = panel_consolekit_can_restart (logout_dialog->priv->consolekit); + if (!ret) { + ret = gdm_supports_logout_action (GDM_LOGOUT_ACTION_REBOOT); + } + return ret; +} + +static gboolean +panel_logout_supports_shutdown (PanelLogoutDialog *logout_dialog) +{ + gboolean ret; + + ret = panel_consolekit_can_stop (logout_dialog->priv->consolekit); + if (!ret) { + ret = gdm_supports_logout_action (GDM_LOGOUT_ACTION_SHUTDOWN); + } + return ret; +} + +gboolean +panel_logout_supports_shutdown_reboot (void) +{ + PanelConsolekit *consolekit; + gboolean ret; + + ret = FALSE; + + /* if we can do any then return true */ + + consolekit = panel_get_consolekit (); + if (consolekit != NULL) { + ret = panel_consolekit_can_restart (consolekit) + || panel_consolekit_can_stop (consolekit); + g_object_unref (consolekit); + } + + if (!ret) { + ret = gdm_supports_logout_action (GDM_LOGOUT_ACTION_REBOOT) + || gdm_supports_logout_action (GDM_LOGOUT_ACTION_SHUTDOWN); + } + + return ret; +} + +static void +do_request_logout (PanelConsolekit *consolekit) +{ + gdm_set_logout_action (GDM_LOGOUT_ACTION_NONE); + panel_session_request_logout (); +} + +static void +maybe_request_session_save (void) +{ + if (gconf_client_get_bool (panel_gconf_get_client (), + "/apps/gnome-session/options/auto_save_session", + NULL)) + panel_session_request_save (); +} + +static void +do_request_reboot (PanelConsolekit *consolekit) +{ + if (panel_consolekit_can_restart (consolekit)) { + gdm_set_logout_action (GDM_LOGOUT_ACTION_NONE); + maybe_request_session_save (); + panel_consolekit_attempt_restart (consolekit); + } else { + gdm_set_logout_action (GDM_LOGOUT_ACTION_REBOOT); + panel_session_request_logout (); + } +} + +static void +do_request_shutdown (PanelConsolekit *consolekit) +{ + if (panel_consolekit_can_stop (consolekit)) { + gdm_set_logout_action (GDM_LOGOUT_ACTION_NONE); + maybe_request_session_save (); + panel_consolekit_attempt_stop (consolekit); + } else { + gdm_set_logout_action (GDM_LOGOUT_ACTION_SHUTDOWN); + panel_session_request_logout (); + } +} + static void panel_logout_response (PanelLogoutDialog *logout_dialog, guint response_id, gpointer data) { PanelPowerManager *power_manager; + PanelConsolekit *consolekit; power_manager = g_object_ref (logout_dialog->priv->power_manager); + consolekit = g_object_ref (logout_dialog->priv->consolekit); gtk_widget_destroy (GTK_WIDGET (logout_dialog)); switch (response_id) { case GTK_RESPONSE_CANCEL: break; case PANEL_LOGOUT_RESPONSE_LOGOUT: - gdm_set_logout_action (GDM_LOGOUT_ACTION_NONE); - panel_session_request_logout (); + do_request_logout (consolekit); break; case PANEL_LOGOUT_RESPONSE_SWITCH_USER: gdm_new_login (); break; case PANEL_LOGOUT_RESPONSE_SHUTDOWN: - gdm_set_logout_action (GDM_LOGOUT_ACTION_SHUTDOWN); - panel_session_request_logout (); + do_request_shutdown (consolekit); break; case PANEL_LOGOUT_RESPONSE_REBOOT: - gdm_set_logout_action (GDM_LOGOUT_ACTION_REBOOT); - panel_session_request_logout (); + do_request_reboot (consolekit); break; case PANEL_LOGOUT_RESPONSE_STD: if (panel_power_manager_can_hibernate (power_manager)) @@ -210,6 +361,7 @@ panel_logout_response (PanelLogoutDialog g_assert_not_reached (); } g_object_unref (power_manager); + g_object_unref (consolekit); } static gboolean @@ -363,7 +515,7 @@ panel_logout_new (PanelLogoutDialogType _("_Hibernate"), PANEL_LOGOUT_RESPONSE_STD); - if (gdm_supports_logout_action (GDM_LOGOUT_ACTION_REBOOT)) + if (panel_logout_supports_reboot (logout_dialog)) gtk_dialog_add_button (GTK_DIALOG (logout_dialog), _("_Restart"), PANEL_LOGOUT_RESPONSE_REBOOT); @@ -372,7 +524,7 @@ panel_logout_new (PanelLogoutDialogType GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); - if (gdm_supports_logout_action (GDM_LOGOUT_ACTION_SHUTDOWN)) + if (panel_logout_supports_shutdown (logout_dialog)) gtk_dialog_add_button (GTK_DIALOG (logout_dialog), _("_Shut Down"), PANEL_LOGOUT_RESPONSE_SHUTDOWN); diff -up gnome-panel-2.22.0/gnome-panel/panel-logout.h.ck-shutdown gnome-panel-2.22.0/gnome-panel/panel-logout.h --- gnome-panel-2.22.0/gnome-panel/panel-logout.h.ck-shutdown 2008-03-10 16:44:57.000000000 -0400 +++ gnome-panel-2.22.0/gnome-panel/panel-logout.h 2008-04-05 20:48:37.000000000 -0400 @@ -57,6 +57,8 @@ struct _PanelLogoutDialogClass { GType panel_logout_get_type (void) G_GNUC_CONST; +gboolean panel_logout_supports_shutdown_reboot (void); + void panel_logout_new (PanelLogoutDialogType type, GdkScreen *screen, guint32 activate_time); diff -up gnome-panel-2.22.0/gnome-panel/panel-session.c.ck-shutdown gnome-panel-2.22.0/gnome-panel/panel-session.c --- gnome-panel-2.22.0/gnome-panel/panel-session.c.ck-shutdown 2008-03-10 16:44:57.000000000 -0400 +++ gnome-panel-2.22.0/gnome-panel/panel-session.c 2008-04-05 20:48:37.000000000 -0400 @@ -60,6 +60,34 @@ panel_session_request_logout (void) recursion_guard--; } +void +panel_session_request_save (void) +{ + GnomeClient *client; + static int recursion_guard = 0; + + if (recursion_guard) + return; + + recursion_guard++; + + if (!(client = gnome_master_client ())) + return; + + /* Only request a Global save. We only want a Local + * save if the user selects 'Save current setup' + * from the dialog. + */ + gnome_client_request_save (client, + GNOME_SAVE_GLOBAL, + FALSE, + GNOME_INTERACT_NONE, + TRUE, /* do not use the gnome-session gui */ + TRUE); + + recursion_guard--; +} + static void panel_session_handle_die_request (GnomeClient *client) { diff -up gnome-panel-2.22.0/gnome-panel/panel-session.h.ck-shutdown gnome-panel-2.22.0/gnome-panel/panel-session.h --- gnome-panel-2.22.0/gnome-panel/panel-session.h.ck-shutdown 2008-03-10 16:44:57.000000000 -0400 +++ gnome-panel-2.22.0/gnome-panel/panel-session.h 2008-04-05 20:48:37.000000000 -0400 @@ -30,6 +30,7 @@ G_BEGIN_DECLS void panel_session_init (void); void panel_session_do_not_restart (void); void panel_session_request_logout (void); +void panel_session_request_save (void); G_END_DECLS diff -up gnome-panel-2.22.0/gnome-panel/panel-toplevel.c.ck-shutdown gnome-panel-2.22.0/gnome-panel/panel-toplevel.c --- gnome-panel-2.22.0/gnome-panel/panel-toplevel.c.ck-shutdown 2008-03-10 16:44:57.000000000 -0400 +++ gnome-panel-2.22.0/gnome-panel/panel-toplevel.c 2008-04-05 20:48:37.000000000 -0400 @@ -3329,7 +3329,8 @@ panel_toplevel_get_animation_time (Panel } static void -panel_toplevel_start_animation (PanelToplevel *toplevel) +panel_toplevel_start_animation (PanelToplevel *toplevel, + gboolean auto_hide) { GdkScreen *screen; int monitor_width, monitor_height; @@ -3480,7 +3481,7 @@ panel_toplevel_hide (PanelToplevel *t } if (toplevel->priv->animate && GTK_WIDGET_REALIZED (toplevel)) - panel_toplevel_start_animation (toplevel); + panel_toplevel_start_animation (toplevel, auto_hide); else if (toplevel->priv->attached) gtk_widget_hide (GTK_WIDGET (toplevel)); @@ -3528,7 +3529,7 @@ panel_toplevel_unhide (PanelToplevel *to panel_toplevel_push_autohide_disabler (toplevel->priv->attach_toplevel); if (toplevel->priv->animate && GTK_WIDGET_REALIZED (toplevel)) - panel_toplevel_start_animation (toplevel); + panel_toplevel_start_animation (toplevel, FALSE); else if (toplevel->priv->attached) gtk_widget_show (GTK_WIDGET (toplevel));