Blame SOURCES/0002-session-support-new-accountsservice-Session-and-Sess.patch

3b7bb8
From 96e78f519a4d5ce2e5b708035ae1f43eb7c1bbd2 Mon Sep 17 00:00:00 2001
f83012
From: Ray Strode <rstrode@redhat.com>
f83012
Date: Tue, 14 Aug 2018 14:52:41 -0400
18ca79
Subject: [PATCH 2/4] session: support new accountsservice Session and
f83012
 SessionType props
f83012
f83012
At the moment the user's session is stored in a property called
f83012
"XSession".  This is pretty weird if the user is using wayland.
f83012
f83012
AccountService now supports a more generic property "Session" and
f83012
a related "SessionType" property to replace "XSession".
f83012
f83012
This commit switches GDM over to use the new properties.
f83012
---
ffa191
 daemon/gdm-session-settings.c | 61 ++++++++++++++++++++++--
f83012
 daemon/gdm-session-settings.h |  3 ++
ffa191
 daemon/gdm-session-worker.c   | 28 +++++++++++
f83012
 daemon/gdm-session-worker.xml |  3 ++
ffa191
 daemon/gdm-session.c          | 87 +++++++++++++++++++++++++----------
ffa191
 5 files changed, 153 insertions(+), 29 deletions(-)
f83012
f83012
diff --git a/daemon/gdm-session-settings.c b/daemon/gdm-session-settings.c
3b7bb8
index 484a3b5b..f2b1addd 100644
f83012
--- a/daemon/gdm-session-settings.c
f83012
+++ b/daemon/gdm-session-settings.c
f83012
@@ -12,114 +12,121 @@
f83012
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
f83012
  * GNU General Public License for more details.
f83012
  *
f83012
  * You should have received a copy of the GNU General Public License
f83012
  * along with this program; if not, write to the Free Software
f83012
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
f83012
  * 02110-1301, USA.
f83012
  *
f83012
  * Written by: Ray Strode <rstrode@redhat.com>
f83012
  */
f83012
 #include "config.h"
f83012
 #include "gdm-session-settings.h"
f83012
 
f83012
 #include <errno.h>
f83012
 #include <pwd.h>
f83012
 #include <string.h>
f83012
 #include <sys/types.h>
f83012
 #include <unistd.h>
f83012
 
f83012
 #include <glib.h>
f83012
 #include <glib-object.h>
f83012
 #include <glib/gi18n.h>
f83012
 
f83012
 #include <act/act-user-manager.h>
f83012
 
f83012
 struct _GdmSessionSettingsPrivate
f83012
 {
f83012
         ActUserManager *user_manager;
f83012
         ActUser *user;
f83012
         char *session_name;
f83012
+        char *session_type;
f83012
         char *language_name;
f83012
 };
f83012
 
f83012
 static void gdm_session_settings_finalize (GObject *object);
f83012
 static void gdm_session_settings_class_install_properties (GdmSessionSettingsClass *
f83012
                                               settings_class);
f83012
 
f83012
 static void gdm_session_settings_set_property (GObject      *object,
f83012
                                               guint         prop_id,
f83012
                                               const GValue *value,
f83012
                                               GParamSpec   *pspec);
f83012
 static void gdm_session_settings_get_property (GObject      *object,
f83012
                                               guint         prop_id,
f83012
                                               GValue       *value,
f83012
                                               GParamSpec   *pspec);
f83012
 
f83012
 enum {
f83012
         PROP_0 = 0,
f83012
         PROP_SESSION_NAME,
f83012
+        PROP_SESSION_TYPE,
f83012
         PROP_LANGUAGE_NAME,
f83012
         PROP_IS_LOADED
f83012
 };
f83012
 
ffa191
 G_DEFINE_TYPE_WITH_PRIVATE (GdmSessionSettings,
ffa191
                             gdm_session_settings,
ffa191
                             G_TYPE_OBJECT)
f83012
 
f83012
 static void
f83012
 gdm_session_settings_class_init (GdmSessionSettingsClass *settings_class)
f83012
 {
f83012
         GObjectClass *object_class;
f83012
 
f83012
         object_class = G_OBJECT_CLASS (settings_class);
f83012
 
f83012
         object_class->finalize = gdm_session_settings_finalize;
f83012
 
f83012
         gdm_session_settings_class_install_properties (settings_class);
f83012
 }
f83012
 
f83012
 static void
f83012
 gdm_session_settings_class_install_properties (GdmSessionSettingsClass *settings_class)
