Description: Session can now handle multiple fallbacks. It will pick the first
             valid one.
             add a corresponding fallback message to display the first time a session is 
             fallbacking to another one.
             A new gconf key schema entry,
             /apps/gnome-session/options/force_fallback_message can be used to
             force displaying the message everytime.
Ubuntu-Bug: https://bugs.launchpad.net/ubuntu/+source/gnome-session/+bug/703653
Author: Didier Roche <didrocks@ubuntu.com>


Index: gnome-session-2.32.1/gnome-session/gsm-session-fill.c
===================================================================
--- gnome-session-2.32.1.orig/gnome-session/gsm-session-fill.c	2011-02-03 14:07:34.728206218 +0100
+++ gnome-session-2.32.1/gnome-session/gsm-session-fill.c	2011-02-03 14:07:34.752206330 +0100
@@ -32,7 +32,8 @@
 
 #define GSM_KEYFILE_SESSION_GROUP "GNOME Session"
 #define GSM_KEYFILE_RUNNABLE_KEY "IsRunnableHelper"
-#define GSM_KEYFILE_FALLBACK_KEY "FallbackSession"
+#define GSM_KEYFILE_FALLBACK_SESSION_ID_KEY "FallbackSessionsID"
+#define GSM_KEYFILE_FALLBACKMSG_SUFFIX "_Message"
 #define GSM_KEYFILE_REQUIRED_KEY "Required"
 #define GSM_KEYFILE_DEFAULT_KEY "DefaultApps"
 
@@ -311,13 +312,22 @@
 get_session_keyfile (const char *session)
 {
         GKeyFile *keyfile;
+        GKeyFile *fallback_keyfile = NULL;
         gboolean  session_runnable;
         char     *value;
+        int       i;
+        char    **fallback_session_ids = NULL;
+        char     *fallback_session_key;
+        char     *fallback_message_key;
+        char     *fallback_message;
 
         g_debug ("fill: *** Getting session '%s'", session);
 
         keyfile = find_valid_session_keyfile (session);
 
+        if (!keyfile)
+                return NULL;
+
         session_runnable = TRUE;
 
         value = g_key_file_get_string (keyfile,
@@ -334,19 +344,60 @@
 
         g_debug ("fill: *** Session is not runnable");
 
-        /* We can't run this session, so try to use the fallback */
-        value = g_key_file_get_string (keyfile,
-                                       GSM_KEYFILE_SESSION_GROUP, GSM_KEYFILE_FALLBACK_KEY,
-                                       NULL);
+        /* now, get the list of fallback key to test */
+        fallback_session_ids = g_key_file_get_string_list (keyfile,
+                                                           GSM_KEYFILE_SESSION_GROUP, GSM_KEYFILE_FALLBACK_SESSION_ID_KEY,
+                                                           NULL, NULL);
+
+        if (!fallback_session_ids) {
+                g_key_file_free (keyfile);
+                return NULL;
+        }
 
-        g_key_file_free (keyfile);
-        keyfile = NULL;
+        for (i = 0; fallback_session_ids[i] != NULL; i++) {
+                g_debug ("fill: *** found %s fallback session candidate", fallback_session_ids[i]);
+                if (IS_STRING_EMPTY (fallback_session_ids[i]))
+                        continue;
+
+                fallback_session_key = g_strdup(fallback_session_ids[i]);
+                value = g_key_file_get_string (keyfile,
+                                               GSM_KEYFILE_SESSION_GROUP, fallback_session_key,
+                                               NULL);
+
+                if (value) {
+                         fallback_keyfile = get_session_keyfile (value);
+                         if (fallback_keyfile) {
+                                  g_debug ("fill: *** found %s suitable fallback session", value);
+                                  break;
+                         }
+                }
+
+                g_free (value);
+                g_free (fallback_session_key);
+        }
 
-        if (!IS_STRING_EMPTY (value))
-                keyfile = get_session_keyfile (value);
         g_free (value);
+        g_strfreev (fallback_session_ids);
 
-        return keyfile;
+        if (!fallback_keyfile) {
+                g_key_file_free (keyfile);
+                return NULL;
+        }
+
+        /* show if we have a message corresponding to the fallback */
+        fallback_message_key = g_strdup_printf ("%s%s", fallback_session_key, GSM_KEYFILE_FALLBACKMSG_SUFFIX);
+        fallback_message = g_key_file_get_string (keyfile,
+                                                  GSM_KEYFILE_SESSION_GROUP, fallback_message_key,
+											      NULL);
+        if (!IS_STRING_EMPTY (fallback_message)) {
+               g_debug ("fill: *** found non empty fallback message: %s", fallback_message);
+               gsm_util_display_fallback_message (fallback_message, session);
+        }
+
+        g_free (fallback_message_key);
+        g_free (fallback_session_key);
+        g_key_file_free (keyfile);
+        return fallback_keyfile;
 }
 
 gboolean
@@ -375,3 +426,4 @@
 
         return TRUE;
 }
