[gnome-session] gsm: Move the definition of a session from gconf to .desktop-like files



commit 30da8bec52103eb812439ddc03dcdb9ff47d34a9
Author: Vincent Untz <vuntz gnome org>
Date:   Mon Nov 29 19:06:30 2010 +0100

    gsm: Move the definition of a session from gconf to .desktop-like files
    
    This will help us both for the GSettings migration and to implement the
    fallback from GNOME Shell to Classic GNOME.
    
    The --default-session-key argument has been changed to --session, which
    takes the basename (without extension) of the .desktop-like file to use.
    By default, gnome is used, and the gnome.session file is looked for in
    $XDG_CONFIG_HOME/gnome-session/sessions,
    $XDG_CONFIG_DIRS/gnome-session/sessions,
    $XDG_DATA_DIRS/gnome-session/sessions.

 data/Makefile.am                 |   26 +++--
 data/gnome-session.schemas.in    |   43 ++++++
 data/gnome-session.schemas.in.in |  101 --------------
 data/gnome.session.desktop.in.in |    7 +
 doc/man/gnome-session.1          |   29 +++--
 gnome-session/gsm-session-fill.c |  278 +++++++++++++++++++++++++++-----------
 gnome-session/gsm-session-fill.h |    6 +-
 gnome-session/main.c             |   12 +-
 8 files changed, 298 insertions(+), 204 deletions(-)
---
diff --git a/data/Makefile.am b/data/Makefile.am
index f023737..65e6c7d 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -15,22 +15,29 @@ desktopdir = $(datadir)/applications
 desktop_in_files = session-properties.desktop.in
 desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
 
+sessiondir = $(datadir)/gnome-session/sessions
+session_in_in_files = gnome.session.desktop.in.in
+session_in_files = $(session_in_in_files:.session.desktop.in.in=.session.desktop.in)
+session_DATA = $(session_in_files:.session.desktop.in=.session)
+
+%.session.desktop.in: %.session.desktop.in.in Makefile
+	$(AM_V_GEN)sed \
+		-e "s|\ DEFAULT_WM\@|$(DEFAULT_WM)|" \
+		-e "s|\ LIBEXECDIR\@|$(libexecdir)|" \
+		$< > $@
+
+%.session: %.session.desktop.in   $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+
 if USE_GNOME_WM
 desktop_in_files += gnome-wm.desktop.in
 endif
 
 @INTLTOOL_DESKTOP_RULE@
 
-schemas_in_in_files = gnome-session.schemas.in.in
-schemas_in_files = $(schemas_in_in_files:.schemas.in.in=.schemas.in)
+schemas_in_files = gnome-session.schemas.in
 schemasdir = $(GCONF_SCHEMA_FILE_DIR)
 schemas_DATA = $(schemas_in_files:.schemas.in=.schemas)
 
-$(schemas_in_files): $(schemas_in_files).in Makefile
-	$(AM_V_GEN)sed \
-		-e "s|\ DEFAULT_WM\@|$(DEFAULT_WM)|" \
-		$< > $@
-
 @INTLTOOL_SCHEMAS_RULE@
 
 if GCONF_SCHEMAS_INSTALL
@@ -49,15 +56,16 @@ endif
 EXTRA_DIST =					\
 	gnome-wm				\
 	$(xsession_in_files)			\
-	$(schemas_in_in_files)			\
+	$(session_in_in_files)			\
+	$(schemas_in_files)			\
 	$(ui_DATA)				\
 	$(pixmap_DATA_dist)
 
 CLEANFILES =					\
-	$(schemas_in_files)			\
 	$(schemas_DATA)				\
 	$(xsession_DATA)			\
 	$(desktop_DATA)				\
+	$(session_DATA)				\
 	gnome-wm.desktop
 
 DISTCLEANFILES =				\