f83012
 {
f83012
         GObjectClass *object_class;
f83012
         GParamSpec   *param_spec;
f83012
 
f83012
         object_class = G_OBJECT_CLASS (settings_class);
f83012
         object_class->set_property = gdm_session_settings_set_property;
f83012
         object_class->get_property = gdm_session_settings_get_property;
f83012
 
f83012
         param_spec = g_param_spec_string ("session-name", "Session Name",
f83012
                                         "The name of the session",
ffa191
                                         NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
f83012
         g_object_class_install_property (object_class, PROP_SESSION_NAME, param_spec);
f83012
 
f83012
+        param_spec = g_param_spec_string ("session-type", "Session Type",
f83012
+                                          "The type of the session",
f83012
+                                          NULL, G_PARAM_READWRITE);
f83012
+        g_object_class_install_property (object_class, PROP_SESSION_TYPE, param_spec);
f83012
+
f83012
         param_spec = g_param_spec_string ("language-name", "Language Name",
f83012
                                         "The name of the language",
f83012
                                         NULL,
ffa191
                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
f83012
         g_object_class_install_property (object_class, PROP_LANGUAGE_NAME, param_spec);
f83012
 
f83012
         param_spec = g_param_spec_boolean ("is-loaded", NULL, NULL,
ffa191
                                            FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
f83012
         g_object_class_install_property (object_class, PROP_IS_LOADED, param_spec);
f83012
 }
f83012
 
f83012
 static void
f83012
 gdm_session_settings_init (GdmSessionSettings *settings)
f83012
 {
f83012
         settings->priv = G_TYPE_INSTANCE_GET_PRIVATE (settings,
f83012
                                                      GDM_TYPE_SESSION_SETTINGS,
f83012
                                                      GdmSessionSettingsPrivate);
f83012
 
f83012
         settings->priv->user_manager = act_user_manager_get_default ();
f83012
 
f83012
 }
f83012
 
f83012
 static void
f83012
 gdm_session_settings_finalize (GObject *object)
f83012
 {
f83012
         GdmSessionSettings *settings;
f83012
         GObjectClass *parent_class;
f83012
 
f83012
         settings = GDM_SESSION_SETTINGS (object);
f83012
 
f83012
@@ -136,172 +143,212 @@ gdm_session_settings_finalize (GObject *object)
f83012
                 parent_class->finalize (object);
f83012
         }
f83012
 }
f83012
 
f83012
 void
f83012
 gdm_session_settings_set_language_name (GdmSessionSettings *settings,
f83012
                                         const char         *language_name)
f83012
 {
f83012
         g_return_if_fail (GDM_IS_SESSION_SETTINGS (settings));
f83012
 
f83012
         if (settings->priv->language_name == NULL ||
f83012
             strcmp (settings->priv->language_name, language_name) != 0) {
f83012
                 settings->priv->language_name = g_strdup (language_name);
f83012
                 g_object_notify (G_OBJECT (settings), "language-name");
f83012
         }
f83012
 }
f83012
 
f83012
 void
f83012
 gdm_session_settings_set_session_name (GdmSessionSettings *settings,
f83012
                                        const char         *session_name)
f83012
 {
f83012
         g_return_if_fail (GDM_IS_SESSION_SETTINGS (settings));
f83012
 
f83012
         if (settings->priv->session_name == NULL ||
f83012
             strcmp (settings->priv->session_name, session_name) != 0) {
f83012
                 settings->priv->session_name = g_strdup (session_name);
f83012
                 g_object_notify (G_OBJECT (settings), "session-name");
f83012
         }
f83012
 }
f83012
 
f83012
+void
f83012
+gdm_session_settings_set_session_type (GdmSessionSettings *settings,
f83012
+                                       const char         *session_type)
f83012
+{
f83012
+        g_return_if_fail (GDM_IS_SESSION_SETTINGS (settings));
f83012
+
f83012
+        if (settings->priv->session_type == NULL ||
f83012
+            g_strcmp0 (settings->priv->session_type, session_type) != 0) {
f83012
+                settings->priv->session_type = g_strdup (session_type);
f83012
+                g_object_notify (G_OBJECT (settings), "session-type");
f83012
+        }
f83012
+}
f83012
+
f83012
 char *
f83012
 gdm_session_settings_get_language_name (GdmSessionSettings *settings)
f83012
 {
f83012
         g_return_val_if_fail (GDM_IS_SESSION_SETTINGS (settings), NULL);
f83012
         return g_strdup (settings->priv->language_name);
f83012
 }
f83012
 
f83012
 char *
f83012
 gdm_session_settings_get_session_name (GdmSessionSettings *settings)
f83012
 {
f83012
         g_return_val_if_fail (GDM_IS_SESSION_SETTINGS (settings), NULL);
f83012
         return g_strdup (settings->priv->session_name);
f83012
 }
f83012
 
f83012
+char *
f83012
+gdm_session_settings_get_session_type (GdmSessionSettings *settings)
f83012
+{
f83012
+        g_return_val_if_fail (GDM_IS_SESSION_SETTINGS (settings), NULL);
f83012
+        return g_strdup (settings->priv->session_type);
f83012
+}
f83012
+
f83012
 static void
f83012
 gdm_session_settings_set_property (GObject      *object,
f83012
                                   guint         prop_id,
f83012
                                   const GValue *value,
f83012
                                   GParamSpec   *pspec)
f83012
 {
f83012
         GdmSessionSettings *settings;
f83012
 
f83012
         settings = GDM_SESSION_SETTINGS (object);
f83012
 
f83012
         switch (prop_id) {
f83012
                 case PROP_LANGUAGE_NAME:
f83012
                         gdm_session_settings_set_language_name (settings, g_value_get_string (value));
f83012
                 break;
f83012
 
f83012
                 case PROP_SESSION_NAME:
f83012
                         gdm_session_settings_set_session_name (settings, g_value_get_string (value));
f83012
                 break;
f83012
 
f83012
+                case PROP_SESSION_TYPE:
f83012
+                        gdm_session_settings_set_session_type (settings, g_value_get_string (value));
f83012
+                break;
f83012
+
f83012
                 default:
f83012
                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
f83012
         }
f83012
 }
f83012
 
f83012
 static void
f83012
 gdm_session_settings_get_property (GObject    *object,
f83012
                                   guint       prop_id,
f83012
                                   GValue     *value,
f83012
                                   GParamSpec *pspec)
f83012
 {
f83012
         GdmSessionSettings *settings;
f83012
 
f83012
         settings = GDM_SESSION_SETTINGS (object);
f83012
 
f83012
         switch (prop_id) {
f83012
                 case PROP_SESSION_NAME:
f83012
                         g_value_set_string (value, settings->priv->session_name);
f83012
                 break;
f83012
 
f83012
+                case PROP_SESSION_TYPE:
f83012
+                        g_value_set_string (value, settings->priv->session_type);
f83012
+                break;
f83012
+
f83012
                 case PROP_LANGUAGE_NAME:
f83012
                         g_value_set_string (value, settings->priv->language_name);
f83012
                 break;
f83012
 
f83012
                 case PROP_IS_LOADED:
f83012
                         g_value_set_boolean (value, gdm_session_settings_is_loaded (settings));
f83012
                 break;
f83012
 
f83012
                 default:
f83012
                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
f83012
     }
f83012
 }
f83012
 
f83012
 GdmSessionSettings *
f83012
 gdm_session_settings_new (void)
f83012
 {
f83012
         GdmSessionSettings *settings;
f83012
 
f83012
         settings = g_object_new (GDM_TYPE_SESSION_SETTINGS,
f83012
                                  NULL);
f83012
 
f83012
         return settings;
f83012
 }
f83012
 
f83012
 gboolean
f83012
 gdm_session_settings_is_loaded (GdmSessionSettings  *settings)
f83012
 {
f83012
         if (settings->priv->user == NULL) {
f83012
                 return FALSE;
f83012
         }
f83012
 
f83012
         return act_user_is_loaded (settings->priv->user);
f83012
 }
f83012
 
f83012
 static void
f83012
 load_settings_from_user (GdmSessionSettings *settings)
f83012
 {
f83012
         const char *session_name;
f83012
+        const char *session_type;
f83012
         const char *language_name;
f83012
 
f83012
         if (!act_user_is_loaded (settings->priv->user)) {
f83012
                 g_warning ("GdmSessionSettings: trying to load user settings from unloaded user");
f83012
                 return;
f83012
         }
f83012
 
f83012
-        session_name = act_user_get_x_session (settings->priv->user);
f83012
-        g_debug ("GdmSessionSettings: saved session is %s", session_name);
3b7bb8
 
3b7bb8
-        if (session_name != NULL) {
18ca79
+
18ca79
+
f83012
+
f83012
+        session_type = act_user_get_session_type (settings->priv->user);
f83012
+        session_name = act_user_get_session (settings->priv->user);
3b7bb8
+
f83012
+        g_debug ("GdmSessionSettings: saved session is %s (type %s)", session_name, session_type);
f83012
+
f83012
+        if (session_type != NULL && session_type[0] != '\0') {
f83012
+                gdm_session_settings_set_session_type (settings, session_type);
f83012
+        }
f83012
+
f83012
+        if (session_name != NULL && session_name[0] != '\0') {
f83012
                 gdm_session_settings_set_session_name (settings, session_name);
f83012
         }
f83012
 
f83012
         language_name = act_user_get_language (settings->priv->user);
f83012
 
f83012
         g_debug ("GdmSessionSettings: saved language is %s", language_name);
f83012
-        if (language_name != NULL) {
f83012
+        if (language_name != NULL && language_name[0] != '\0') {
f83012
                 gdm_session_settings_set_language_name (settings, language_name);
f83012
         }
f83012
 
f83012
+out:
f83012
         g_object_notify (G_OBJECT (settings), "is-loaded");
f83012
 }
f83012
 
f83012
 static void
f83012
 on_user_is_loaded_changed (ActUser            *user,
f83012
                            GParamSpec         *pspec,
f83012
                            GdmSessionSettings *settings)
f83012
 {
f83012
         if (act_user_is_loaded (settings->priv->user)) {
f83012
                 load_settings_from_user (settings);
f83012
                 g_signal_handlers_disconnect_by_func (G_OBJECT (settings->priv->user),
f83012
                                                       G_CALLBACK (on_user_is_loaded_changed),
f83012
                                                       settings);
f83012
         }
f83012
 }
f83012
 
f83012
 gboolean
f83012
 gdm_session_settings_load (GdmSessionSettings  *settings,
f83012
                            const char          *username)
f83012
 {
f83012
         ActUser *old_user;
f83012
 
f83012
         g_return_val_if_fail (settings != NULL, FALSE);
f83012
         g_return_val_if_fail (username != NULL, FALSE);
f83012
         g_return_val_if_fail (!gdm_session_settings_is_loaded (settings), FALSE);
f83012
 
f83012
         if (settings->priv->user != NULL) {
f83012
                 old_user = settings->priv->user;
f83012
 
f83012
                 g_signal_handlers_disconnect_by_func (G_OBJECT (settings->priv->user),
f83012
@@ -322,40 +369,44 @@ gdm_session_settings_load (GdmSessionSettings  *settings,
f83012
                                   G_CALLBACK (on_user_is_loaded_changed),
f83012
                                   settings);
f83012
                 return FALSE;
f83012
         }
f83012
 
f83012
         load_settings_from_user (settings);
f83012
 
f83012
         return TRUE;
f83012
 }
f83012
 
f83012
 gboolean
f83012
 gdm_session_settings_save (GdmSessionSettings  *settings,
f83012
                            const char          *username)
f83012
 {
f83012
         ActUser  *user;
f83012
 
f83012
         g_return_val_if_fail (GDM_IS_SESSION_SETTINGS (settings), FALSE);
f83012
         g_return_val_if_fail (username != NULL, FALSE);
f83012
         g_return_val_if_fail (gdm_session_settings_is_loaded (settings), FALSE);
f83012
 
f83012
         user = act_user_manager_get_user (settings->priv->user_manager,
f83012
                                           username);
f83012
 
f83012
 
f83012
         if (!act_user_is_loaded (user)) {
f83012
                 g_object_unref (user);
f83012
                 return FALSE;
f83012
         }
f83012
 
f83012
         if (settings->priv->session_name != NULL) {
f83012
-                act_user_set_x_session (user, settings->priv->session_name);
f83012
+                act_user_set_session (user, settings->priv->session_name);
f83012
+        }
f83012
+
f83012
+        if (settings->priv->session_type != NULL) {
f83012
+                act_user_set_session_type (user, settings->priv->session_type);
f83012
         }
f83012
 
f83012
         if (settings->priv->language_name != NULL) {
f83012
                 act_user_set_language (user, settings->priv->language_name);
f83012
         }
f83012
         g_object_unref (user);
f83012
 
f83012
         return TRUE;
f83012
 }
f83012
diff --git a/daemon/gdm-session-settings.h b/daemon/gdm-session-settings.h
3b7bb8
index 20946bff..db38ffc7 100644
f83012
--- a/daemon/gdm-session-settings.h
f83012
+++ b/daemon/gdm-session-settings.h
f83012
@@ -33,37 +33,40 @@ G_BEGIN_DECLS
f83012
 #define GDM_IS_SESSION_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDM_TYPE_SESSION_SETTINGS))
f83012
 #define GDM_SESSION_SETTINGS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), GDM_TYPE_SESSION_SETTINGS, GdmSessionSettingsClass))
f83012
 #define GDM_SESSION_SETTINGS_ERROR (gdm_session_settings_error_quark ())
f83012
 typedef struct _GdmSessionSettings GdmSessionSettings;
f83012
 typedef struct _GdmSessionSettingsClass GdmSessionSettingsClass;
f83012
 typedef struct _GdmSessionSettingsPrivate GdmSessionSettingsPrivate;
f83012
 
f83012
 struct _GdmSessionSettings
f83012
 {
f83012
         GObject                   parent;
f83012
 
f83012
         /*< private > */
f83012
         GdmSessionSettingsPrivate *priv;
f83012
 };
f83012
 
f83012
 struct _GdmSessionSettingsClass
f83012
 {
f83012
         GObjectClass        parent_class;
f83012
 };
f83012
 
f83012
 GType               gdm_session_settings_get_type           (void);
f83012
 GdmSessionSettings *gdm_session_settings_new                (void);
f83012
 
f83012
 gboolean            gdm_session_settings_load               (GdmSessionSettings  *settings,
f83012
                                                              const char          *username);
f83012
 gboolean            gdm_session_settings_save               (GdmSessionSettings  *settings,
f83012
                                                              const char          *username);
f83012
 gboolean            gdm_session_settings_is_loaded          (GdmSessionSettings  *settings);
f83012
 char               *gdm_session_settings_get_language_name  (GdmSessionSettings *settings);
f83012
 char               *gdm_session_settings_get_session_name   (GdmSessionSettings *settings);
f83012
+char               *gdm_session_settings_get_session_type   (GdmSessionSettings *settings);
f83012
 void                gdm_session_settings_set_language_name  (GdmSessionSettings *settings,
f83012
                                                              const char         *language_name);
f83012
 void                gdm_session_settings_set_session_name   (GdmSessionSettings *settings,
f83012
                                                              const char         *session_name);
f83012
+void                gdm_session_settings_set_session_type   (GdmSessionSettings *settings,
f83012
+                                                             const char         *session_type);
f83012
 
f83012
 G_END_DECLS
f83012
 #endif /* GDM_SESSION_SETTINGS_H */
f83012
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
3b7bb8
index 88fe36c1..c1201b70 100644
f83012
--- a/daemon/gdm-session-worker.c
f83012
+++ b/daemon/gdm-session-worker.c
ffa191
@@ -2664,60 +2664,74 @@ gdm_session_worker_handle_set_language_name (GdmDBusWorker         *object,
f83012
         gdm_dbus_worker_complete_set_language_name (object, invocation);
f83012
         return TRUE;
f83012
 }
f83012
 
f83012
 static void
f83012
 on_saved_language_name_read (GdmSessionWorker *worker)
f83012
 {
f83012
         char *language_name;
f83012
 
f83012
         language_name = gdm_session_settings_get_language_name (worker->priv->user_settings);
f83012
 
f83012
         g_debug ("GdmSessionWorker: Saved language is %s", language_name);
f83012
         gdm_dbus_worker_emit_saved_language_name_read (GDM_DBUS_WORKER (worker),
f83012
                                                        language_name);
f83012
         g_free (language_name);
f83012
 }
f83012
 
f83012
 static void
f83012
 on_saved_session_name_read (GdmSessionWorker *worker)
f83012
 {
f83012
         char *session_name;
f83012
 
f83012
         session_name = gdm_session_settings_get_session_name (worker->priv->user_settings);
f83012
 
f83012
         g_debug ("GdmSessionWorker: Saved session is %s", session_name);
f83012
         gdm_dbus_worker_emit_saved_session_name_read (GDM_DBUS_WORKER (worker),
f83012
                                                       session_name);
f83012
         g_free (session_name);
f83012
 }
f83012
 
f83012
+static void
f83012
+on_saved_session_type_read (GdmSessionWorker *worker)
f83012
+{
f83012
+        char *session_type;
f83012
+
f83012
+        session_type = gdm_session_settings_get_session_type (worker->priv->user_settings);
f83012
+
f83012
+        g_debug ("GdmSessionWorker: Saved session type is %s", session_type);
f83012
+        gdm_dbus_worker_emit_saved_session_type_read (GDM_DBUS_WORKER (worker),
f83012
+                                                      session_type);
f83012
+        g_free (session_type);
f83012
+}
f83012
+
f83012
+
f83012
 static void
f83012
 do_setup (GdmSessionWorker *worker)
f83012
 {
f83012
         GError  *error;
f83012
         gboolean res;
f83012
 
f83012
         error = NULL;
f83012
         res = gdm_session_worker_initialize_pam (worker,
f83012
                                                  worker->priv->service,
f83012
                                                  (const char **) worker->priv->extensions,
f83012
                                                  worker->priv->username,
f83012
                                                  worker->priv->hostname,
f83012
                                                  worker->priv->display_is_local,
f83012
                                                  worker->priv->x11_display_name,
f83012
                                                  worker->priv->x11_authority_file,
f83012
                                                  worker->priv->display_device,
f83012
                                                  worker->priv->display_seat_id,
f83012
                                                  &error);
f83012
 
f83012
         if (res) {
f83012
                 g_dbus_method_invocation_return_value (worker->priv->pending_invocation, NULL);
f83012
         } else {
f83012
                 g_dbus_method_invocation_take_error (worker->priv->pending_invocation, error);
f83012
         }
f83012
         worker->priv->pending_invocation = NULL;
f83012
 }
f83012
 
f83012
 static void
f83012
 do_authenticate (GdmSessionWorker *worker)
f83012
 {
ffa191
@@ -3127,158 +3141,172 @@ gdm_session_worker_handle_initialize (GdmDBusWorker         *object,
f83012
                 } else if (g_strcmp0 (key, "x11-authority-file") == 0) {
f83012
                         worker->priv->x11_authority_file = g_variant_dup_string (value, NULL);
f83012
                 } else if (g_strcmp0 (key, "console") == 0) {
f83012
                         worker->priv->display_device = g_variant_dup_string (value, NULL);
f83012
                 } else if (g_strcmp0 (key, "seat-id") == 0) {
f83012
                         worker->priv->display_seat_id = g_variant_dup_string (value, NULL);
f83012
                 } else if (g_strcmp0 (key, "hostname") == 0) {
f83012
                         worker->priv->hostname = g_variant_dup_string (value, NULL);
f83012
                 } else if (g_strcmp0 (key, "display-is-local") == 0) {
f83012
                         worker->priv->display_is_local = g_variant_get_boolean (value);
f83012
                 } else if (g_strcmp0 (key, "display-is-initial") == 0) {
f83012
                         worker->priv->display_is_initial = g_variant_get_boolean (value);
f83012
                 }
f83012
         }
f83012
 
f83012
         worker->priv->pending_invocation = invocation;
f83012
 
f83012
         if (!worker->priv->is_program_session) {
f83012
                 worker->priv->user_settings = gdm_session_settings_new ();
f83012
 
f83012
                 g_signal_connect_swapped (worker->priv->user_settings,
f83012
                                           "notify::language-name",
f83012
                                           G_CALLBACK (on_saved_language_name_read),
f83012
                                           worker);
f83012
 
f83012
                 g_signal_connect_swapped (worker->priv->user_settings,
f83012
                                           "notify::session-name",
f83012
                                           G_CALLBACK (on_saved_session_name_read),
f83012
                                           worker);
f83012
 
f83012
+                g_signal_connect_swapped (worker->priv->user_settings,
f83012
+                                          "notify::session-type",
f83012
+                                          G_CALLBACK (on_saved_session_type_read),
f83012
+                                          worker);
f83012
+
f83012
                 if (worker->priv->username) {
f83012
                         wait_for_settings = !gdm_session_settings_load (worker->priv->user_settings,
f83012
                                                                         worker->priv->username);
f83012
                 }
f83012
         }
f83012
 
f83012
         if (wait_for_settings) {
f83012
                 /* Load settings from accounts daemon before continuing
f83012
                  */
f83012
                 g_signal_connect (G_OBJECT (worker->priv->user_settings),
f83012
                                   "notify::is-loaded",
f83012
                                   G_CALLBACK (on_settings_is_loaded_changed),
f83012
                                   worker);
f83012
         } else {
f83012
                 queue_state_change (worker);
f83012
         }
f83012
 
f83012
         return TRUE;
f83012
 }
f83012
 
f83012
 static gboolean
f83012
 gdm_session_worker_handle_setup (GdmDBusWorker         *object,
f83012
                                  GDBusMethodInvocation *invocation,
f83012
                                  const char            *service,
f83012
                                  const char            *x11_display_name,
f83012
                                  const char            *x11_authority_file,
f83012
                                  const char            *console,
f83012
                                  const char            *seat_id,
f83012
                                  const char            *hostname,
f83012
                                  gboolean               display_is_local,
f83012
                                  gboolean               display_is_initial)
f83012
 {
f83012
         GdmSessionWorker *worker = GDM_SESSION_WORKER (object);
f83012
         validate_and_queue_state_change (worker, invocation, GDM_SESSION_WORKER_STATE_SETUP_COMPLETE);
f83012
 
f83012
         worker->priv->service = g_strdup (service);
f83012
         worker->priv->x11_display_name = g_strdup (x11_display_name);
f83012
         worker->priv->x11_authority_file = g_strdup (x11_authority_file);
f83012
         worker->priv->display_device = g_strdup (console);
f83012
         worker->priv->display_seat_id = g_strdup (seat_id);
f83012
         worker->priv->hostname = g_strdup (hostname);
f83012
         worker->priv->display_is_local = display_is_local;
f83012
         worker->priv->display_is_initial = display_is_initial;
f83012
         worker->priv->username = NULL;
f83012
 
f83012
         worker->priv->user_settings = gdm_session_settings_new ();
f83012
 
f83012
         g_signal_connect_swapped (worker->priv->user_settings,
f83012
                                   "notify::language-name",
f83012
                                   G_CALLBACK (on_saved_language_name_read),
f83012
                                   worker);
f83012
 
f83012
         g_signal_connect_swapped (worker->priv->user_settings,
f83012
                                   "notify::session-name",
f83012
                                   G_CALLBACK (on_saved_session_name_read),
f83012
                                   worker);
f83012
+        g_signal_connect_swapped (worker->priv->user_settings,
f83012
+                                  "notify::session-type",
f83012
+                                  G_CALLBACK (on_saved_session_type_read),
f83012
+                                  worker);
f83012
+
f83012
         return TRUE;
f83012
 }
f83012
 
f83012
 static gboolean
f83012
 gdm_session_worker_handle_setup_for_user (GdmDBusWorker         *object,
f83012
                                           GDBusMethodInvocation *invocation,
f83012
                                           const char            *service,
f83012
                                           const char            *username,
f83012
                                           const char            *x11_display_name,
f83012
                                           const char            *x11_authority_file,
f83012
                                           const char            *console,
f83012
                                           const char            *seat_id,
f83012
                                           const char            *hostname,
f83012
                                           gboolean               display_is_local,
f83012
                                           gboolean               display_is_initial)
f83012
 {
f83012
         GdmSessionWorker *worker = GDM_SESSION_WORKER (object);
f83012
 
f83012
         if (!validate_state_change (worker, invocation, GDM_SESSION_WORKER_STATE_SETUP_COMPLETE))
f83012
                 return TRUE;
f83012
 
f83012
         worker->priv->service = g_strdup (service);
f83012
         worker->priv->x11_display_name = g_strdup (x11_display_name);
f83012
         worker->priv->x11_authority_file = g_strdup (x11_authority_file);
f83012
         worker->priv->display_device = g_strdup (console);
f83012
         worker->priv->display_seat_id = g_strdup (seat_id);
f83012
         worker->priv->hostname = g_strdup (hostname);
f83012
         worker->priv->display_is_local = display_is_local;
f83012
         worker->priv->display_is_initial = display_is_initial;
f83012
         worker->priv->username = g_strdup (username);
f83012
 
f83012
         worker->priv->user_settings = gdm_session_settings_new ();
f83012
 
f83012
         g_signal_connect_swapped (worker->priv->user_settings,
f83012
                                   "notify::language-name",
f83012
                                   G_CALLBACK (on_saved_language_name_read),
f83012
                                   worker);
f83012
 
f83012
         g_signal_connect_swapped (worker->priv->user_settings,
f83012
                                   "notify::session-name",
f83012
                                   G_CALLBACK (on_saved_session_name_read),
f83012
                                   worker);
f83012
+        g_signal_connect_swapped (worker->priv->user_settings,
f83012
+                                  "notify::session-type",
f83012
+                                  G_CALLBACK (on_saved_session_type_read),
f83012
+                                  worker);
f83012
 
f83012
         /* Load settings from accounts daemon before continuing
f83012
          */
f83012
         worker->priv->pending_invocation = invocation;
f83012
         if (gdm_session_settings_load (worker->priv->user_settings, username)) {
f83012
                 queue_state_change (worker);
f83012
         } else {
f83012
                 g_signal_connect (G_OBJECT (worker->priv->user_settings),
f83012
                                   "notify::is-loaded",
f83012
                                   G_CALLBACK (on_settings_is_loaded_changed),
f83012
                                   worker);
f83012
         }
f83012
 
f83012
         return TRUE;
f83012
 }
f83012
 
f83012
 static gboolean
f83012
 gdm_session_worker_handle_setup_for_program (GdmDBusWorker         *object,
f83012
                                              GDBusMethodInvocation *invocation,
f83012
                                              const char            *service,
f83012
                                              const char            *username,
f83012
                                              const char            *x11_display_name,
f83012
                                              const char            *x11_authority_file,
f83012
                                              const char            *console,
f83012
                                              const char            *seat_id,
f83012
                                              const char            *hostname,
f83012
                                              gboolean               display_is_local,
f83012
                                              gboolean               display_is_initial,
f83012
                                              const char            *log_file)
f83012
 {
f83012
diff --git a/daemon/gdm-session-worker.xml b/daemon/gdm-session-worker.xml
3b7bb8
index 4280fe09..a215779c 100644
f83012
--- a/daemon/gdm-session-worker.xml
f83012
+++ b/daemon/gdm-session-worker.xml
f83012
@@ -51,40 +51,43 @@
f83012
     <method name="SetupForProgram">
f83012
       <arg name="service_name" direction="in" type="s"/>
f83012
       <arg name="user_name" direction="in" type="s"/>
f83012
       <arg name="x11_display_name" direction="in" type="s"/>
f83012
       <arg name="x11_authority_file" direction="in" type="s"/>
f83012
       <arg name="display_device" direction="in" type="s"/>
f83012
       <arg name="display_seat" direction="in" type="s"/>
f83012
       <arg name="hostname" direction="in" type="s"/>
f83012
       <arg name="display_is_local" direction="in" type="b"/>
f83012
       <arg name="display_is_initial" direction="in" type="b"/>
f83012
       <arg name="log_file" direction="in" type="s"/>
f83012
     </method>
f83012
     <method name="StartReauthentication">
f83012
       <arg name="pid_of_caller" direction="in" type="i"/>
f83012
       <arg name="uid_of_caller" direction="in" type="i"/>
f83012
       <arg name="address" direction="out" type="s"/>
f83012
     </method>
f83012
 
f83012
     <signal name="SessionExited">
f83012
       <arg name="service_name" type="s" />
f83012
       
f83012
            signal. Use macros in sys/wait.h to handle it. -->
f83012
       <arg name="status" type="i" />
f83012
     </signal>
f83012
     <signal name="SavedLanguageNameRead">
f83012
       <arg name="language_name" type="s"/>
f83012
     </signal>
f83012
     <signal name="SavedSessionNameRead">
f83012
       <arg name="session_name" type="s"/>
f83012
     </signal>
f83012
+    <signal name="SavedSessionTypeRead">
f83012
+      <arg name="session_type" type="s"/>
f83012
+    </signal>
f83012
     <signal name="UsernameChanged">
f83012
       <arg name="new_username" type="s"/>
f83012
     </signal>
f83012
     <signal name="Reauthenticated">
f83012
       <arg name="service_name" type="s"/>
f83012
     </signal>
f83012
     <signal name="CancelPendingQuery">
f83012
     </signal>
f83012
   </interface>
f83012
 </node>
f83012
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
3b7bb8
index 29459346..43da024f 100644
f83012
--- a/daemon/gdm-session.c
f83012
+++ b/daemon/gdm-session.c
ffa191
@@ -61,60 +61,61 @@
f83012
 #define GDM_SESSION_DBUS_OBJECT_PATH "/org/gnome/DisplayManager/Session"
f83012
 
f83012
 #define GDM_WORKER_DBUS_PATH "/org/gnome/DisplayManager/Worker"
f83012
 
f83012
 typedef struct
f83012
 {
f83012
         GdmSession            *session;
f83012
         GdmSessionWorkerJob   *job;
f83012
         GPid                   worker_pid;
f83012
         char                  *service_name;
f83012
         GDBusMethodInvocation *starting_invocation;
f83012
         char                  *starting_username;
f83012
         GDBusMethodInvocation *pending_invocation;
f83012
         GdmDBusWorkerManager  *worker_manager_interface;
f83012
         GdmDBusWorker         *worker_proxy;
f83012
         GCancellable          *worker_cancellable;
f83012
         char                  *session_id;
f83012
         guint32                is_stopping : 1;
f83012
 
f83012
         GPid                   reauth_pid_of_caller;
f83012
 } GdmSessionConversation;
f83012
 
ffa191
 struct _GdmSession
f83012
 {
ffa191
         GObject              parent;
ffa191
 
f83012
         /* per open scope */
f83012
         char                *selected_program;
f83012
         char                *selected_session;
f83012
         char                *saved_session;
f83012
+        char                *saved_session_type;
f83012
         char                *saved_language;
f83012
         char                *selected_user;
f83012
         char                *user_x11_authority_file;
f83012
 
f83012
         char                *timed_login_username;
f83012
         int                  timed_login_delay;
f83012
         GList               *pending_timed_login_invocations;
f83012
 
f83012
         GHashTable          *conversations;
f83012
 
f83012
         GdmSessionConversation *session_conversation;
f83012
 
f83012
         char                 **conversation_environment;
f83012
 
f83012
         GdmDBusUserVerifier   *user_verifier_interface;
f83012
         GHashTable            *user_verifier_extensions;
f83012
         GdmDBusGreeter        *greeter_interface;
f83012
         GdmDBusRemoteGreeter  *remote_greeter_interface;
f83012
         GdmDBusChooser        *chooser_interface;
f83012
 
f83012
         GList               *pending_worker_connections;
f83012
         GList               *outside_connections;
f83012
 
f83012
         GPid                 session_pid;
f83012
 
f83012
         /* object lifetime scope */
f83012
         char                *session_type;
f83012
         char                *display_name;
f83012
         char                *display_hostname;
f83012
         char                *display_device;
18ca79
@@ -328,309 +329,325 @@ on_establish_credentials_cb (GdmDBusWorker *proxy,
f83012
                 case GDM_SESSION_VERIFICATION_MODE_REAUTHENTICATE:
18ca79
                         if (self->user_verifier_interface != NULL) {
18ca79
                                 gdm_dbus_user_verifier_emit_verification_complete (self->user_verifier_interface,
18ca79
                                                                                    service_name);
18ca79
                                 g_signal_emit (self, signals[VERIFICATION_COMPLETE], 0, service_name);
18ca79
                         }
18ca79
                         break;
f83012
                 default:
f83012
                         break;
f83012
                 }
f83012
         } else {
f83012
                 report_and_stop_conversation (self, service_name, error);
f83012
         }
f83012
 
f83012
         g_free (service_name);
f83012
         g_object_unref (self);
f83012
 }
f83012
 
18ca79
 static gboolean
18ca79
 supports_session_type (GdmSession *self,
18ca79
                        const char *session_type)
18ca79
 {
18ca79
         if (session_type == NULL)
18ca79
                 return TRUE;
18ca79
 
18ca79
         return g_strv_contains ((const char * const *) self->supported_session_types,
18ca79
                                 session_type);
18ca79
 }
18ca79
 
f83012
 static char **
f83012
-get_system_session_dirs (GdmSession *self)
f83012
+get_system_session_dirs (GdmSession *self,
f83012
+                         const char *type)
f83012
 {
f83012
         GArray *search_array = NULL;
f83012
         char **search_dirs;
18ca79
         int i, j;
ffa191
         const gchar * const *system_data_dirs = g_get_system_data_dirs ();
f83012
 
f83012
         static const char *x_search_dirs[] = {
f83012
                 "/etc/X11/sessions/",
f83012
                 DMCONFDIR "/Sessions/",
f83012
                 DATADIR "/gdm/BuiltInSessions/",
f83012
                 DATADIR "/xsessions/",
f83012
         };
f83012
 
f83012
         static const char *wayland_search_dir = DATADIR "/wayland-sessions/";
f83012
 
f83012
         search_array = g_array_new (TRUE, TRUE, sizeof (char *));
f83012
 
18ca79
         for (j = 0; self->supported_session_types[j] != NULL; j++) {
18ca79
                 const char *supported_type = self->supported_session_types[j];
ffa191
 
18ca79
-                if (g_str_equal (supported_type, "x11")) {
18ca79
+                if (g_str_equal (supported_type, "x11") ||
18ca79
+                    (type == NULL || g_str_equal (type, supported_type))) {
18ca79
                         for (i = 0; system_data_dirs[i]; i++) {
18ca79
                                 gchar *dir = g_build_filename (system_data_dirs[i], "xsessions", NULL);
18ca79
                                 g_array_append_val (search_array, dir);
18ca79
                         }
f83012
 
18ca79
                         g_array_append_vals (search_array, x_search_dirs, G_N_ELEMENTS (x_search_dirs));
ffa191
                 }
ffa191
 
18ca79
 #ifdef ENABLE_WAYLAND_SUPPORT
18ca79
-                if (g_str_equal (supported_type, "wayland")) {
18ca79
+                if (g_str_equal (supported_type, "wayland") ||
18ca79
+                    (type == NULL || g_str_equal (type, supported_type))) {
18ca79
                         for (i = 0; system_data_dirs[i]; i++) {
18ca79
                                 gchar *dir = g_build_filename (system_data_dirs[i], "wayland-sessions", NULL);
18ca79
                                 g_array_append_val (search_array, dir);
18ca79
                         }
18ca79
 
18ca79
                         g_array_append_val (search_array, wayland_search_dir);
18ca79
                 }
f83012
 #endif
f83012
         }
f83012
 
f83012
         search_dirs = g_strdupv ((char **) search_array->data);
f83012
 
f83012
         g_array_free (search_array, TRUE);
f83012
 
f83012
         return search_dirs;
f83012
 }
f83012
 
f83012
 static gboolean
f83012
 is_prog_in_path (const char *prog)
f83012
 {
f83012
         char    *f;
f83012
         gboolean ret;
f83012
 
f83012
         f = g_find_program_in_path (prog);
f83012
         ret = (f != NULL);
f83012
         g_free (f);
f83012
         return ret;
f83012
 }
f83012
 
f83012
 static GKeyFile *
f83012
 load_key_file_for_file (GdmSession   *self,
f83012
                         const char   *file,
f83012
+                        const char   *type,
f83012
                         char        **full_path)
f83012
 {
f83012
         GKeyFile   *key_file;
f83012
-        GError     *error;
f83012
+        GError     *error = NULL;
f83012
         gboolean    res;
f83012
         char      **search_dirs;
f83012
 
f83012
         key_file = g_key_file_new ();
f83012
 
f83012
-        search_dirs = get_system_session_dirs (self),
f83012
+        search_dirs = get_system_session_dirs (self, type);
f83012
+
f83012
         error = NULL;
f83012
         res = g_key_file_load_from_dirs (key_file,
f83012
                                          file,
f83012
                                          (const char **) search_dirs,
f83012
                                          full_path,
f83012
                                          G_KEY_FILE_NONE,
f83012
                                          &error);
f83012
         if (! res) {
f83012
-                g_debug ("GdmSession: File '%s' not found: %s", file, error->message);
f83012
-                g_error_free (error);
f83012
+                g_debug ("GdmSession: File '%s' not found in search dirs", file);
f83012
+                if (error != NULL) {
f83012
+                        g_debug ("GdmSession: %s", error->message);
f83012
+                        g_error_free (error);
f83012
+                }
f83012
                 g_key_file_free (key_file);
f83012
                 key_file = NULL;
f83012
         }
f83012
 
f83012
         g_strfreev (search_dirs);
f83012
 
f83012
         return key_file;
f83012
 }
f83012
 
f83012
 static gboolean
f83012
 get_session_command_for_file (GdmSession  *self,
f83012
                               const char  *file,
f83012
+                              const char  *type,
f83012
                               char       **command)
f83012
 {
f83012
         GKeyFile   *key_file;
f83012
         GError     *error;
f83012
         char       *exec;
f83012
         gboolean    ret;
f83012
         gboolean    res;
f83012
 
f83012
         exec = NULL;
f83012
         ret = FALSE;
f83012
         if (command != NULL) {
f83012
                 *command = NULL;
f83012
         }
f83012
 
18ca79
+        if (!supports_session_type (self, type)) {
18ca79
+                g_debug ("GdmSession: ignoring %s session command request for file '%s'",
18ca79
+                         type, file);
f83012
+                goto out;
f83012
+        }
f83012
+
f83012
         g_debug ("GdmSession: getting session command for file '%s'", file);
f83012
-        key_file = load_key_file_for_file (self, file, NULL);
f83012
+        key_file = load_key_file_for_file (self, file, type, NULL);
f83012
         if (key_file == NULL) {
f83012
                 goto out;
f83012
         }
f83012
 
f83012
         error = NULL;
f83012
         res = g_key_file_get_boolean (key_file,
f83012
                                       G_KEY_FILE_DESKTOP_GROUP,
f83012
                                       G_KEY_FILE_DESKTOP_KEY_HIDDEN,
f83012
                                       &error);
f83012
         if (error == NULL && res) {
f83012
                 g_debug ("GdmSession: Session %s is marked as hidden", file);
f83012
                 goto out;
f83012
         }
f83012
 
f83012
         exec = g_key_file_get_string (key_file,
f83012
                                       G_KEY_FILE_DESKTOP_GROUP,
f83012
                                       G_KEY_FILE_DESKTOP_KEY_TRY_EXEC,
f83012
                                       NULL);
f83012
         if (exec != NULL) {
f83012
                 res = is_prog_in_path (exec);
f83012
                 g_free (exec);
f83012
                 exec = NULL;
f83012
 
f83012
                 if (! res) {
f83012
                         g_debug ("GdmSession: Command not found: %s",
f83012
                                  G_KEY_FILE_DESKTOP_KEY_TRY_EXEC);
f83012
                         goto out;
f83012
                 }
f83012
         }
f83012
 
f83012
         error = NULL;
f83012
         exec = g_key_file_get_string (key_file,
f83012
                                       G_KEY_FILE_DESKTOP_GROUP,
f83012
                                       G_KEY_FILE_DESKTOP_KEY_EXEC,
f83012
                                       &error);
f83012
         if (error != NULL) {
f83012
                 g_debug ("GdmSession: %s key not found: %s",
f83012
                          G_KEY_FILE_DESKTOP_KEY_EXEC,
f83012
                          error->message);
f83012
                 g_error_free (error);
f83012
                 goto out;
f83012
         }
f83012
 
f83012
         if (command != NULL) {
f83012
                 *command = g_strdup (exec);
f83012
         }
f83012
         ret = TRUE;
f83012
 
f83012
 out:
f83012
         g_free (exec);
f83012
 
f83012
         return ret;
f83012
 }
f83012
 
f83012
 static gboolean
f83012
 get_session_command_for_name (GdmSession  *self,
f83012
                               const char  *name,
f83012
+                              const char  *type,
f83012
                               char       **command)
f83012
 {
f83012
         gboolean res;
f83012
         char    *filename;
f83012
 
f83012
         filename = g_strdup_printf ("%s.desktop", name);
f83012
-        res = get_session_command_for_file (self, filename, command);
f83012
+        res = get_session_command_for_file (self, filename, type, command);
f83012
         g_free (filename);
f83012
 
f83012
         return res;
f83012
 }
f83012
 
f83012
 static const char *
f83012
 get_default_language_name (GdmSession *self)
f83012
 {
f83012
     const char *default_language;
f83012
 
ffa191
     if (self->saved_language != NULL) {
ffa191
             return self->saved_language;
f83012
     }
f83012
 
ffa191
     default_language = g_hash_table_lookup (self->environment,
f83012
                                             "LANG");
f83012
 
f83012
     if (default_language != NULL) {
f83012
             return default_language;
f83012
     }
f83012
 
f83012
     return setlocale (LC_MESSAGES, NULL);
f83012
 }
f83012
 
f83012
 static const char *
f83012
 get_fallback_session_name (GdmSession *self)
f83012
 {
f83012
         char          **search_dirs;
f83012
         int             i;
f83012
         char           *name;
f83012
         GSequence      *sessions;
f83012
         GSequenceIter  *session;
f83012
 
ffa191
         if (self->fallback_session_name != NULL) {
f83012
                 /* verify that the cached version still exists */
ffa191
-                if (get_session_command_for_name (self, self->fallback_session_name, NULL)) {
ffa191
+                if (get_session_command_for_name (self, self->fallback_session_name, NULL, NULL)) {
f83012
                         goto out;
f83012
                 }
f83012
         }
f83012
 
f83012
         name = g_strdup ("gnome");
f83012
-        if (get_session_command_for_name (self, name, NULL)) {
f83012
+        if (get_session_command_for_name (self, name, NULL, NULL)) {
ffa191
                 g_free (self->fallback_session_name);
ffa191
                 self->fallback_session_name = name;
f83012
                 goto out;
f83012
         }
f83012
         g_free (name);
f83012
 
f83012
         sessions = g_sequence_new (g_free);
f83012
 
f83012
-        search_dirs = get_system_session_dirs (self);
f83012
+        search_dirs = get_system_session_dirs (self, NULL);
f83012
         for (i = 0; search_dirs[i] != NULL; i++) {
f83012
                 GDir       *dir;
f83012
                 const char *base_name;
f83012
 
f83012
                 dir = g_dir_open (search_dirs[i], 0, NULL);
f83012
 
f83012
                 if (dir == NULL) {
f83012
                         continue;
f83012
                 }
f83012
 
f83012
                 do {
f83012
                         base_name = g_dir_read_name (dir);
f83012
 
f83012
                         if (base_name == NULL) {
f83012
                                 break;
f83012
                         }
f83012
 
f83012
                         if (!g_str_has_suffix (base_name, ".desktop")) {
f83012
                                 continue;
f83012
                         }
f83012
 
f83012
-                        if (get_session_command_for_file (self, base_name, NULL)) {
f83012
+                        if (get_session_command_for_file (self, base_name, NULL, NULL)) {
f83012
                                 name = g_strndup (base_name, strlen (base_name) - strlen (".desktop"));
f83012
                                 g_sequence_insert_sorted (sessions, name, (GCompareDataFunc) g_strcmp0, NULL);
f83012
                         }
f83012
                 } while (base_name != NULL);
f83012
 
f83012
                 g_dir_close (dir);
f83012
         }
f83012
         g_strfreev (search_dirs);
f83012
 
f83012
         name = NULL;
f83012
         session = g_sequence_get_begin_iter (sessions);
f83012
 
f83012
         if (g_sequence_iter_is_end (session))
f83012
                 g_error ("GdmSession: no session desktop files installed, aborting...");
f83012
 
f83012
         do {
f83012
                name = g_sequence_get (session);
f83012
                if (name) {
f83012
                        break;
f83012
                }
f83012
                session = g_sequence_iter_next (session);
f83012
         } while (!g_sequence_iter_is_end (session));
f83012
 
ffa191
         g_free (self->fallback_session_name);
ffa191
         self->fallback_session_name = g_strdup (name);
f83012
 
f83012
         g_sequence_free (sessions);
f83012
 
f83012
  out:
ffa191
         return self->fallback_session_name;
18ca79
@@ -649,60 +666,63 @@ get_default_session_name (GdmSession *self)
f83012
 static void
f83012
 gdm_session_defaults_changed (GdmSession *self)
f83012
 {
f83012
 
f83012
         update_session_type (self);
f83012
 
ffa191
         if (self->greeter_interface != NULL) {
ffa191
                 gdm_dbus_greeter_emit_default_language_name_changed (self->greeter_interface,
f83012
                                                                      get_default_language_name (self));
ffa191
                 gdm_dbus_greeter_emit_default_session_name_changed (self->greeter_interface,
f83012
                                                                     get_default_session_name (self));
f83012
         }
f83012
 }
f83012
 
f83012
 void
f83012
 gdm_session_select_user (GdmSession *self,
f83012
                          const char *text)
f83012
 {
f83012
 
ffa191
         g_debug ("GdmSession: selecting user '%s' for session '%s' (%p)",
ffa191
                  text,
ffa191
                  gdm_session_get_session_id (self),
ffa191
                  self);
f83012
 
ffa191
         g_free (self->selected_user);
ffa191
         self->selected_user = g_strdup (text);
f83012
 
ffa191
         g_free (self->saved_session);
ffa191
         self->saved_session = NULL;
f83012
 
ffa191
+        g_free (self->saved_session_type);
ffa191
+        self->saved_session_type = NULL;
f83012
+
ffa191
         g_free (self->saved_language);
ffa191
         self->saved_language = NULL;
f83012
 }
f83012
 
f83012
 static void
f83012
 cancel_pending_query (GdmSessionConversation *conversation)
f83012
 {
f83012
         if (conversation->pending_invocation == NULL) {
f83012
                 return;
f83012
         }
f83012
 
f83012
         g_debug ("GdmSession: Cancelling pending query");
f83012
 
f83012
         g_dbus_method_invocation_return_dbus_error (conversation->pending_invocation,
f83012
                                                     GDM_SESSION_DBUS_ERROR_CANCEL,
f83012
                                                     "Operation cancelled");
f83012
         conversation->pending_invocation = NULL;
f83012
 }
f83012
 
f83012
 static void
f83012
 answer_pending_query (GdmSessionConversation *conversation,
f83012
                       const char             *answer)
f83012
 {
f83012
         g_dbus_method_invocation_return_value (conversation->pending_invocation,
f83012
                                                g_variant_new ("(s)", answer));
f83012
         conversation->pending_invocation = NULL;
f83012
 }
f83012
 
f83012
 static void
f83012
 set_pending_query (GdmSessionConversation *conversation,
3b7bb8
@@ -969,83 +989,94 @@ worker_on_reauthenticated (GdmDBusWorker          *worker,
f83012
         GdmSession *self = conversation->session;
f83012
         g_debug ("GdmSession: Emitting 'reauthenticated' signal ");
f83012
         g_signal_emit (self, signals[REAUTHENTICATED], 0, service_name);
f83012
 }
f83012
 
f83012
 static void
f83012
 worker_on_saved_language_name_read (GdmDBusWorker          *worker,
f83012
                                     const char             *language_name,
f83012
                                     GdmSessionConversation *conversation)
f83012
 {
f83012
         GdmSession *self = conversation->session;
f83012
 
f83012
         if (strlen (language_name) > 0) {
ffa191
                 g_free (self->saved_language);
ffa191
                 self->saved_language = g_strdup (language_name);
f83012
 
ffa191
                 if (self->greeter_interface != NULL) {
ffa191
                         gdm_dbus_greeter_emit_default_language_name_changed (self->greeter_interface,
f83012
                                                                              language_name);
f83012
                 }
f83012
         }
f83012
 }
f83012
 
f83012
 static void
f83012
 worker_on_saved_session_name_read (GdmDBusWorker          *worker,
f83012
                                    const char             *session_name,
f83012
                                    GdmSessionConversation *conversation)
f83012
 {
f83012
         GdmSession *self = conversation->session;
f83012
 
f83012
-        if (! get_session_command_for_name (self, session_name, NULL)) {
ffa191
+        if (! get_session_command_for_name (self, session_name, self->saved_session_type, NULL)) {
f83012
                 /* ignore sessions that don't exist */
f83012
                 g_debug ("GdmSession: not using invalid .dmrc session: %s", session_name);
ffa191
                 g_free (self->saved_session);
ffa191
                 self->saved_session = NULL;
3b7bb8
                 update_session_type (self);
3b7bb8
         } else {
3b7bb8
                 if (strcmp (session_name,
3b7bb8
                             get_default_session_name (self)) != 0) {
3b7bb8
                         g_free (self->saved_session);
3b7bb8
                         self->saved_session = g_strdup (session_name);
3b7bb8
 
3b7bb8
                         if (self->greeter_interface != NULL) {
3b7bb8
                                 gdm_dbus_greeter_emit_default_session_name_changed (self->greeter_interface,
3b7bb8
                                                                                     session_name);
3b7bb8
                         }
f83012
                 }
3b7bb8
                 if (self->saved_session_type != NULL)
3b7bb8
                         set_session_type (self, self->saved_session_type);
f83012
         }
f83012
 
f83012
 }
f83012
 
f83012
+static void
f83012
+worker_on_saved_session_type_read (GdmDBusWorker          *worker,
f83012
+                                   const char             *session_type,
f83012
+                                   GdmSessionConversation *conversation)
f83012
+{
f83012
+        GdmSession *self = conversation->session;
f83012
+
ffa191
+        g_free (self->saved_session_type);
ffa191
+        self->saved_session_type = g_strdup (session_type);
f83012
+}
f83012
+
f83012
 static GdmSessionConversation *
f83012
 find_conversation_by_pid (GdmSession *self,
f83012
                           GPid        pid)
f83012
 {
f83012
         GHashTableIter iter;
f83012
         gpointer key, value;
f83012
 
ffa191
         g_hash_table_iter_init (&iter, self->conversations);
f83012
         while (g_hash_table_iter_next (&iter, &key, &value)) {
f83012
                 GdmSessionConversation *conversation;
f83012
 
f83012
                 conversation = (GdmSessionConversation *) value;
f83012
 
f83012
                 if (conversation->worker_pid == pid) {
f83012
                         return conversation;
f83012
                 }
f83012
         }
f83012
 
f83012
         return NULL;
f83012
 }
f83012
 
f83012
 static gboolean
f83012
 allow_worker_function (GDBusAuthObserver *observer,
f83012
                        GIOStream         *stream,
f83012
                        GCredentials      *credentials,
f83012
                        GdmSession        *self)
f83012
 {
f83012
         uid_t connecting_user;
f83012
 
f83012
         connecting_user = g_credentials_get_unix_user (credentials, NULL);
3b7bb8
@@ -1125,60 +1156,63 @@ register_worker (GdmDBusWorkerManager  *worker_manager_interface,
f83012
         g_dbus_method_invocation_return_value (invocation, NULL);
f83012
 
f83012
         conversation->worker_proxy = gdm_dbus_worker_proxy_new_sync (connection,
f83012
                                                                      G_DBUS_PROXY_FLAGS_NONE,
f83012
                                                                      NULL,
f83012
                                                                      GDM_WORKER_DBUS_PATH,
f83012
                                                                      NULL, NULL);
f83012
         /* drop the reference we stole from the pending connections list
f83012
          * since the proxy owns the connection now */
f83012
         g_object_unref (connection);
f83012
 
f83012
         g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (conversation->worker_proxy), G_MAXINT);
f83012
 
f83012
         conversation->worker_cancellable = g_cancellable_new ();
f83012
 
f83012
         g_signal_connect (conversation->worker_proxy,
f83012
                           "username-changed",
f83012
                           G_CALLBACK (worker_on_username_changed), conversation);
f83012
         g_signal_connect (conversation->worker_proxy,
f83012
                           "session-exited",
f83012
                           G_CALLBACK (worker_on_session_exited), conversation);
f83012
         g_signal_connect (conversation->worker_proxy,
f83012
                           "reauthenticated",
f83012
                           G_CALLBACK (worker_on_reauthenticated), conversation);
f83012
         g_signal_connect (conversation->worker_proxy,
f83012
                           "saved-language-name-read",
f83012
                           G_CALLBACK (worker_on_saved_language_name_read), conversation);
f83012
         g_signal_connect (conversation->worker_proxy,
f83012
                           "saved-session-name-read",
f83012
                           G_CALLBACK (worker_on_saved_session_name_read), conversation);
f83012
+        g_signal_connect (conversation->worker_proxy,
f83012
+                          "saved-session-type-read",
f83012
+                          G_CALLBACK (worker_on_saved_session_type_read), conversation);
f83012
         g_signal_connect (conversation->worker_proxy,
f83012
                           "cancel-pending-query",
f83012
                           G_CALLBACK (worker_on_cancel_pending_query), conversation);
f83012
 
f83012
         conversation->worker_manager_interface = g_object_ref (worker_manager_interface);
f83012
         g_debug ("GdmSession: worker connection is %p", connection);
f83012
 
f83012
         g_debug ("GdmSession: Emitting conversation-started signal");
f83012
         g_signal_emit (self, signals[CONVERSATION_STARTED], 0, conversation->service_name);
f83012
 
ffa191
         if (self->user_verifier_interface != NULL) {
ffa191
                 gdm_dbus_user_verifier_emit_conversation_started (self->user_verifier_interface,
f83012
                                                                   conversation->service_name);
f83012
         }
f83012
 
f83012
         if (conversation->starting_invocation != NULL) {
f83012
                 if (conversation->starting_username != NULL) {
f83012
                         gdm_session_setup_for_user (self, conversation->service_name, conversation->starting_username);
f83012
 
f83012
                         g_clear_pointer (&conversation->starting_username,
f83012
                                          (GDestroyNotify)
f83012
                                          g_free);
f83012
                 } else {
f83012
                         gdm_session_setup (self, conversation->service_name);
f83012
                 }
f83012
         }
f83012
 
f83012
         g_debug ("GdmSession: Conversation started");
f83012
 
f83012
         return TRUE;
3b7bb8
@@ -1921,60 +1955,63 @@ free_conversation (GdmSessionConversation *conversation)
ffa191
         close_conversation (conversation);
ffa191
 
f83012
         if (conversation->job != NULL) {
f83012
                 g_warning ("Freeing conversation '%s' with active job", conversation->service_name);
f83012
         }
f83012
 
f83012
         g_free (conversation->service_name);
f83012
         g_free (conversation->starting_username);
f83012
         g_free (conversation->session_id);
f83012
         g_clear_object (&conversation->worker_manager_interface);
f83012
 
f83012
         g_cancellable_cancel (conversation->worker_cancellable);
f83012
         g_clear_object (&conversation->worker_cancellable);
f83012
 
f83012
         if (conversation->worker_proxy != NULL) {
f83012
                 g_signal_handlers_disconnect_by_func (conversation->worker_proxy,
f83012
                                                       G_CALLBACK (worker_on_username_changed),
f83012
                                                       conversation);
f83012
                 g_signal_handlers_disconnect_by_func (conversation->worker_proxy,
f83012
                                                       G_CALLBACK (worker_on_session_exited),
f83012
                                                       conversation);
f83012
                 g_signal_handlers_disconnect_by_func (conversation->worker_proxy,
f83012
                                                       G_CALLBACK (worker_on_reauthenticated),
f83012
                                                       conversation);
f83012
                 g_signal_handlers_disconnect_by_func (conversation->worker_proxy,
f83012
                                                       G_CALLBACK (worker_on_saved_language_name_read),
f83012
                                                       conversation);
f83012
                 g_signal_handlers_disconnect_by_func (conversation->worker_proxy,
f83012
                                                       G_CALLBACK (worker_on_saved_session_name_read),
f83012
                                                       conversation);
f83012
+                g_signal_handlers_disconnect_by_func (conversation->worker_proxy,
f83012
+                                                      G_CALLBACK (worker_on_saved_session_type_read),
f83012
+                                                      conversation);
f83012
                 g_signal_handlers_disconnect_by_func (conversation->worker_proxy,
f83012
                                                       G_CALLBACK (worker_on_cancel_pending_query),
f83012
                                                       conversation);
f83012
                 g_clear_object (&conversation->worker_proxy);
f83012
         }
f83012
         g_clear_object (&conversation->session);
f83012
         g_free (conversation);
f83012
 }
f83012
 
f83012
 static void
f83012
 load_lang_config_file (GdmSession *self)
f83012
 {
f83012
         static const char *config_file = LANG_CONFIG_FILE;
f83012
         gchar         *contents = NULL;
f83012
         gchar         *p;
f83012
         gchar         *key;
f83012
         gchar         *value;
f83012
         gsize          length;
f83012
         GError        *error;
f83012
         GString       *line;
f83012
         GRegex        *re;
f83012
 
f83012
         if (!g_file_test (config_file, G_FILE_TEST_EXISTS)) {
f83012
                 g_debug ("Cannot access '%s'", config_file);
f83012
                 return;
f83012
         }
f83012
 
f83012
         error = NULL;
f83012
         if (!g_file_get_contents (config_file, &contents, &length, &error)) {
f83012
                 g_debug ("Failed to parse '%s': %s",
3b7bb8
@@ -2533,83 +2570,83 @@ gdm_session_send_environment (GdmSession *self,
f83012
         g_return_if_fail (GDM_IS_SESSION (self));
f83012
 
f83012
         conversation = find_conversation_by_name (self, service_name);
f83012
         if (conversation != NULL) {
f83012
                 send_environment (self, conversation);
f83012
         }
f83012
 }
f83012
 
f83012
 static const char *
f83012
 get_session_name (GdmSession *self)
f83012
 {
f83012
         /* FIXME: test the session names before we use them? */
f83012
 
ffa191
         if (self->selected_session != NULL) {
ffa191
                 return self->selected_session;
f83012
         }
f83012
 
f83012
         return get_default_session_name (self);
f83012
 }
f83012
 
f83012
 static char *
f83012
 get_session_command (GdmSession *self)
f83012
 {
f83012
         gboolean    res;
f83012
         char       *command;
f83012
         const char *session_name;
f83012
 
f83012
         session_name = get_session_name (self);
f83012
 
f83012
         command = NULL;
f83012
-        res = get_session_command_for_name (self, session_name, &command);
f83012
+        res = get_session_command_for_name (self, session_name, NULL, &command);
f83012
         if (! res) {
f83012
                 g_critical ("Cannot find a command for specified session: %s", session_name);
f83012
                 exit (EXIT_FAILURE);
f83012
         }
f83012
 
f83012
         return command;
f83012
 }
f83012
 
f83012
 static gchar *
f83012
 get_session_desktop_names (GdmSession *self)
f83012
 {
f83012
         gchar *filename;
f83012
         GKeyFile *keyfile;
f83012
         gchar *desktop_names = NULL;
f83012
 
ffa191
         if (self->selected_program != NULL) {
f83012
                 return g_strdup ("GNOME-Greeter:GNOME");
f83012
         }
f83012
 
f83012
         filename = g_strdup_printf ("%s.desktop", get_session_name (self));
f83012
         g_debug ("GdmSession: getting desktop names for file '%s'", filename);
f83012
-        keyfile = load_key_file_for_file (self, filename, NULL);
f83012
+        keyfile = load_key_file_for_file (self, filename, NULL, NULL);
f83012
         if (keyfile != NULL) {
f83012
               gchar **names;
f83012
 
f83012
               names = g_key_file_get_string_list (keyfile, G_KEY_FILE_DESKTOP_GROUP,
f83012
                                                   "DesktopNames", NULL, NULL);
f83012
               if (names != NULL) {
f83012
                       desktop_names = g_strjoinv (":", names);
f83012
 
f83012
                       g_strfreev (names);
f83012
               }
f83012
         }
f83012
 
f83012
         g_key_file_free (keyfile);
f83012
         g_free (filename);
f83012
         return desktop_names;
f83012
 }
f83012
 
f83012
 void
f83012
 gdm_session_set_environment_variable (GdmSession *self,
f83012
                                       const char *key,
f83012
                                       const char *value)
f83012
 {
f83012
         g_return_if_fail (key != NULL);
f83012
         g_return_if_fail (value != NULL);
f83012
 
ffa191
         g_hash_table_replace (self->environment,
f83012
                               g_strdup (key),
f83012
                               g_strdup (value));
f83012
 }
f83012
 
3b7bb8
@@ -3179,148 +3216,150 @@ gdm_session_get_conversation_session_id (GdmSession *self,
f83012
         conversation = find_conversation_by_name (self, service_name);
f83012
 
f83012
         if (conversation == NULL) {
f83012
                 return NULL;
f83012
         }
f83012
 
f83012
         return conversation->session_id;
f83012
 }
f83012
 
f83012
 static char *
f83012
 get_session_filename (GdmSession *self)
f83012
 {
f83012
         return g_strdup_printf ("%s.desktop", get_session_name (self));
f83012
 }
f83012
 
f83012
 #ifdef ENABLE_WAYLAND_SUPPORT
f83012
 static gboolean
f83012
 gdm_session_is_wayland_session (GdmSession *self)
f83012
 {
f83012
         GKeyFile   *key_file;
f83012
         gboolean    is_wayland_session = FALSE;
f83012
         char       *filename;
f83012
         char       *full_path = NULL;
f83012
 
f83012
         g_return_val_if_fail (self != NULL, FALSE);
f83012
         g_return_val_if_fail (GDM_IS_SESSION (self), FALSE);
f83012
 
f83012
         filename = get_session_filename (self);
f83012
 
18ca79
         if (supports_session_type (self, "wayland")) {
18ca79
-            key_file = load_key_file_for_file (self, filename, &full_path);
18ca79
+                key_file = load_key_file_for_file (self, filename, NULL, &full_path);
f83012
 
18ca79
-            if (key_file == NULL) {
18ca79
-                    goto out;
18ca79
-            }
18ca79
+                if (key_file == NULL) {
18ca79
+                        goto out;
18ca79
+                }
f83012
         }
f83012
 
f83012
         if (full_path != NULL && strstr (full_path, "/wayland-sessions/") != NULL) {
f83012
                 is_wayland_session = TRUE;
f83012
         }
f83012
         g_debug ("GdmSession: checking if file '%s' is wayland session: %s", filename, is_wayland_session? "yes" : "no");
f83012
 
f83012
 out:
ffa191
         g_clear_pointer (&key_file, g_key_file_free);
f83012
         g_free (filename);
f83012
         return is_wayland_session;
f83012
 }
f83012
 #endif
f83012
 
f83012
 static void
f83012
 update_session_type (GdmSession *self)
f83012
 {
f83012
 #ifdef ENABLE_WAYLAND_SUPPORT
f83012
-        gboolean is_wayland_session;
f83012
+        gboolean is_wayland_session = FALSE;
f83012
+
18ca79
+        if (supports_session_type (self, "wayland"))
f83012
+                is_wayland_session = gdm_session_is_wayland_session (self);
f83012
 
f83012
-        is_wayland_session = gdm_session_is_wayland_session (self);
f83012
         if (is_wayland_session) {
f83012
                 set_session_type (self, "wayland");
f83012
         } else {
f83012
                 set_session_type (self, NULL);
f83012
         }
f83012
 #endif
f83012
 }
f83012
 
f83012
 gboolean
ffa191
 gdm_session_session_registers (GdmSession *self)
ffa191
 {
ffa191
         g_autoptr(GError) error = NULL;
ffa191
         g_autoptr(GKeyFile) key_file = NULL;
ffa191
         gboolean session_registers = FALSE;
ffa191
         g_autofree char *filename = NULL;
ffa191
 
ffa191
         g_return_val_if_fail (self != NULL, FALSE);
ffa191
         g_return_val_if_fail (GDM_IS_SESSION (self), FALSE);
ffa191
 
ffa191
         filename = get_session_filename (self);
ffa191
 
18ca79
-        key_file = load_key_file_for_file (self, filename, NULL);
18ca79
+        key_file = load_key_file_for_file (self, filename, NULL, NULL);
ffa191
 
ffa191
         session_registers = g_key_file_get_boolean (key_file,
ffa191
                                                     G_KEY_FILE_DESKTOP_GROUP,
ffa191
                                                     "X-GDM-SessionRegisters",
ffa191
                                                     &error);
ffa191
         if (!session_registers &&
ffa191
             error != NULL &&
ffa191
             !g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND)) {
18ca79
                 g_warning ("GdmSession: Couldn't read session file '%s'", filename);
ffa191
                 return FALSE;
ffa191
         }
ffa191
 
ffa191
         g_debug ("GdmSession: '%s' %s self", filename,
ffa191
                  session_registers ? "registers" : "does not register");
ffa191
 
ffa191
         return session_registers;
ffa191
 }
ffa191
 
ffa191
 gboolean
f83012
 gdm_session_bypasses_xsession (GdmSession *self)
f83012
 {
f83012
         GError     *error;
f83012
         GKeyFile   *key_file;
f83012
         gboolean    res;
f83012
         gboolean    bypasses_xsession = FALSE;
f83012
         char       *filename = NULL;
f83012
 
f83012
         g_return_val_if_fail (self != NULL, FALSE);
f83012
         g_return_val_if_fail (GDM_IS_SESSION (self), FALSE);
f83012
 
f83012
 #ifdef ENABLE_WAYLAND_SUPPORT
f83012
         if (gdm_session_is_wayland_session (self)) {
f83012
                 bypasses_xsession = TRUE;
f83012
                 goto out;
f83012
         }
f83012
 #endif
f83012
 
f83012
         filename = get_session_filename (self);
f83012
 
f83012
-        key_file = load_key_file_for_file (self, filename, NULL);
f83012
+        key_file = load_key_file_for_file (self, filename, "x11",  NULL);
f83012
 
f83012
         error = NULL;
f83012
         res = g_key_file_has_key (key_file, G_KEY_FILE_DESKTOP_GROUP, "X-GDM-BypassXsession", NULL);
f83012
         if (!res) {
f83012
                 goto out;
f83012
         } else {
f83012
                 bypasses_xsession = g_key_file_get_boolean (key_file, G_KEY_FILE_DESKTOP_GROUP, "X-GDM-BypassXsession", &error);
f83012
                 if (error) {
f83012
                         bypasses_xsession = FALSE;
f83012
                         g_error_free (error);
f83012
                         goto out;
f83012
                 }
f83012
         }
f83012
 
f83012
 out:
f83012
         if (bypasses_xsession) {
f83012
                 g_debug ("GdmSession: Session %s bypasses Xsession wrapper script", filename);
f83012
         }
f83012
         g_free (filename);
f83012
         return bypasses_xsession;
f83012
 }
f83012
 
f83012
 GdmSessionDisplayMode
f83012
 gdm_session_get_display_mode (GdmSession *self)
f83012
 {
f83012
         g_debug ("GdmSession: type %s, program? %s, seat %s",
ffa191
                  self->session_type,
ffa191
                  self->is_program_session? "yes" : "no",
ffa191
                  self->display_seat_id);
f83012
 
f83012
-- 
3b7bb8
2.27.0
f83012