+
Index: gnome-session-2.32.1/gnome-session/gsm-util.c
===================================================================
--- gnome-session-2.32.1.orig/gnome-session/gsm-util.c	2010-02-09 14:22:01.000000000 +0100
+++ gnome-session-2.32.1/gnome-session/gsm-util.c	2011-02-03 14:07:34.752206330 +0100
@@ -34,8 +34,12 @@
 
 #include <dbus/dbus-glib.h>
 
+#include <gconf/gconf-client.h>
+
 #include "gsm-util.h"
 
+#define GTK_RESPONSE_CHANGE_SESSION -20
+
 static gchar *_saved_session_dir = NULL;
 
 char *
@@ -373,6 +377,84 @@
 }
 
 /**
+ * gsm_util_display_fallback_message:
+ * @message: message to print to the user
+ * @session: session for which fallback message is to be displayed
+ *
+ * Displays the message to the user when we have to fallback to another session
+ * type.
+ *
+ * The dialog will be runned without blocking further session loading and offers
+ * a convenient way to the user to launch g-c-c to change its default session in
+ * gdm.
+ **/
+void
+gsm_util_display_fallback_message (const char *message,
+                                   const char *session)
+{
+        GtkWidget   *dialog;
+        gint         result;
+        GConfClient *gconf_client;
+        gboolean     fallback_msg_displayed;
+        gchar       *gconf_session_msg_key;
+
+        gconf_client = gconf_client_get_default ();
+        gconf_session_msg_key =
+              g_strdup_printf ("/apps/gnome-session/session-messages/%s",
+                               session);
+        fallback_msg_displayed =
+              gconf_client_get_bool (gconf_client, gconf_session_msg_key, NULL);
+
+        if (gconf_client_get_bool (gconf_client,
+                                   "/apps/gnome-session/options/force_fallback_message",
+                                   NULL))
+                fallback_msg_displayed = FALSE;
+
+        if (fallback_msg_displayed) {
+                g_debug ("Fallback message already displayed");
+                g_free (gconf_session_msg_key);
+                g_object_unref (gconf_client);
+                return;
+        }
+
+        /* If option parsing failed, Gtk won't have been initialized... */
+        if (!gdk_display_get_default ()) {
+                if (!gtk_init_check (NULL, NULL)) {
+                        /* Oh well, no X for you! */
+                        g_printerr (_("Unable to connect to the X server"));
+                        g_printerr ("%s", message);
+                        exit (1);
+                }
+        }
+
+        dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_WARNING,
+                                         GTK_BUTTONS_NONE, "%s", message);
+        gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+        //                        _("Change user session"), GTK_RESPONSE_CHANGE_SESSION,
+                                GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
+                                NULL);
+
+        gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
+        result = gtk_dialog_run (GTK_DIALOG (dialog));
+
+        switch (result)
+        {
+                case GTK_RESPONSE_CHANGE_SESSION:
+                        // not yet implemented on g-c-c side
+                default:
+                        gconf_client_set_bool (gconf_client,
+                                               gconf_session_msg_key,
+                                               TRUE, NULL);
+        }
+
+        g_free (gconf_session_msg_key);
+        g_object_unref (gconf_client);
+
+        gtk_widget_destroy (dialog);
+
+}
+
+/**
  * gsm_util_generate_startup_id:
  *
  * Generates a new SM client ID.
Index: gnome-session-2.32.1/gnome-session/Makefile.am
===================================================================
--- gnome-session-2.32.1.orig/gnome-session/Makefile.am	2011-02-03 14:07:34.652205854 +0100
+++ gnome-session-2.32.1/gnome-session/Makefile.am	2011-02-03 14:07:34.756206348 +0100
@@ -89,7 +89,12 @@
 	gsm-util.c				\
 	gsm-util.h
 
+libgsmutil_la_CPPFLAGS =		\
+	$(AM_CPPFLAGS)				\
+	$(GCONF_CFLAGS)
+
 libgsmutil_la_LIBADD = 				\
+	$(GCONF_LIBS)					\
 	$(GNOME_SESSION_LIBS)
 
 test_inhibit_SOURCES = test-inhibit.c
Index: gnome-session-2.32.1/gnome-session/gsm-util.h
===================================================================
--- gnome-session-2.32.1.orig/gnome-session/gsm-util.h	2011-02-03 14:07:34.664205890 +0100
+++ gnome-session-2.32.1/gnome-session/gsm-util.h	2011-02-03 14:07:34.756206348 +0100
@@ -44,6 +44,9 @@
 void        gsm_util_init_error                     (gboolean    fatal,
                                                      const char *format, ...);
 
+void        gsm_util_display_fallback_message (const char *message,
+                                               const char *session);
+
 char *      gsm_util_generate_startup_id            (void);
 
 void        gsm_util_setenv                         (const char *variable,
Index: gnome-session-2.32.1/data/gnome-session.schemas.in
===================================================================
--- gnome-session-2.32.1.orig/data/gnome-session.schemas.in	2011-02-03 14:07:34.660205871 +0100
+++ gnome-session-2.32.1/data/gnome-session.schemas.in	2011-02-03 14:07:34.756206348 +0100
@@ -14,6 +14,17 @@
          </locale>
       </schema>
       <schema>
+         <key>/schemas/apps/gnome-session/options/force_fallback_message</key>
+         <applyto>/apps/gnome-session/options/force_fallback_message</applyto>
+         <owner>gnome</owner>
+         <type>bool</type>
+         <default>false</default>
+         <locale name="C">
+            <short>Force Fallback Message to show</short>
+            <long>If enabled, the fallback message of the session (if present), will be displayed each time the session fallbacks.</long>
+         </locale>
+      </schema>
+      <schema>
          <key>/schemas/apps/gnome-session/options/logout_prompt</key>
          <applyto>/apps/gnome-session/options/logout_prompt</applyto>
          <owner>gnome</owner>
Index: gnome-session-2.32.1/data/gnome.session.desktop.in.in
===================================================================
--- gnome-session-2.32.1.orig/data/gnome.session.desktop.in.in	2011-02-03 14:07:48.740275707 +0100
+++ gnome-session-2.32.1/data/gnome.session.desktop.in.in	2011-02-03 14:08:46.032559788 +0100
@@ -6,4 +6,5 @@
 Required-filemanager=nautilus
 DefaultApps=gnome-settings-daemon;
 IsRunnableHelper=@LIBEXECDIR@/gnome-session-is-accelerated
-FallbackSession=classic-gnome
+FallbackSessionsID=FallbackClassicGnome
+FallbackClassicGnome=classic-gnome
