[gnome-session] shell: add support for shell logout/shutdown dialog
- From: Ray Strode <halfline src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-session] shell: add support for shell logout/shutdown dialog
- Date: Mon, 24 Jan 2011 18:12:34 +0000 (UTC)
commit 1f9ed4829f56826b05c9d4f9fbab8fb7bca53e8c
Author: Ray Strode <rstrode redhat com>
Date: Tue Oct 26 17:04:51 2010 -0400
shell: add support for shell logout/shutdown dialog
This commit changes gnome-session to use the shell for
presenting the logout and shutdown dialogs.
Coordination happens over the session bus.
https://bugzilla.gnome.org/show_bug.cgi?id=637188
gnome-session/Makefile.am | 2 +
gnome-session/gsm-manager.c | 194 +++++++++++++--
gnome-session/gsm-shell.c | 569 +++++++++++++++++++++++++++++++++++++++++++
gnome-session/gsm-shell.h | 85 +++++++
4 files changed, 828 insertions(+), 22 deletions(-)
---
diff --git a/gnome-session/Makefile.am b/gnome-session/Makefile.am
index 030052e..23855da 100644
--- a/gnome-session/Makefile.am
+++ b/gnome-session/Makefile.am
@@ -55,6 +55,8 @@ gnome_session_SOURCES = \
gsm-session-fill.h \
gsm-session-save.c \
gsm-session-save.h \
+ gsm-shell.c \
+ gsm-shell.h \
gsm-xsmp-server.c \
gsm-xsmp-server.h
diff --git a/gnome-session/gsm-manager.c b/gnome-session/gsm-manager.c
index 326d859..0198e12 100644
--- a/gnome-session/gsm-manager.c
+++ b/gnome-session/gsm-manager.c
@@ -48,6 +48,7 @@
#include "gsm-store.h"
#include "gsm-inhibitor.h"
#include "gsm-presence.h"
+#include "gsm-shell.h"
#include "gsm-xsmp-client.h"
#include "gsm-dbus-client.h"
@@ -130,6 +131,11 @@ struct GsmManagerPrivate
/* Interface with other parts of the system */
UpClient *up_client;
+
+ GsmShell *shell;
+ guint shell_end_session_dialog_canceled_id;
+ guint shell_end_session_dialog_open_failed_id;
+ guint shell_end_session_dialog_confirmed_id;
};
enum {
@@ -164,7 +170,8 @@ static void _handle_client_end_session_response (GsmManager *manager,
gboolean do_last,
gboolean cancel,
const char *reason);
-
+static void show_shell_end_session_dialog (GsmManager *manager,
+ GsmShellEndSessionDialogType type);
static gpointer manager_object = NULL;
G_DEFINE_TYPE (GsmManager, gsm_manager, G_TYPE_OBJECT)
@@ -1100,24 +1107,10 @@ inhibit_dialog_response (GsmInhibitDialog *dialog,
}
static void
-query_end_session_complete (GsmManager *manager)
+end_session_or_show_fallback_dialog (GsmManager *manager)
{
GsmLogoutAction action;
- g_debug ("GsmManager: query end session complete");
-
- /* Remove the timeout since this can be called from outside the timer
- * and we don't want to have it called twice */
- if (manager->priv->query_timeout_id > 0) {
- g_source_remove (manager->priv->query_timeout_id);
- manager->priv->query_timeout_id = 0;
- }
-
- if (! gsm_manager_is_logout_inhibited (manager)) {
- end_phase (manager);
- return;
- }
-
if (manager->priv->inhibit_dialog != NULL) {
g_debug ("GsmManager: inhibit dialog already up");
gtk_window_present (GTK_WINDOW (manager->priv->inhibit_dialog));
@@ -1145,6 +1138,11 @@ query_end_session_complete (GsmManager *manager)
break;
}
+ if (! gsm_manager_is_logout_inhibited (manager)) {
+ end_phase (manager);
+ return;
+ }
+
/* Note: GSM_LOGOUT_ACTION_SHUTDOWN and GSM_LOGOUT_ACTION_REBOOT are
* actually handled the same way as GSM_LOGOUT_ACTION_LOGOUT in the
* inhibit dialog; the action, if the button is clicked, will be to
@@ -1158,6 +1156,69 @@ query_end_session_complete (GsmManager *manager)
G_CALLBACK (inhibit_dialog_response),
manager);
gtk_widget_show (manager->priv->inhibit_dialog);
+}
+
+static void
+end_session_or_show_shell_dialog (GsmManager *manager)
+{
+ GsmShellEndSessionDialogType type;
+
+ switch (manager->priv->logout_type) {
+ case GSM_MANAGER_LOGOUT_LOGOUT:
+ type = GSM_SHELL_END_SESSION_DIALOG_TYPE_LOGOUT;
+ break;
+ case GSM_MANAGER_LOGOUT_REBOOT:
+ case GSM_MANAGER_LOGOUT_REBOOT_INTERACT:
+ case GSM_MANAGER_LOGOUT_REBOOT_GDM:
+ type = GSM_SHELL_END_SESSION_DIALOG_TYPE_RESTART;
+ break;
+ case GSM_MANAGER_LOGOUT_SHUTDOWN:
+ case GSM_MANAGER_LOGOUT_SHUTDOWN_INTERACT:
+ case GSM_MANAGER_LOGOUT_SHUTDOWN_GDM:
+ type = GSM_SHELL_END_SESSION_DIALOG_TYPE_SHUTDOWN;
+ break;
+ default:
+ g_warning ("Unexpected logout type %d when creating end session dialog",
+ manager->priv->logout_type);
+ type = GSM_SHELL_END_SESSION_DIALOG_TYPE_LOGOUT;
+ break;
+ }
+
+ if (! gsm_manager_is_logout_inhibited (manager)) {
+ gboolean logout_prompt;
+
+ logout_prompt = g_settings_get_boolean (manager->priv->settings,
+ KEY_LOGOUT_PROMPT);
+ if (logout_prompt) {
+ show_shell_end_session_dialog (manager, type);
+ return;
+ } else {
+ end_phase (manager);
+ }
+ return;
+ }
+
+ show_shell_end_session_dialog (manager, type);
+}
+
+static void
+query_end_session_complete (GsmManager *manager)
+{
+
+ g_debug ("GsmManager: query end session complete");
+
+ /* Remove the timeout since this can be called from outside the timer
+ * and we don't want to have it called twice */
+ if (manager->priv->query_timeout_id > 0) {
+ g_source_remove (manager->priv->query_timeout_id);
+ manager->priv->query_timeout_id = 0;
+ }
+
+ if (gsm_shell_is_running (manager->priv->shell)) {
+ end_session_or_show_shell_dialog (manager);
+ } else {
+ end_session_or_show_fallback_dialog (manager);
+ }
}
@@ -2241,6 +2302,11 @@ gsm_manager_dispose (GObject *object)
manager->priv->up_client = NULL;
}
+ if (manager->priv->shell != NULL) {
+ g_object_unref (manager->priv->shell);
+ manager->priv->shell = NULL;
+ }
+
G_OBJECT_CLASS (gsm_manager_parent_class)->dispose (object);
}
@@ -2421,6 +2487,8 @@ gsm_manager_init (GsmManager *manager)
G_CALLBACK (on_setting_changed),
manager);
+ manager->priv->shell = gsm_get_shell ();
+
fetch_idle_delay_setting (manager);
}
@@ -2810,7 +2878,7 @@ logout_dialog_response (GsmLogoutDialog *logout_dialog,
}
static void
-show_shutdown_dialog (GsmManager *manager)
+show_fallback_shutdown_dialog (GsmManager *manager)
{
GtkWidget *dialog;
@@ -2830,7 +2898,7 @@ show_shutdown_dialog (GsmManager *manager)
}
static void
-show_logout_dialog (GsmManager *manager)
+show_fallback_logout_dialog (GsmManager *manager)
{
GtkWidget *dialog;
@@ -2850,27 +2918,101 @@ show_logout_dialog (GsmManager *manager)
}
static void
+on_shell_end_session_dialog_canceled (GsmShell *shell,
+ GsmManager *manager)
+{
+ cancel_end_session (manager);
+ manager->priv->shell_end_session_dialog_canceled_id = 0;
+
+ if (manager->priv->shell_end_session_dialog_canceled_id != 0) {
+ g_signal_handler_disconnect (manager->priv->shell,
+ manager->priv->shell_end_session_dialog_canceled_id);
+ manager->priv->shell_end_session_dialog_canceled_id = 0;
+ }
+
+ if (manager->priv->shell_end_session_dialog_confirmed_id != 0) {
+ g_signal_handler_disconnect (manager->priv->shell,
+ manager->priv->shell_end_session_dialog_confirmed_id);
+ manager->priv->shell_end_session_dialog_confirmed_id = 0;
+ }
+
+ if (manager->priv->shell_end_session_dialog_open_failed_id != 0) {
+ g_signal_handler_disconnect (manager->priv->shell,
+ manager->priv->shell_end_session_dialog_open_failed_id);
+ manager->priv->shell_end_session_dialog_open_failed_id = 0;
+ }
+}
+
+static void
+on_shell_end_session_dialog_confirmed (GsmShell *shell,
+ GsmManager *manager)
+{
+ manager->priv->forceful_logout = TRUE;
+ end_phase (manager);
+
+ manager->priv->shell_end_session_dialog_confirmed_id = 0;
+}
+
+static void
+show_shell_end_session_dialog (GsmManager *manager,
+ GsmShellEndSessionDialogType type)
+{
+ if (!gsm_shell_is_running (manager->priv->shell))
+ return;
+
+ gsm_shell_open_end_session_dialog (manager->priv->shell,
+ type,
+ manager->priv->inhibitors,
+ manager->priv->clients);
+ if (manager->priv->shell_end_session_dialog_canceled_id != 0)
+ return;
+
+ manager->priv->shell_end_session_dialog_canceled_id =
+ g_signal_connect (manager->priv->shell,
+ "end-session-dialog-canceled",
+ G_CALLBACK (on_shell_end_session_dialog_canceled),
+ manager);
+
+ manager->priv->shell_end_session_dialog_open_failed_id =
+ g_signal_connect (manager->priv->shell,
+ "end-session-dialog-open-failed",
+ G_CALLBACK (on_shell_end_session_dialog_canceled),
+ manager);
+
+ manager->priv->shell_end_session_dialog_confirmed_id =
+ g_signal_connect (manager->priv->shell,
+ "end-session-dialog-confirmed",
+ G_CALLBACK (on_shell_end_session_dialog_confirmed),
+ manager);
+}
+
+static void
user_logout (GsmManager *manager,
gboolean show_confirmation,
gboolean forceful_logout)
{
gboolean logout_prompt;
+ gboolean shell_running;
if (manager->priv->phase >= GSM_MANAGER_PHASE_QUERY_END_SESSION) {
/* Already shutting down, nothing more to do */
return;
}
+ shell_running = gsm_shell_is_running (manager->priv->shell);
logout_prompt = g_settings_get_boolean (manager->priv->settings,
KEY_LOGOUT_PROMPT);
/* Global settings overides input parameter in order to disable confirmation
- * dialog accordingly. If we're shutting down, we always show the confirmation
+ * dialog accordingly. For the shell, we never show the confirmation dialog,
+ * since the dialog is merged with the inhibit dialog.
+ *
+ * If we're shutting down and the shell isn't running, we show the confirmation
* dialog */
- logout_prompt = (logout_prompt && show_confirmation);
+ logout_prompt = (logout_prompt && show_confirmation && !shell_running);
if (logout_prompt) {
- show_logout_dialog (manager);
+ show_fallback_logout_dialog (manager);
} else {
request_logout (manager, forceful_logout);
}
@@ -2896,6 +3038,8 @@ gboolean
gsm_manager_shutdown (GsmManager *manager,
GError **error)
{
+ gboolean shell_running;
+
g_debug ("GsmManager: Shutdown called");
g_return_val_if_fail (GSM_IS_MANAGER (manager), FALSE);
@@ -2908,7 +3052,13 @@ gsm_manager_shutdown (GsmManager *manager,
return FALSE;
}
- show_shutdown_dialog (manager);
+ shell_running = gsm_shell_is_running (manager->priv->shell);
+
+ if (!shell_running) {
+ show_fallback_shutdown_dialog (manager);
+ } else {
+ request_shutdown (manager);
+ }
return TRUE;
}
diff --git a/gnome-session/gsm-shell.c b/gnome-session/gsm-shell.c
new file mode 100644
index 0000000..0144e17
--- /dev/null
+++ b/gnome-session/gsm-shell.c
@@ -0,0 +1,569 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Red Hat, Inc
+ *
+ * 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 <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <glib-object.h>
+#include <glib/gi18n.h>
+
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include "gsm-inhibitor.h"
+#include "gsm-shell.h"
+
+#define SHELL_NAME "org.gnome.Shell"
+#define SHELL_PATH "/org/gnome/Shell"
+#define SHELL_INTERFACE "org.gnome.Shell"
+
+#define SHELL_END_SESSION_DIALOG_PATH "/org/gnome/SessionManager/EndSessionDialog"
+#define SHELL_END_SESSION_DIALOG_INTERFACE "org.gnome.SessionManager.EndSessionDialog"
+
+#define GSM_SHELL_DBUS_TYPE_G_OBJECT_PATH_ARRAY (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH))
+
+#define AUTOMATIC_ACTION_TIMEOUT 60
+
+#define GSM_SHELL_GET_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSM_TYPE_SHELL, GsmShellPrivate))
+
+struct _GsmShellPrivate
+{
+ DBusGConnection *bus_connection;
+ DBusGProxy *bus_proxy;
+ DBusGProxy *proxy;
+ DBusGProxy *end_session_dialog_proxy;
+
+ guint32 is_running : 1;
+
+ DBusGProxyCall *end_session_open_call;
+ GsmShellEndSessionDialogType end_session_dialog_type;
+};
+
+enum {
+ PROP_0,
+ PROP_IS_RUNNING
+};
+
+enum {
+ END_SESSION_DIALOG_OPENED = 0,
+ END_SESSION_DIALOG_OPEN_FAILED,
+ END_SESSION_DIALOG_CANCELED,
+ END_SESSION_DIALOG_CONFIRMED,
+ NUMBER_OF_SIGNALS
+};
+
+static guint signals[NUMBER_OF_SIGNALS] = { 0 };
+
+static void gsm_shell_class_init (GsmShellClass *klass);
+static void gsm_shell_init (GsmShell *ck);
+static void gsm_shell_finalize (GObject *object);
+
+static void gsm_shell_disconnect_from_bus (GsmShell *shell);
+
+static DBusHandlerResult gsm_shell_bus_filter (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data);
+
+static void gsm_shell_on_name_owner_changed (DBusGProxy *bus_proxy,
+ const char *name,
+ const char *prev_owner,
+ const char *new_owner,
+ GsmShell *shell);
+
+G_DEFINE_TYPE (GsmShell, gsm_shell, G_TYPE_OBJECT);
+
+static void
+gsm_shell_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GsmShell *shell = GSM_SHELL (object);
+
+ switch (prop_id) {
+ case PROP_IS_RUNNING:
+ g_value_set_boolean (value,
+ shell->priv->is_running);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
+ prop_id,
+ pspec);
+ }
+}
+
+static void
+gsm_shell_class_init (GsmShellClass *shell_class)
+{
+ GObjectClass *object_class;
+ GParamSpec *param_spec;
+
+ object_class = G_OBJECT_CLASS (shell_class);
+
+ object_class->finalize = gsm_shell_finalize;
+ object_class->get_property = gsm_shell_get_property;
+
+ param_spec = g_param_spec_boolean ("is-running",
+ "Is running",
+ "Whether the session is running to ConsoleKit",
+ FALSE,
+ G_PARAM_READABLE);
+
+ g_object_class_install_property (object_class, PROP_IS_RUNNING,
+ param_spec);
+
+ signals [END_SESSION_DIALOG_OPENED] =
+ g_signal_new ("end-session-dialog-opened",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GsmShellClass, end_session_dialog_opened),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals [END_SESSION_DIALOG_OPEN_FAILED] =
+ g_signal_new ("end-session-dialog-open-failed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GsmShellClass, end_session_dialog_open_failed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals [END_SESSION_DIALOG_CANCELED] =
+ g_signal_new ("end-session-dialog-canceled",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GsmShellClass, end_session_dialog_canceled),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals [END_SESSION_DIALOG_CONFIRMED] =
+ g_signal_new ("end-session-dialog-confirmed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GsmShellClass, end_session_dialog_confirmed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ g_type_class_add_private (shell_class, sizeof (GsmShellPrivate));
+}
+
+static DBusHandlerResult
+gsm_shell_bus_filter (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ GsmShell *shell;
+
+ shell = GSM_SHELL (user_data);
+
+ if (dbus_message_is_signal (message,
+ DBUS_INTERFACE_LOCAL, "Disconnected") &&
+ strcmp (dbus_message_get_path (message), DBUS_PATH_LOCAL) == 0) {
+ gsm_shell_disconnect_from_bus (shell);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static gboolean
+gsm_shell_ensure_connection (GsmShell *shell,
+ GError **error)
+{
+ GError *connection_error;
+ gboolean is_running;
+
+ connection_error = NULL;
+
+ if (shell->priv->bus_connection == NULL) {
+ DBusConnection *connection;
+
+ shell->priv->bus_connection = dbus_g_bus_get (DBUS_BUS_SESSION,
+ &connection_error);
+
+ if (shell->priv->bus_connection == NULL) {
+ g_propagate_error (error, connection_error);
+ is_running = FALSE;
+ goto out;
+ }
+
+ connection = dbus_g_connection_get_connection (shell->priv->bus_connection);
+ dbus_connection_set_exit_on_disconnect (connection, FALSE);
+ dbus_connection_add_filter (connection,
+ gsm_shell_bus_filter,
+ shell, NULL);
+ }
+
+ if (shell->priv->bus_proxy == NULL) {
+ shell->priv->bus_proxy =
+ dbus_g_proxy_new_for_name_owner (shell->priv->bus_connection,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS,
+ &connection_error);
+
+ if (shell->priv->bus_proxy == NULL) {
+ g_propagate_error (error, connection_error);
+ is_running = FALSE;
+ goto out;
+ }
+
+ dbus_g_proxy_add_signal (shell->priv->bus_proxy,
+ "NameOwnerChanged",
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_INVALID);
+
+ dbus_g_proxy_connect_signal (shell->priv->bus_proxy,
+ "NameOwnerChanged",
+ G_CALLBACK (gsm_shell_on_name_owner_changed),
+ shell, NULL);
+ }
+
+ if (shell->priv->proxy == NULL) {
+ shell->priv->proxy =
+ dbus_g_proxy_new_for_name_owner (shell->priv->bus_connection,
+ SHELL_NAME,
+ SHELL_PATH,
+ SHELL_INTERFACE,
+ &connection_error);
+
+ if (shell->priv->proxy == NULL) {
+ g_propagate_error (error, connection_error);
+ is_running = FALSE;
+ goto out;
+ }
+ }
+
+ is_running = TRUE;
+
+ out:
+ if (shell->priv->is_running != is_running) {
+ shell->priv->is_running = is_running;
+ g_object_notify (G_OBJECT (shell), "is-running");
+ }
+
+ if (!is_running) {
+ if (shell->priv->bus_connection == NULL) {
+ if (shell->priv->bus_proxy != NULL) {
+ g_object_unref (shell->priv->bus_proxy);
+ shell->priv->bus_proxy = NULL;
+ }
+
+ if (shell->priv->proxy != NULL) {
+ g_object_unref (shell->priv->proxy);
+ shell->priv->proxy = NULL;
+ }
+ } else if (shell->priv->bus_proxy == NULL) {
+ if (shell->priv->proxy != NULL) {
+ g_object_unref (shell->priv->proxy);
+ shell->priv->proxy = NULL;
+ }
+ }
+ }
+
+ return is_running;
+}
+
+static void
+gsm_shell_on_name_owner_changed (DBusGProxy *bus_proxy,
+ const char *name,
+ const char *prev_owner,
+ const char *new_owner,
+ GsmShell *shell)
+{
+ if (name != NULL && strcmp (name, SHELL_NAME) != 0) {
+ return;
+ }
+
+ if (shell->priv->proxy != NULL) {
+ g_object_unref (shell->priv->proxy);
+ shell->priv->proxy = NULL;
+ }
+
+ gsm_shell_ensure_connection (shell, NULL);
+}
+
+static void
+gsm_shell_init (GsmShell *shell)
+{
+ GError *error;
+
+ shell->priv = GSM_SHELL_GET_PRIVATE (shell);
+
+ error = NULL;
+
+ if (!gsm_shell_ensure_connection (shell, &error)) {
+ g_warning ("Could not connect to the shell: %s",
+ error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+gsm_shell_disconnect_from_bus (GsmShell *shell)
+{
+ if (shell->priv->bus_proxy != NULL) {
+ g_object_unref (shell->priv->bus_proxy);
+ shell->priv->bus_proxy = NULL;
+ }
+
+ if (shell->priv->proxy != NULL) {
+ g_object_unref (shell->priv->proxy);
+ shell->priv->proxy = NULL;
+ }
+
+ if (shell->priv->bus_connection != NULL) {
+ DBusConnection *connection;
+ connection = dbus_g_connection_get_connection (shell->priv->bus_connection);
+ dbus_connection_remove_filter (connection,
+ gsm_shell_bus_filter,
+ shell);
+
+ dbus_g_connection_unref (shell->priv->bus_connection);
+ shell->priv->bus_connection = NULL;
+ }
+}
+
+static void
+gsm_shell_finalize (GObject *object)
+{
+ GsmShell *shell;
+ GObjectClass *parent_class;
+
+ shell = GSM_SHELL (object);
+
+ parent_class = G_OBJECT_CLASS (gsm_shell_parent_class);
+
+ gsm_shell_disconnect_from_bus (shell);
+
+ if (parent_class->finalize != NULL) {
+ parent_class->finalize (object);
+ }
+}
+
+GsmShell *
+gsm_shell_new (void)
+{
+ GsmShell *shell;
+
+ shell = g_object_new (GSM_TYPE_SHELL, NULL);
+
+ return shell;
+}
+
+GsmShell *
+gsm_get_shell (void)
+{
+ static GsmShell *shell = NULL;
+
+ if (shell == NULL) {
+ shell = gsm_shell_new ();
+ }
+
+ return g_object_ref (shell);
+}
+
+gboolean
+gsm_shell_is_running (GsmShell *shell)
+{
+ gsm_shell_ensure_connection (shell, NULL);
+
+ return shell->priv->is_running;
+}
+
+static gboolean
+add_inhibitor_to_array (const char *id,
+ GsmInhibitor *inhibitor,
+ GPtrArray *array)
+{
+
+ g_ptr_array_add (array,
+ g_strdup (gsm_inhibitor_peek_id (inhibitor)));
+ return FALSE;
+}
+
+static GPtrArray *
+get_array_from_store (GsmStore *inhibitors)
+{
+ GPtrArray *array;
+
+ array = g_ptr_array_new ();
+
+ gsm_store_foreach (inhibitors,
+ (GsmStoreFunc) add_inhibitor_to_array,
+ array);
+
+ return array;
+}
+
+static void
+on_open_finished (DBusGProxy *proxy,
+ DBusGProxyCall *call,
+ GsmShell *shell)
+{
+ GError *error;
+ gboolean res;
+
+ g_assert (shell->priv->end_session_open_call == call);
+
+ error = NULL;
+ res = dbus_g_proxy_end_call (proxy,
+ call,
+ &error,
+ G_TYPE_INVALID);
+ shell->priv->end_session_open_call = NULL;
+
+ if (!res) {
+ g_warning ("Unable to open shell end session dialog");
+ g_signal_emit (G_OBJECT (shell), signals[END_SESSION_DIALOG_OPEN_FAILED], 0);
+ return;
+ }
+
+ g_signal_emit (G_OBJECT (shell), signals[END_SESSION_DIALOG_OPENED], 0);
+}
+
+static void
+on_end_session_dialog_canceled (DBusGProxy *proxy,
+ GsmShell *shell)
+{
+ g_signal_emit (G_OBJECT (shell), signals[END_SESSION_DIALOG_CANCELED], 0);
+}
+
+static void
+on_end_session_dialog_confirmed (DBusGProxy *proxy,
+ GsmShell *shell)
+{
+ g_signal_emit (G_OBJECT (shell), signals[END_SESSION_DIALOG_CONFIRMED], 0);
+}
+
+static void
+on_end_session_dialog_proxy_destroyed (DBusGProxy *proxy,
+ GsmShell *shell)
+{
+ if (shell->priv->end_session_dialog_proxy != NULL) {
+ g_object_unref (shell->priv->proxy);
+ shell->priv->end_session_dialog_proxy = NULL;
+ }
+}
+
+gboolean
+gsm_shell_open_end_session_dialog (GsmShell *shell,
+ GsmShellEndSessionDialogType type,
+ GsmStore *inhibitors,
+ GsmStore *clients)
+{
+ DBusGProxyCall *call;
+ GPtrArray *inhibitor_array;
+ GError *error;
+
+ error = NULL;
+ if (!gsm_shell_ensure_connection (shell, &error)) {
+ g_warning ("Could not connect to the shell: %s",
+ error->message);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ if (shell->priv->end_session_open_call != NULL) {
+ g_return_val_if_fail (shell->priv->end_session_dialog_type == type,
+ FALSE);
+
+ return TRUE;
+ }
+
+ if (shell->priv->end_session_dialog_proxy == NULL) {
+ DBusGProxy *proxy;
+
+ proxy = dbus_g_proxy_new_for_name (shell->priv->bus_connection,
+ SHELL_NAME,
+ SHELL_END_SESSION_DIALOG_PATH,
+ SHELL_END_SESSION_DIALOG_INTERFACE);
+
+ g_assert (proxy != NULL);
+
+ shell->priv->end_session_dialog_proxy = proxy;
+
+ g_signal_connect (proxy, "destroy",
+ G_CALLBACK (on_end_session_dialog_proxy_destroyed),
+ shell);
+
+ dbus_g_proxy_add_signal (shell->priv->end_session_dialog_proxy,
+ "Canceled", G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal (shell->priv->end_session_dialog_proxy,
+ "Canceled",
+ G_CALLBACK (on_end_session_dialog_canceled),
+ shell, NULL);
+
+ dbus_g_proxy_add_signal (shell->priv->end_session_dialog_proxy,
+ "Confirmed", G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal (shell->priv->end_session_dialog_proxy,
+ "Confirmed",
+ G_CALLBACK (on_end_session_dialog_confirmed),
+ shell, NULL);
+
+ }
+
+ inhibitor_array = get_array_from_store (inhibitors);
+
+ call = dbus_g_proxy_begin_call_with_timeout (shell->priv->end_session_dialog_proxy,
+ "Open",
+ (DBusGProxyCallNotify)
+ on_open_finished,
+ shell,
+ NULL,
+ INT_MAX,
+ G_TYPE_UINT,
+ (guint) type,
+ G_TYPE_UINT,
+ (guint) 0,
+ G_TYPE_UINT,
+ AUTOMATIC_ACTION_TIMEOUT,
+ GSM_SHELL_DBUS_TYPE_G_OBJECT_PATH_ARRAY,
+ inhibitor_array,
+ G_TYPE_INVALID);
+ g_ptr_array_foreach (inhibitor_array, (GFunc) g_free, NULL);
+ g_ptr_array_free (inhibitor_array, TRUE);
+
+ if (call == NULL) {
+ g_warning ("Unable to make Open call");
+ return FALSE;
+ }
+
+ shell->priv->end_session_open_call = call;
+ shell->priv->end_session_dialog_type = type;
+
+ return TRUE;
+}
diff --git a/gnome-session/gsm-shell.h b/gnome-session/gsm-shell.h
new file mode 100644
index 0000000..7908696
--- /dev/null
+++ b/gnome-session/gsm-shell.h
@@ -0,0 +1,85 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2010 Red Hat, Inc.
+ *
+ * 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:
+ * Ray Strode <rstrode redhat com>
+ */
+
+#ifndef __GSM_SHELL_H__
+#define __GSM_SHELL_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "gsm-store.h"
+
+G_BEGIN_DECLS
+
+#define GSM_TYPE_SHELL (gsm_shell_get_type ())
+#define GSM_SHELL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSM_TYPE_SHELL, GsmShell))
+#define GSM_SHELL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSM_TYPE_SHELL, GsmShellClass))
+#define GSM_IS_SHELL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSM_TYPE_SHELL))
+#define GSM_IS_SHELL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSM_TYPE_SHELL))
+#define GSM_SHELL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GSM_TYPE_SHELL, GsmShellClass))
+#define GSM_SHELL_ERROR (gsm_shell_error_quark ())
+
+typedef struct _GsmShell GsmShell;
+typedef struct _GsmShellClass GsmShellClass;
+typedef struct _GsmShellPrivate GsmShellPrivate;
+
+typedef enum
+{
+ GSM_SHELL_END_SESSION_DIALOG_TYPE_LOGOUT = 0,
+ GSM_SHELL_END_SESSION_DIALOG_TYPE_SHUTDOWN,
+ GSM_SHELL_END_SESSION_DIALOG_TYPE_RESTART,
+} GsmShellEndSessionDialogType;
+
+struct _GsmShell
+{
+ GObject parent;
+
+ GsmShellPrivate *priv;
+};
+
+struct _GsmShellClass
+{
+ GObjectClass parent_class;
+
+ void (* end_session_dialog_opened) (GsmShell *shell);
+ void (* end_session_dialog_open_failed) (GsmShell *shell);
+ void (* end_session_dialog_canceled) (GsmShell *shell);
+ void (* end_session_dialog_confirmed) (GsmShell *shell);
+
+};
+
+GType gsm_shell_get_type (void);
+
+GsmShell *gsm_shell_new (void);
+
+GsmShell *gsm_get_shell (void);
+gboolean gsm_shell_is_running (GsmShell *shell);
+
+gboolean gsm_shell_open_end_session_dialog (GsmShell *shell,
+ GsmShellEndSessionDialogType type,
+ GsmStore *inhibitors,
+ GsmStore *clients);
+
+G_END_DECLS
+
+#endif /* __GSM_SHELL_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]