diff --git a/data/gnome-session.schemas.in b/data/gnome-session.schemas.in
new file mode 100644
index 0000000..f55db08
--- /dev/null
+++ b/data/gnome-session.schemas.in
@@ -0,0 +1,43 @@
+<?xml version="1.0"?>
+<gconfschemafile>
+   <schemalist>
+
+      <schema>
+         <key>/schemas/apps/gnome-session/options/auto_save_session</key>
+         <applyto>/apps/gnome-session/options/auto_save_session</applyto>
+         <owner>gnome</owner>
+         <type>bool</type>
+         <default>false</default>
+         <locale name="C">
+            <short>Save sessions</short>
+            <long>If enabled, gnome-session will save the session automatically.</long>
+         </locale>
+      </schema>
+      <schema>
+         <key>/schemas/apps/gnome-session/options/logout_prompt</key>
+         <applyto>/apps/gnome-session/options/logout_prompt</applyto>
+         <owner>gnome</owner>
+         <type>bool</type>
+         <default>true</default>
+         <locale name="C">
+            <short>Logout prompt</short>
+            <long>If enabled, gnome-session will prompt the user before ending a session.</long>
+         </locale>
+      </schema>
+      <schema>
+        <key>/schemas/desktop/gnome/session/idle_delay</key>
+        <applyto>/desktop/gnome/session/idle_delay</applyto>
+        <owner>gnome</owner>
+        <type>int</type>
+        <default>5</default>
+        <locale name="C">
+          <short>Time before session is considered idle</short>
+          <long>
+            The number of minutes of inactivity before the session is
+            considered idle.
+          </long>
+        </locale>
+      </schema>
+
+   </schemalist>
+</gconfschemafile>
diff --git a/data/gnome.session.desktop.in.in b/data/gnome.session.desktop.in.in
new file mode 100644
index 0000000..e088f3c
--- /dev/null
+++ b/data/gnome.session.desktop.in.in
@@ -0,0 +1,7 @@
+[GNOME Session]
+_Name=GNOME
+Required=windowmanager;panel;filemanager;
+Required-windowmanager= DEFAULT_WM@
+Required-panel=gnome-panel
+Required-filemanager=nautilus
+DefaultApps=gnome-settings-daemon;
diff --git a/doc/man/gnome-session.1 b/doc/man/gnome-session.1
index 59cf661..e55d058 100644
--- a/doc/man/gnome-session.1
+++ b/doc/man/gnome-session.1
@@ -7,7 +7,7 @@
 .SH NAME
 gnome-session \- Start the GNOME desktop environment
 .SH SYNOPSIS
-.B gnome-session [\-\-autostart=DIR] [\-\-default-session-key=KEY] [\-\-failsafe|\-f] [\-\-debug]
+.B gnome-session [\-\-autostart=DIR] [\-\-session=SESSION] [\-\-failsafe|\-f] [\-\-debug]
 .SH DESCRIPTION
 The \fIgnome-session\fP program starts up the GNOME desktop
 environment. This command is typically executed by your login manager
@@ -16,8 +16,12 @@ either your saved session, or it will provide a default session for the
 user as defined by the system administrator (or the default GNOME
 installation on your system).
 .PP
-The default session is defined in the GConf keys under
-\fB/desktop/gnome/session\fP.
+The default session is defined in \fBgnome.session\fP, a .desktop-like
+file that is looked for in
+\fB$XDG_CONFIG_HOME/gnome-session/sessions\fP,
+\fB$XDG_CONFIG_DIRS/gnome-session/sessions\fP and
+\fB$XDG_DATA_DIRS/gnome-session/sessions\fP.
+.PP
 When saving a session, \fIgnome-session\fP saves the currently running
 applications in the \fB$XDG_CONFIG_HOME/gnome-session/saved-session\fP
 directory.
@@ -29,14 +33,12 @@ The following options are supported:
 .TP
 .I "--autostart=DIR"
 Start all applications defined in \fIDIR\fP, instead of starting the
-applications defined in \fB/desktop/gnome/session/default_session\fP,
-or via the \fI--default-session-key\fP option. Multiple
-\fI--autostart\fP options can be passed.
+applications defined in \fBgnome.session\fP, or via the \fI--session\fP
+option. Multiple \fI--autostart\fP options can be passed.
 .TP
