gnome-session r4813 - in branches/dbus_based: . gnome-session
- From: mccann svn gnome org
- To: svn-commits-list gnome org
- Subject: gnome-session r4813 - in branches/dbus_based: . gnome-session
- Date: Fri, 18 Jul 2008 19:53:46 +0000 (UTC)
Author: mccann
Date: Fri Jul 18 19:53:46 2008
New Revision: 4813
URL: http://svn.gnome.org/viewvc/gnome-session?rev=4813&view=rev
Log:
2008-07-18 William Jon McCann <jmccann redhat com>
* gnome-session/gsm-client.h:
* gnome-session/gsm-manager.c (phase_num_to_name), (end_phase),
(on_phase_timeout), (do_phase_startup), (_client_end_session),
(do_phase_end_session), (_client_query_end_session),
(inhibitor_has_flag), (gsm_manager_is_logout_inhibited),
(_client_cancel_end_session), (inhibitor_is_jit),
(cancel_end_session), (manager_switch_user), (do_attempt_reboot),
(do_attempt_shutdown), (manager_attempt_reboot),
(manager_attempt_shutdown), (manager_attempt_hibernate),
(manager_attempt_suspend), (do_dialog_action),
(inhibit_dialog_response), (query_end_session_complete),
(generate_cookie), (_generate_unique_cookie),
(on_query_end_session_timeout), (do_phase_query_end_session),
(start_phase), (gsm_manager_start), (find_app_for_app_id),
(disconnect_client), (_disconnect_dbus_client),
(remove_clients_for_connection), (inhibitor_has_bus_name),
(remove_inhibitors_for_connection), (_app_has_startup_id),
(on_xsmp_client_register_request),
(on_client_end_session_response), (gsm_manager_setenv),
(gsm_manager_initialization_error), (request_logout),
(logout_dialog_response), (show_shutdown_dialog),
(show_logout_dialog), (user_logout), (gsm_manager_logout),
(gsm_manager_register_client):
* gnome-session/gsm-manager.h:
* gnome-session/gsm-xsmp-client.c (do_save_yourself),
(xsmp_query_end_session), (xsmp_end_session),
(save_yourself_request_callback), (save_yourself_done_callback):
Add a forceful shutdown path. Make shutdown path use
same state machine as phases.
Modified:
branches/dbus_based/ChangeLog
branches/dbus_based/gnome-session/gsm-client.h
branches/dbus_based/gnome-session/gsm-manager.c
branches/dbus_based/gnome-session/gsm-manager.h
branches/dbus_based/gnome-session/gsm-xsmp-client.c
Modified: branches/dbus_based/gnome-session/gsm-client.h
==============================================================================
--- branches/dbus_based/gnome-session/gsm-client.h (original)
+++ branches/dbus_based/gnome-session/gsm-client.h Fri Jul 18 19:53:46 2008
@@ -46,6 +46,10 @@
GSM_CLIENT_FAILED,
} GsmClientStatus;
+typedef enum {
+ GSM_CLIENT_END_SESSION_FLAG_FORCEFUL = 1 << 0,
+} GsmClientEndSessionFlag;
+
struct _GsmClient
{
GObject parent;
Modified: branches/dbus_based/gnome-session/gsm-manager.c
==============================================================================
--- branches/dbus_based/gnome-session/gsm-manager.c (original)
+++ branches/dbus_based/gnome-session/gsm-manager.c Fri Jul 18 19:53:46 2008
@@ -87,6 +87,9 @@
GsmManagerPhase phase;
guint phase_timeout_id;
GSList *pending_apps;
+ gboolean forceful;
+ GSList *query_clients;
+ guint query_timeout_id;
GtkWidget *inhibit_dialog;
@@ -94,9 +97,6 @@
* and shouldn't be automatically restarted */
GSList *condition_clients;
- guint query_timeout_id;
- GSList *query_clients;
- GSList *busy_clients;
DBusGProxy *bus_proxy;
DBusGConnection *connection;
@@ -261,24 +261,89 @@
}
}
+static const char *
+phase_num_to_name (guint phase)
+{
+ const char *name;
+
+ switch (phase) {
+ case GSM_MANAGER_PHASE_STARTUP:
+ name = "STARTUP";
+ case GSM_MANAGER_PHASE_INITIALIZATION:
+ name = "INITIALIZATION";
+ case GSM_MANAGER_PHASE_WINDOW_MANAGER:
+ name = "WINDOW_MANAGER";
+ case GSM_MANAGER_PHASE_PANEL:
+ name = "PANEL";
+ case GSM_MANAGER_PHASE_DESKTOP:
+ name = "DESKTOP";
+ case GSM_MANAGER_PHASE_APPLICATION:
+ name = "APPLICATION";
+ break;
+ case GSM_MANAGER_PHASE_RUNNING:
+ name = "RUNNING";
+ break;
+ case GSM_MANAGER_PHASE_QUERY_END_SESSION:
+ name = "QUERY_END_SESSION";
+ break;
+ case GSM_MANAGER_PHASE_END_SESSION:
+ name = "END_SESSION";
+ break;
+ case GSM_MANAGER_PHASE_EXIT:
+ name = "EXIT";
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ return name;
+}
+
static void start_phase (GsmManager *manager);
static void
end_phase (GsmManager *manager)
{
+ g_debug ("GsmManager: ending phase %s\n",
+ phase_num_to_name (manager->priv->phase));
+
g_slist_free (manager->priv->pending_apps);
manager->priv->pending_apps = NULL;
- g_debug ("GsmManager: ending phase %d\n", manager->priv->phase);
+ g_slist_free (manager->priv->query_clients);
+ manager->priv->query_clients = NULL;
+
+ if (manager->priv->phase_timeout_id > 0) {
+ g_source_remove (manager->priv->phase_timeout_id);
+ manager->priv->phase_timeout_id = 0;
+ }
manager->priv->phase++;
- if (manager->priv->phase < GSM_MANAGER_PHASE_RUNNING) {
- start_phase (manager);
+ switch (manager->priv->phase) {
+ case GSM_MANAGER_PHASE_STARTUP:
+ case GSM_MANAGER_PHASE_INITIALIZATION:
+ case GSM_MANAGER_PHASE_WINDOW_MANAGER:
+ case GSM_MANAGER_PHASE_PANEL:
+ case GSM_MANAGER_PHASE_DESKTOP:
+ case GSM_MANAGER_PHASE_APPLICATION:
+ break;
+ case GSM_MANAGER_PHASE_RUNNING:
+ break;
+ case GSM_MANAGER_PHASE_QUERY_END_SESSION:
+ case GSM_MANAGER_PHASE_END_SESSION:
+ break;
+ case GSM_MANAGER_PHASE_EXIT:
+ gtk_main_quit ();
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
}
- if (manager->priv->phase == GSM_MANAGER_PHASE_RUNNING) {
- g_signal_emit (manager, signals[SESSION_RUNNING], 0);
+ if (manager->priv->phase != GSM_MANAGER_PHASE_RUNNING) {
+ start_phase (manager);
}
}
@@ -300,20 +365,40 @@
}
static gboolean
-phase_timeout (GsmManager *manager)
+on_phase_timeout (GsmManager *manager)
{
GSList *a;
manager->priv->phase_timeout_id = 0;
- for (a = manager->priv->pending_apps; a; a = a->next) {
- g_warning ("Application '%s' failed to register before timeout",
- gsm_app_get_id (a->data));
- g_signal_handlers_disconnect_by_func (a->data, app_registered, manager);
- /* FIXME: what if the app was filling in a required slot? */
+ switch (manager->priv->phase) {
+ case GSM_MANAGER_PHASE_STARTUP:
+ case GSM_MANAGER_PHASE_INITIALIZATION:
+ case GSM_MANAGER_PHASE_WINDOW_MANAGER:
+ case GSM_MANAGER_PHASE_PANEL:
+ case GSM_MANAGER_PHASE_DESKTOP:
+ case GSM_MANAGER_PHASE_APPLICATION:
+ for (a = manager->priv->pending_apps; a; a = a->next) {
+ g_warning ("Application '%s' failed to register before timeout",
+ gsm_app_get_id (a->data));
+ g_signal_handlers_disconnect_by_func (a->data, app_registered, manager);
+ /* FIXME: what if the app was filling in a required slot? */
+ }
+ break;
+ case GSM_MANAGER_PHASE_RUNNING:
+ break;
+ case GSM_MANAGER_PHASE_QUERY_END_SESSION:
+ case GSM_MANAGER_PHASE_END_SESSION:
+ break;
+ case GSM_MANAGER_PHASE_EXIT:
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
}
end_phase (manager);
+
return FALSE;
}
@@ -381,14 +466,8 @@
}
static void
-start_phase (GsmManager *manager)
+do_phase_startup (GsmManager *manager)
{
-
- g_debug ("GsmManager: starting phase %d\n", manager->priv->phase);
-
- g_slist_free (manager->priv->pending_apps);
- manager->priv->pending_apps = NULL;
-
g_hash_table_foreach (manager->priv->apps_by_id,
(GHFunc)_start_app,
manager);
@@ -396,7 +475,7 @@
if (manager->priv->pending_apps != NULL) {
if (manager->priv->phase < GSM_MANAGER_PHASE_APPLICATION) {
manager->priv->phase_timeout_id = g_timeout_add_seconds (GSM_MANAGER_PHASE_TIMEOUT,
- (GSourceFunc)phase_timeout,
+ (GSourceFunc)on_phase_timeout,
manager);
}
} else {
@@ -404,204 +483,678 @@
}
}
-void
-gsm_manager_start (GsmManager *manager)
-{
- g_debug ("GsmManager: GSM starting to manage");
-
- manager->priv->phase = GSM_MANAGER_PHASE_INITIALIZATION;
+typedef struct {
+ GsmManager *manager;
+ guint flags;
+} ClientEndSessionData;
- start_phase (manager);
-}
-static GsmApp *
-find_app_for_app_id (GsmManager *manager,
- const char *app_id)
+static gboolean
+_client_end_session (const char *id,
+ GsmClient *client,
+ ClientEndSessionData *data)
{
- GsmApp *app;
- app = g_hash_table_lookup (manager->priv->apps_by_id, app_id);
- return app;
+ g_debug ("GsmManager: adding client to end-session clients: %s", gsm_client_get_id (client));
+ data->manager->priv->query_clients = g_slist_prepend (data->manager->priv->query_clients,
+ client);
+
+ gsm_client_end_session (client, data->flags);
+
+ return FALSE;
}
static void
-disconnect_client (GsmManager *manager,
- GsmClient *client)
+do_phase_end_session (GsmManager *manager)
{
- gboolean is_condition_client;
- GsmApp *app;
- GError *error;
- gboolean res;
- const char *app_id;
-
- g_debug ("GsmManager: disconnect client");
-
- /* take a ref so it doesn't get finalized */
- g_object_ref (client);
+ ClientEndSessionData data;
- gsm_client_store_remove (manager->priv->store, client);
-
- is_condition_client = FALSE;
- if (g_slist_find (manager->priv->condition_clients, client)) {
- manager->priv->condition_clients = g_slist_remove (manager->priv->condition_clients, client);
-
- is_condition_client = TRUE;
- }
+ data.manager = manager;
+ data.flags = 0;
- app_id = gsm_client_get_app_id (client);
- if (app_id == NULL) {
- g_debug ("GsmManager: no application associated with client, not restarting application");
- goto out;
+ if (manager->priv->forceful) {
+ data.flags |= GSM_CLIENT_END_SESSION_FLAG_FORCEFUL;
}
- g_debug ("GsmManager: disconnect for app '%s'", app_id);
- app = find_app_for_app_id (manager, app_id);
- if (app == NULL) {
- g_debug ("GsmManager: invalid application id, not restarting application");
- goto out;
+ if (manager->priv->phase_timeout_id > 0) {
+ g_source_remove (manager->priv->phase_timeout_id);
+ manager->priv->phase_timeout_id = 0;
}
- if (manager->priv->phase == GSM_MANAGER_PHASE_SHUTDOWN) {
- g_debug ("GsmManager: in shutdown, not restarting application");
- goto out;
- }
+ if (gsm_client_store_size (manager->priv->store) > 0) {
+ manager->priv->phase_timeout_id = g_timeout_add_seconds (10,
+ (GSourceFunc)on_phase_timeout,
+ manager);
- if (! gsm_app_get_autorestart (app)) {
- g_debug ("GsmManager: autorestart not set, not restarting application");
- goto out;
+ gsm_client_store_foreach (manager->priv->store,
+ (GsmClientStoreFunc)_client_end_session,
+ &data);
+ } else {
+ end_phase (manager);
}
+}
- if (is_condition_client) {
- g_debug ("GsmManager: app conditionally disabled, not restarting application");
- goto out;
- }
+static gboolean
+_client_query_end_session (const char *id,
+ GsmClient *client,
+ ClientEndSessionData *data)
+{
+ g_debug ("GsmManager: adding client to query clients: %s", gsm_client_get_id (client));
+ data->manager->priv->query_clients = g_slist_prepend (data->manager->priv->query_clients,
+ client);
+ gsm_client_query_end_session (client, data->flags);
- g_debug ("GsmManager: restarting app");
+ return FALSE;
+}
- error = NULL;
- res = gsm_app_restart (app, &error);
- if (error != NULL) {
- g_warning ("Error on restarting session managed app: %s", error->message);
- g_error_free (error);
- }
+static gboolean
+inhibitor_has_flag (gpointer key,
+ GsmInhibitor *inhibitor,
+ gpointer data)
+{
+ int flag;
+ int flags;
- out:
- g_object_unref (client);
+ flag = GPOINTER_TO_INT (data);
+ flags = gsm_inhibitor_get_flags (inhibitor);
- if (manager->priv->phase == GSM_MANAGER_PHASE_SHUTDOWN
- && gsm_client_store_size (manager->priv->store) == 0) {
- g_debug ("GsmManager: last client disconnected - exiting");
- gtk_main_quit ();
- }
+ return (flags & flag);
}
-typedef struct {
- const char *service_name;
- GsmManager *manager;
-} RemoveClientData;
-
static gboolean
-_disconnect_dbus_client (const char *id,
- GsmClient *client,
- RemoveClientData *data)
+gsm_manager_is_logout_inhibited (GsmManager *manager)
{
- const char *name;
+ GsmInhibitor *inhibitor;
- if (! GSM_IS_DBUS_CLIENT (client)) {
+ if (manager->priv->inhibitors == NULL) {
return FALSE;
}
- name = gsm_dbus_client_get_bus_name (GSM_DBUS_CLIENT (client));
- if (name == NULL) {
+ inhibitor = gsm_inhibitor_store_find (manager->priv->inhibitors,
+ (GsmInhibitorStoreFunc)inhibitor_has_flag,
+ GINT_TO_POINTER (GSM_INHIBITOR_FLAG_LOGOUT));
+ if (inhibitor == NULL) {
return FALSE;
}
-
- if (strcmp (data->service_name, name) == 0) {
- disconnect_client (data->manager, client);
- }
-
- return FALSE;
+ return TRUE;
}
-static void
-remove_clients_for_connection (GsmManager *manager,
- const char *service_name)
+static gboolean
+_client_cancel_end_session (const char *id,
+ GsmClient *client,
+ GsmManager *manager)
{
- RemoveClientData data;
-
- data.service_name = service_name;
- data.manager = manager;
+ gsm_client_cancel_end_session (client);
- /* disconnect dbus clients for name */
- gsm_client_store_foreach (manager->priv->store,
- (GsmClientStoreFunc)_disconnect_dbus_client,
- &data);
+ return FALSE;
}
static gboolean
-inhibitor_has_bus_name (gpointer key,
- GsmInhibitor *inhibitor,
- RemoveClientData *data)
+inhibitor_is_jit (gpointer key,
+ GsmInhibitor *inhibitor,
+ GsmManager *manager)
{
gboolean matches;
- const char *bus_name_b;
+ const char *id;
- bus_name_b = gsm_inhibitor_get_bus_name (inhibitor);
+ id = gsm_inhibitor_get_client_id (inhibitor);
- matches = FALSE;
- if (data->service_name != NULL && bus_name_b != NULL) {
- matches = (strcmp (data->service_name, bus_name_b) == 0);
- if (matches) {
- g_debug ("GsmManager: removing inhibitor from %s for reason '%s' on connection %s",
- gsm_inhibitor_get_app_id (inhibitor),
- gsm_inhibitor_get_reason (inhibitor),
- gsm_inhibitor_get_bus_name (inhibitor));
- }
- }
+ matches = (id != NULL && id[0] != '\0');
return matches;
}
static void
-remove_inhibitors_for_connection (GsmManager *manager,
- const char *service_name)
+cancel_end_session (GsmManager *manager)
{
- guint n_removed;
- RemoveClientData data;
+ /* switch back to running phase */
- data.service_name = service_name;
- data.manager = manager;
+ /* clear all JIT inhibitors */
+ gsm_inhibitor_store_foreach_remove (manager->priv->inhibitors,
+ (GsmInhibitorStoreFunc)inhibitor_is_jit,
+ (gpointer)manager);
- debug_inhibitors (manager);
+ gsm_client_store_foreach (manager->priv->store,
+ (GsmClientStoreFunc)_client_cancel_end_session,
+ NULL);
- n_removed = gsm_inhibitor_store_foreach_remove (manager->priv->inhibitors,
- (GsmInhibitorStoreFunc)inhibitor_has_bus_name,
- &data);
+ manager->priv->phase = GSM_MANAGER_PHASE_RUNNING;
+ manager->priv->forceful = FALSE;
+
+ start_phase (manager);
}
-static gboolean
-_app_has_startup_id (const char *id,
- GsmApp *app,
- const char *startup_id_a)
+
+static void
+manager_switch_user (GsmManager *manager)
{
- const char *startup_id_b;
+ GError *error;
+ gboolean res;
+ char *command;
- startup_id_b = gsm_app_get_startup_id (app);
+ command = g_strdup_printf ("%s %s",
+ GDM_FLEXISERVER_COMMAND,
+ GDM_FLEXISERVER_ARGS);
- if (startup_id_b == NULL) {
- return FALSE;
- }
+ error = NULL;
+ res = gdk_spawn_command_line_on_screen (gdk_screen_get_default (),
+ command,
+ &error);
- return (strcmp (startup_id_a, startup_id_b) == 0);
-}
+ g_free (command);
-static GsmApp *
-find_app_for_startup_id (GsmManager *manager,
- const char *startup_id)
-{
- GsmApp *found_app;
- GSList *a;
+ if (! res) {
+ g_debug ("GsmManager: Unable to start GDM greeter: %s", error->message);
+ g_error_free (error);
+ }
+}
- found_app = NULL;
+
+static void
+do_attempt_reboot (GsmConsolekit *consolekit)
+{
+ if (gsm_consolekit_can_restart (consolekit)) {
+ gdm_set_logout_action (GDM_LOGOUT_ACTION_NONE);
+ gsm_consolekit_attempt_restart (consolekit);
+ } else {
+ gdm_set_logout_action (GDM_LOGOUT_ACTION_REBOOT);
+ }
+}
+
+static void
+do_attempt_shutdown (GsmConsolekit *consolekit)
+{
+ if (gsm_consolekit_can_stop (consolekit)) {
+ gdm_set_logout_action (GDM_LOGOUT_ACTION_NONE);
+ gsm_consolekit_attempt_stop (consolekit);
+ } else {
+ gdm_set_logout_action (GDM_LOGOUT_ACTION_SHUTDOWN);
+ }
+}
+
+static void
+manager_attempt_reboot (GsmManager *manager)
+{
+ GsmConsolekit *consolekit;
+
+ consolekit = gsm_get_consolekit ();
+ do_attempt_reboot (consolekit);
+ g_object_unref (consolekit);
+}
+
+static void
+manager_attempt_shutdown (GsmManager *manager)
+{
+ GsmConsolekit *consolekit;
+
+ consolekit = gsm_get_consolekit ();
+ do_attempt_shutdown (consolekit);
+ g_object_unref (consolekit);
+}
+
+static void
+manager_attempt_hibernate (GsmManager *manager)
+{
+ GsmPowerManager *power_manager;
+
+ power_manager = gsm_get_power_manager ();
+
+ if (gsm_power_manager_can_hibernate (power_manager)) {
+ gsm_power_manager_attempt_hibernate (power_manager);
+ }
+
+ g_object_unref (power_manager);
+}
+
+static void
+manager_attempt_suspend (GsmManager *manager)
+{
+ GsmPowerManager *power_manager;
+
+ power_manager = gsm_get_power_manager ();
+
+ if (gsm_power_manager_can_suspend (power_manager)) {
+ gsm_power_manager_attempt_suspend (power_manager);
+ }
+
+ g_object_unref (power_manager);
+}
+
+static void
+do_dialog_action (GsmManager *manager,
+ int action)
+{
+ switch (action) {
+ case GSM_LOGOUT_ACTION_SWITCH_USER:
+ manager_switch_user (manager);
+ break;
+ case GSM_LOGOUT_ACTION_HIBERNATE:
+ manager_attempt_hibernate (manager);
+ break;
+ case GSM_LOGOUT_ACTION_SLEEP:
+ manager_attempt_suspend (manager);
+ break;
+ case GSM_LOGOUT_ACTION_SHUTDOWN:
+ manager_attempt_shutdown (manager);
+ break;
+ case GSM_LOGOUT_ACTION_REBOOT:
+ manager_attempt_reboot (manager);
+ break;
+ case GSM_LOGOUT_ACTION_LOGOUT:
+ manager->priv->forceful = TRUE;
+ end_phase (manager);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
+static void
+inhibit_dialog_response (GsmInhibitDialog *dialog,
+ guint response_id,
+ GsmManager *manager)
+{
+ int action;
+
+ g_debug ("GsmManager: Inhibit dialog response: %d", response_id);
+
+ /* must destroy dialog before cancelling since we'll
+ remove JIT inhibitors and we don't want to trigger
+ action. */
+ g_object_get (dialog, "action", &action, NULL);
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ manager->priv->inhibit_dialog = NULL;
+
+ /* In case of dialog cancel, switch user, hibernate and
+ * suspend, we just perform the respective action and return,
+ * without shutting down the session. */
+ switch (response_id) {
+ case GTK_RESPONSE_CANCEL:
+ case GTK_RESPONSE_NONE:
+ case GTK_RESPONSE_DELETE_EVENT:
+ if (action == GSM_LOGOUT_ACTION_LOGOUT
+ || action == GSM_LOGOUT_ACTION_SHUTDOWN
+ || action == GSM_LOGOUT_ACTION_REBOOT) {
+ cancel_end_session (manager);
+ }
+ break;
+ case GTK_RESPONSE_ACCEPT:
+ g_debug ("GsmManager: doing action %d", action);
+ do_dialog_action (manager, action);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
+static void
+query_end_session_complete (GsmManager *manager)
+{
+ g_debug ("GsmManager: query end session complete");
+
+ 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));
+ return;
+ }
+
+ manager->priv->inhibit_dialog = gsm_inhibit_dialog_new (manager->priv->inhibitors,
+ GSM_LOGOUT_ACTION_LOGOUT);
+
+ g_signal_connect (manager->priv->inhibit_dialog,
+ "response",
+ G_CALLBACK (inhibit_dialog_response),
+ manager);
+ gtk_widget_show (manager->priv->inhibit_dialog);
+
+}
+
+static guint32
+generate_cookie (void)
+{
+ guint32 cookie;
+
+ cookie = (guint32)g_random_int_range (1, G_MAXINT32);
+
+ return cookie;
+}
+
+static guint32
+_generate_unique_cookie (GsmManager *manager)
+{
+ guint32 cookie;
+
+ do {
+ cookie = generate_cookie ();
+ } while (gsm_inhibitor_store_lookup (manager->priv->inhibitors, cookie) != NULL);
+
+ return cookie;
+}
+
+static gboolean
+on_query_end_session_timeout (GsmManager *manager)
+{
+ GSList *l;
+
+ manager->priv->query_timeout_id = 0;
+
+ g_debug ("GsmManager: query end session timed out");
+
+ for (l = manager->priv->query_clients; l != NULL; l = l->next) {
+ guint cookie;
+ GsmInhibitor *inhibitor;
+ const char *bus_name;
+
+ g_warning ("Client '%s' failed to reply before timeout",
+ gsm_client_get_id (l->data));
+
+ /* Add JIT inhibit for unresponsive client */
+ if (GSM_IS_DBUS_CLIENT (l->data)) {
+ bus_name = gsm_dbus_client_get_bus_name (l->data);
+ } else {
+ bus_name = NULL;
+ }
+
+ cookie = _generate_unique_cookie (manager);
+ inhibitor = gsm_inhibitor_new_for_client (gsm_client_get_id (l->data),
+ gsm_client_get_app_id (l->data),
+ GSM_INHIBITOR_FLAG_LOGOUT,
+ _("Not responding"),
+ bus_name,
+ cookie);
+ gsm_inhibitor_store_add (manager->priv->inhibitors, inhibitor);
+ g_object_unref (inhibitor);
+ }
+
+ g_slist_free (manager->priv->query_clients);
+ manager->priv->query_clients = NULL;
+
+ query_end_session_complete (manager);
+
+ return FALSE;
+}
+
+static void
+do_phase_query_end_session (GsmManager *manager)
+{
+ ClientEndSessionData data;
+
+ /* This phase doesn't time out. This separate timer
+ * is only used to show UI.
+ */
+
+ if (manager->priv->query_timeout_id > 0) {
+ g_source_remove (manager->priv->query_timeout_id);
+ manager->priv->query_timeout_id = 0;
+ }
+ manager->priv->query_timeout_id = g_timeout_add_seconds (1, (GSourceFunc)on_query_end_session_timeout, manager);
+
+ data.manager = manager;
+ data.flags = 0;
+
+ if (manager->priv->forceful) {
+ data.flags |= GSM_CLIENT_END_SESSION_FLAG_FORCEFUL;
+ }
+
+ debug_clients (manager);
+ g_debug ("GsmManager: sending query-end-session to clients forceful:%d", manager->priv->forceful);
+ gsm_client_store_foreach (manager->priv->store,
+ (GsmClientStoreFunc)_client_query_end_session,
+ &data);
+}
+
+static void
+start_phase (GsmManager *manager)
+{
+
+ g_debug ("GsmManager: starting phase %s\n",
+ phase_num_to_name (manager->priv->phase));
+
+ /* reset state */
+ g_slist_free (manager->priv->pending_apps);
+ manager->priv->pending_apps = NULL;
+ g_slist_free (manager->priv->query_clients);
+ manager->priv->query_clients = NULL;
+
+ if (manager->priv->query_timeout_id > 0) {
+ g_source_remove (manager->priv->query_timeout_id);
+ manager->priv->query_timeout_id = 0;
+ }
+ if (manager->priv->phase_timeout_id > 0) {
+ g_source_remove (manager->priv->phase_timeout_id);
+ manager->priv->phase_timeout_id = 0;
+ }
+
+ switch (manager->priv->phase) {
+ case GSM_MANAGER_PHASE_STARTUP:
+ case GSM_MANAGER_PHASE_INITIALIZATION:
+ case GSM_MANAGER_PHASE_WINDOW_MANAGER:
+ case GSM_MANAGER_PHASE_PANEL:
+ case GSM_MANAGER_PHASE_DESKTOP:
+ case GSM_MANAGER_PHASE_APPLICATION:
+ do_phase_startup (manager);
+ break;
+ case GSM_MANAGER_PHASE_RUNNING:
+ g_signal_emit (manager, signals[SESSION_RUNNING], 0);
+ break;
+ case GSM_MANAGER_PHASE_QUERY_END_SESSION:
+ do_phase_query_end_session (manager);
+ break;
+ case GSM_MANAGER_PHASE_END_SESSION:
+ do_phase_end_session (manager);
+ break;
+ case GSM_MANAGER_PHASE_EXIT:
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
+void
+gsm_manager_start (GsmManager *manager)
+{
+ g_debug ("GsmManager: GSM starting to manage");
+
+ manager->priv->phase = GSM_MANAGER_PHASE_INITIALIZATION;
+
+ start_phase (manager);
+}
+
+static GsmApp *
+find_app_for_app_id (GsmManager *manager,
+ const char *app_id)
+{
+ GsmApp *app;
+ app = g_hash_table_lookup (manager->priv->apps_by_id, app_id);
+ return app;
+}
+
+static void
+disconnect_client (GsmManager *manager,
+ GsmClient *client)
+{
+ gboolean is_condition_client;
+ GsmApp *app;
+ GError *error;
+ gboolean res;
+ const char *app_id;
+
+ g_debug ("GsmManager: disconnect client");
+
+ /* take a ref so it doesn't get finalized */
+ g_object_ref (client);
+
+ gsm_client_store_remove (manager->priv->store, client);
+
+ is_condition_client = FALSE;
+ if (g_slist_find (manager->priv->condition_clients, client)) {
+ manager->priv->condition_clients = g_slist_remove (manager->priv->condition_clients, client);
+
+ is_condition_client = TRUE;
+ }
+
+ app_id = gsm_client_get_app_id (client);
+ if (app_id == NULL) {
+ g_debug ("GsmManager: no application associated with client, not restarting application");
+ goto out;
+ }
+
+ g_debug ("GsmManager: disconnect for app '%s'", app_id);
+ app = find_app_for_app_id (manager, app_id);
+ if (app == NULL) {
+ g_debug ("GsmManager: invalid application id, not restarting application");
+ goto out;
+ }
+
+ if (manager->priv->phase >= GSM_MANAGER_PHASE_QUERY_END_SESSION) {
+ g_debug ("GsmManager: in shutdown, not restarting application");
+ goto out;
+ }
+
+ if (! gsm_app_get_autorestart (app)) {
+ g_debug ("GsmManager: autorestart not set, not restarting application");
+ goto out;
+ }
+
+ if (is_condition_client) {
+ g_debug ("GsmManager: app conditionally disabled, not restarting application");
+ goto out;
+ }
+
+ g_debug ("GsmManager: restarting app");
+
+ error = NULL;
+ res = gsm_app_restart (app, &error);
+ if (error != NULL) {
+ g_warning ("Error on restarting session managed app: %s", error->message);
+ g_error_free (error);
+ }
+
+ out:
+ g_object_unref (client);
+
+ if (manager->priv->phase >= GSM_MANAGER_PHASE_QUERY_END_SESSION
+ && gsm_client_store_size (manager->priv->store) == 0) {
+ g_debug ("GsmManager: last client disconnected - exiting");
+ end_phase (manager);
+ }
+}
+
+typedef struct {
+ const char *service_name;
+ GsmManager *manager;
+} RemoveClientData;
+
+static gboolean
+_disconnect_dbus_client (const char *id,
+ GsmClient *client,
+ RemoveClientData *data)
+{
+ const char *name;
+
+ if (! GSM_IS_DBUS_CLIENT (client)) {
+ return FALSE;
+ }
+
+ name = gsm_dbus_client_get_bus_name (GSM_DBUS_CLIENT (client));
+ if (name == NULL) {
+ return FALSE;
+ }
+
+ if (strcmp (data->service_name, name) == 0) {
+ disconnect_client (data->manager, client);
+ }
+
+ return FALSE;
+}
+
+static void
+remove_clients_for_connection (GsmManager *manager,
+ const char *service_name)
+{
+ RemoveClientData data;
+
+ data.service_name = service_name;
+ data.manager = manager;
+
+ /* disconnect dbus clients for name */
+ gsm_client_store_foreach (manager->priv->store,
+ (GsmClientStoreFunc)_disconnect_dbus_client,
+ &data);
+}
+
+static gboolean
+inhibitor_has_bus_name (gpointer key,
+ GsmInhibitor *inhibitor,
+ RemoveClientData *data)
+{
+ gboolean matches;
+ const char *bus_name_b;
+
+ bus_name_b = gsm_inhibitor_get_bus_name (inhibitor);
+
+ matches = FALSE;
+ if (data->service_name != NULL && bus_name_b != NULL) {
+ matches = (strcmp (data->service_name, bus_name_b) == 0);
+ if (matches) {
+ g_debug ("GsmManager: removing inhibitor from %s for reason '%s' on connection %s",
+ gsm_inhibitor_get_app_id (inhibitor),
+ gsm_inhibitor_get_reason (inhibitor),
+ gsm_inhibitor_get_bus_name (inhibitor));
+ }
+ }
+
+ return matches;
+}
+
+static void
+remove_inhibitors_for_connection (GsmManager *manager,
+ const char *service_name)
+{
+ guint n_removed;
+ RemoveClientData data;
+
+ data.service_name = service_name;
+ data.manager = manager;
+
+ debug_inhibitors (manager);
+
+ n_removed = gsm_inhibitor_store_foreach_remove (manager->priv->inhibitors,
+ (GsmInhibitorStoreFunc)inhibitor_has_bus_name,
+ &data);
+}
+
+static gboolean
+_app_has_startup_id (const char *id,
+ GsmApp *app,
+ const char *startup_id_a)
+{
+ const char *startup_id_b;
+
+ startup_id_b = gsm_app_get_startup_id (app);
+
+ if (startup_id_b == NULL) {
+ return FALSE;
+ }
+
+ return (strcmp (startup_id_a, startup_id_b) == 0);
+}
+
+static GsmApp *
+find_app_for_startup_id (GsmManager *manager,
+ const char *startup_id)
+{
+ GsmApp *found_app;
+ GSList *a;
+
+ found_app = NULL;
/* If we're starting up the session, try to match the new client
* with one pending apps for the current phase. If not, try to match
@@ -760,7 +1313,7 @@
handled = TRUE;
new_id = NULL;
- if (manager->priv->phase == GSM_MANAGER_PHASE_SHUTDOWN) {
+ if (manager->priv->phase >= GSM_MANAGER_PHASE_QUERY_END_SESSION) {
goto out;
}
@@ -833,34 +1386,17 @@
return matches;
}
-static guint32
-generate_cookie (void)
-{
- guint32 cookie;
-
- cookie = (guint32)g_random_int_range (1, G_MAXINT32);
-
- return cookie;
-}
-
-static guint32
-_generate_unique_cookie (GsmManager *manager)
-{
- guint32 cookie;
-
- do {
- cookie = generate_cookie ();
- } while (gsm_inhibitor_store_lookup (manager->priv->inhibitors, cookie) != NULL);
-
- return cookie;
-}
-
static void
on_client_end_session_response (GsmClient *client,
gboolean is_ok,
const char *reason,
GsmManager *manager)
{
+ /* just ignore if received outside of shutdown */
+ if (manager->priv->phase < GSM_MANAGER_PHASE_QUERY_END_SESSION) {
+ return;
+ }
+
g_debug ("GsmManager: Response from end session request: is-ok=%d reason=%s", is_ok, reason);
manager->priv->query_clients = g_slist_remove (manager->priv->query_clients, client);
@@ -900,6 +1436,16 @@
(GsmInhibitorStoreFunc)inhibitor_has_client_id,
(gpointer)gsm_client_get_id (client));
}
+
+ if (manager->priv->query_clients == NULL
+ && gsm_inhibitor_store_size (manager->priv->inhibitors) == 0) {
+ if (manager->priv->query_timeout_id > 0) {
+ g_source_remove (manager->priv->query_timeout_id);
+ manager->priv->query_timeout_id = 0;
+ }
+
+ end_phase (manager);
+ }
}
static void
@@ -1462,153 +2008,35 @@
GError **error)
{
if (manager->priv->phase > GSM_MANAGER_PHASE_INITIALIZATION) {
- g_set_error (error,
- GSM_MANAGER_ERROR,
- GSM_MANAGER_ERROR_NOT_IN_INITIALIZATION,
- "Setenv interface is only available during the Initialization phase");
- return FALSE;
- }
-
- g_setenv (variable, value, TRUE);
-
- return TRUE;
-}
-
-gboolean
-gsm_manager_initialization_error (GsmManager *manager,
- const char *message,
- gboolean fatal,
- GError **error)
-{
- if (manager->priv->phase > GSM_MANAGER_PHASE_INITIALIZATION) {
- g_set_error (error,
- GSM_MANAGER_ERROR,
- GSM_MANAGER_ERROR_NOT_IN_INITIALIZATION,
- "InitializationError interface is only available during the Initialization phase");
- return FALSE;
- }
-
- gsm_util_init_error (fatal, "%s", message);
-
- return TRUE;
-}
-
-static void
-do_attempt_reboot (GsmConsolekit *consolekit)
-{
- if (gsm_consolekit_can_restart (consolekit)) {
- gdm_set_logout_action (GDM_LOGOUT_ACTION_NONE);
- gsm_consolekit_attempt_restart (consolekit);
- } else {
- gdm_set_logout_action (GDM_LOGOUT_ACTION_REBOOT);
- }
-}
-
-static void
-do_attempt_shutdown (GsmConsolekit *consolekit)
-{
- if (gsm_consolekit_can_stop (consolekit)) {
- gdm_set_logout_action (GDM_LOGOUT_ACTION_NONE);
- gsm_consolekit_attempt_stop (consolekit);
- } else {
- gdm_set_logout_action (GDM_LOGOUT_ACTION_SHUTDOWN);
- }
-}
-
-static void
-manager_attempt_reboot (GsmManager *manager)
-{
- GsmConsolekit *consolekit;
-
- consolekit = gsm_get_consolekit ();
- do_attempt_reboot (consolekit);
- g_object_unref (consolekit);
-}
-
-static void
-manager_attempt_shutdown (GsmManager *manager)
-{
- GsmConsolekit *consolekit;
-
- consolekit = gsm_get_consolekit ();
- do_attempt_shutdown (consolekit);
- g_object_unref (consolekit);
-}
-
-static gboolean
-_shutdown_client (const char *id,
- GsmClient *client,
- GsmManager *manager)
-{
- guint flags;
-
- flags = 0;
- gsm_client_end_session (client, flags);
-
- return FALSE;
-}
-
-static gboolean
-_cancel_shutdown_client (const char *id,
- GsmClient *client,
- GsmManager *manager)
-{
- gsm_client_cancel_end_session (client);
-
- return FALSE;
-}
-
-static void
-manager_logout (GsmManager *manager)
-{
- gsm_client_store_foreach (manager->priv->store,
- (GsmClientStoreFunc)_shutdown_client,
- NULL);
-
- g_debug ("GsmManager: session shutdown complete, exiting");
- gtk_main_quit ();
-}
-
-static void
-manager_attempt_hibernate (GsmManager *manager)
-{
- GsmPowerManager *power_manager;
-
- power_manager = gsm_get_power_manager ();
-
- if (gsm_power_manager_can_hibernate (power_manager)) {
- gsm_power_manager_attempt_hibernate (power_manager);
- }
-
- g_object_unref (power_manager);
-}
-
-static void
-manager_attempt_suspend (GsmManager *manager)
-{
- GsmPowerManager *power_manager;
-
- power_manager = gsm_get_power_manager ();
-
- if (gsm_power_manager_can_suspend (power_manager)) {
- gsm_power_manager_attempt_suspend (power_manager);
+ g_set_error (error,
+ GSM_MANAGER_ERROR,
+ GSM_MANAGER_ERROR_NOT_IN_INITIALIZATION,
+ "Setenv interface is only available during the Initialization phase");
+ return FALSE;
}
- g_object_unref (power_manager);
+ g_setenv (variable, value, TRUE);
+
+ return TRUE;
}
-static gboolean
-inhibitor_has_flag (gpointer key,
- GsmInhibitor *inhibitor,
- gpointer data)
+gboolean
+gsm_manager_initialization_error (GsmManager *manager,
+ const char *message,
+ gboolean fatal,
+ GError **error)
{
- int flag;
- int flags;
+ if (manager->priv->phase > GSM_MANAGER_PHASE_INITIALIZATION) {
+ g_set_error (error,
+ GSM_MANAGER_ERROR,
+ GSM_MANAGER_ERROR_NOT_IN_INITIALIZATION,
+ "InitializationError interface is only available during the Initialization phase");
+ return FALSE;
+ }
- flag = GPOINTER_TO_INT (data);
- flags = gsm_inhibitor_get_flags (inhibitor);
+ gsm_util_init_error (fatal, "%s", message);
- return (flags & flag);
+ return TRUE;
}
static gboolean
@@ -1647,145 +2075,6 @@
return TRUE;
}
-static gboolean
-gsm_manager_is_logout_inhibited (GsmManager *manager)
-{
- GsmInhibitor *inhibitor;
-
- if (manager->priv->inhibitors == NULL) {
- return FALSE;
- }
-
- inhibitor = gsm_inhibitor_store_find (manager->priv->inhibitors,
- (GsmInhibitorStoreFunc)inhibitor_has_flag,
- GINT_TO_POINTER (GSM_INHIBITOR_FLAG_LOGOUT));
- if (inhibitor == NULL) {
- return FALSE;
- }
- return TRUE;
-}
-
-static void
-manager_switch_user (GsmManager *manager)
-{
- GError *error;
- gboolean res;
- char *command;
-
- command = g_strdup_printf ("%s %s",
- GDM_FLEXISERVER_COMMAND,
- GDM_FLEXISERVER_ARGS);
-
- error = NULL;
- res = gdk_spawn_command_line_on_screen (gdk_screen_get_default (),
- command,
- &error);
-
- g_free (command);
-
- if (! res) {
- g_debug ("GsmManager: Unable to start GDM greeter: %s", error->message);
- g_error_free (error);
- }
-}
-
-static void
-do_action (GsmManager *manager,
- int action)
-{
- switch (action) {
- case GSM_LOGOUT_ACTION_SWITCH_USER:
- manager_switch_user (manager);
- break;
- case GSM_LOGOUT_ACTION_HIBERNATE:
- manager_attempt_hibernate (manager);
- break;
- case GSM_LOGOUT_ACTION_SLEEP:
- manager_attempt_suspend (manager);
- break;
- case GSM_LOGOUT_ACTION_SHUTDOWN:
- manager_attempt_shutdown (manager);
- break;
- case GSM_LOGOUT_ACTION_REBOOT:
- manager_attempt_reboot (manager);
- break;
- case GSM_LOGOUT_ACTION_LOGOUT:
- manager_logout (manager);
- break;
- default:
- g_assert_not_reached ();
- break;
- }
-}
-
-static gboolean
-inhibitor_is_jit (gpointer key,
- GsmInhibitor *inhibitor,
- GsmManager *manager)
-{
- gboolean matches;
- const char *id;
-
- id = gsm_inhibitor_get_client_id (inhibitor);
-
- matches = (id != NULL && id[0] != '\0');
-
- return matches;
-}
-
-static void
-cancel_end_session (GsmManager *manager)
-{
- /* clear all JIT inhibitors */
-
- gsm_inhibitor_store_foreach_remove (manager->priv->inhibitors,
- (GsmInhibitorStoreFunc)inhibitor_is_jit,
- (gpointer)manager);
-
- gsm_client_store_foreach (manager->priv->store,
- (GsmClientStoreFunc)_cancel_shutdown_client,
- NULL);
-}
-
-static void
-inhibit_dialog_response (GsmInhibitDialog *dialog,
- guint response_id,
- GsmManager *manager)
-{
- int action;
-
- g_debug ("GsmManager: Inhibit dialog response: %d", response_id);
-
- /* must destroy dialog before cancelling since we'll
- remove JIT inhibitors and we don't want to trigger
- action. */
- g_object_get (dialog, "action", &action, NULL);
- gtk_widget_destroy (GTK_WIDGET (dialog));
- manager->priv->inhibit_dialog = NULL;
-
- /* In case of dialog cancel, switch user, hibernate and
- * suspend, we just perform the respective action and return,
- * without shutting down the session. */
- switch (response_id) {
- case GTK_RESPONSE_CANCEL:
- case GTK_RESPONSE_NONE:
- case GTK_RESPONSE_DELETE_EVENT:
- if (action == GSM_LOGOUT_ACTION_LOGOUT
- || action == GSM_LOGOUT_ACTION_SHUTDOWN
- || action == GSM_LOGOUT_ACTION_REBOOT) {
- cancel_end_session (manager);
- }
- break;
- case GTK_RESPONSE_ACCEPT:
- g_debug ("GsmManager: doing action %d", action);
- do_action (manager, action);
- break;
- default:
- g_assert_not_reached ();
- break;
- }
-}
-
static void
request_reboot (GsmManager *manager)
{
@@ -1893,112 +2182,14 @@
gtk_widget_show (manager->priv->inhibit_dialog);
}
-static gboolean
-_client_query_end_session (const char *id,
- GsmClient *client,
- GsmManager *manager)
-{
- g_debug ("GsmManager: adding client to query clients: %s", gsm_client_get_id (client));
- manager->priv->query_clients = g_slist_prepend (manager->priv->query_clients,
- client);
- gsm_client_query_end_session (client, 0);
-
- return FALSE;
-}
-
-static void
-query_end_session_complete (GsmManager *manager)
-{
- g_debug ("GsmManager: query end session complete");
-
- if (! gsm_manager_is_logout_inhibited (manager)) {
- manager_logout (manager);
- return;
- }
-
- if (manager->priv->inhibit_dialog != NULL) {
- g_debug ("GsmManager: inhibit dialog already up");
- gtk_window_present (GTK_WINDOW (manager->priv->inhibit_dialog));
- return;
- }
-
- manager->priv->inhibit_dialog = gsm_inhibit_dialog_new (manager->priv->inhibitors,
- GSM_LOGOUT_ACTION_LOGOUT);
-
- g_signal_connect (manager->priv->inhibit_dialog,
- "response",
- G_CALLBACK (inhibit_dialog_response),
- manager);
- gtk_widget_show (manager->priv->inhibit_dialog);
-
-}
-
-
-static gboolean
-on_query_end_session_timeout (GsmManager *manager)
-{
- GSList *l;
-
- manager->priv->query_timeout_id = 0;
-
- g_debug ("GsmManager: query end session timed out");
-
- for (l = manager->priv->query_clients; l != NULL; l = l->next) {
- guint cookie;
- GsmInhibitor *inhibitor;
- const char *bus_name;
-
- g_warning ("Client '%s' failed to reply before timeout",
- gsm_client_get_id (l->data));
-
- /* Add JIT inhibit for unresponsive client */
- if (GSM_IS_DBUS_CLIENT (l->data)) {
- bus_name = gsm_dbus_client_get_bus_name (l->data);
- } else {
- bus_name = NULL;
- }
-
- cookie = _generate_unique_cookie (manager);
- inhibitor = gsm_inhibitor_new_for_client (gsm_client_get_id (l->data),
- gsm_client_get_app_id (l->data),
- GSM_INHIBITOR_FLAG_LOGOUT,
- _("Not responding"),
- bus_name,
- cookie);
- gsm_inhibitor_store_add (manager->priv->inhibitors, inhibitor);
- g_object_unref (inhibitor);
- }
-
- query_end_session_complete (manager);
-
- return FALSE;
-}
-
-static void
-query_end_session (GsmManager *manager)
-{
- if (manager->priv->query_timeout_id > 0) {
- g_source_remove (manager->priv->query_timeout_id);
- manager->priv->query_timeout_id = 0;
- }
- manager->priv->query_timeout_id = g_timeout_add_seconds (1, (GSourceFunc)on_query_end_session_timeout, manager);
-
- debug_clients (manager);
- g_debug ("GsmManager: sending query-end-session to clients");
- gsm_client_store_foreach (manager->priv->store,
- (GsmClientStoreFunc)_client_query_end_session,
- manager);
-}
static void
-request_logout (GsmManager *manager)
+request_logout (GsmManager *manager,
+ gboolean forceful)
{
g_debug ("GsmManager: requesting logout");
-
- /* First thing is to alert clients that a logout has been requested.
- * We wait for all clients to respond or 1 second, which ever occurs first.
- */
- query_end_session (manager);
+ manager->priv->forceful = forceful;
+ end_phase (manager);
}
static void
@@ -2060,7 +2251,7 @@
request_reboot (manager);
break;
case GSM_LOGOUT_RESPONSE_LOGOUT:
- request_logout (manager);
+ request_logout (manager, FALSE);
break;
default:
g_assert_not_reached ();
@@ -2073,7 +2264,7 @@
{
GtkWidget *dialog;
- if (manager->priv->phase == GSM_MANAGER_PHASE_SHUTDOWN) {
+ if (manager->priv->phase >= GSM_MANAGER_PHASE_QUERY_END_SESSION) {
/* Already shutting down, nothing more to do */
return;
}
@@ -2093,7 +2284,7 @@
{
GtkWidget *dialog;
- if (manager->priv->phase == GSM_MANAGER_PHASE_SHUTDOWN) {
+ if (manager->priv->phase >= GSM_MANAGER_PHASE_QUERY_END_SESSION) {
/* Already shutting down, nothing more to do */
return;
}
@@ -2110,12 +2301,13 @@
static void
user_logout (GsmManager *manager,
- gboolean show_confirmation)
+ gboolean show_confirmation,
+ gboolean forceful)
{
gboolean logout_prompt;
GConfClient *client;
- if (manager->priv->phase == GSM_MANAGER_PHASE_SHUTDOWN) {
+ if (manager->priv->phase >= GSM_MANAGER_PHASE_QUERY_END_SESSION) {
/* Already shutting down, nothing more to do */
return;
}
@@ -2133,7 +2325,7 @@
if (logout_prompt) {
show_logout_dialog (manager);
} else {
- request_logout (manager);
+ request_logout (manager, forceful);
}
}
@@ -2180,15 +2372,15 @@
switch (logout_mode) {
case GSM_MANAGER_LOGOUT_MODE_NORMAL:
- user_logout (manager, TRUE);
+ user_logout (manager, TRUE, FALSE);
break;
case GSM_MANAGER_LOGOUT_MODE_NO_CONFIRMATION:
- user_logout (manager, FALSE);
+ user_logout (manager, FALSE, FALSE);
break;
case GSM_MANAGER_LOGOUT_MODE_FORCE:
- /* FIXME: Implement when session state saving is ready */
+ user_logout (manager, FALSE, TRUE);
break;
default:
@@ -2263,7 +2455,7 @@
g_debug ("GsmManager: RegisterClient %s", startup_id);
- if (manager->priv->phase == GSM_MANAGER_PHASE_SHUTDOWN) {
+ if (manager->priv->phase >= GSM_MANAGER_PHASE_QUERY_END_SESSION) {
GError *new_error;
g_debug ("Unable to register client: shutting down");
Modified: branches/dbus_based/gnome-session/gsm-manager.h
==============================================================================
--- branches/dbus_based/gnome-session/gsm-manager.h (original)
+++ branches/dbus_based/gnome-session/gsm-manager.h Fri Jul 18 19:53:46 2008
@@ -77,7 +77,9 @@
/* done launching */
GSM_MANAGER_PHASE_RUNNING,
/* shutting down */
- GSM_MANAGER_PHASE_SHUTDOWN
+ GSM_MANAGER_PHASE_QUERY_END_SESSION,
+ GSM_MANAGER_PHASE_END_SESSION,
+ GSM_MANAGER_PHASE_EXIT
} GsmManagerPhase;
typedef enum
Modified: branches/dbus_based/gnome-session/gsm-xsmp-client.c
==============================================================================
--- branches/dbus_based/gnome-session/gsm-xsmp-client.c (original)
+++ branches/dbus_based/gnome-session/gsm-xsmp-client.c Fri Jul 18 19:53:46 2008
@@ -417,7 +417,8 @@
static void
do_save_yourself (GsmXSMPClient *client,
- int save_type)
+ int save_type,
+ gboolean forceful)
{
if (client->priv->next_save_yourself != -1) {
/* Either we're currently doing a shutdown and there's a checkpoint
@@ -445,30 +446,25 @@
default:
/* Logout */
- SmsSaveYourself (client->priv->conn,
- save_type,
- TRUE,
- SmInteractStyleAny,
- FALSE);
+ if (forceful) {
+ SmsSaveYourself (client->priv->conn,
+ save_type, /* save type */
+ TRUE, /* shutdown */
+ SmInteractStyleNone, /* interact style */
+ TRUE); /* fast */
+ } else {
+ SmsSaveYourself (client->priv->conn,
+ save_type,
+ TRUE,
+ SmInteractStyleAny,
+ FALSE);
+ }
break;
}
}
}
static void
-xsmp_save_yourself (GsmClient *client,
- gboolean save_state)
-{
- GsmXSMPClient *xsmp = (GsmXSMPClient *) client;
-
- g_debug ("GsmXSMPClient: xsmp_save_yourself ('%s', %s)",
- xsmp->priv->description,
- save_state ? "True" : "False");
-
- do_save_yourself (xsmp, save_state ? SmSaveBoth : SmSaveGlobal);
-}
-
-static void
xsmp_save_yourself_phase2 (GsmClient *client)
{
GsmXSMPClient *xsmp = (GsmXSMPClient *) client;
@@ -515,14 +511,20 @@
xsmp_query_end_session (GsmClient *client,
guint flags)
{
- xsmp_save_yourself (client, FALSE);
+ gboolean forceful;
+
+ forceful = (flags & GSM_CLIENT_END_SESSION_FLAG_FORCEFUL);
+ do_save_yourself (GSM_XSMP_CLIENT (client), SmSaveGlobal, forceful);
}
static void
xsmp_end_session (GsmClient *client,
guint flags)
{
- xsmp_save_yourself (client, FALSE);
+ gboolean forceful;
+
+ forceful = (flags & GSM_CLIENT_END_SESSION_FLAG_FORCEFUL);
+ do_save_yourself (GSM_XSMP_CLIENT (client), SmSaveGlobal, forceful);
}
static char *
@@ -802,7 +804,7 @@
g_signal_emit (client, signals[LOGOUT_REQUEST], 0, !fast);
} else if (!shutdown && !global) {
g_debug ("GsmXSMPClient: initiating checkpoint");
- do_save_yourself (client, SmSaveLocal);
+ do_save_yourself (client, SmSaveLocal, FALSE);
} else {
g_debug ("GsmXSMPClient: ignoring");
}
@@ -892,7 +894,7 @@
int save_type = client->priv->next_save_yourself;
client->priv->next_save_yourself = -1;
- do_save_yourself (client, save_type);
+ do_save_yourself (client, save_type, FALSE);
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]