Blame SOURCES/0008-Add-Remember-Currently-Running-Applications-button.patch

f47161
From ade647861a671eca584d25432722ac2661854748 Mon Sep 17 00:00:00 2001
b31790
From: Josselin Mouette <joss@malsain.org>
b31790
Date: Mon, 21 Jun 2010 15:22:23 -0400
b31790
Subject: [PATCH 08/19] Add "Remember Currently Running Applications" button
b31790
b31790
This adds back session saving that's not at logout.
b31790
---
f47161
 capplet/gsm-properties-dialog.c            |  63 ++++++++-
f47161
 capplet/meson.build                        |   3 +-
f47161
 data/session-properties.ui                 |  12 ++
b31790
 gnome-session/gsm-client.c                 |  10 ++
f47161
 gnome-session/gsm-client.h                 |   6 +
f47161
 gnome-session/gsm-dbus-client.c            |  14 ++
f47161
 gnome-session/gsm-manager.c                | 150 ++++++++++++++++++++-
b31790
 gnome-session/gsm-manager.h                |   3 +
f47161
 gnome-session/gsm-xsmp-client.c            |  37 +++++
b31790
 gnome-session/gsm-xsmp-client.h            |   3 +-
b31790
 gnome-session/org.gnome.SessionManager.xml |   8 ++
f47161
 meson.build                                |   1 +
f47161
 12 files changed, 305 insertions(+), 5 deletions(-)
b31790
b31790
diff --git a/capplet/gsm-properties-dialog.c b/capplet/gsm-properties-dialog.c
b31790
index 33812b8b..d2be778b 100644
b31790
--- a/capplet/gsm-properties-dialog.c
b31790
+++ b/capplet/gsm-properties-dialog.c
b31790
@@ -5,70 +5,77 @@
b31790
  * Copyright (C) 2008 Lucas Rocha.
b31790
  * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
b31790
  *
b31790
  * This program is free software; you can redistribute it and/or modify
b31790
  * it under the terms of the GNU General Public License as published by
b31790
  * the Free Software Foundation; either version 2 of the License, or
b31790
  * (at your option) any later version.
b31790
  *
b31790
  * This program is distributed in the hope that it will be useful,
b31790
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
b31790
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
b31790
  * GNU General Public License for more details.
b31790
  *
b31790
  * You should have received a copy of the GNU General Public License
b31790
  * along with this program; if not, write to the Free Software
b31790
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
b31790
  *
b31790
  */
b31790
 
b31790
 #include "config.h"
b31790
 
b31790
 #include <glib.h>
b31790
 #include <glib/gi18n.h>
b31790
 #include <gtk/gtk.h>
b31790
 
b31790
 #include "gsm-properties-dialog.h"
b31790
 #include "gsm-app-dialog.h"
b31790
 #include "gsm-util.h"
b31790
 #include "gsp-app.h"
b31790
 #include "gsp-app-manager.h"
b31790
+#include <dbus/dbus-glib.h>
b31790
+#include <dbus/dbus-glib-lowlevel.h>
b31790
+
b31790
+#define GSM_SERVICE_DBUS   "org.gnome.SessionManager"
b31790
+#define GSM_PATH_DBUS      "/org/gnome/SessionManager"
b31790
+#define GSM_INTERFACE_DBUS "org.gnome.SessionManager"
b31790
 
b31790
 #define GSM_PROPERTIES_DIALOG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSM_TYPE_PROPERTIES_DIALOG, GsmPropertiesDialogPrivate))
b31790
 
b31790
 #define GTKBUILDER_FILE "session-properties.ui"
b31790
 
b31790
 #define CAPPLET_TREEVIEW_WIDGET_NAME      "session_properties_treeview"
b31790
 #define CAPPLET_ADD_WIDGET_NAME           "session_properties_add_button"
b31790
 #define CAPPLET_DELETE_WIDGET_NAME        "session_properties_delete_button"
b31790
 #define CAPPLET_EDIT_WIDGET_NAME          "session_properties_edit_button"
b31790
 #define CAPPLET_SAVE_WIDGET_NAME          "session_properties_save_button"
b31790
+#define CAPPLET_SESSION_SAVED_WIDGET_NAME "session_properties_session_saved_label"
b31790
 #define CAPPLET_REMEMBER_WIDGET_NAME      "session_properties_remember_toggle"
b31790
 
b31790
 #define STARTUP_APP_ICON     "system-run"
b31790
 
b31790
 #define SPC_SETTINGS_SCHEMA          "org.gnome.SessionManager"
b31790
 #define SPC_SETTINGS_AUTOSAVE_KEY    "auto-save-session"
b31790
 
b31790
 struct GsmPropertiesDialogPrivate
b31790
 {
b31790
         GtkBuilder        *xml;
b31790
         GtkListStore      *list_store;
b31790
         GtkTreeModel      *tree_filter;
b31790
 
b31790
         GtkTreeView       *treeview;
b31790
         GtkWidget         *add_button;
b31790
         GtkWidget         *delete_button;
b31790
         GtkWidget         *edit_button;
b31790
 
b31790
         GSettings         *settings;
b31790
 
b31790
         GspAppManager     *manager;
b31790
 };
b31790
 
b31790
 enum {
b31790
         STORE_COL_VISIBLE = 0,
b31790
         STORE_COL_ENABLED,
b31790
         STORE_COL_GICON,
b31790
         STORE_COL_DESCRIPTION,
b31790
         STORE_COL_APP,
b31790
         STORE_COL_SEARCH,
b31790
@@ -430,65 +437,119 @@ on_edit_app_clicked (GtkWidget           *widget,
b31790
                 char       *exec;
b31790
                 char       *comment;
b31790
 
b31790
                 edit_dialog = gsm_app_dialog_new (gsp_app_get_name (app),
b31790
                                                   gsp_app_get_exec (app),
b31790
                                                   gsp_app_get_comment (app));
b31790
                 gtk_window_set_transient_for (GTK_WINDOW (edit_dialog),
b31790
                                               GTK_WINDOW (dialog));
b31790
 
b31790
                 if (gsm_app_dialog_run (GSM_APP_DIALOG (edit_dialog),
b31790
                                         &name, &exec, &comment)) {
b31790
                         gsp_app_update (app, name, comment, exec);
b31790
                         g_free (name);
b31790
                         g_free (exec);
b31790
                         g_free (comment);
b31790
                 }
b31790
 
b31790
                 g_object_unref (app);
b31790
         }
b31790
 }
b31790
 
b31790
 static void
b31790
 on_row_activated (GtkTreeView         *tree_view,
b31790
                   GtkTreePath         *path,
b31790
                   GtkTreeViewColumn   *column,
b31790
                   GsmPropertiesDialog *dialog)
b31790
 {
b31790
         on_edit_app_clicked (NULL, dialog);
b31790
 }
b31790
 
b31790
+static void
b31790
+session_saved_message (GsmPropertiesDialog *dialog,
b31790
+                       const char *msg,
b31790
+                       gboolean is_error)
b31790
+{
b31790
+        GtkLabel *label;
b31790
+        gchar *markup;
b31790
+        label = GTK_LABEL (gtk_builder_get_object (dialog->priv->xml, CAPPLET_SESSION_SAVED_WIDGET_NAME));
b31790
+        if (is_error)
b31790
+                markup = g_markup_printf_escaped ("%s", msg);
b31790
+        else
b31790
+                markup = g_markup_escape_text (msg, -1);
b31790
+        gtk_label_set_markup (label, markup);
b31790
+        g_free (markup);
b31790
+}
b31790
+
b31790
+static void
b31790
+session_saved_cb (DBusGProxy *proxy,
b31790
+                  DBusGProxyCall *call_id,
b31790
+                  void *user_data)
b31790
+{
b31790
+        gboolean res;
b31790
+        GsmPropertiesDialog *dialog = user_data;
b31790
+
b31790
+        res = dbus_g_proxy_end_call (proxy, call_id, NULL, G_TYPE_INVALID);
b31790
+        if (res)
b31790
+                session_saved_message (dialog, _("Your session has been saved."), FALSE);
b31790
+        else
b31790
+                session_saved_message (dialog, _("Failed to save session"), TRUE);
b31790
+
b31790
+        g_object_unref (proxy);
b31790
+}
b31790
+
b31790
 static void
b31790
 on_save_session_clicked (GtkWidget           *widget,
b31790
                          GsmPropertiesDialog *dialog)
b31790
 {
b31790
-        g_debug ("Session saving is not implemented yet!");
b31790
+        DBusGConnection *conn;
b31790
+        DBusGProxy *proxy;
b31790
+        DBusGProxyCall *call;
b31790
+
b31790
+        conn = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
b31790
+        if (conn == NULL) {
b31790
+                session_saved_message (dialog, _("Could not connect to the session bus"), TRUE);
b31790
+                return;
b31790
+        }
b31790
+
b31790
+        proxy = dbus_g_proxy_new_for_name (conn, GSM_SERVICE_DBUS, GSM_PATH_DBUS, GSM_INTERFACE_DBUS);
b31790
+        if (proxy == NULL) {
b31790
+                session_saved_message (dialog, _("Could not connect to the session manager"), TRUE);
b31790
+                return;
b31790
+        }
b31790
+
b31790
+        call = dbus_g_proxy_begin_call (proxy, "SaveSession", session_saved_cb, dialog, NULL, G_TYPE_INVALID);
b31790
+        if (call == NULL) {
b31790
+                session_saved_message (dialog, _("Failed to save session"), TRUE);
b31790
+                g_object_unref (proxy);
b31790
+                return;
b31790
+        }
b31790
 }
b31790
 
b31790
 static void
b31790
 setup_dialog (GsmPropertiesDialog *dialog)