-.I "--default-session-key=KEY"
-Set the GConf key from which applications running a default session
-should be read to \fIKEY\fP. If not specificed,
-\fB/desktop/gnome/session/default_session\fP will be used.
+.I "--session=SESSION"
+Use the applications defined in \fBSESSION.session\fP. If not specified,
+\fBgnome.session\fP will be used.
 .TP
 .I "--failsafe"
 Run in fail-safe mode. User-specified applications will not be started.
@@ -67,6 +69,13 @@ when gnome-session is invoked.
 The applications defined in those directories will be started on login.
 \fIgnome-session-properties(1)\fP can be used to easily configure them.
 .PP
+.B $XDG_CONFIG_HOME/gnome-session/sessions
+.B $XDG_CONFIG_DIRS/gnome-session/sessions
+.B $XDG_DATA_DIRS/gnome-session/sessions
+.IP
+These directories contain the \fB.session\fP files that can be used
+with the \fI--session\fP option.
+.PP
 .B $XDG_CONFIG_HOME/gnome-session/saved-session
 .IP
 This directory contains the list of applications of the saved session.
diff --git a/gnome-session/gsm-session-fill.c b/gnome-session/gsm-session-fill.c
index 4745ea5..12825cd 100644
--- a/gnome-session/gsm-session-fill.c
+++ b/gnome-session/gsm-session-fill.c
@@ -24,114 +24,103 @@
 #include "gsm-session-fill.h"
 
 #include "gsm-consolekit.h"
-#include "gsm-gconf.h"
-#include "gsm-util.h"
 #include "gsm-manager.h"
+#include "gsm-util.h"
 
