Blob Blame History Raw
From 83cdeb662961f8910e79c56f38d9e5e296ac93be Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 14 Aug 2018 14:52:41 -0400
Subject: [PATCH 2/5] session: support new accountsservice Session and
 SessionType props

At the moment the user's session is stored in a property called
"XSession".  This is pretty weird if the user is using wayland.

AccountService now supports a more generic property "Session" and
a related "SessionType" property to replace "XSession".

This commit switches GDM over to use the new properties.
---
 daemon/gdm-session-settings.c | 61 ++++++++++++++++++++++--
 daemon/gdm-session-settings.h |  3 ++
 daemon/gdm-session-worker.c   | 28 +++++++++++
 daemon/gdm-session-worker.xml |  3 ++
 daemon/gdm-session.c          | 87 +++++++++++++++++++++++++----------
 5 files changed, 153 insertions(+), 29 deletions(-)

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