b31790
 {
b31790
         GtkTreeView       *treeview;
b31790
         GtkWidget         *button;
b31790
         GtkTreeModel      *tree_filter;
b31790
         GtkTreeViewColumn *column;
b31790
         GtkCellRenderer   *renderer;
b31790
         GtkTreeSelection  *selection;
b31790
         GtkTargetList     *targetlist;
b31790
 
b31790
         gtk_dialog_add_buttons (GTK_DIALOG (dialog),
b31790
                                 GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
b31790
                                 NULL);
b31790
 
b31790
         dialog->priv->list_store = gtk_list_store_new (NUMBER_OF_COLUMNS,
b31790
                                                        G_TYPE_BOOLEAN,
b31790
                                                        G_TYPE_BOOLEAN,
b31790
                                                        G_TYPE_ICON,
b31790
                                                        G_TYPE_STRING,
b31790
                                                        G_TYPE_OBJECT,
b31790
                                                        G_TYPE_STRING);
b31790
         tree_filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (dialog->priv->list_store),
b31790
                                                  NULL);
b31790
         g_object_unref (dialog->priv->list_store);
b31790
         dialog->priv->tree_filter = tree_filter;
b31790
 
b31790
         gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (tree_filter),
f47161
diff --git a/capplet/meson.build b/capplet/meson.build
f47161
index 8dad9c80..ae6cb6b9 100644
f47161
--- a/capplet/meson.build
f47161
+++ b/capplet/meson.build
f47161
@@ -1,36 +1,37 @@
f47161
 install_data(
f47161
   install_dir: session_bindir
b31790
 )
b31790
 
f47161
 deps = session_deps + [
f47161
   glib_dep,
f47161
   gtk_dep,
f47161
   x11_dep,
f47161
   sm_dep,
f47161
-  ice_dep
f47161
+  ice_dep,
f47161
+  dbus_glib_dep
f47161
 ]
f47161
 
f47161
 cflags = [
f47161
   '-DLOCALE_DIR="@0@"'.format(session_localedir),
f47161
   '-DGTKBUILDER_DIR="@0@"'.format(session_pkgdatadir)
f47161
 ]
f47161
 
f47161
 sources = files(
f47161
   '../gnome-session/gsm-util.c',
f47161
   'gsm-app-dialog.c',
f47161
   'gsm-properties-dialog.c',
f47161
   'gsp-app.c',
f47161
   'gsp-app-manager.c',
f47161
   'gsp-keyfile.c',
f47161
   'main.c'
b31790
 )
b31790
 
f47161
 executable(
f47161
   'gnome-session-properties',
f47161
   sources,
f47161
   include_directories: [ top_inc, include_directories('../gnome-session') ],
f47161
   dependencies: deps,
f47161
   c_args: cflags,
f47161
   install: true,
f47161
   install_dir: session_bindir
f47161
 )
b31790
diff --git a/data/session-properties.ui b/data/session-properties.ui
b31790
index 47a30f78..b43759ff 100644
b31790
--- a/data/session-properties.ui
b31790
+++ b/data/session-properties.ui
b31790
@@ -133,108 +133,120 @@
b31790
       </packing>
b31790
     </child>
b31790
     <child>
b31790
       <object class="GtkVBox" id="vbox3">
b31790
         <property name="visible">True</property>
b31790
         <property name="can_focus">False</property>
b31790
         <property name="border_width">12</property>
b31790
         <property name="spacing">6</property>
b31790
         <child>
b31790
           <object class="GtkCheckButton" id="session_properties_remember_toggle">
b31790
             <property name="label" translatable="yes">_Automatically remember running applications when logging out</property>
b31790
             <property name="visible">True</property>
b31790
             <property name="can_focus">True</property>
b31790
             <property name="receives_default">False</property>
b31790
             <property name="use_underline">True</property>
b31790
             <property name="xalign">0.5</property>
b31790
             <property name="draw_indicator">True</property>
b31790
           </object>
b31790
           <packing>
b31790
             <property name="expand">False</property>
b31790
             <property name="fill">False</property>
b31790
             <property name="position">0</property>
b31790
           </packing>
b31790
         </child>
b31790
         <child>
b31790
           <object class="GtkHButtonBox" id="hbuttonbox1">
b31790
             <property name="visible">True</property>
b31790
             <property name="can_focus">False</property>
b31790
             <child>
b31790
               <object class="GtkButton" id="session_properties_save_button">
b31790
+                <property name="visible">True</property>
b31790
                 <property name="can_focus">True</property>
b31790
                 <property name="receives_default">True</property>
b31790
                 <child>
b31790
                   <object class="GtkHBox" id="hbox2">
b31790
                     <property name="visible">True</property>
b31790
                     <property name="can_focus">False</property>
b31790
                     <property name="spacing">4</property>
b31790
                     <child>
b31790
                       <object class="GtkImage" id="image1">
b31790
                         <property name="visible">True</property>
b31790
                         <property name="can_focus">False</property>
b31790
                         <property name="stock">gtk-save</property>
b31790
                       </object>
b31790
                       <packing>
b31790
                         <property name="expand">False</property>
b31790
                         <property name="fill">False</property>
b31790
                         <property name="position">0</property>
b31790
                       </packing>
b31790
                     </child>
b31790
                     <child>
b31790
                       <object class="GtkLabel" id="label7">
b31790
                         <property name="visible">True</property>
b31790
                         <property name="can_focus">False</property>
b31790
                         <property name="label" translatable="yes">_Remember Currently Running Applications</property>
b31790
                         <property name="use_underline">True</property>
b31790
                       </object>
b31790
                       <packing>
b31790
                         <property name="expand">True</property>
b31790
                         <property name="fill">True</property>
b31790
                         <property name="position">1</property>
b31790
                       </packing>
b31790
                     </child>
b31790
                   </object>
b31790
                 </child>
b31790
               </object>
b31790
               <packing>
b31790
                 <property name="expand">False</property>
b31790
                 <property name="fill">False</property>
b31790
                 <property name="position">0</property>
b31790
               </packing>
b31790
             </child>
b31790
           </object>
b31790
           <packing>
b31790
             <property name="expand">False</property>
b31790
             <property name="fill">False</property>
b31790
             <property name="position">1</property>
b31790
           </packing>
b31790
         </child>
b31790
+        <child>
b31790
+          <object class="GtkLabel" id="session_properties_session_saved_label">
b31790
+            <property name="visible">True</property>
b31790
+            <property name="wrap">True</property>
b31790
+          </object>
b31790
+          <packing>
b31790
+            <property name="expand">False</property>
b31790
+            <property name="fill">False</property>
b31790
+            <property name="position">2</property>
b31790
+          </packing>
b31790
+        </child>
b31790
       </object>
b31790
       <packing>
b31790
         <property name="position">1</property>
b31790
       </packing>
b31790
     </child>
b31790
     <child type="tab">
b31790
       <object class="GtkLabel" id="label5">
b31790
         <property name="visible">True</property>
b31790
         <property name="can_focus">False</property>
b31790
         <property name="label" translatable="yes">Options</property>
b31790
       </object>
b31790
       <packing>
b31790
         <property name="position">1</property>
b31790
         <property name="tab_fill">False</property>
b31790
       </packing>
b31790
     </child>
b31790
   </object>
b31790
   <object class="GtkTable" id="main-table">
b31790
     <property name="visible">True</property>
b31790
     <property name="can_focus">False</property>
b31790
     <property name="border_width">6</property>
b31790
     <property name="n_rows">3</property>
b31790
     <property name="n_columns">2</property>
b31790
     <property name="column_spacing">12</property>
b31790
     <property name="row_spacing">6</property>
b31790
     <child>
b31790
       <object class="GtkHBox" id="hbox3">
b31790
         <property name="visible">True</property>
b31790
         <property name="can_focus">False</property>
b31790
         <property name="spacing">12</property>
b31790
diff --git a/gnome-session/gsm-client.c b/gnome-session/gsm-client.c
f47161
index 6828ad44..3f216b22 100644
b31790
--- a/gnome-session/gsm-client.c
b31790
+++ b/gnome-session/gsm-client.c
f47161
@@ -514,50 +514,60 @@ gsm_client_query_end_session (GsmClient                *client,
b31790
         g_return_val_if_fail (GSM_IS_CLIENT (client), FALSE);
b31790
 
b31790
         return GSM_CLIENT_GET_CLASS (client)->impl_query_end_session (client, flags, error);
b31790
 }
b31790
 
b31790
 gboolean
b31790
 gsm_client_end_session (GsmClient                *client,
b31790
                         GsmClientEndSessionFlag   flags,
b31790
                         GError                  **error)
b31790
 {
b31790
         g_return_val_if_fail (GSM_IS_CLIENT (client), FALSE);
b31790
 
b31790
         return GSM_CLIENT_GET_CLASS (client)->impl_end_session (client, flags, error);
b31790
 }
b31790
 
b31790
 gboolean
b31790
 gsm_client_stop (GsmClient *client,
b31790
                  GError   **error)
b31790
 {
b31790
         g_return_val_if_fail (GSM_IS_CLIENT (client), FALSE);
b31790
 
b31790
         return GSM_CLIENT_GET_CLASS (client)->impl_stop (client, error);
b31790
 }
b31790
 
b31790
 void
b31790
 gsm_client_disconnected (GsmClient *client)
b31790
 {
b31790
         g_signal_emit (client, signals[DISCONNECTED], 0);
b31790
 }
b31790
 
b31790
+gboolean
b31790
+gsm_client_request_save (GsmClient *client,
b31790
+                         guint      flags,
b31790
+                         GError   **error)
b31790
+{
b31790
+        g_return_val_if_fail (GSM_IS_CLIENT (client), FALSE);
b31790
+
b31790
+        return GSM_CLIENT_GET_CLASS (client)->impl_request_save (client, flags, error);
b31790
+}
b31790
+
b31790
 GKeyFile *
b31790
 gsm_client_save (GsmClient *client,
f47161
                  GsmApp    *app,
b31790
                  GError   **error)
b31790
 {
b31790
         g_return_val_if_fail (GSM_IS_CLIENT (client), FALSE);
b31790
 
f47161
         return GSM_CLIENT_GET_CLASS (client)->impl_save (client, app, error);
b31790
 }
b31790
 
b31790
 void