-#define GSM_GCONF_DEFAULT_SESSION_KEY           "/desktop/gnome/session/default_session"
-#define GSM_GCONF_REQUIRED_COMPONENTS_DIRECTORY "/desktop/gnome/session/required_components"
-#define GSM_GCONF_REQUIRED_COMPONENTS_LIST_KEY  "/desktop/gnome/session/required_components_list"
+#define GSM_DEFAULT_SESSION "gnome"
+
+#define GSM_KEYFILE_SESSION_GROUP "GNOME Session"
+#define GSM_KEYFILE_REQUIRED_KEY "Required"
+#define GSM_KEYFILE_DEFAULT_KEY "DefaultApps"
 
 /* This doesn't contain the required components, so we need to always
  * call append_required_apps() after a call to append_default_apps(). */
 static void
 append_default_apps (GsmManager *manager,
-                     const char *default_session_key,
+                     GKeyFile   *keyfile,
                      char      **autostart_dirs)
 {
-        GSList      *default_apps;
-        GSList      *a;
-        GConfClient *client;
+        char **default_apps;
+        int    i;
 
-        g_debug ("main: *** Adding default apps");
+        g_debug ("fill: *** Adding default apps");
 
-        g_assert (default_session_key != NULL);
+        g_assert (keyfile != NULL);
         g_assert (autostart_dirs != NULL);
 
-        client = gconf_client_get_default ();
-        default_apps = gconf_client_get_list (client,
-                                              default_session_key,
-                                              GCONF_VALUE_STRING,
-                                              NULL);
-        g_object_unref (client);
+        default_apps = g_key_file_get_string_list (keyfile,
+                                                   GSM_KEYFILE_SESSION_GROUP, GSM_KEYFILE_DEFAULT_KEY,
+                                                   NULL, NULL);
 
-        for (a = default_apps; a; a = a->next) {
+        if (!default_apps)
+                return;
+
+        for (i = 0; default_apps[i] != NULL; i++) {
                 char *app_path;
 
-                if (IS_STRING_EMPTY ((char *)a->data)) {
+                if (IS_STRING_EMPTY (default_apps[i]))
                         continue;
-                }
 
-                app_path = gsm_util_find_desktop_file_for_app_name (a->data, autostart_dirs);
+                app_path = gsm_util_find_desktop_file_for_app_name (default_apps[i], autostart_dirs);
                 if (app_path != NULL) {
                         gsm_manager_add_autostart_app (manager, app_path, NULL);
                         g_free (app_path);
                 }
         }
 
-        g_slist_foreach (default_apps, (GFunc) g_free, NULL);
-        g_slist_free (default_apps);
+        g_strfreev (default_apps);
 }
 
 static void
-append_required_apps (GsmManager *manager)
+append_required_apps (GsmManager *manager,
+                      GKeyFile   *keyfile)
 {
-        GSList      *required_components;
-        GSList      *r;
-        GConfClient *client;
+        char **required_components;
+        int    i;
+
+        g_debug ("fill: *** Adding required apps");
 
-        g_debug ("main: *** Adding required apps");
+        required_components = g_key_file_get_string_list (keyfile,
+                                                          GSM_KEYFILE_SESSION_GROUP, GSM_KEYFILE_REQUIRED_KEY,
+                                                          NULL, NULL);
 
-        client = gconf_client_get_default ();
-        required_components = gconf_client_get_list (client,
-                                                     GSM_GCONF_REQUIRED_COMPONENTS_LIST_KEY,
-                                                     GCONF_VALUE_STRING,
-                                                     NULL);
         if (required_components == NULL) {
                 g_warning ("No required applications specified");
+                return;
         }
 
-        for (r = required_components; r != NULL; r = r->next) {
-                char       *path;
-                char       *default_provider;
-                const char *component;
+        for (i = 0; required_components[i] != NULL; i++) {
+                char *key;
+                char *value;
+                char *app_path;
+
+                key = g_strdup_printf ("%s-%s", GSM_KEYFILE_REQUIRED_KEY, required_components[i]);
+                value = g_key_file_get_string (keyfile,
+                                               GSM_KEYFILE_SESSION_GROUP, key,
+                                               NULL);
+                g_free (key);
 
-                if (IS_STRING_EMPTY ((char *)r->data)) {
+                if (IS_STRING_EMPTY (value)) {
+                        g_free (value);
                         continue;
                 }
 
-                component = r->data;
-
-                path = g_strdup_printf ("%s/%s",
-                                        GSM_GCONF_REQUIRED_COMPONENTS_DIRECTORY,
-                                        component);
-
-                default_provider = gconf_client_get_string (client, path, NULL);
-                g_debug ("main: %s looking for component: '%s'", path, default_provider);
-                if (default_provider != NULL) {
-                        char *app_path;
-
-                        app_path = gsm_util_find_desktop_file_for_app_name (default_provider, NULL);
-                        if (app_path != NULL) {
-                                gsm_manager_add_autostart_app (manager, app_path, component);
-                        } else {
-                                g_warning ("Unable to find provider '%s' of required component '%s'",
-                                           default_provider,
-                                           component);
-                        }
-                        g_free (app_path);
+                g_debug ("fill: %s looking for component: '%s'", required_components[i], value);
+                app_path = gsm_util_find_desktop_file_for_app_name (value, NULL);
+                if (app_path != NULL) {
+                        gsm_manager_add_autostart_app (manager, app_path, required_components[i]);
+                } else {
+                        g_warning ("Unable to find provider '%s' of required component '%s'",
+                                   value, required_components[i]);
                 }
+                g_free (app_path);
 
-                g_free (default_provider);
-                g_free (path);
+                g_free (value);
         }
 
-        g_debug ("main: *** Done adding required apps");
-
-        g_slist_foreach (required_components, (GFunc)g_free, NULL);
-        g_slist_free (required_components);
+        g_debug ("fill: *** Done adding required apps");
 
-        g_object_unref (client);
+        g_strfreev (required_components);
 }
 
 static void
@@ -153,7 +142,7 @@ maybe_load_saved_session_apps (GsmManager *manager)
 
 static void
 load_standard_apps (GsmManager *manager,
-                    const char *default_session_key)
+                    GKeyFile   *keyfile)
 {
         char **autostart_dirs;
         int    i;
@@ -171,8 +160,8 @@ load_standard_apps (GsmManager *manager,
 
         /* We do this at the end in case a saved session contains an
          * application that already provides one of the components. */
-        append_default_apps (manager, default_session_key, autostart_dirs);
-        append_required_apps (manager);
+        append_default_apps (manager, keyfile, autostart_dirs);
+        append_required_apps (manager, keyfile);
 
         g_strfreev (autostart_dirs);
 }
@@ -187,18 +176,155 @@ load_override_apps (GsmManager *manager,
         }
 }
 
-void
+static GKeyFile *
+get_session_keyfile_if_valid (const char *path)
+{
+        GKeyFile  *keyfile;
+        gsize      len;
+        char     **list;
+
+        g_debug ("fill: *** Looking if %s is a valid session file", path);
+
+        keyfile = g_key_file_new ();
+
+        if (!g_key_file_load_from_file (keyfile, path, G_KEY_FILE_NONE, NULL)) {
+                g_debug ("Cannot use session '%s': non-existing or invalid file.", path);
+                goto error;
+        }
+
+        if (!g_key_file_has_group (keyfile, GSM_KEYFILE_SESSION_GROUP)) {
+                g_warning ("Cannot use session '%s': no '%s' group.", path, GSM_KEYFILE_SESSION_GROUP);
+                goto error;
+        }
+
+        list = g_key_file_get_string_list (keyfile,
+                                           GSM_KEYFILE_SESSION_GROUP, GSM_KEYFILE_REQUIRED_KEY,
+                                           &len, NULL);
+        if (list != NULL) {
+                int i;
+                char *key;
+                char *value;
+
+                for (i = 0; list[i] != NULL; i++) {
+                        key = g_strdup_printf ("%s-%s", GSM_KEYFILE_REQUIRED_KEY, list[i]);
+                        value = g_key_file_get_string (keyfile,
+                                                       GSM_KEYFILE_SESSION_GROUP, key,
+                                                       NULL);
+                        g_free (key);
+
+                        if (IS_STRING_EMPTY (value)) {
+                                g_free (value);
+                                break;
+                        }
+
+                        g_free (value);
+                }
+
+                if (list[i] != NULL) {
+                        g_warning ("Cannot use session '%s': required component '%s' is not defined.", path, list[i]);
+                        g_strfreev (list);
+                        goto error;
+                }
+
+                g_strfreev (list);
+        }
+
+        /* we don't want an empty session, so if there's no required app, check
+         * that we do have some default apps */
+        if (len == 0) {
+                list = g_key_file_get_string_list (keyfile,
+                                                   GSM_KEYFILE_SESSION_GROUP, GSM_KEYFILE_DEFAULT_KEY,
+                                                   &len, NULL);
+                if (list)
+                        g_strfreev (list);
+                if (len == 0) {
+                        g_warning ("Cannot use session '%s': no application in the session.", path);
+                        goto error;
+                }
+        }
+
+        return keyfile;
+
+error:
+        g_key_file_free (keyfile);
+        return NULL;
+}
+
+/**
+ * find_valid_session_keyfile:
+ * @session: name of session
+ *
+ * We look for the session file in XDG_CONFIG_HOME, XDG_CONFIG_DIRS and
+ * XDG_DATA_DIRS. This enables users and sysadmins to override a specific
+ * session that is shipped in XDG_DATA_DIRS.
+ */
+static GKeyFile *
+find_valid_session_keyfile (const char *session)
+{
+        GPtrArray          *dirs;
+        const char * const *system_config_dirs;
+        const char * const *system_data_dirs;
+        int                 i;
+        GKeyFile           *keyfile;
+        char               *basename;
+        char               *path;
+
+        dirs = g_ptr_array_new ();
+
+        g_ptr_array_add (dirs, (gpointer) g_get_user_config_dir ());
+
+        system_config_dirs = g_get_system_config_dirs ();
+        for (i = 0; system_config_dirs[i]; i++)
+                g_ptr_array_add (dirs, (gpointer) system_config_dirs[i]);
+
+        system_data_dirs = g_get_system_data_dirs ();
+        for (i = 0; system_data_dirs[i]; i++)
+                g_ptr_array_add (dirs, (gpointer) system_data_dirs[i]);
+
+        keyfile = NULL;
+        basename = g_strdup_printf ("%s.session", session);
+        path = NULL;
+
+        for (i = 0; i < dirs->len; i++) {
+                path = g_build_filename (dirs->pdata[i], "gnome-session", "sessions", basename, NULL);
+                keyfile = get_session_keyfile_if_valid (path);
+                if (keyfile != NULL)
+                        break;
+        }
+
+        if (dirs)
+                g_ptr_array_free (dirs, TRUE);
+        if (basename)
+                g_free (basename);
+        if (path)
+                g_free (path);
+
+        return keyfile;
+}
+
+gboolean
 gsm_session_fill (GsmManager  *manager,
                   char       **override_autostart_dirs,
-                  char        *default_session_key)
+                  const char  *session)
 {
+        GKeyFile *keyfile;
+
         if (override_autostart_dirs != NULL) {
                 load_override_apps (manager, override_autostart_dirs);
-        } else {
-                if (! IS_STRING_EMPTY (default_session_key)) {
-                        load_standard_apps (manager, default_session_key);
-                } else {
-                        load_standard_apps (manager, GSM_GCONF_DEFAULT_SESSION_KEY);
-                }
+                return TRUE;
         }
+
+        if (IS_STRING_EMPTY (session))
+                session = GSM_DEFAULT_SESSION;
+
+        keyfile = find_valid_session_keyfile (session);
+
+        if (!keyfile)
+                return FALSE;
+
+        load_standard_apps (manager, keyfile);
+
+        g_key_file_free (keyfile);
+
+        return TRUE;
 }
diff --git a/gnome-session/gsm-session-fill.h b/gnome-session/gsm-session-fill.h
index 5d09d77..2a8ec08 100644
--- a/gnome-session/gsm-session-fill.h
+++ b/gnome-session/gsm-session-fill.h
@@ -26,9 +26,9 @@
 
 G_BEGIN_DECLS
 
-void gsm_session_fill (GsmManager  *manager,
-                       char       **override_autostart_dirs,
-                       char        *default_session_key);
+gboolean gsm_session_fill (GsmManager  *manager,
+                           char       **override_autostart_dirs,
+                           const char  *session);
 
 G_END_DECLS
 
diff --git a/gnome-session/main.c b/gnome-session/main.c
index 25f3fb4..1c17120 100644
--- a/gnome-session/main.c
+++ b/gnome-session/main.c
@@ -271,10 +271,10 @@ main (int argc, char **argv)
         GsmXsmpServer    *xsmp_server;
         GdmSignalHandler *signal_handler;
         static char     **override_autostart_dirs = NULL;
-        static char      *default_session_key = NULL;
+        static char      *session_name = NULL;
         static GOptionEntry entries[] = {
                 { "autostart", 'a', 0, G_OPTION_ARG_STRING_ARRAY, &override_autostart_dirs, N_("Override standard autostart directories"), NULL },
-                { "default-session-key", 0, 0, G_OPTION_ARG_STRING, &default_session_key, N_("GConf key used to look up default session"), NULL },
+                { "session", 0, 0, G_OPTION_ARG_STRING, &session_name, N_("Session to use"), NULL },
                 { "debug", 0, 0, G_OPTION_ARG_NONE, &debug, N_("Enable debugging code"), NULL },
                 { "failsafe", 'f', 0, G_OPTION_ARG_NONE, &failsafe, N_("Do not load user-specified applications"), NULL },
                 { "version", 0, 0, G_OPTION_ARG_NONE, &show_version, N_("Version of this application"), NULL },
@@ -350,9 +350,11 @@ main (int argc, char **argv)
         gdm_signal_handler_add (signal_handler, SIGINT, signal_cb, manager);
         gdm_signal_handler_set_fatal_func (signal_handler, shutdown_cb, manager);
 
-        gsm_session_fill (manager,
-                          override_autostart_dirs,
-                          default_session_key);
+        if (!gsm_session_fill (manager,
+                               override_autostart_dirs,
+                               session_name)) {
+                gsm_util_init_error (TRUE, "%s", "No valid session found.");
+        }
 
         gsm_xsmp_server_start (xsmp_server);
         gsm_manager_start (manager);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]