--- gnome-panel/Makefile.am | 4 gnome-panel/libpanel-util/panel-session-manager.c | 23 + gnome-panel/panel-gdm.c | 417 ++++++++++++++++++++++ gnome-panel/panel-gdm.h | 52 ++ gnome-panel/panel-logout.c | 402 +++++++++++++++++++++ gnome-panel/panel-logout.h | 66 +++ gnome-panel/panel-session.c | 28 + gnome-panel/panel-session.h | 1 8 files changed, 993 insertions(+) Index: b/gnome-panel/panel-gdm.c =================================================================== --- /dev/null +++ b/gnome-panel/panel-gdm.c @@ -0,0 +1,417 @@ +/* + * gdm-protocol.c: GDM logout action protocol implementation + * + * Copyright (C) 2005 Raffaele Sandrini + * Copyright (C) 2005 Red Hat, Inc. + * Copyright (C) 2002, 2003 George Lebl + * Copyright (C) 2001 Queen of England, + * + * 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: + * Raffaele Sandrini + * George Lebl + * Mark McLoughlin + */ + +#include + +#include "panel-gdm.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#define GDM_PROTOCOL_UPDATE_INTERVAL 1 /* seconds */ + +#define GDM_PROTOCOL_SOCKET_PATH "/var/run/gdm_socket" + +#define GDM_PROTOCOL_MSG_CLOSE "CLOSE" +#define GDM_PROTOCOL_MSG_VERSION "VERSION" +#define GDM_PROTOCOL_MSG_AUTHENTICATE "AUTH_LOCAL" +#define GDM_PROTOCOL_MSG_QUERY_ACTION "QUERY_LOGOUT_ACTION" +#define GDM_PROTOCOL_MSG_SET_ACTION "SET_SAFE_LOGOUT_ACTION" +#define GDM_PROTOCOL_MSG_FLEXI_XSERVER "FLEXI_XSERVER" + +#define GDM_ACTION_STR_NONE "NONE" +#define GDM_ACTION_STR_SHUTDOWN "HALT" +#define GDM_ACTION_STR_REBOOT "REBOOT" +#define GDM_ACTION_STR_SUSPEND "SUSPEND" + +typedef struct { + int fd; + char *auth_cookie; + + GdmLogoutAction available_actions; + GdmLogoutAction current_actions; + + time_t last_update; +} GdmProtocolData; + +static GdmProtocolData gdm_protocol_data = { + 0, + NULL, + GDM_LOGOUT_ACTION_NONE, + GDM_LOGOUT_ACTION_NONE, + 0 +}; + +static char * +gdm_send_protocol_msg (GdmProtocolData *data, + const char *msg) +{ + GString *retval; + char buf[256]; + char *p; + int len; + + p = g_strconcat (msg, "\n", NULL); + if (write (data->fd, p, strlen (p)) < 0) { + g_free (p); + + g_warning ("Failed to send message to GDM: %s", + g_strerror (errno)); + return NULL; + } + g_free (p); + + p = NULL; + retval = NULL; + while ((len = read (data->fd, buf, sizeof (buf) - 1)) > 0) { + buf[len] = '\0'; + + if (!retval) + retval = g_string_new (buf); + else + retval = g_string_append (retval, buf); + + if ((p = strchr (retval->str, '\n'))) + break; + } + + if (p) *p = '\0'; + + return retval ? g_string_free (retval, FALSE) : NULL; +} + +static char * +get_display_number (void) +{ + const char *display_name; + char *retval; + char *p; + + display_name = gdk_display_get_name (gdk_display_get_default ()); + + p = strchr (display_name, ':'); + if (!p) + return g_strdup ("0"); + + while (*p == ':') p++; + + retval = g_strdup (p); + + p = strchr (retval, '.'); + if (p != NULL) + *p = '\0'; + + return retval; +} + +static gboolean +gdm_authenticate_connection (GdmProtocolData *data) +{ +#define GDM_MIT_MAGIC_COOKIE_LEN 16 + + const char *xau_path; + FILE *f; + Xauth *xau; + char *display_number; + gboolean retval; + + if (data->auth_cookie) { + char *msg; + char *response; + + msg = g_strdup_printf (GDM_PROTOCOL_MSG_AUTHENTICATE " %s", + data->auth_cookie); + response = gdm_send_protocol_msg (data, msg); + g_free (msg); + + if (response && !strcmp (response, "OK")) { + g_free (response); + return TRUE; + } else { + g_free (response); + g_free (data->auth_cookie); + data->auth_cookie = NULL; + } + } + + if (!(xau_path = XauFileName ())) + return FALSE; + + if (!(f = fopen (xau_path, "r"))) + return FALSE; + + retval = FALSE; + display_number = get_display_number (); + + while ((xau = XauReadAuth (f))) { + char buffer[40]; /* 2*16 == 32, so 40 is enough */ + char *msg; + char *response; + int i; + + if (xau->family != FamilyLocal || + strncmp (xau->number, display_number, xau->number_length) || + strncmp (xau->name, "MIT-MAGIC-COOKIE-1", xau->name_length) || + xau->data_length != GDM_MIT_MAGIC_COOKIE_LEN) { + XauDisposeAuth (xau); + continue; + } + + for (i = 0; i < GDM_MIT_MAGIC_COOKIE_LEN; i++) + g_snprintf (buffer + 2*i, 3, "%02x", (guint)(guchar)xau->data[i]); + + XauDisposeAuth (xau); + + msg = g_strdup_printf (GDM_PROTOCOL_MSG_AUTHENTICATE " %s", buffer); + response = gdm_send_protocol_msg (data, msg); + g_free (msg); + + if (response && !strcmp (response, "OK")) { + data->auth_cookie = g_strdup (buffer); + g_free (response); + retval = TRUE; + break; + } + + g_free (response); + } + + g_free (display_number); + + fclose (f); + + return retval; + +#undef GDM_MIT_MAGIC_COOKIE_LEN +} + +static void +gdm_shutdown_protocol_connection (GdmProtocolData *data) +{ + if (data->fd) + close (data->fd); + data->fd = 0; +} + +static gboolean +gdm_init_protocol_connection (GdmProtocolData *data) +{ + struct sockaddr_un addr; + char *response; + + g_assert (data->fd <= 0); + + data->fd = socket (AF_UNIX, SOCK_STREAM, 0); + if (data->fd < 0) { + g_warning ("Failed to create GDM socket: %s", + g_strerror (errno)); + gdm_shutdown_protocol_connection (data); + return FALSE; + } + + if (g_file_test (GDM_PROTOCOL_SOCKET_PATH, G_FILE_TEST_EXISTS)) + strcpy (addr.sun_path, GDM_PROTOCOL_SOCKET_PATH); + else + strcpy (addr.sun_path, "/tmp/.gdm_socket"); + + addr.sun_family = AF_UNIX; + + if (connect (data->fd, (struct sockaddr *) &addr, sizeof (addr)) < 0) { + g_warning ("Failed to establish a connection with GDM: %s", + g_strerror (errno)); + gdm_shutdown_protocol_connection (data); + return FALSE; + } + + response = gdm_send_protocol_msg (data, GDM_PROTOCOL_MSG_VERSION); + if (!response || strncmp (response, "GDM ", strlen ("GDM ") != 0)) { + g_free (response); + + g_warning ("Failed to get protocol version from GDM"); + gdm_shutdown_protocol_connection (data); + + return FALSE; + } + g_free (response); + + if (!gdm_authenticate_connection (data)) { + g_warning ("Failed to authenticate with GDM"); + gdm_shutdown_protocol_connection (data); + return FALSE; + } + + return TRUE; +} + +static void +gdm_parse_query_response (GdmProtocolData *data, + const char *response) +{ + char **actions; + int i; + + data->available_actions = GDM_LOGOUT_ACTION_NONE; + data->current_actions = GDM_LOGOUT_ACTION_NONE; + + if (strncmp (response, "OK ", 3) != 0) + return; + + response += 3; + + actions = g_strsplit (response, ";", -1); + for (i = 0; actions[i]; i++) { + GdmLogoutAction action = GDM_LOGOUT_ACTION_NONE; + gboolean selected = FALSE; + char *str = actions [i]; + int len; + + len = strlen (str); + if (!len) + continue; + + if (str[len - 1] == '!') { + selected = TRUE; + str[len - 1] = '\0'; + } + + if (!strcmp (str, GDM_ACTION_STR_SHUTDOWN)) + action = GDM_LOGOUT_ACTION_SHUTDOWN; + else if (!strcmp (str, GDM_ACTION_STR_REBOOT)) + action = GDM_LOGOUT_ACTION_REBOOT; + else if (!strcmp (str, GDM_ACTION_STR_SUSPEND)) + action = GDM_LOGOUT_ACTION_SUSPEND; + + data->available_actions |= action; + if (selected) + data->current_actions |= action; + } + + g_strfreev (actions); +} + +static void +gdm_update_logout_actions (GdmProtocolData *data) +{ + time_t current_time; + char *response; + + current_time = time (NULL); + if (current_time <= (data->last_update + GDM_PROTOCOL_UPDATE_INTERVAL)) + return; + + data->last_update = current_time; + + if (!gdm_init_protocol_connection (data)) + return; + + if ((response = gdm_send_protocol_msg (data, GDM_PROTOCOL_MSG_QUERY_ACTION))) { + gdm_parse_query_response (data, response); + g_free (response); + } + + gdm_shutdown_protocol_connection (data); +} + +gboolean +gdm_supports_logout_action (GdmLogoutAction action) +{ + gdm_update_logout_actions (&gdm_protocol_data); + + return (gdm_protocol_data.available_actions & action) != 0; +} + +GdmLogoutAction +gdm_get_logout_action (void) +{ + gdm_update_logout_actions (&gdm_protocol_data); + + return gdm_protocol_data.current_actions; +} + +void +gdm_set_logout_action (GdmLogoutAction action) +{ + char *action_str = NULL; + char *msg; + char *response; + + if (!gdm_init_protocol_connection (&gdm_protocol_data)) + return; + + switch (action) { + case GDM_LOGOUT_ACTION_NONE: + action_str = GDM_ACTION_STR_NONE; + break; + case GDM_LOGOUT_ACTION_SHUTDOWN: + action_str = GDM_ACTION_STR_SHUTDOWN; + break; + case GDM_LOGOUT_ACTION_REBOOT: + action_str = GDM_ACTION_STR_REBOOT; + break; + case GDM_LOGOUT_ACTION_SUSPEND: + action_str = GDM_ACTION_STR_SUSPEND; + break; + } + + msg = g_strdup_printf (GDM_PROTOCOL_MSG_SET_ACTION " %s", action_str); + + response = gdm_send_protocol_msg (&gdm_protocol_data, msg); + + g_free (msg); + g_free (response); + + gdm_protocol_data.last_update = 0; + + gdm_shutdown_protocol_connection (&gdm_protocol_data); +} + +void +gdm_new_login (void) +{ + char *response; + + if (!gdm_init_protocol_connection (&gdm_protocol_data)) + return; + + response = gdm_send_protocol_msg (&gdm_protocol_data, + GDM_PROTOCOL_MSG_FLEXI_XSERVER); + + g_free (response); + + gdm_protocol_data.last_update = 0; + + gdm_shutdown_protocol_connection (&gdm_protocol_data); +} Index: b/gnome-panel/panel-logout.c =================================================================== --- /dev/null +++ b/gnome-panel/panel-logout.c @@ -0,0 +1,402 @@ +/* + * panel-logout.c: + * + * Copyright (C) 2006 Vincent Untz + * + * 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: + * Vincent Untz + */ + + +#include + +#include + +#include +#include +#include +#include + +#include + +#include "panel-logout.h" +#include "panel-gdm.h" +#include "panel-session.h" +#include "panel-icon-names.h" + +#define PANEL_LOGOUT_DIALOG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PANEL_TYPE_LOGOUT_DIALOG, PanelLogoutDialogPrivate)) + +#define AUTOMATIC_ACTION_TIMEOUT 60 + +enum { + PANEL_LOGOUT_RESPONSE_LOGOUT, + PANEL_LOGOUT_RESPONSE_SWITCH_USER, + PANEL_LOGOUT_RESPONSE_SHUTDOWN, + PANEL_LOGOUT_RESPONSE_REBOOT, + PANEL_LOGOUT_RESPONSE_STD, + PANEL_LOGOUT_RESPONSE_STR +}; + +struct _PanelLogoutDialogPrivate { + PanelLogoutDialogType type; + + PanelPowerManager *power_manager; + + int timeout; + unsigned int timeout_id; + + unsigned int default_response; +}; + +static PanelLogoutDialog *current_dialog = NULL; + +static void panel_logout_destroy (PanelLogoutDialog *logout_dialog, + gpointer data); +static void panel_logout_response (PanelLogoutDialog *logout_dialog, + guint response_id, + gpointer data); + +enum { + PROP_0, + PROP_MESSAGE_TYPE +}; +G_DEFINE_TYPE (PanelLogoutDialog, panel_logout, GTK_TYPE_MESSAGE_DIALOG); + +static void +panel_logout_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) { + case PROP_MESSAGE_TYPE: + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +panel_logout_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) { + case PROP_MESSAGE_TYPE: + g_value_set_enum (value, GTK_MESSAGE_WARNING); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +panel_logout_class_init (PanelLogoutDialogClass *klass) +{ + GObjectClass *gobject_class; + + gobject_class = G_OBJECT_CLASS (klass); + + /* This is a workaround to avoid a stupid crash: libgnomeui + * listens for the "show" signal on all GtkMessageDialog and + * gets the "message-type" of the dialogs. We will crash when + * it accesses this property if we don't override it since we + * didn't define it. */ + gobject_class->set_property = panel_logout_set_property; + gobject_class->get_property = panel_logout_get_property; + + g_object_class_override_property (gobject_class, + PROP_MESSAGE_TYPE, + "message-type"); + + g_type_class_add_private (klass, sizeof (PanelLogoutDialogPrivate)); +} + +static void +panel_logout_init (PanelLogoutDialog *logout_dialog) +{ + logout_dialog->priv = PANEL_LOGOUT_DIALOG_GET_PRIVATE (logout_dialog); + + logout_dialog->priv->timeout_id = 0; + logout_dialog->priv->timeout = 0; + logout_dialog->priv->default_response = GTK_RESPONSE_CANCEL; + + /* FIXME: we should most probably use gtk_window_set_transient_for(PANEL) */ + gtk_window_set_skip_taskbar_hint (GTK_WINDOW (logout_dialog), TRUE); + gtk_window_set_keep_above (GTK_WINDOW (logout_dialog), TRUE); + gtk_window_stick (GTK_WINDOW (logout_dialog)); + gtk_window_set_position (GTK_WINDOW (logout_dialog), + GTK_WIN_POS_CENTER_ALWAYS); + + logout_dialog->priv->power_manager = panel_power_manager_get (); + + g_signal_connect (logout_dialog, "destroy", + G_CALLBACK (panel_logout_destroy), NULL); + g_signal_connect (logout_dialog, "response", + G_CALLBACK (panel_logout_response), NULL); +} + +static void +panel_logout_destroy (PanelLogoutDialog *logout_dialog, + gpointer data) +{ + if (logout_dialog->priv->timeout_id != 0) + g_source_remove (logout_dialog->priv->timeout_id); + logout_dialog->priv->timeout_id = 0; + + g_object_unref (logout_dialog->priv->power_manager); + logout_dialog->priv->power_manager = NULL; + + current_dialog = NULL; +} + +static void +panel_logout_response (PanelLogoutDialog *logout_dialog, + guint response_id, + gpointer data) +{ + PanelPowerManager *power_manager; + + power_manager = g_object_ref (logout_dialog->priv->power_manager); + 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 (); + 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 (); + break; + case PANEL_LOGOUT_RESPONSE_REBOOT: + gdm_set_logout_action (GDM_LOGOUT_ACTION_REBOOT); + panel_session_request_logout (); + break; + case PANEL_LOGOUT_RESPONSE_STD: + if (panel_power_manager_can_hibernate (power_manager)) + panel_power_manager_attempt_hibernate (power_manager); + break; + case PANEL_LOGOUT_RESPONSE_STR: + if (panel_power_manager_can_suspend (power_manager)) + panel_power_manager_attempt_suspend (power_manager); + break; + case GTK_RESPONSE_NONE: + case GTK_RESPONSE_DELETE_EVENT: + break; + default: + g_assert_not_reached (); + } + g_object_unref (power_manager); +} + +static gboolean +panel_logout_timeout (gpointer data) +{ + PanelLogoutDialog *logout_dialog; + char *secondary_text; + char *name; + int seconds_to_show; + + logout_dialog = (PanelLogoutDialog *) data; + + if (!logout_dialog->priv->timeout) { + gtk_dialog_response (GTK_DIALOG (logout_dialog), + logout_dialog->priv->default_response); + + return FALSE; + } + + if (logout_dialog->priv->timeout <= 30) + seconds_to_show = logout_dialog->priv->timeout; + else { + seconds_to_show = (logout_dialog->priv->timeout/10) * 10; + if (logout_dialog->priv->timeout % 10) + seconds_to_show += 10; + } + + switch (logout_dialog->priv->type) { + case PANEL_LOGOUT_DIALOG_LOGOUT: + secondary_text = ngettext ("You are currently logged in as " + "\"%s\".\n" + "You will be automatically logged " + "out in %d second.", + "You are currently logged in as " + "\"%s\".\n" + "You will be automatically logged " + "out in %d seconds.", + seconds_to_show); + break; + case PANEL_LOGOUT_DIALOG_SHUTDOWN: + secondary_text = ngettext ("You are currently logged in as " + "\"%s\".\n" + "This system will be automatically " + "shut down in %d second.", + "You are currently logged in as " + "\"%s\".\n" + "This system will be automatically " + "shut down in %d seconds.", + seconds_to_show); + break; + default: + g_assert_not_reached (); + } + + name = g_locale_to_utf8 (g_get_real_name (), -1, NULL, NULL, NULL); + if (!name || name[0] == '\0' || strcmp (name, "Unknown") == 0) + name = g_locale_to_utf8 (g_get_user_name (), -1 , NULL, NULL, NULL); + + if (!name) + name = g_strdup (g_get_user_name ()); + + gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (logout_dialog), + secondary_text, + name, + seconds_to_show, + NULL); + + logout_dialog->priv->timeout--; + + g_free (name); + + return TRUE; +} + +static void +panel_logout_set_timeout (PanelLogoutDialog *logout_dialog) +{ + logout_dialog->priv->timeout = AUTOMATIC_ACTION_TIMEOUT; + + /* Sets the secondary text */ + panel_logout_timeout (logout_dialog); + + if (logout_dialog->priv->timeout_id != 0) + g_source_remove (logout_dialog->priv->timeout_id); + + logout_dialog->priv->timeout_id = g_timeout_add (1000, + panel_logout_timeout, + logout_dialog); +} + +void +panel_logout_new (PanelLogoutDialogType type, + GdkScreen *screen, + guint32 activate_time) +{ + PanelLogoutDialog *logout_dialog; + char *icon_name; + char *primary_text; + + if (current_dialog != NULL) { + if (current_dialog->priv->type == type) { + gtk_window_set_screen (GTK_WINDOW (current_dialog), + screen); + gtk_window_present_with_time (GTK_WINDOW (current_dialog), + activate_time); + panel_logout_set_timeout (current_dialog); + //FIXME center the dialog on screen, and reset sticky and above_all? + return; + } else { + gtk_widget_destroy (GTK_WIDGET (current_dialog)); + } + } + + logout_dialog = g_object_new (PANEL_TYPE_LOGOUT_DIALOG, NULL); + current_dialog = logout_dialog; + + gtk_window_set_title (GTK_WINDOW (logout_dialog), ""); + + logout_dialog->priv->type = type; + + icon_name = NULL; + primary_text = NULL; + + switch (type) { + case PANEL_LOGOUT_DIALOG_LOGOUT: + icon_name = PANEL_ICON_LOGOUT; + primary_text = _("Log out of this system now?"); + // FIXME need to verify that this response can be used + logout_dialog->priv->default_response = PANEL_LOGOUT_DIALOG_LOGOUT; + + //FIXME is gdm running? + gtk_dialog_add_button (GTK_DIALOG (logout_dialog), + _("_Switch User"), + PANEL_LOGOUT_RESPONSE_SWITCH_USER); + gtk_dialog_add_button (GTK_DIALOG (logout_dialog), + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL); + gtk_dialog_add_button (GTK_DIALOG (logout_dialog), + _("_Log Out"), + PANEL_LOGOUT_RESPONSE_LOGOUT); + break; + case PANEL_LOGOUT_DIALOG_SHUTDOWN: + icon_name = PANEL_ICON_SHUTDOWN; + primary_text = _("Shut down this system now?"); + + logout_dialog->priv->default_response = PANEL_LOGOUT_RESPONSE_SHUTDOWN; + if (panel_power_manager_can_suspend (logout_dialog->priv->power_manager)) + gtk_dialog_add_button (GTK_DIALOG (logout_dialog), + _("S_uspend"), + PANEL_LOGOUT_RESPONSE_STR); + + if (panel_power_manager_can_hibernate (logout_dialog->priv->power_manager)) + gtk_dialog_add_button (GTK_DIALOG (logout_dialog), + _("_Hibernate"), + PANEL_LOGOUT_RESPONSE_STD); + + if (gdm_supports_logout_action (GDM_LOGOUT_ACTION_REBOOT)) + gtk_dialog_add_button (GTK_DIALOG (logout_dialog), + _("_Restart"), + PANEL_LOGOUT_RESPONSE_REBOOT); + + gtk_dialog_add_button (GTK_DIALOG (logout_dialog), + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL); + + if (gdm_supports_logout_action (GDM_LOGOUT_ACTION_SHUTDOWN)) + gtk_dialog_add_button (GTK_DIALOG (logout_dialog), + _("_Shut Down"), + PANEL_LOGOUT_RESPONSE_SHUTDOWN); + break; + default: + g_assert_not_reached (); + } + + gtk_image_set_from_icon_name (GTK_IMAGE (GTK_MESSAGE_DIALOG (logout_dialog)->image), + icon_name, GTK_ICON_SIZE_DIALOG); + + gtk_label_set_text (GTK_LABEL (GTK_MESSAGE_DIALOG (logout_dialog)->label), + primary_text); + + gtk_dialog_set_default_response (GTK_DIALOG (logout_dialog), + logout_dialog->priv->default_response); + + panel_logout_set_timeout (logout_dialog); + + gtk_window_set_screen (GTK_WINDOW (logout_dialog), screen); + gtk_widget_show (GTK_WIDGET (logout_dialog)); + gdk_window_focus (GTK_WIDGET (current_dialog)->window, activate_time); +} Index: b/gnome-panel/panel-gdm.h =================================================================== --- /dev/null +++ b/gnome-panel/panel-gdm.h @@ -0,0 +1,52 @@ +/* + * gdm-logout-action.h: GDM logout action protocol implementation + * + * Copyright (C) 2005 Raffaele Sandrini + * Copyright (C) 2005 Red Hat, Inc. + * Copyright (C) 2002, 2003 George Lebl + * Copyright (C) 2001 Queen of England, + * + * 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: + * Raffaele Sandrini + * George Lebl + * Mark McLoughlin + */ + +#ifndef __GDM_LOGOUT_ACTION_H__ +#define __GDM_LOGOUT_ACTION_H__ + +#include + +G_BEGIN_DECLS + +typedef enum { + GDM_LOGOUT_ACTION_NONE = 0, + GDM_LOGOUT_ACTION_SHUTDOWN = 1 << 0, + GDM_LOGOUT_ACTION_REBOOT = 1 << 1, + GDM_LOGOUT_ACTION_SUSPEND = 1 << 2 +} GdmLogoutAction; + +gboolean gdm_supports_logout_action (GdmLogoutAction action); + +void gdm_set_logout_action (GdmLogoutAction action); +GdmLogoutAction gdm_get_logout_action (void); +void gdm_new_login (void); + +G_END_DECLS + +#endif /* __GDM_LOGOUT_ACTION_H__ */ Index: b/gnome-panel/panel-logout.h =================================================================== --- /dev/null +++ b/gnome-panel/panel-logout.h @@ -0,0 +1,66 @@ +/* + * panel-logout.h: + * + * Copyright (C) 2006 Vincent Untz + * + * 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: + * Vincent Untz + */ + +#ifndef PANEL_LOGOUT_H +#define PANEL_LOGOUT_H + +#include "gtk/gtkmessagedialog.h" + +G_BEGIN_DECLS + +typedef enum { + PANEL_LOGOUT_DIALOG_LOGOUT, + PANEL_LOGOUT_DIALOG_SHUTDOWN +} PanelLogoutDialogType; + +#define PANEL_TYPE_LOGOUT_DIALOG (panel_logout_get_type ()) +#define PANEL_LOGOUT_DIALOG(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), PANEL_TYPE_LOGOUT_DIALOG, PanelLogoutDialog)) +#define PANEL_LOGOUT_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), PANEL_TYPE_LOGOUT_DIALOG, PanelLogoutDialogClass)) +#define PANEL_IS_LOGOUT_DIALOG(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), PANEL_TYPE_LOGOUT_DIALOG)) +#define PANEL_IS_LOGOUT_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), PANEL_TYPE_LOGOUT_DIALOG)) +#define PANEL_LOGOUT_DIALOG_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), PANEL_TYPE_LOGOUT_DIALOG, PanelLogoutDialogClass)) + +typedef struct _PanelLogoutDialog PanelLogoutDialog; +typedef struct _PanelLogoutDialogClass PanelLogoutDialogClass; +typedef struct _PanelLogoutDialogPrivate PanelLogoutDialogPrivate; + +struct _PanelLogoutDialog { + GtkMessageDialog parent; + + PanelLogoutDialogPrivate *priv; +}; + +struct _PanelLogoutDialogClass { + GtkMessageDialogClass parent_class; +}; + +GType panel_logout_get_type (void) G_GNUC_CONST; + +void panel_logout_new (PanelLogoutDialogType type, + GdkScreen *screen, + guint32 activate_time); + +G_END_DECLS + +#endif /* PANEL_LOGOUT_H */ Index: b/gnome-panel/panel-session.c =================================================================== --- a/gnome-panel/panel-session.c +++ b/gnome-panel/panel-session.c @@ -32,6 +32,34 @@ #include "panel-profile.h" #include "panel-shell.h" +void +panel_session_request_logout (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, + TRUE, + GNOME_INTERACT_ANY, + TRUE, /* do not use the gnome-session gui */ + TRUE); + + recursion_guard--; +} + static void panel_session_handle_die_request (GnomeClient *client) { Index: b/gnome-panel/panel-session.h =================================================================== --- a/gnome-panel/panel-session.h +++ b/gnome-panel/panel-session.h @@ -29,6 +29,7 @@ G_BEGIN_DECLS void panel_session_init (void); void panel_session_do_not_restart (void); +void panel_session_request_logout (void); G_END_DECLS Index: b/gnome-panel/Makefile.am =================================================================== --- a/gnome-panel/Makefile.am +++ b/gnome-panel/Makefile.am @@ -97,6 +97,8 @@ panel_sources = \ panel-force-quit.c \ panel-lockdown.c \ panel-addto.c \ + panel-logout.c \ + panel-gdm.c \ panel-ditem-editor.c \ $(NULL) @@ -143,6 +145,8 @@ panel_headers = \ panel-force-quit.h \ panel-lockdown.h \ panel-addto.h \ + panel-logout.h \ + panel-gdm.h \ panel-ditem-editor.h \ panel-icon-names.h \ $(NULL) Index: b/gnome-panel/libpanel-util/panel-session-manager.c =================================================================== --- a/gnome-panel/libpanel-util/panel-session-manager.c +++ b/gnome-panel/libpanel-util/panel-session-manager.c @@ -23,10 +23,13 @@ */ #include +#include #include "panel-cleanup.h" #include "panel-dbus-service.h" +#include "panel-logout.h" +#include "panel-session.h" #include "panel-session-manager.h" static GObject *panel_session_manager_constructor (GType type, @@ -96,6 +99,20 @@ panel_session_manager_request_logout (Pa g_warning ("Could not connect to session manager: %s", error->message); g_error_free (error); + + /* Fall back to the old way */ + switch (mode) { + case PANEL_SESSION_MANAGER_LOGOUT_MODE_NORMAL: + panel_logout_new (PANEL_LOGOUT_DIALOG_LOGOUT, + gdk_screen_get_default (), + gtk_get_current_event_time ()); + break; + case PANEL_SESSION_MANAGER_LOGOUT_MODE_NO_CONFIRMATION: + panel_session_request_logout (); + break; + default: + g_warning ("Invalid mode requested for logout"); + } return; } @@ -126,6 +143,12 @@ panel_session_manager_request_shutdown ( g_warning ("Could not connect to session manager: %s", error->message); g_error_free (error); + + /* Fall back to the old way */ + panel_logout_new (PANEL_LOGOUT_DIALOG_SHUTDOWN, + gdk_screen_get_default (), + gtk_get_current_event_time ()); + return; }