b31790
 gsm_client_end_session_response (GsmClient  *client,
b31790
                                  gboolean    is_ok,
b31790
                                  gboolean    do_last,
b31790
                                  gboolean    cancel,
b31790
                                  const char *reason)
b31790
 {
b31790
         g_signal_emit (client, signals[END_SESSION_RESPONSE], 0,
b31790
                        is_ok, do_last, cancel, reason);
b31790
 }
b31790
diff --git a/gnome-session/gsm-client.h b/gnome-session/gsm-client.h
f47161
index 78cb15d8..19c9cd8d 100644
b31790
--- a/gnome-session/gsm-client.h
b31790
+++ b/gnome-session/gsm-client.h
f47161
@@ -64,91 +64,97 @@ struct _GsmClient
b31790
         GObject           parent;
b31790
         GsmClientPrivate *priv;
b31790
 };
b31790
 
b31790
 struct _GsmClientClass
b31790
 {
b31790
         GObjectClass parent_class;
b31790
 
b31790
         /* signals */
b31790
         void         (*disconnected)               (GsmClient  *client);
b31790
         void         (*end_session_response)       (GsmClient  *client,
b31790
                                                     gboolean    ok,
b31790
                                                     gboolean    do_last,
b31790
                                                     gboolean    cancel,
b31790
                                                     const char *reason);
b31790
 
b31790
         /* virtual methods */
b31790
         char *                (*impl_get_app_name)           (GsmClient *client);
b31790
         GsmClientRestartStyle (*impl_get_restart_style_hint) (GsmClient *client);
b31790
         guint                 (*impl_get_unix_process_id)    (GsmClient *client);
b31790
         gboolean              (*impl_query_end_session)      (GsmClient *client,
b31790
                                                               GsmClientEndSessionFlag flags,
b31790
                                                               GError   **error);
b31790
         gboolean              (*impl_end_session)            (GsmClient *client,
b31790
                                                               GsmClientEndSessionFlag flags,
b31790
                                                               GError   **error);
b31790
         gboolean              (*impl_cancel_end_session)     (GsmClient *client,
b31790
                                                               GError   **error);
b31790
         gboolean              (*impl_stop)                   (GsmClient *client,
b31790
                                                               GError   **error);
b31790
+        gboolean              (*impl_request_save)           (GsmClient *client,
b31790
+                                                              guint      flags,
b31790
+                                                              GError   **error);
b31790
         GKeyFile *            (*impl_save)                   (GsmClient *client,
f47161
                                                               GsmApp    *app,
b31790
                                                               GError   **error);
b31790
 };
b31790
 
b31790
 typedef enum
b31790
 {
b31790
         GSM_CLIENT_ERROR_GENERAL = 0,
b31790
         GSM_CLIENT_ERROR_NOT_REGISTERED,
b31790
         GSM_CLIENT_NUM_ERRORS
b31790
 } GsmClientError;
b31790
 
b31790
 #define GSM_CLIENT_ERROR gsm_client_error_quark ()
b31790
 GQuark                gsm_client_error_quark                (void);
b31790
 
b31790
 GType                 gsm_client_get_type                   (void) G_GNUC_CONST;
b31790
 
b31790
 const char           *gsm_client_peek_id                    (GsmClient  *client);
b31790
 
b31790
 
b31790
 const char *          gsm_client_peek_startup_id            (GsmClient  *client);
b31790
 const char *          gsm_client_peek_app_id                (GsmClient  *client);
b31790
 guint                 gsm_client_peek_restart_style_hint    (GsmClient  *client);
b31790
 guint                 gsm_client_peek_status                (GsmClient  *client);
b31790
 
b31790
 
b31790
 char                 *gsm_client_get_app_name               (GsmClient  *client);
b31790
 void                  gsm_client_set_app_id                 (GsmClient  *client,
b31790
                                                              const char *app_id);
b31790
 void                  gsm_client_set_status                 (GsmClient  *client,
b31790
                                                              guint       status);
b31790
 
b31790
 gboolean              gsm_client_end_session                (GsmClient  *client,
b31790
                                                              guint       flags,
b31790
                                                              GError    **error);
b31790
 gboolean              gsm_client_query_end_session          (GsmClient  *client,
b31790
                                                              guint       flags,
b31790
                                                              GError    **error);
b31790
 gboolean              gsm_client_cancel_end_session         (GsmClient  *client,
b31790
                                                              GError    **error);
b31790
 
b31790
 void                  gsm_client_disconnected               (GsmClient  *client);
b31790
 
b31790
+gboolean              gsm_client_request_save               (GsmClient  *client,
b31790
+                                                             guint       flags,
b31790
+                                                             GError    **error);
b31790
 GKeyFile             *gsm_client_save                       (GsmClient  *client,
f47161
                                                              GsmApp     *app,
b31790
                                                              GError    **error);
b31790
 
b31790
 gboolean              gsm_client_stop                       (GsmClient  *client,
b31790
                                                              GError    **error);
b31790
 
b31790
 /* private */
b31790
 
b31790
 void                  gsm_client_end_session_response       (GsmClient  *client,
b31790
                                                              gboolean    is_ok,
b31790
                                                              gboolean    do_last,
b31790
                                                              gboolean    cancel,
b31790
                                                              const char *reason);
b31790
 
b31790
 G_END_DECLS
b31790
 
b31790
 #endif /* __GSM_CLIENT_H__ */
b31790
diff --git a/gnome-session/gsm-dbus-client.c b/gnome-session/gsm-dbus-client.c
f47161
index 6e9b002b..5793f830 100644
b31790
--- a/gnome-session/gsm-dbus-client.c
b31790
+++ b/gnome-session/gsm-dbus-client.c
b31790
@@ -300,60 +300,73 @@ gsm_dbus_client_get_property (GObject    *object,
b31790
         case PROP_BUS_NAME:
b31790
                 g_value_set_string (value, self->priv->bus_name);
b31790
                 break;
b31790
         default:
b31790
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
b31790
                 break;
b31790
         }
b31790
 }
b31790
 
b31790
 static void
b31790
 gsm_dbus_client_finalize (GObject *object)
b31790
 {
b31790
         GsmDBusClient *client = (GsmDBusClient *) object;
b31790
 
b31790
         g_free (client->priv->bus_name);
b31790
 
b31790
         if (client->priv->skeleton != NULL) {
b31790
                 g_dbus_interface_skeleton_unexport_from_connection (G_DBUS_INTERFACE_SKELETON (client->priv->skeleton),
b31790
                                                                     client->priv->connection);
b31790
                 g_clear_object (&client->priv->skeleton);
b31790
         }
b31790
 
b31790
         g_clear_object (&client->priv->connection);
b31790
 
b31790
         if (client->priv->watch_id != 0)
b31790
                 g_bus_unwatch_name (client->priv->watch_id);
b31790
 
b31790
         G_OBJECT_CLASS (gsm_dbus_client_parent_class)->finalize (object);
b31790
 }
b31790
 
b31790
+static gboolean
b31790
+dbus_client_request_save (GsmClient *client,
b31790
+                          guint      flags,
b31790
+                          GError   **error)
b31790
+{
b31790
+        g_debug ("GsmDBusClient: sending save request to client with id %s",
b31790
+                 gsm_client_peek_id (client));
b31790
+
b31790
+        /* FIXME: The protocol does not support this */
b31790
+
b31790
+        return FALSE;
b31790
+}
b31790
+
b31790
 static GKeyFile *
b31790
 dbus_client_save (GsmClient *client,
f47161
                   GsmApp    *app,
b31790
                   GError   **error)
b31790
 {
b31790
         g_debug ("GsmDBusClient: saving client with id %s",
b31790
                  gsm_client_peek_id (client));
b31790
 
b31790
         /* FIXME: We still don't support client saving for D-Bus
b31790
          * session clients */
b31790
 
b31790
         return NULL;
b31790
 }
b31790
 
b31790
 static gboolean
b31790
 dbus_client_stop (GsmClient *client,
b31790
                   GError   **error)
b31790
 {
b31790
         GsmDBusClient  *dbus_client = (GsmDBusClient *) client;
b31790
         gsm_exported_client_private_emit_stop (dbus_client->priv->skeleton);
b31790
         return TRUE;
b31790
 }
b31790
 
b31790
 static char *
b31790
 dbus_client_get_app_name (GsmClient *client)
b31790
 {
b31790
         /* Always use app-id instead */
b31790
         return NULL;
b31790
 }
b31790
 
f47161
@@ -394,60 +407,61 @@ static gboolean
b31790
 dbus_client_end_session (GsmClient                *client,
b31790
                          GsmClientEndSessionFlag   flags,
b31790
                          GError                  **error)
b31790
 {
b31790
         GsmDBusClient  *dbus_client = (GsmDBusClient *) client;
b31790
 
b31790
         gsm_exported_client_private_emit_end_session (dbus_client->priv->skeleton, flags);
b31790
         return TRUE;
b31790
 }
b31790
 
b31790
 static gboolean
b31790
 dbus_client_cancel_end_session (GsmClient *client,
b31790
                                 GError   **error)
b31790
 {
b31790
         GsmDBusClient  *dbus_client = (GsmDBusClient *) client;
b31790
         gsm_exported_client_private_emit_cancel_end_session (dbus_client->priv->skeleton);
b31790
         return TRUE;
b31790
 }
b31790
 
b31790
 static void
b31790
 gsm_dbus_client_class_init (GsmDBusClientClass *klass)
b31790
 {
b31790
         GObjectClass   *object_class = G_OBJECT_CLASS (klass);
b31790
         GsmClientClass *client_class = GSM_CLIENT_CLASS (klass);
b31790
 
b31790
         object_class->finalize             = gsm_dbus_client_finalize;
b31790
         object_class->constructor          = gsm_dbus_client_constructor;
b31790
         object_class->get_property         = gsm_dbus_client_get_property;
b31790
         object_class->set_property         = gsm_dbus_client_set_property;
b31790
 
b31790
+        client_class->impl_request_save           = dbus_client_request_save;
b31790
         client_class->impl_save                   = dbus_client_save;
b31790
         client_class->impl_stop                   = dbus_client_stop;
b31790
         client_class->impl_query_end_session      = dbus_client_query_end_session;
b31790
         client_class->impl_end_session            = dbus_client_end_session;
b31790
         client_class->impl_cancel_end_session     = dbus_client_cancel_end_session;
b31790
         client_class->impl_get_app_name           = dbus_client_get_app_name;
b31790
         client_class->impl_get_restart_style_hint = dbus_client_get_restart_style_hint;
b31790
         client_class->impl_get_unix_process_id    = dbus_client_get_unix_process_id;
b31790
 
b31790
         g_object_class_install_property (object_class,
b31790
                                          PROP_BUS_NAME,
b31790
                                          g_param_spec_string ("bus-name",
b31790
                                                               "bus-name",
b31790
                                                               "bus-name",
b31790
                                                               NULL,
b31790
                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
b31790
 
b31790
         g_type_class_add_private (klass, sizeof (GsmDBusClientPrivate));
b31790
 }
b31790
 
b31790
 GsmClient *
b31790
 gsm_dbus_client_new (const char *startup_id,
b31790
                      const char *bus_name)
b31790
 {
b31790
         GsmDBusClient *client;
b31790
 
b31790
         client = g_object_new (GSM_TYPE_DBUS_CLIENT,
b31790
                                "startup-id", startup_id,
b31790
                                "bus-name", bus_name,
b31790
                                NULL);
b31790
diff --git a/gnome-session/gsm-manager.c b/gnome-session/gsm-manager.c
f47161
index 4bb81e04..ede4186a 100644
b31790
--- a/gnome-session/gsm-manager.c
b31790
+++ b/gnome-session/gsm-manager.c
b31790
@@ -54,60 +54,61 @@
b31790
 #include "gsm-dbus-client.h"
b31790
 
b31790
 #include "gsm-autostart-app.h"
b31790
 
b31790
 #include "gsm-util.h"
b31790
 #include "gsm-icon-names.h"
b31790
 #include "gsm-system.h"
b31790
 #include "gsm-session-save.h"
b31790
 #include "gsm-shell-extensions.h"
b31790
 #include "gsm-fail-whale.h"
b31790
 
b31790
 #define GSM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSM_TYPE_MANAGER, GsmManagerPrivate))
b31790
 
b31790
 /* UUIDs for log messages */
b31790
 #define GSM_MANAGER_STARTUP_SUCCEEDED_MSGID     "0ce153587afa4095832d233c17a88001"
b31790
 #define GSM_MANAGER_UNRECOVERABLE_FAILURE_MSGID "10dd2dc188b54a5e98970f56499d1f73"
b31790
 
b31790
 #define GSM_MANAGER_DBUS_PATH "/org/gnome/SessionManager"
b31790
 #define GSM_MANAGER_DBUS_NAME "org.gnome.SessionManager"
b31790
 #define GSM_MANAGER_DBUS_IFACE "org.gnome.SessionManager"
b31790
 
b31790
 /* Probably about the longest amount of time someone could reasonably
b31790
  * want to wait, at least for something happening more than once.
b31790
  * We can get deployed on very slow media though like CDROM devices,
b31790
  * often with complex stacking/compressing filesystems on top, which
b31790
  * is not a recipie for speed.   Particularly now that we throw up
b31790
  * a fail whale if required components don't show up quickly enough,
b31790
  * let's make this fairly long.
b31790
  */
b31790
 #define GSM_MANAGER_PHASE_TIMEOUT 90 /* seconds */
b31790
+#define GSM_MANAGER_SAVE_SESSION_TIMEOUT 2
b31790
 
b31790
 #define GDM_FLEXISERVER_COMMAND "gdmflexiserver"
b31790
 #define GDM_FLEXISERVER_ARGS    "--startnew Standard"
b31790
 
b31790
 #define SESSION_SCHEMA            "org.gnome.desktop.session"
b31790
 #define KEY_IDLE_DELAY            "idle-delay"
b31790
 #define KEY_SESSION_NAME          "session-name"
b31790
 
b31790
 #define GSM_MANAGER_SCHEMA        "org.gnome.SessionManager"
b31790
 #define KEY_AUTOSAVE              "auto-save-session"
b31790
 #define KEY_AUTOSAVE_ONE_SHOT     "auto-save-session-one-shot"
b31790
 #define KEY_LOGOUT_PROMPT         "logout-prompt"
b31790
 #define KEY_SHOW_FALLBACK_WARNING "show-fallback-warning"
b31790
 
b31790
 #define SCREENSAVER_SCHEMA        "org.gnome.desktop.screensaver"
b31790
 #define KEY_SLEEP_LOCK            "lock-enabled"
b31790
 
b31790
 #define LOCKDOWN_SCHEMA           "org.gnome.desktop.lockdown"
b31790
 #define KEY_DISABLE_LOG_OUT       "disable-log-out"
b31790
 #define KEY_DISABLE_USER_SWITCHING "disable-user-switching"
b31790
 
b31790
 static void app_registered (GsmApp     *app, GParamSpec *spec, GsmManager *manager);
b31790
 
b31790
 typedef enum
b31790
 {
b31790
         GSM_MANAGER_LOGOUT_NONE,
b31790
         GSM_MANAGER_LOGOUT_LOGOUT,
b31790
         GSM_MANAGER_LOGOUT_REBOOT,
b31790
         GSM_MANAGER_LOGOUT_REBOOT_INTERACT,
b31790
         GSM_MANAGER_LOGOUT_SHUTDOWN,
b31790
@@ -1172,60 +1173,123 @@ end_session_or_show_shell_dialog (GsmManager *manager)
b31790
                         end_phase (manager);
b31790
                 }
b31790
                 break;
b31790
 
b31790
         case GSM_MANAGER_LOGOUT_MODE_FORCE:
b31790
                 end_phase (manager);
b31790
                 break;
b31790
         default:
b31790
                 g_assert_not_reached ();
b31790
                 break;
b31790
         }
b31790
 
b31790
 }
b31790
 
b31790
 static void
b31790
 query_end_session_complete (GsmManager *manager)
b31790
 {
b31790
 
b31790
         g_debug ("GsmManager: query end session complete");
b31790
 
b31790
         /* Remove the timeout since this can be called from outside the timer
b31790
          * and we don't want to have it called twice */
b31790
         if (manager->priv->query_timeout_id > 0) {
b31790
                 g_source_remove (manager->priv->query_timeout_id);
b31790
                 manager->priv->query_timeout_id = 0;
b31790
         }
b31790
 
b31790
         end_session_or_show_shell_dialog (manager);
b31790
 }
b31790
 
b31790
+static gboolean
b31790
+_client_request_save (GsmClient            *client,
b31790
+                      ClientEndSessionData *data)
b31790
+{
b31790
+        gboolean ret;
b31790
+        GError  *error;
b31790
+
b31790
+        error = NULL;
b31790
+        ret = gsm_client_request_save (client, data->flags, &error);
b31790
+        if (ret) {
b31790
+                g_debug ("GsmManager: adding client to query clients: %s", gsm_client_peek_id (client));
b31790
+                data->manager->priv->query_clients = g_slist_prepend (data->manager->priv->query_clients,
b31790
+                                                                      client);
b31790
+        } else if (error) {
b31790
+                g_debug ("GsmManager: unable to query client: %s", error->message);
b31790
+                g_error_free (error);
b31790
+        }
b31790
+
b31790
+        return FALSE;
b31790
+}
b31790
+
b31790
+static gboolean
b31790
+_client_request_save_helper (const char           *id,
b31790
+                             GsmClient            *client,
b31790
+                             ClientEndSessionData *data)
b31790
+{
b31790
+        return _client_request_save (client, data);
b31790
+}
b31790
+
b31790
+static void
b31790
+query_save_session_complete (GsmManager *manager)
b31790
+{
b31790
+        GError *error = NULL;
b31790
+
b31790
+        if (g_slist_length (manager->priv->next_query_clients) > 0) {
b31790
+                ClientEndSessionData data;
b31790
+
b31790
+                data.manager = manager;
b31790
+                data.flags = GSM_CLIENT_END_SESSION_FLAG_LAST;
b31790
+
b31790
+                g_slist_foreach (manager->priv->next_query_clients,
b31790
+                                 (GFunc)_client_request_save,
b31790
+                                 &data);
b31790
+
b31790
+                g_slist_free (manager->priv->next_query_clients);
b31790
+                manager->priv->next_query_clients = NULL;
b31790
+
b31790
+                return;
b31790
+        }
b31790
+
b31790
+        if (manager->priv->query_timeout_id > 0) {
b31790
+                g_source_remove (manager->priv->query_timeout_id);
b31790
+                manager->priv->query_timeout_id = 0;
b31790
+        }
b31790
+
b31790
+        gsm_session_save (manager->priv->clients, &error);
b31790
+
b31790
+        if (error) {
b31790
+                g_warning ("Error saving session: %s", error->message);
b31790
+                g_error_free (error);
b31790
+        }
b31790
+}
b31790
+
b31790
 static guint32
b31790
 generate_cookie (void)
b31790
 {
b31790
         guint32 cookie;
b31790
 
b31790
         cookie = (guint32)g_random_int_range (1, G_MAXINT32);
b31790
 
b31790
         return cookie;
b31790
 }
b31790
 
b31790
 static guint32
b31790
 _generate_unique_cookie (GsmManager *manager)
b31790
 {
b31790
         guint32 cookie;
b31790
 
b31790
         do {
b31790
                 cookie = generate_cookie ();
b31790
         } while (gsm_store_find (manager->priv->inhibitors, (GsmStoreFunc)_find_by_cookie, &cookie) != NULL);
b31790
 
b31790
         return cookie;
b31790
 }
b31790
 
b31790
 static gboolean
b31790
 _on_query_end_session_timeout (GsmManager *manager)
b31790
 {
b31790
         GSList *l;
b31790
 
b31790
         manager->priv->query_timeout_id = 0;
b31790
 
b31790
         g_debug ("GsmManager: query end session timed out");
b31790
@@ -1252,60 +1316,75 @@ _on_query_end_session_timeout (GsmManager *manager)
b31790
                         bus_name = NULL;
b31790
                 }
b31790
 
b31790
                 app_id = g_strdup (gsm_client_peek_app_id (l->data));
b31790
                 if (IS_STRING_EMPTY (app_id)) {
b31790
                         /* XSMP clients don't give us an app id unless we start them */
b31790
                         g_free (app_id);
b31790
                         app_id = gsm_client_get_app_name (l->data);
b31790
                 }
b31790
 
b31790
                 cookie = _generate_unique_cookie (manager);
b31790
                 inhibitor = gsm_inhibitor_new_for_client (gsm_client_peek_id (l->data),
b31790
                                                           app_id,
b31790
                                                           GSM_INHIBITOR_FLAG_LOGOUT,
b31790
                                                           _("Not responding"),
b31790
                                                           bus_name,
b31790
                                                           cookie);
b31790
                 g_free (app_id);
b31790
                 gsm_store_add (manager->priv->inhibitors, gsm_inhibitor_peek_id (inhibitor), G_OBJECT (inhibitor));
b31790
                 g_object_unref (inhibitor);
b31790
         }
b31790
 
b31790
         g_slist_free (manager->priv->query_clients);
b31790
         manager->priv->query_clients = NULL;
b31790
 
b31790
         query_end_session_complete (manager);
b31790
 
b31790
         return FALSE;
b31790
 }
b31790
 
b31790
+static gboolean
b31790
+_on_query_save_session_timeout (GsmManager *manager)
b31790
+{
b31790
+        manager->priv->query_timeout_id = 0;
b31790
+
b31790
+        g_debug ("GsmManager: query to save session timed out");
b31790
+
b31790
+        g_slist_free (manager->priv->query_clients);
b31790
+        manager->priv->query_clients = NULL;
b31790
+
b31790
+        query_save_session_complete (manager);
b31790
+
b31790
+        return FALSE;
b31790
+}
b31790
+
b31790
 static void
b31790
 do_phase_query_end_session (GsmManager *manager)
b31790
 {
b31790
         ClientEndSessionData data;
b31790
 
b31790
         data.manager = manager;
b31790
         data.flags = 0;
b31790
 
b31790
         if (manager->priv->logout_mode == GSM_MANAGER_LOGOUT_MODE_FORCE) {
b31790
                 data.flags |= GSM_CLIENT_END_SESSION_FLAG_FORCEFUL;
b31790
         }
b31790
         /* We only query if an app is ready to log out, so we don't use
b31790
          * GSM_CLIENT_END_SESSION_FLAG_SAVE here.
b31790
          */
b31790
 
b31790
         debug_clients (manager);
b31790
         g_debug ("GsmManager: sending query-end-session to clients (logout mode: %s)",
b31790
                  manager->priv->logout_mode == GSM_MANAGER_LOGOUT_MODE_NORMAL? "normal" :
b31790
                  manager->priv->logout_mode == GSM_MANAGER_LOGOUT_MODE_FORCE? "forceful":
b31790
                  "no confirmation");
b31790
         gsm_store_foreach (manager->priv->clients,
b31790
                            (GsmStoreFunc)_client_query_end_session,
b31790
                            &data);
b31790
 
b31790
         /* This phase doesn't time out unless logout is forced. Typically, this
b31790
          * separate timer is only used to show UI. */
b31790
         manager->priv->query_timeout_id = g_timeout_add_seconds (1, (GSourceFunc)_on_query_end_session_timeout, manager);
b31790
 }
b31790
 
b31790
 static void
b31790
@@ -1848,67 +1927,86 @@ maybe_save_session (GsmManager *manager)
b31790
                 return;
b31790
 
b31790
         /* We only allow session saving when session is running or when
b31790
          * logging out */
b31790
         if (manager->priv->phase != GSM_MANAGER_PHASE_RUNNING &&
b31790
             manager->priv->phase != GSM_MANAGER_PHASE_END_SESSION) {
b31790
                 return;
b31790
         }
b31790
 
b31790
         if (!auto_save_is_enabled (manager)) {
b31790
                 return;
b31790
         }
b31790
 
b31790
         error = NULL;
f47161
         gsm_session_save (manager->priv->clients, manager->priv->apps, &error);
b31790
 
b31790
         if (error) {
b31790
                 g_warning ("Error saving session: %s", error->message);
b31790
                 g_error_free (error);
b31790
         }
b31790
 }
b31790
 
b31790
 static void
b31790
 _handle_client_end_session_response (GsmManager *manager,
b31790
                                      GsmClient  *client,
b31790
                                      gboolean    is_ok,
b31790
                                      gboolean    do_last,
b31790
                                      gboolean    cancel,
b31790
                                      const char *reason)
b31790
 {
b31790
-        /* just ignore if received outside of shutdown */
b31790
-        if (manager->priv->phase < GSM_MANAGER_PHASE_QUERY_END_SESSION) {
b31790
+        /* just ignore if we are not yet running */
b31790
+        if (manager->priv->phase < GSM_MANAGER_PHASE_RUNNING) {
b31790
                 return;
b31790
         }
b31790
 
b31790
         g_debug ("GsmManager: Response from end session request: is-ok=%d do-last=%d cancel=%d reason=%s", is_ok, do_last, cancel, reason ? reason :"");
b31790
 
b31790
+        if (manager->priv->phase == GSM_MANAGER_PHASE_RUNNING) {
b31790
+                /* Ignore responses when no requests were sent */
b31790
+                if (manager->priv->query_clients == NULL) {
b31790
+                        return;
b31790
+                }
b31790
+
b31790
+                manager->priv->query_clients = g_slist_remove (manager->priv->query_clients, client);
b31790
+
b31790
+                if (do_last) {
b31790
+                        manager->priv->next_query_clients = g_slist_prepend (manager->priv->next_query_clients,
b31790
+                                                                             client);
b31790
+                }
b31790
+
b31790
+                if (manager->priv->query_clients == NULL) {
b31790
+                        query_save_session_complete (manager);
b31790
+                }
b31790
+                return;
b31790
+        }
b31790
+
b31790
         if (cancel) {
b31790
                 cancel_end_session (manager);
b31790
                 return;
b31790
         }
b31790
 
b31790
         manager->priv->query_clients = g_slist_remove (manager->priv->query_clients, client);
b31790
 
b31790
         if (! is_ok && manager->priv->logout_mode != GSM_MANAGER_LOGOUT_MODE_FORCE) {
b31790
                 guint         cookie;
b31790
                 GsmInhibitor *inhibitor;
b31790
                 char         *app_id;
b31790
                 const char   *bus_name;
b31790
 
b31790
                 /* FIXME: do we support updating the reason? */
b31790
 
b31790
                 /* Create JIT inhibit */
b31790
                 if (GSM_IS_DBUS_CLIENT (client)) {
b31790
                         bus_name = gsm_dbus_client_get_bus_name (GSM_DBUS_CLIENT (client));
b31790
                 } else {
b31790
                         bus_name = NULL;
b31790
                 }
b31790
 
b31790
                 app_id = g_strdup (gsm_client_peek_app_id (client));
b31790
                 if (IS_STRING_EMPTY (app_id)) {
b31790
                         /* XSMP clients don't give us an app id unless we start them */
b31790
                         g_free (app_id);
b31790
                         app_id = gsm_client_get_app_name (client);
b31790
                 }
b31790
 
b31790
                 cookie = _generate_unique_cookie (manager);
b31790
@@ -1968,85 +2066,98 @@ on_client_end_session_response (GsmClient  *client,
b31790
         _handle_client_end_session_response (manager,
b31790
                                              client,
b31790
                                              is_ok,
b31790
                                              do_last,
b31790
                                              cancel,
b31790
                                              reason);
b31790
 }
b31790
 
b31790
 static void
b31790
 on_xsmp_client_logout_request (GsmXSMPClient *client,
b31790
                                gboolean       show_dialog,
b31790
                                GsmManager    *manager)
b31790
 {
b31790
         GError *error;
b31790
         int     logout_mode;
b31790
 
b31790
         if (show_dialog) {
b31790
                 logout_mode = GSM_MANAGER_LOGOUT_MODE_NORMAL;
b31790
         } else {
b31790
                 logout_mode = GSM_MANAGER_LOGOUT_MODE_NO_CONFIRMATION;
b31790
         }
b31790
 
b31790
         error = NULL;
b31790
         gsm_manager_logout (manager, logout_mode, &error);
b31790
         if (error != NULL) {
b31790
                 g_warning ("Unable to logout: %s", error->message);
b31790
                 g_error_free (error);
b31790
         }
b31790
 }
b31790
 
b31790
+static void
b31790
+on_xsmp_client_save_request (GsmXSMPClient *client,
b31790
+                             gboolean       show_dialog,
b31790
+                             GsmManager    *manager)
b31790
+{
b31790
+        g_debug ("GsmManager: save_request");
b31790
+        gsm_manager_save_session (manager, NULL);
b31790
+}
b31790
+
b31790
 static void
b31790
 on_store_client_added (GsmStore   *store,
b31790
                        const char *id,
b31790
                        GsmManager *manager)
b31790
 {
b31790
         GsmClient *client;
b31790
 
b31790
         g_debug ("GsmManager: Client added: %s", id);
b31790
 
b31790
         client = (GsmClient *)gsm_store_lookup (store, id);
b31790
 
b31790
         /* a bit hacky */
b31790
         if (GSM_IS_XSMP_CLIENT (client)) {
b31790
                 g_signal_connect (client,
b31790
                                   "register-request",
b31790
                                   G_CALLBACK (on_xsmp_client_register_request),
b31790
                                   manager);
b31790
                 g_signal_connect (client,
b31790
                                   "register-confirmed",
b31790
                                   G_CALLBACK (on_xsmp_client_register_confirmed),
b31790
                                   manager);
b31790
                 g_signal_connect (client,
b31790
                                   "logout-request",
b31790
                                   G_CALLBACK (on_xsmp_client_logout_request),
b31790
                                   manager);
b31790
+		g_signal_connect (client,
b31790
+				  "save-request",
b31790
+				  G_CALLBACK (on_xsmp_client_save_request),
b31790
+				  manager);
b31790
         }
b31790
 
b31790
         g_signal_connect (client,
b31790
                           "end-session-response",
b31790
                           G_CALLBACK (on_client_end_session_response),
b31790
                           manager);
b31790
 
b31790
         gsm_exported_manager_emit_client_added (manager->priv->skeleton, id);
b31790
         /* FIXME: disconnect signal handler */
b31790
 }
b31790
 
b31790
 static void
b31790
 on_store_client_removed (GsmStore   *store,
b31790
                          const char *id,
b31790
                          GsmManager *manager)
b31790
 {
b31790
         g_debug ("GsmManager: Client removed: %s", id);
b31790
 
b31790
         gsm_exported_manager_emit_client_removed (manager->priv->skeleton, id);
b31790
 }
b31790
 
b31790
 static void
b31790
 gsm_manager_set_client_store (GsmManager *manager,
b31790
                               GsmStore   *store)
b31790
 {
b31790
         g_return_if_fail (GSM_IS_MANAGER (manager));
b31790
 
b31790
         if (store != NULL) {
b31790
                 g_object_ref (store);
b31790
         }
b31790
@@ -2625,60 +2736,95 @@ gsm_manager_initialization_error (GsmExportedManager    *skeleton,
b31790
                                   gboolean               fatal,
b31790
                                   GsmManager            *manager)
b31790
 {
b31790
         if (manager->priv->phase != GSM_MANAGER_PHASE_INITIALIZATION) {
b31790
                 g_dbus_method_invocation_return_error (invocation,
b31790
                                                        GSM_MANAGER_ERROR,
b31790
                                                        GSM_MANAGER_ERROR_NOT_IN_INITIALIZATION,
b31790
                                                        "InitializationError interface is only available during the Initialization phase");
b31790
                 return TRUE;
b31790
         }
b31790
 
b31790
         gsm_util_init_error (fatal, "%s", message);
b31790
         gsm_exported_manager_complete_initialization_error (skeleton, invocation);
b31790
 
b31790
         return TRUE;
b31790
 }
b31790
 
b31790
 static void
b31790
 user_logout (GsmManager           *manager,
b31790
              GsmManagerLogoutMode  mode)
b31790
 {
b31790
         if (manager->priv->phase >= GSM_MANAGER_PHASE_QUERY_END_SESSION) {
b31790
                 manager->priv->logout_mode = mode;
b31790
                 end_session_or_show_shell_dialog (manager);
b31790
                 return;
b31790
         }
b31790
 
b31790
         request_logout (manager, mode);
b31790
 }
b31790
 
b31790
+gboolean
b31790
+gsm_manager_save_session (GsmManager *manager,
b31790
+                          GError     **error)
b31790
+{
b31790
+        ClientEndSessionData data;
b31790
+
b31790
+        g_debug ("GsmManager: SaveSession called");
b31790
+
b31790
+        g_return_val_if_fail (GSM_IS_MANAGER (manager), FALSE);
b31790
+
b31790
+        if (manager->priv->phase != GSM_MANAGER_PHASE_RUNNING) {
b31790
+                g_set_error (error,
b31790
+                             GSM_MANAGER_ERROR,
b31790
+                             GSM_MANAGER_ERROR_NOT_IN_RUNNING,
b31790
+                             "SaveSession interface is only available during the Running phase");
b31790
+                return FALSE;
b31790
+        }
b31790
+
b31790
+        data.manager = manager;
b31790
+        data.flags = 0;
b31790
+        gsm_store_foreach (manager->priv->clients,
b31790
+                           (GsmStoreFunc)_client_request_save_helper,
b31790
+                           &data);
b31790
+
b31790
+        if (manager->priv->query_clients) {
b31790
+                manager->priv->query_timeout_id = g_timeout_add_seconds (GSM_MANAGER_SAVE_SESSION_TIMEOUT,
b31790
+                                                                         (GSourceFunc)_on_query_save_session_timeout,
b31790
+                                                                         manager);
b31790
+                return TRUE;
b31790
+        } else {
b31790
+                g_debug ("GsmManager: Nothing to save");
b31790
+                return FALSE;
b31790
+        }
b31790
+}
b31790
+
b31790
 gboolean
b31790
 gsm_manager_logout (GsmManager *manager,
b31790
                     guint logout_mode,
b31790
                     GError **error)
b31790
 {
b31790
         if (manager->priv->phase < GSM_MANAGER_PHASE_RUNNING) {
b31790
                 g_set_error (error,
b31790
                              GSM_MANAGER_ERROR,
b31790
                              GSM_MANAGER_ERROR_NOT_IN_RUNNING,
b31790
                              "Logout interface is only available after the Running phase starts");
b31790
                 return FALSE;
b31790
         }
b31790
 
b31790
         if (_log_out_is_locked_down (manager)) {
b31790
                 g_set_error (error,
b31790
                              GSM_MANAGER_ERROR,
b31790
                              GSM_MANAGER_ERROR_LOCKED_DOWN,
b31790
                              "Logout has been locked down");
b31790
                 return FALSE;
b31790
         }
b31790
 
b31790
         switch (logout_mode) {
b31790
         case GSM_MANAGER_LOGOUT_MODE_NORMAL:
b31790
         case GSM_MANAGER_LOGOUT_MODE_NO_CONFIRMATION:
b31790
         case GSM_MANAGER_LOGOUT_MODE_FORCE:
b31790
                 user_logout (manager, logout_mode);
b31790
                 break;
b31790
 
b31790
         default:
b31790
                 g_debug ("Unknown logout mode option");
b31790
diff --git a/gnome-session/gsm-manager.h b/gnome-session/gsm-manager.h
b31790
index bc440cb0..4d14aa34 100644
b31790
--- a/gnome-session/gsm-manager.h
b31790
+++ b/gnome-session/gsm-manager.h
b31790
@@ -96,40 +96,43 @@ GQuark              gsm_manager_error_quark                    (void);
b31790
 GType               gsm_manager_get_type                       (void);
b31790
 
b31790
 GsmManager *        gsm_manager_new                            (GsmStore       *client_store,
b31790
                                                                 gboolean        failsafe);
b31790
 GsmManager *        gsm_manager_get                            (void);
b31790
 
b31790
 gboolean            gsm_manager_get_failsafe                   (GsmManager     *manager);
b31790
 
b31790
 gboolean            gsm_manager_add_autostart_app              (GsmManager     *manager,
b31790
                                                                 const char     *path,
b31790
                                                                 const char     *provides);
b31790
 gboolean            gsm_manager_add_required_app               (GsmManager     *manager,
b31790
                                                                 const char     *path,
b31790
                                                                 const char     *provides);
b31790
 gboolean            gsm_manager_add_autostart_apps_from_dir    (GsmManager     *manager,
b31790
                                                                 const char     *path);
b31790
 gboolean            gsm_manager_add_legacy_session_apps        (GsmManager     *manager,
b31790
                                                                 const char     *path);
b31790
 
b31790
 void                gsm_manager_start                          (GsmManager     *manager);
b31790
 
b31790
 const char *        _gsm_manager_get_default_session           (GsmManager     *manager);
b31790
 
b31790
 void                _gsm_manager_set_active_session            (GsmManager     *manager,
b31790
                                                                 const char     *session_name,
b31790
                                                                 gboolean        is_fallback);
b31790
 
b31790
 void                _gsm_manager_set_renderer                  (GsmManager     *manager,
b31790
                                                                 const char     *renderer);
b31790
 
b31790
+gboolean            gsm_manager_save_session                   (GsmManager     *manager,
b31790
+                                                                GError        **error);
b31790
+
b31790
 gboolean            gsm_manager_logout                         (GsmManager     *manager,
b31790
                                                                 guint           logout_mode,
b31790
                                                                 GError        **error);
b31790
 
b31790
 gboolean            gsm_manager_set_phase                      (GsmManager     *manager,
b31790
                                                                 GsmManagerPhase phase);
b31790
 
b31790
 G_END_DECLS
b31790
 
b31790
 #endif /* __GSM_MANAGER_H */
b31790
diff --git a/gnome-session/gsm-xsmp-client.c b/gnome-session/gsm-xsmp-client.c
f47161
index 8a30926f..cbecd68c 100644
b31790
--- a/gnome-session/gsm-xsmp-client.c
b31790
+++ b/gnome-session/gsm-xsmp-client.c
b31790
@@ -39,60 +39,61 @@
b31790
 #define GsmDesktopFile "_GSM_DesktopFile"
b31790
 
b31790
 #define GSM_XSMP_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSM_TYPE_XSMP_CLIENT, GsmXSMPClientPrivate))
b31790
 
b31790
 struct GsmXSMPClientPrivate
b31790
 {
b31790
 
b31790
         SmsConn    conn;
b31790
         IceConn    ice_connection;
b31790
 
b31790
         guint      watch_id;
b31790
 
b31790
         char      *description;
b31790
         GPtrArray *props;
b31790
 
b31790
         /* SaveYourself state */
b31790
         int        current_save_yourself;
b31790
         int        next_save_yourself;
b31790
         guint      next_save_yourself_allow_interact : 1;
b31790
 };
b31790
 
b31790
 enum {
b31790
         PROP_0,
b31790
         PROP_ICE_CONNECTION
b31790
 };
b31790
 
b31790
 enum {
b31790
         REGISTER_REQUEST,
b31790
         REGISTER_CONFIRMED,
b31790
         LOGOUT_REQUEST,
b31790
+	SAVE_REQUEST,
b31790
         LAST_SIGNAL
b31790
 };
b31790
 
b31790
 static guint signals[LAST_SIGNAL] = { 0 };
b31790
 
b31790
 G_DEFINE_TYPE (GsmXSMPClient, gsm_xsmp_client, GSM_TYPE_CLIENT)
b31790
 
b31790
 static gboolean
b31790
 client_iochannel_watch (GIOChannel    *channel,
b31790
                         GIOCondition   condition,
b31790
                         GsmXSMPClient *client)
b31790
 {
b31790
         gboolean keep_going;
b31790
 
b31790
         g_object_ref (client);
b31790
         switch (IceProcessMessages (client->priv->ice_connection, NULL, NULL)) {
b31790
         case IceProcessMessagesSuccess:
b31790
                 keep_going = TRUE;
b31790
                 break;
b31790
 
b31790
         case IceProcessMessagesIOError:
b31790
                 g_debug ("GsmXSMPClient: IceProcessMessagesIOError on '%s'", client->priv->description);
b31790
                 gsm_client_set_status (GSM_CLIENT (client), GSM_CLIENT_FAILED);
b31790
                 /* Emitting "disconnected" will eventually cause
b31790
                  * IceCloseConnection() to be called.
b31790
                  */
b31790
                 gsm_client_disconnected (GSM_CLIENT (client));
b31790
                 keep_going = FALSE;
b31790
                 break;
b31790
 
b31790
@@ -472,60 +473,84 @@ xsmp_interact (GsmClient *client)
b31790
 
b31790
         SmsInteract (xsmp->priv->conn);
b31790
 }
b31790
 
b31790
 static gboolean
b31790
 xsmp_cancel_end_session (GsmClient *client,
b31790
                          GError   **error)
b31790
 {
b31790
         GsmXSMPClient *xsmp = (GsmXSMPClient *) client;
b31790
 
b31790
         g_debug ("GsmXSMPClient: xsmp_cancel_end_session ('%s')", xsmp->priv->description);
b31790
 
b31790
         if (xsmp->priv->conn == NULL) {
b31790
                 g_set_error (error,
b31790
                              GSM_CLIENT_ERROR,
b31790
                              GSM_CLIENT_ERROR_NOT_REGISTERED,
b31790
                              "Client is not registered");
b31790
                 return FALSE;
b31790
         }
b31790
 
b31790
         SmsShutdownCancelled (xsmp->priv->conn);
b31790
 
b31790
         /* reset the state */
b31790
         xsmp->priv->current_save_yourself = -1;
b31790
         xsmp->priv->next_save_yourself = -1;
b31790
         xsmp->priv->next_save_yourself_allow_interact = FALSE;
b31790
 
b31790
         return TRUE;
b31790
 }
b31790
 
b31790
+static gboolean
b31790
+xsmp_request_save (GsmClient *client,
b31790
+                   guint      flags,
b31790
+                   GError   **error)
b31790
+{
b31790
+        GsmXSMPClient *xsmp = (GsmXSMPClient *) client;
b31790
+
b31790
+        g_debug ("GsmXSMPClient: xsmp_request_save ('%s')", xsmp->priv->description);
b31790
+
b31790
+        if (xsmp->priv->conn == NULL) {
b31790
+                g_set_error (error,
b31790
+                             GSM_CLIENT_ERROR,
b31790
+                             GSM_CLIENT_ERROR_NOT_REGISTERED,
b31790
+                             "Client is not registered");
b31790
+                return FALSE;
b31790
+        }
b31790
+
b31790
+        if (flags & GSM_CLIENT_END_SESSION_FLAG_LAST)
b31790
+                xsmp_save_yourself_phase2 (client);
b31790
+        else
b31790
+                do_save_yourself (xsmp, SmSaveLocal, FALSE);
b31790
+
b31790
+        return TRUE;
b31790
+}
b31790
 static char *
b31790
 get_desktop_file_path (GsmXSMPClient *client)
b31790
 {
b31790
         SmProp     *prop;
b31790
         char       *desktop_file_path = NULL;
b31790
         const char *program_name;
b31790
 
b31790
         /* XSMP clients using eggsmclient defines a special property
b31790
          * pointing to their respective desktop entry file */
b31790
         prop = find_property (client, GsmDesktopFile, NULL);
b31790
 
b31790
         if (prop) {
b31790
                 GFile *file = g_file_new_for_uri (prop->vals[0].value);
b31790
                 desktop_file_path = g_file_get_path (file);
b31790
                 g_object_unref (file);
b31790
                 goto out;
b31790
         }
b31790
 
b31790
         /* If we can't get desktop file from GsmDesktopFile then we
b31790
          * try to find the desktop file from its program name */
b31790
         prop = find_property (client, SmProgram, NULL);
b31790
 
b31790
         if (!prop) {
b31790
                 goto out;
b31790
         }
b31790
 
b31790
         program_name = prop->vals[0].value;
b31790
         desktop_file_path =
b31790
                 gsm_util_find_desktop_file_for_app_name (program_name,
b31790
                                                          TRUE, FALSE);
f47161
@@ -964,100 +989,112 @@ xsmp_get_unix_process_id (GsmClient *client)
b31790
         gboolean res;
b31790
 
b31790
         g_debug ("GsmXSMPClient: getting pid");
b31790
 
b31790
         prop = find_property (GSM_XSMP_CLIENT (client), SmProcessID, NULL);
b31790
 
b31790
         if (!prop || strcmp (prop->type, SmARRAY8) != 0) {
b31790
                 return 0;
b31790
         }
b31790
 
b31790
         pid = 0;
b31790
         res = _parse_value_as_uint ((char *)prop->vals[0].value, &pid;;
b31790
         if (! res) {
b31790
                 pid = 0;
b31790
         }
b31790
 
b31790
         return pid;
b31790
 }
b31790
 
b31790
 static void
b31790
 gsm_xsmp_client_class_init (GsmXSMPClientClass *klass)
b31790
 {
b31790
         GObjectClass   *object_class = G_OBJECT_CLASS (klass);
b31790
         GsmClientClass *client_class = GSM_CLIENT_CLASS (klass);
b31790
 
b31790
         object_class->finalize             = gsm_xsmp_client_finalize;
b31790
         object_class->constructor          = gsm_xsmp_client_constructor;
b31790
         object_class->get_property         = gsm_xsmp_client_get_property;
b31790
         object_class->set_property         = gsm_xsmp_client_set_property;
b31790
 
b31790
+        client_class->impl_request_save           = xsmp_request_save;
b31790
         client_class->impl_save                   = xsmp_save;
b31790
         client_class->impl_stop                   = xsmp_stop;
b31790
         client_class->impl_query_end_session      = xsmp_query_end_session;
b31790
         client_class->impl_end_session            = xsmp_end_session;
b31790
         client_class->impl_cancel_end_session     = xsmp_cancel_end_session;
b31790
         client_class->impl_get_app_name           = xsmp_get_app_name;
b31790
         client_class->impl_get_restart_style_hint = xsmp_get_restart_style_hint;
b31790
         client_class->impl_get_unix_process_id    = xsmp_get_unix_process_id;
b31790
 
b31790
         signals[REGISTER_REQUEST] =
b31790
                 g_signal_new ("register-request",
b31790
                               G_OBJECT_CLASS_TYPE (object_class),
b31790
                               G_SIGNAL_RUN_LAST,
b31790
                               G_STRUCT_OFFSET (GsmXSMPClientClass, register_request),
b31790
                               _boolean_handled_accumulator,
b31790
                               NULL,
b31790
                               NULL,
b31790
                               G_TYPE_BOOLEAN,
b31790
                               1, G_TYPE_POINTER);
b31790
         signals[REGISTER_CONFIRMED] =
b31790
                 g_signal_new ("register-confirmed",
b31790
                               G_OBJECT_CLASS_TYPE (object_class),
b31790
                               G_SIGNAL_RUN_LAST,
b31790
                               G_STRUCT_OFFSET (GsmXSMPClientClass, register_confirmed),
b31790
                               NULL,
b31790
                               NULL,
b31790
                               NULL,
b31790
                               G_TYPE_NONE,
b31790
                               1, G_TYPE_POINTER);
b31790
         signals[LOGOUT_REQUEST] =
b31790
                 g_signal_new ("logout-request",
b31790
                               G_OBJECT_CLASS_TYPE (object_class),
b31790
                               G_SIGNAL_RUN_LAST,
b31790
                               G_STRUCT_OFFSET (GsmXSMPClientClass, logout_request),
b31790
                               NULL,
b31790
                               NULL,
b31790
                               NULL,
b31790
                               G_TYPE_NONE,
b31790
                               1, G_TYPE_BOOLEAN);
b31790
 
b31790
+	signals[SAVE_REQUEST] =
b31790
+		g_signal_new ("save-request",
b31790
+                              G_OBJECT_CLASS_TYPE (object_class),
b31790
+                              G_SIGNAL_RUN_LAST,
b31790
+                              G_STRUCT_OFFSET (GsmXSMPClientClass, save_request),
b31790
+                              NULL,
b31790
+                              NULL,
b31790
+                              g_cclosure_marshal_VOID__BOOLEAN,
b31790
+                              G_TYPE_NONE,
b31790
+                              1, G_TYPE_BOOLEAN);
b31790
+
b31790
         g_object_class_install_property (object_class,
b31790
                                          PROP_ICE_CONNECTION,
b31790
                                          g_param_spec_pointer ("ice-connection",
b31790
                                                                "ice-connection",
b31790
                                                                "ice-connection",
b31790
                                                                G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
b31790
 
b31790
         g_type_class_add_private (klass, sizeof (GsmXSMPClientPrivate));
b31790
 }
b31790
 
b31790
 GsmClient *
b31790
 gsm_xsmp_client_new (IceConn ice_conn)
b31790
 {
b31790
         GsmXSMPClient *xsmp;
b31790
 
b31790
         xsmp = g_object_new (GSM_TYPE_XSMP_CLIENT,
b31790
                              "ice-connection", ice_conn,
b31790
                              NULL);
b31790
 
b31790
         return GSM_CLIENT (xsmp);
b31790
 }
b31790
 
b31790
 static Status
b31790
 register_client_callback (SmsConn    conn,
b31790
                           SmPointer  manager_data,
b31790
                           char      *previous_id)
b31790
 {
b31790
         GsmXSMPClient *client = manager_data;
b31790
         gboolean       handled;
b31790
         char          *id;
b31790
diff --git a/gnome-session/gsm-xsmp-client.h b/gnome-session/gsm-xsmp-client.h
b31790
index 1bb27975..6b95c51b 100644
b31790
--- a/gnome-session/gsm-xsmp-client.h
b31790
+++ b/gnome-session/gsm-xsmp-client.h
b31790
@@ -27,61 +27,62 @@ G_BEGIN_DECLS
b31790
 
b31790
 #define GSM_TYPE_XSMP_CLIENT            (gsm_xsmp_client_get_type ())
b31790
 #define GSM_XSMP_CLIENT(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSM_TYPE_XSMP_CLIENT, GsmXSMPClient))
b31790
 #define GSM_XSMP_CLIENT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GSM_TYPE_XSMP_CLIENT, GsmXSMPClientClass))
b31790
 #define GSM_IS_XSMP_CLIENT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSM_TYPE_XSMP_CLIENT))
b31790
 #define GSM_IS_XSMP_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSM_TYPE_XSMP_CLIENT))
b31790
 #define GSM_XSMP_CLIENT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GSM_TYPE_XSMP_CLIENT, GsmXSMPClientClass))
b31790
 
b31790
 typedef struct _GsmXSMPClient        GsmXSMPClient;
b31790
 typedef struct _GsmXSMPClientClass   GsmXSMPClientClass;
b31790
 
b31790
 typedef struct GsmXSMPClientPrivate  GsmXSMPClientPrivate;
b31790
 
b31790
 struct _GsmXSMPClient
b31790
 {
b31790
         GsmClient             parent;
b31790
         GsmXSMPClientPrivate *priv;
b31790
 };
b31790
 
b31790
 struct _GsmXSMPClientClass
b31790
 {
b31790
         GsmClientClass parent_class;
b31790
 
b31790
         /* signals */
b31790
         gboolean (*register_request)     (GsmXSMPClient  *client,
b31790
                                           char          **client_id);
b31790
         void     (*register_confirmed)   (GsmXSMPClient  *client,
b31790
                                           const char     *client_id);
b31790
         gboolean (*logout_request)       (GsmXSMPClient  *client,
b31790
                                           gboolean        prompt);
b31790
-
b31790
+        gboolean (*save_request)         (GsmXSMPClient  *client,
b31790
+                                          gboolean        prompt);
b31790
 
b31790
         void     (*saved_state)          (GsmXSMPClient  *client);
b31790
 
b31790
         void     (*request_phase2)       (GsmXSMPClient  *client);
b31790
 
b31790
         void     (*request_interaction)  (GsmXSMPClient  *client);
b31790
         void     (*interaction_done)     (GsmXSMPClient  *client,
b31790
                                           gboolean        cancel_shutdown);
b31790
 
b31790
         void     (*save_yourself_done)   (GsmXSMPClient  *client);
b31790
 
b31790
 };
b31790
 
b31790
 GType       gsm_xsmp_client_get_type             (void) G_GNUC_CONST;
b31790
 
b31790
 GsmClient  *gsm_xsmp_client_new                  (IceConn         ice_conn);
b31790
 
b31790
 void        gsm_xsmp_client_connect              (GsmXSMPClient  *client,
b31790
                                                   SmsConn         conn,
b31790
                                                   unsigned long  *mask_ret,
b31790
                                                   SmsCallbacks   *callbacks_ret);
b31790
 
b31790
 void        gsm_xsmp_client_save_state           (GsmXSMPClient  *client);
b31790
 void        gsm_xsmp_client_save_yourself        (GsmXSMPClient  *client,
b31790
                                                   gboolean        save_state);
b31790
 void        gsm_xsmp_client_save_yourself_phase2 (GsmXSMPClient  *client);
b31790
 void        gsm_xsmp_client_interact             (GsmXSMPClient  *client);
b31790
 void        gsm_xsmp_client_shutdown_cancelled   (GsmXSMPClient  *client);
b31790
 
b31790
 G_END_DECLS
b31790
diff --git a/gnome-session/org.gnome.SessionManager.xml b/gnome-session/org.gnome.SessionManager.xml
b31790
index 580ec356..29eb0990 100644
b31790
--- a/gnome-session/org.gnome.SessionManager.xml
b31790
+++ b/gnome-session/org.gnome.SessionManager.xml
b31790
@@ -255,60 +255,68 @@
b31790
       </arg>
b31790
       <arg name="handled" direction="out" type="b">
b31790
         <doc:doc>
b31790
           <doc:summary>True if condition is handled, false otherwise</doc:summary>
b31790
         </doc:doc>
b31790
       </arg>
b31790
       <doc:doc>
b31790
         <doc:description>
b31790
           <doc:para>Allows the caller to determine whether the session manager is
b31790
           handling changes to the specified autostart condition.</doc:para>
b31790
         </doc:description>
b31790
       </doc:doc>
b31790
     </method>
b31790
 
b31790
     <method name="Shutdown">
b31790
       <doc:doc>
b31790
         <doc:description>
b31790
           <doc:para>Request a shutdown dialog.</doc:para>
b31790
         </doc:description>
b31790
       </doc:doc>
b31790
     </method>
b31790
 
b31790
     <method name="Reboot">
b31790
       <doc:doc>
b31790
         <doc:description>
b31790
           <doc:para>Request a reboot dialog.</doc:para>
b31790
         </doc:description>
b31790
       </doc:doc>
b31790
     </method>
b31790
 
b31790
+    <method name="SaveSession">
b31790
+      <doc:doc>
b31790
+	<doc:description>
b31790
+	  <doc:para>Request to save session</doc:para>
b31790
+	</doc:description>
b31790
+      </doc:doc>
b31790
+    </method>
b31790
+
b31790
     <method name="CanShutdown">
b31790
       <arg name="is_available" direction="out" type="b">
b31790
         <doc:doc>
b31790
           <doc:summary>True if shutdown is available to the user, false otherwise</doc:summary>
b31790
         </doc:doc>
b31790
       </arg>
b31790
       <doc:doc>
b31790
         <doc:description>
b31790
           <doc:para>Allows the caller to determine whether or not it's okay to show
b31790
           a shutdown option in the UI</doc:para>
b31790
         </doc:description>
b31790
       </doc:doc>
b31790
     </method>
b31790
 
b31790
     <method name="Logout">
b31790
       <arg name="mode" type="u" direction="in">
b31790
         <doc:doc>
b31790
           <doc:summary>The type of logout that is being requested</doc:summary>
b31790
         </doc:doc>
b31790
       </arg>
b31790
       <doc:doc>
b31790
         <doc:description>
b31790
           <doc:para>Request a logout dialog</doc:para>
b31790
           <doc:para>
b31790
             Allowed values for the mode parameter are:
b31790
             <doc:list>
b31790
               <doc:item>
b31790
                 <doc:term>0</doc:term>
b31790
                 <doc:definition>Normal.</doc:definition>
b31790
               </doc:item>
f47161
diff --git a/meson.build b/meson.build
f47161
index 9a16d5b1..24221bb6 100644
f47161
--- a/meson.build
f47161
+++ b/meson.build
f47161
@@ -72,60 +72,61 @@ if enable_deprecation_flags
f47161
 endif
f47161
 
f47161
 compiler_flags = []
f47161
 if session_debug
f47161
   test_cflags = [
f47161
     '-Werror=format=2',
f47161
     '-Werror=implicit-function-declaration',
f47161
     '-Werror=init-self',
f47161
     '-Werror=missing-include-dirs',
f47161
     '-Werror=missing-prototypes',
f47161
     '-Werror=pointer-arith',
f47161
     '-Werror=return-type',
f47161
     '-Wnested-externs',
f47161
     '-Wstrict-prototypes'
f47161
   ]
f47161
 
f47161
   compiler_flags += cc.get_supported_arguments(test_cflags)
f47161
 endif
f47161
 
f47161
 add_project_arguments(common_flags + compiler_flags, language: 'c')
f47161
 
f47161
 glib_req_version = '>= 2.46.0'
f47161
 
f47161
 gio_dep = dependency('gio-2.0', version: glib_req_version)
f47161
 glib_dep = dependency('glib-2.0', version: glib_req_version)
f47161
 gtk_dep = dependency('gtk+-3.0', version: '>= 3.18.0')
f47161
 xtrans_dep = dependency('xtrans')
f47161
 ice_dep = dependency('ice')
f47161
 sm_dep = dependency('sm')
f47161
 x11_dep = dependency('x11')
f47161
+dbus_glib_dep = dependency('dbus-glib-1')
f47161
 
f47161
 session_deps = [
f47161
   gio_dep,
f47161
   glib_dep,
f47161
   dependency('gnome-desktop-3.0', version: '>= 3.18.0'),
f47161
   dependency('json-glib-1.0', version: '>= 0.10')
f47161
 ]
f47161
 
f47161
 session_bin_deps = session_deps + [
f47161
   xtrans_dep,
f47161
   ice_dep,
f47161
   sm_dep
f47161
 ]
f47161
 
f47161
 # Check for session selector GTK+ UI
f47161
 enable_session_selector = get_option('session_selector')
f47161
 
f47161
 # Check for session tracking backend
f47161
 session_tracking = 'null backend'
f47161
 
f47161
 enable_systemd = get_option('systemd')
f47161
 enable_systemd_journal = get_option('systemd_journal')
f47161
 enable_consolekit = get_option('consolekit')
f47161
 if enable_systemd or enable_consolekit
f47161
   session_bin_deps += dependency('gio-unix-2.0', version: glib_req_version)
f47161
 
f47161
   # Check for systemd
f47161
   if enable_systemd
f47161
     libsystemd_dep = dependency('libsystemd', version: '>= 209', required: false)
f47161
     session_bin_deps += libsystemd_dep
b31790
-- 
f47161
2.17.0
b31790