Blame SOURCES/0001-local-display-factory-Provide-more-flexibility-for-c.patch

39d8c7
From a8f8a5ee422d6ae3d87c1fba351313a5d98ded6e Mon Sep 17 00:00:00 2001
39d8c7
From: Ray Strode <rstrode@redhat.com>
39d8c7
Date: Fri, 16 Jul 2021 12:34:57 -0400
39d8c7
Subject: [PATCH] local-display-factory: Provide more flexibility for
39d8c7
 configuring display server
39d8c7
39d8c7
There's currently a way to disable wayland, but no way to disable Xorg.
39d8c7
We currently prefer wayland if it's not disabled, but have no way to
39d8c7
prefer Xorg without disabling wayland entirely.
39d8c7
39d8c7
There's currently no way use legacy Xorg support at all if user display
39d8c7
server support is enabled at a build time.
39d8c7
39d8c7
This commit adds more flexibility to display server selection. It adds
39d8c7
two new keys: XorgEnable and and PreferredDisplayServer.
39d8c7
39d8c7
XorgEnable=false disables Xorg support entirely on seat 0.
39d8c7
39d8c7
PreferredDisplayServer can be set to "wayland", "xorg", "legacy-xorg" or
39d8c7
"none" to select which display server is used by default. If it's set to
39d8c7
"wayland", it will fall back to "xorg". If it's set to "xorg" it will
39d8c7
fall back to "wayland".
39d8c7
---
39d8c7
 common/gdm-settings-keys.h         |   2 +
39d8c7
 daemon/gdm-display.c               |  36 +++++
39d8c7
 daemon/gdm-launch-environment.c    |   9 ++
39d8c7
 daemon/gdm-local-display-factory.c | 224 ++++++++++++++++++++++++-----
39d8c7
 daemon/gdm-manager.c               |  22 ++-
39d8c7
 daemon/gdm-session.c               | 115 ++++++++-------
39d8c7
 data/gdm.schemas.in                |  10 ++
39d8c7
 libgdm/gdm-sessions.c              |  72 +++++++---
39d8c7
 8 files changed, 366 insertions(+), 124 deletions(-)
39d8c7
39d8c7
diff --git a/common/gdm-settings-keys.h b/common/gdm-settings-keys.h
39d8c7
index f0059b5cf..87685d3cd 100644
39d8c7
--- a/common/gdm-settings-keys.h
39d8c7
+++ b/common/gdm-settings-keys.h
39d8c7
@@ -6,59 +6,61 @@
39d8c7
  * modify it under the terms of the GNU Library General Public
39d8c7
  * License as published by the Free Software Foundation; either
39d8c7
  * version 2 of the License, or (at your option) any later version.
39d8c7
  *
39d8c7
  * This library is distributed in the hope that it will be useful,
39d8c7
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
39d8c7
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
39d8c7
  * Library General Public License for more details.
39d8c7
  *
39d8c7
  * You should have received a copy of the GNU Library General Public
39d8c7
  * License along with this library; if not, write to the
39d8c7
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
39d8c7
  * Boston, MA 02110-1301, USA.
39d8c7
  */
39d8c7
 
39d8c7
 #ifndef _GDM_SETTINGS_KEYS_H
39d8c7
 #define _GDM_SETTINGS_KEYS_H
39d8c7
 
39d8c7
 #include <glib.h>
39d8c7
 
39d8c7
 G_BEGIN_DECLS
39d8c7
 
39d8c7
 #define GDM_KEY_USER "daemon/User"
39d8c7
 #define GDM_KEY_GROUP "daemon/Group"
39d8c7
 #define GDM_KEY_AUTO_LOGIN_ENABLE "daemon/AutomaticLoginEnable"
39d8c7
 #define GDM_KEY_AUTO_LOGIN_USER "daemon/AutomaticLogin"
39d8c7
 #define GDM_KEY_TIMED_LOGIN_ENABLE "daemon/TimedLoginEnable"
39d8c7
 #define GDM_KEY_TIMED_LOGIN_USER "daemon/TimedLogin"
39d8c7
 #define GDM_KEY_TIMED_LOGIN_DELAY "daemon/TimedLoginDelay"
39d8c7
 #define GDM_KEY_INITIAL_SETUP_ENABLE "daemon/InitialSetupEnable"
39d8c7
+#define GDM_KEY_PREFERRED_DISPLAY_SERVER "daemon/PreferredDisplayServer"
39d8c7
 #define GDM_KEY_WAYLAND_ENABLE "daemon/WaylandEnable"
39d8c7
+#define GDM_KEY_XORG_ENABLE "daemon/XorgEnable"
39d8c7
 
39d8c7
 #define GDM_KEY_DEBUG "debug/Enable"
39d8c7
 
39d8c7
 #define GDM_KEY_INCLUDE "greeter/Include"
39d8c7
 #define GDM_KEY_EXCLUDE "greeter/Exclude"
39d8c7
 #define GDM_KEY_INCLUDE_ALL "greeter/IncludeAll"
39d8c7
 
39d8c7
 #define GDM_KEY_DISALLOW_TCP "security/DisallowTCP"
39d8c7
 #define GDM_KEY_ALLOW_REMOTE_AUTOLOGIN "security/AllowRemoteAutoLogin"
39d8c7
 
39d8c7
 #define GDM_KEY_XDMCP_ENABLE "xdmcp/Enable"
39d8c7
 #define GDM_KEY_SHOW_LOCAL_GREETER "xdmcp/ShowLocalGreeter"
39d8c7
 #define GDM_KEY_MAX_PENDING "xdmcp/MaxPending"
39d8c7
 #define GDM_KEY_MAX_SESSIONS "xdmcp/MaxSessions"
39d8c7
 #define GDM_KEY_MAX_WAIT "xdmcp/MaxWait"
39d8c7
 #define GDM_KEY_DISPLAYS_PER_HOST "xdmcp/DisplaysPerHost"
39d8c7
 #define GDM_KEY_UDP_PORT "xdmcp/Port"
39d8c7
 #define GDM_KEY_INDIRECT "xdmcp/HonorIndirect"
39d8c7
 #define GDM_KEY_MAX_WAIT_INDIRECT "xdmcp/MaxWaitIndirect"
39d8c7
 #define GDM_KEY_PING_INTERVAL "xdmcp/PingIntervalSeconds"
39d8c7
 #define GDM_KEY_WILLING "xdmcp/Willing"
39d8c7
 
39d8c7
 #define GDM_KEY_MULTICAST "chooser/Multicast"
39d8c7
 #define GDM_KEY_MULTICAST_ADDR "chooser/MulticastAddr"
39d8c7
 
39d8c7
 G_END_DECLS
39d8c7
 
39d8c7
 #endif /* _GDM_SETTINGS_KEYS_H */
39d8c7
diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c
39d8c7
index 3a260923a..46d5a7732 100644
39d8c7
--- a/daemon/gdm-display.c
39d8c7
+++ b/daemon/gdm-display.c
39d8c7
@@ -66,83 +66,86 @@ typedef struct _GdmDisplayPrivate
39d8c7
         char                 *x11_display_name;
39d8c7
         int                   status;
39d8c7
         time_t                creation_time;
39d8c7
 
39d8c7
         char                 *x11_cookie;
39d8c7
         gsize                 x11_cookie_size;
39d8c7
         GdmDisplayAccessFile *access_file;
39d8c7
 
39d8c7
         guint                 finish_idle_id;
39d8c7
 
39d8c7
         xcb_connection_t     *xcb_connection;
39d8c7
         int                   xcb_screen_number;
39d8c7
 
39d8c7
         GDBusConnection      *connection;
39d8c7
         GdmDisplayAccessFile *user_access_file;
39d8c7
 
39d8c7
         GdmDBusDisplay       *display_skeleton;
39d8c7
         GDBusObjectSkeleton  *object_skeleton;
39d8c7
 
39d8c7
         GDBusProxy           *accountsservice_proxy;
39d8c7
 
39d8c7
         /* this spawns and controls the greeter session */
39d8c7
         GdmLaunchEnvironment *launch_environment;
39d8c7
 
39d8c7
         guint                 is_local : 1;
39d8c7
         guint                 is_initial : 1;
39d8c7
         guint                 allow_timed_login : 1;
39d8c7
         guint                 have_existing_user_accounts : 1;
39d8c7
         guint                 doing_initial_setup : 1;
39d8c7
         guint                 session_registered : 1;
39d8c7
+
39d8c7
+        GStrv                 supported_session_types;
39d8c7
 } GdmDisplayPrivate;
39d8c7
 
39d8c7
 enum {
39d8c7
         PROP_0,
39d8c7
         PROP_ID,
39d8c7
         PROP_STATUS,
39d8c7
         PROP_SEAT_ID,
39d8c7
         PROP_SESSION_ID,
39d8c7
         PROP_SESSION_CLASS,
39d8c7
         PROP_SESSION_TYPE,
39d8c7
         PROP_REMOTE_HOSTNAME,
39d8c7
         PROP_X11_DISPLAY_NUMBER,
39d8c7
         PROP_X11_DISPLAY_NAME,
39d8c7
         PROP_X11_COOKIE,
39d8c7
         PROP_X11_AUTHORITY_FILE,
39d8c7
         PROP_IS_CONNECTED,
39d8c7
         PROP_IS_LOCAL,
39d8c7
         PROP_LAUNCH_ENVIRONMENT,
39d8c7
         PROP_IS_INITIAL,
39d8c7
         PROP_ALLOW_TIMED_LOGIN,
39d8c7
         PROP_HAVE_EXISTING_USER_ACCOUNTS,
39d8c7
         PROP_DOING_INITIAL_SETUP,
39d8c7
         PROP_SESSION_REGISTERED,
39d8c7
+        PROP_SUPPORTED_SESSION_TYPES,
39d8c7
 };
39d8c7
 
39d8c7
 static void     gdm_display_class_init  (GdmDisplayClass *klass);
39d8c7
 static void     gdm_display_init        (GdmDisplay      *self);
39d8c7
 static void     gdm_display_finalize    (GObject         *object);
39d8c7
 static void     queue_finish            (GdmDisplay      *self);
39d8c7
 static void     _gdm_display_set_status (GdmDisplay *self,
39d8c7
                                          int         status);
39d8c7
 static gboolean wants_initial_setup (GdmDisplay *self);
39d8c7
 G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GdmDisplay, gdm_display, G_TYPE_OBJECT)
39d8c7
 
39d8c7
 GQuark
39d8c7
 gdm_display_error_quark (void)
39d8c7
 {
39d8c7
         static GQuark ret = 0;
39d8c7
         if (ret == 0) {
39d8c7
                 ret = g_quark_from_static_string ("gdm_display_error");
39d8c7
         }
39d8c7
 
39d8c7
         return ret;
39d8c7
 }
39d8c7
 
39d8c7
 time_t
39d8c7
 gdm_display_get_creation_time (GdmDisplay *self)
39d8c7
 {
39d8c7
         GdmDisplayPrivate *priv;
39d8c7
 
39d8c7
         g_return_val_if_fail (GDM_IS_DISPLAY (self), 0);
39d8c7
 
39d8c7
         priv = gdm_display_get_instance_private (self);
39d8c7
@@ -883,116 +886,136 @@ _gdm_display_set_launch_environment (GdmDisplay           *self,
39d8c7
 
39d8c7
         priv = gdm_display_get_instance_private (self);
39d8c7
 
39d8c7
         g_clear_object (&priv->launch_environment);
39d8c7
 
39d8c7
         priv->launch_environment = g_object_ref (launch_environment);
39d8c7
 }
39d8c7
 
39d8c7
 static void
39d8c7
 _gdm_display_set_is_initial (GdmDisplay     *self,
39d8c7
                              gboolean        initial)
39d8c7
 {
39d8c7
         GdmDisplayPrivate *priv;
39d8c7
 
39d8c7
         priv = gdm_display_get_instance_private (self);
39d8c7
         g_debug ("GdmDisplay: initial: %s", initial? "yes" : "no");
39d8c7
         priv->is_initial = initial;
39d8c7
 }
39d8c7
 
39d8c7
 static void
39d8c7
 _gdm_display_set_allow_timed_login (GdmDisplay     *self,
39d8c7
                                     gboolean        allow_timed_login)
39d8c7
 {
39d8c7
         GdmDisplayPrivate *priv;
39d8c7
 
39d8c7
         priv = gdm_display_get_instance_private (self);
39d8c7
         g_debug ("GdmDisplay: allow timed login: %s", allow_timed_login? "yes" : "no");
39d8c7
         priv->allow_timed_login = allow_timed_login;
39d8c7
 }
39d8c7
 
39d8c7
+static void
39d8c7
+_gdm_display_set_supported_session_types (GdmDisplay         *self,
39d8c7
+                                          const char * const *supported_session_types)
39d8c7
+
39d8c7
+{
39d8c7
+        GdmDisplayPrivate *priv;
39d8c7
+        g_autofree char *supported_session_types_string = NULL;
39d8c7
+
39d8c7
+        if (supported_session_types != NULL)
39d8c7
+                supported_session_types_string = g_strjoinv (":", (GStrv) supported_session_types);
39d8c7
+
39d8c7
+        priv = gdm_display_get_instance_private (self);
39d8c7
+        g_debug ("GdmDisplay: supported session types: %s", supported_session_types_string);
39d8c7
+        g_strfreev (priv->supported_session_types);
39d8c7
+        priv->supported_session_types = g_strdupv ((GStrv) supported_session_types);
39d8c7
+}
39d8c7
+
39d8c7
 static void
39d8c7
 gdm_display_set_property (GObject        *object,
39d8c7
                           guint           prop_id,
39d8c7
                           const GValue   *value,
39d8c7
                           GParamSpec     *pspec)
39d8c7
 {
39d8c7
         GdmDisplay *self;
39d8c7
 
39d8c7
         self = GDM_DISPLAY (object);
39d8c7
 
39d8c7
         switch (prop_id) {
39d8c7
         case PROP_ID:
39d8c7
                 _gdm_display_set_id (self, g_value_get_string (value));
39d8c7
                 break;
39d8c7
         case PROP_STATUS:
39d8c7
                 _gdm_display_set_status (self, g_value_get_int (value));
39d8c7
                 break;
39d8c7
         case PROP_SEAT_ID:
39d8c7
                 _gdm_display_set_seat_id (self, g_value_get_string (value));
39d8c7
                 break;
39d8c7
         case PROP_SESSION_ID:
39d8c7
                 _gdm_display_set_session_id (self, g_value_get_string (value));
39d8c7
                 break;
39d8c7
         case PROP_SESSION_CLASS:
39d8c7
                 _gdm_display_set_session_class (self, g_value_get_string (value));
39d8c7
                 break;
39d8c7
         case PROP_SESSION_TYPE:
39d8c7
                 _gdm_display_set_session_type (self, g_value_get_string (value));
39d8c7
                 break;
39d8c7
         case PROP_REMOTE_HOSTNAME:
39d8c7
                 _gdm_display_set_remote_hostname (self, g_value_get_string (value));
39d8c7
                 break;
39d8c7
         case PROP_X11_DISPLAY_NUMBER:
39d8c7
                 _gdm_display_set_x11_display_number (self, g_value_get_int (value));
39d8c7
                 break;
39d8c7
         case PROP_X11_DISPLAY_NAME:
39d8c7
                 _gdm_display_set_x11_display_name (self, g_value_get_string (value));
39d8c7
                 break;
39d8c7
         case PROP_X11_COOKIE:
39d8c7
                 _gdm_display_set_x11_cookie (self, g_value_get_string (value));
39d8c7
                 break;
39d8c7
         case PROP_IS_LOCAL:
39d8c7
                 _gdm_display_set_is_local (self, g_value_get_boolean (value));
39d8c7
                 break;
39d8c7
         case PROP_ALLOW_TIMED_LOGIN:
39d8c7
                 _gdm_display_set_allow_timed_login (self, g_value_get_boolean (value));
39d8c7
                 break;
39d8c7
         case PROP_LAUNCH_ENVIRONMENT:
39d8c7
                 _gdm_display_set_launch_environment (self, g_value_get_object (value));
39d8c7
                 break;
39d8c7
         case PROP_IS_INITIAL:
39d8c7
                 _gdm_display_set_is_initial (self, g_value_get_boolean (value));
39d8c7
                 break;
39d8c7
         case PROP_SESSION_REGISTERED:
39d8c7
                 _gdm_display_set_session_registered (self, g_value_get_boolean (value));
39d8c7
                 break;
39d8c7
+        case PROP_SUPPORTED_SESSION_TYPES:
39d8c7
+                _gdm_display_set_supported_session_types (self, g_value_get_boxed (value));
39d8c7
+                break;
39d8c7
         default:
39d8c7
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
39d8c7
                 break;
39d8c7
         }
39d8c7
 }
39d8c7
 
39d8c7
 static void
39d8c7
 gdm_display_get_property (GObject        *object,
39d8c7
                           guint           prop_id,
39d8c7
                           GValue         *value,
39d8c7
                           GParamSpec     *pspec)
39d8c7
 {
39d8c7
         GdmDisplay *self;
39d8c7
         GdmDisplayPrivate *priv;
39d8c7
 
39d8c7
         self = GDM_DISPLAY (object);
39d8c7
         priv = gdm_display_get_instance_private (self);
39d8c7
 
39d8c7
         switch (prop_id) {
39d8c7
         case PROP_ID:
39d8c7
                 g_value_set_string (value, priv->id);
39d8c7
                 break;
39d8c7
         case PROP_STATUS:
39d8c7
                 g_value_set_int (value, priv->status);
39d8c7
                 break;
39d8c7
         case PROP_SEAT_ID:
39d8c7
                 g_value_set_string (value, priv->seat_id);
39d8c7
                 break;
39d8c7
         case PROP_SESSION_ID:
39d8c7
                 g_value_set_string (value, priv->session_id);
39d8c7
@@ -1017,60 +1040,63 @@ gdm_display_get_property (GObject        *object,
39d8c7
                 break;
39d8c7
         case PROP_X11_AUTHORITY_FILE:
39d8c7
                 g_value_take_string (value,
39d8c7
                                      priv->access_file?
39d8c7
                                      gdm_display_access_file_get_path (priv->access_file) : NULL);
39d8c7
                 break;
39d8c7
         case PROP_IS_LOCAL:
39d8c7
                 g_value_set_boolean (value, priv->is_local);
39d8c7
                 break;
39d8c7
         case PROP_IS_CONNECTED:
39d8c7
                 g_value_set_boolean (value, priv->xcb_connection != NULL);
39d8c7
                 break;
39d8c7
         case PROP_LAUNCH_ENVIRONMENT:
39d8c7
                 g_value_set_object (value, priv->launch_environment);
39d8c7
                 break;
39d8c7
         case PROP_IS_INITIAL:
39d8c7
                 g_value_set_boolean (value, priv->is_initial);
39d8c7
                 break;
39d8c7
         case PROP_HAVE_EXISTING_USER_ACCOUNTS:
39d8c7
                 g_value_set_boolean (value, priv->have_existing_user_accounts);
39d8c7
                 break;
39d8c7
         case PROP_DOING_INITIAL_SETUP:
39d8c7
                 g_value_set_boolean (value, priv->doing_initial_setup);
39d8c7
                 break;
39d8c7
         case PROP_SESSION_REGISTERED:
39d8c7
                 g_value_set_boolean (value, priv->session_registered);
39d8c7
                 break;
39d8c7
         case PROP_ALLOW_TIMED_LOGIN:
39d8c7
                 g_value_set_boolean (value, priv->allow_timed_login);
39d8c7
                 break;
39d8c7
+        case PROP_SUPPORTED_SESSION_TYPES:
39d8c7
+                g_value_set_boxed (value, priv->supported_session_types);
39d8c7
+                break;
39d8c7
         default:
39d8c7
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
39d8c7
                 break;
39d8c7
         }
39d8c7
 }
39d8c7
 
39d8c7
 static gboolean
39d8c7
 handle_get_id (GdmDBusDisplay        *skeleton,
39d8c7
                GDBusMethodInvocation *invocation,
39d8c7
                GdmDisplay            *self)
39d8c7
 {
39d8c7
         char *id;
39d8c7
 
39d8c7
         gdm_display_get_id (self, &id, NULL);
39d8c7
 
39d8c7
         gdm_dbus_display_complete_get_id (skeleton, invocation, id);
39d8c7
 
39d8c7
         g_free (id);
39d8c7
         return TRUE;
39d8c7
 }
39d8c7
 
39d8c7
 static gboolean
39d8c7
 handle_get_remote_hostname (GdmDBusDisplay        *skeleton,
39d8c7
                             GDBusMethodInvocation *invocation,
39d8c7
                             GdmDisplay            *self)
39d8c7
 {
39d8c7
         char *hostname;
39d8c7
 
39d8c7
         gdm_display_get_remote_hostname (self, &hostname, NULL);
39d8c7
 
39d8c7
@@ -1202,60 +1228,61 @@ gdm_display_constructor (GType                  type,
39d8c7
         priv = gdm_display_get_instance_private (self);
39d8c7
 
39d8c7
         g_free (priv->id);
39d8c7
         priv->id = g_strdup_printf ("/org/gnome/DisplayManager/Displays/%lu",
39d8c7
                                           (gulong) self);
39d8c7
 
39d8c7
         res = register_display (self);
39d8c7
         if (! res) {
39d8c7
                 g_warning ("Unable to register display with system bus");
39d8c7
         }
39d8c7
 
39d8c7
         return G_OBJECT (self);
39d8c7
 }
39d8c7
 
39d8c7
 static void
39d8c7
 gdm_display_dispose (GObject *object)
39d8c7
 {
39d8c7
         GdmDisplay *self;
39d8c7
         GdmDisplayPrivate *priv;
39d8c7
 
39d8c7
         self = GDM_DISPLAY (object);
39d8c7
         priv = gdm_display_get_instance_private (self);
39d8c7
 
39d8c7
         g_debug ("GdmDisplay: Disposing display");
39d8c7
 
39d8c7
         if (priv->finish_idle_id != 0) {
39d8c7
                 g_source_remove (priv->finish_idle_id);
39d8c7
                 priv->finish_idle_id = 0;
39d8c7
         }
39d8c7
         g_clear_object (&priv->launch_environment);
39d8c7
+        g_clear_pointer (&priv->supported_session_types, g_strfreev);
39d8c7
 
39d8c7
         g_warn_if_fail (priv->status != GDM_DISPLAY_MANAGED);
39d8c7
         g_warn_if_fail (priv->user_access_file == NULL);
39d8c7
         g_warn_if_fail (priv->access_file == NULL);
39d8c7
 
39d8c7
         G_OBJECT_CLASS (gdm_display_parent_class)->dispose (object);
39d8c7
 }
39d8c7
 
39d8c7
 static void
39d8c7
 gdm_display_class_init (GdmDisplayClass *klass)
39d8c7
 {
39d8c7
         GObjectClass   *object_class = G_OBJECT_CLASS (klass);
39d8c7
 
39d8c7
         object_class->get_property = gdm_display_get_property;
39d8c7
         object_class->set_property = gdm_display_set_property;
39d8c7
         object_class->constructor = gdm_display_constructor;
39d8c7
         object_class->dispose = gdm_display_dispose;
39d8c7
         object_class->finalize = gdm_display_finalize;
39d8c7
 
39d8c7
         klass->prepare = gdm_display_real_prepare;
39d8c7
 
39d8c7
         g_object_class_install_property (object_class,
39d8c7
                                          PROP_ID,
39d8c7
                                          g_param_spec_string ("id",
39d8c7
                                                               "id",
39d8c7
                                                               "id",
39d8c7
                                                               NULL,
39d8c7
                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
39d8c7
         g_object_class_install_property (object_class,
39d8c7
                                          PROP_REMOTE_HOSTNAME,
39d8c7
@@ -1362,60 +1389,68 @@ gdm_display_class_init (GdmDisplayClass *klass)
39d8c7
                                          PROP_DOING_INITIAL_SETUP,
39d8c7
                                          g_param_spec_boolean ("doing-initial-setup",
39d8c7
                                                                NULL,
39d8c7
                                                                NULL,
39d8c7
                                                                FALSE,
39d8c7
                                                                G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
39d8c7
         g_object_class_install_property (object_class,
39d8c7
                                          PROP_SESSION_REGISTERED,
39d8c7
                                          g_param_spec_boolean ("session-registered",
39d8c7
                                                                NULL,
39d8c7
                                                                NULL,
39d8c7
                                                                FALSE,
39d8c7
                                                                G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
39d8c7
 
39d8c7
         g_object_class_install_property (object_class,
39d8c7
                                          PROP_LAUNCH_ENVIRONMENT,
39d8c7
                                          g_param_spec_object ("launch-environment",
39d8c7
                                                               NULL,
39d8c7
                                                               NULL,
39d8c7
                                                               GDM_TYPE_LAUNCH_ENVIRONMENT,
39d8c7
                                                               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
39d8c7
         g_object_class_install_property (object_class,
39d8c7
                                          PROP_STATUS,
39d8c7
                                          g_param_spec_int ("status",
39d8c7
                                                            "status",
39d8c7
                                                            "status",
39d8c7
                                                            -1,
39d8c7
                                                            G_MAXINT,
39d8c7
                                                            GDM_DISPLAY_UNMANAGED,
39d8c7
                                                            G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
39d8c7
+
39d8c7
+        g_object_class_install_property (object_class,
39d8c7
+                                         PROP_SUPPORTED_SESSION_TYPES,
39d8c7
+                                         g_param_spec_boxed ("supported-session-types",
39d8c7
+                                                             "supported session types",
39d8c7
+                                                             "supported session types",
39d8c7
+                                                             G_TYPE_STRV,
39d8c7
+                                                             G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
39d8c7
 }
39d8c7
 
39d8c7
 static void
39d8c7
 gdm_display_init (GdmDisplay *self)
39d8c7
 {
39d8c7
         GdmDisplayPrivate *priv;
39d8c7
 
39d8c7
         priv = gdm_display_get_instance_private (self);
39d8c7
 
39d8c7
         priv->creation_time = time (NULL);
39d8c7
 }
39d8c7
 
39d8c7
 static void
39d8c7
 gdm_display_finalize (GObject *object)
39d8c7
 {
39d8c7
         GdmDisplay *self;
39d8c7
         GdmDisplayPrivate *priv;
39d8c7
 
39d8c7
         g_return_if_fail (object != NULL);
39d8c7
         g_return_if_fail (GDM_IS_DISPLAY (object));
39d8c7
 
39d8c7
         self = GDM_DISPLAY (object);
39d8c7
         priv = gdm_display_get_instance_private (self);
39d8c7
 
39d8c7
         g_return_if_fail (priv != NULL);
39d8c7
 
39d8c7
         g_debug ("GdmDisplay: Finalizing display: %s", priv->id);
39d8c7
         g_free (priv->id);
39d8c7
         g_free (priv->seat_id);
39d8c7
         g_free (priv->session_class);
39d8c7
@@ -1694,60 +1729,61 @@ gdm_display_start_greeter_session (GdmDisplay *self)
39d8c7
                                  G_CALLBACK (on_launch_environment_session_opened),
39d8c7
                                  self, 0);
39d8c7
         g_signal_connect_object (priv->launch_environment,
39d8c7
                                  "started",
39d8c7
                                  G_CALLBACK (on_launch_environment_session_started),
39d8c7
                                  self, 0);
39d8c7
         g_signal_connect_object (priv->launch_environment,
39d8c7
                                  "stopped",
39d8c7
                                  G_CALLBACK (on_launch_environment_session_stopped),
39d8c7
                                  self, 0);
39d8c7
         g_signal_connect_object (priv->launch_environment,
39d8c7
                                  "exited",
39d8c7
                                  G_CALLBACK (on_launch_environment_session_exited),
39d8c7
                                  self, 0);
39d8c7
         g_signal_connect_object (priv->launch_environment,
39d8c7
                                  "died",
39d8c7
                                  G_CALLBACK (on_launch_environment_session_died),
39d8c7
                                  self, 0);
39d8c7
 
39d8c7
         if (auth_file != NULL) {
39d8c7
                 g_object_set (priv->launch_environment,
39d8c7
                               "x11-authority-file", auth_file,
39d8c7
                               NULL);
39d8c7
         }
39d8c7
 
39d8c7
         gdm_launch_environment_start (priv->launch_environment);
39d8c7
 
39d8c7
         session = gdm_launch_environment_get_session (priv->launch_environment);
39d8c7
         g_object_set (G_OBJECT (session),
39d8c7
                       "display-is-initial", priv->is_initial,
39d8c7
+                      "supported-session-types", priv->supported_session_types,
39d8c7
                       NULL);
39d8c7
 
39d8c7
         g_free (display_name);
39d8c7
         g_free (seat_id);
39d8c7
         g_free (hostname);
39d8c7
         g_free (auth_file);
39d8c7
 }
39d8c7
 
39d8c7
 void
39d8c7
 gdm_display_stop_greeter_session (GdmDisplay *self)
39d8c7
 {
39d8c7
         GdmDisplayPrivate *priv;
39d8c7
 
39d8c7
         priv = gdm_display_get_instance_private (self);
39d8c7
 
39d8c7
         if (priv->launch_environment != NULL) {
39d8c7
 
39d8c7
                 g_signal_handlers_disconnect_by_func (priv->launch_environment,
39d8c7
                                                       G_CALLBACK (on_launch_environment_session_opened),
39d8c7
                                                       self);
39d8c7
                 g_signal_handlers_disconnect_by_func (priv->launch_environment,
39d8c7
                                                       G_CALLBACK (on_launch_environment_session_started),
39d8c7
                                                       self);
39d8c7
                 g_signal_handlers_disconnect_by_func (priv->launch_environment,
39d8c7
                                                       G_CALLBACK (on_launch_environment_session_stopped),
39d8c7
                                                       self);
39d8c7
                 g_signal_handlers_disconnect_by_func (priv->launch_environment,
39d8c7
                                                       G_CALLBACK (on_launch_environment_session_exited),
39d8c7
                                                       self);
39d8c7
                 g_signal_handlers_disconnect_by_func (priv->launch_environment,
39d8c7
diff --git a/daemon/gdm-launch-environment.c b/daemon/gdm-launch-environment.c
39d8c7
index 87a1c5ffe..14ecfac2d 100644
39d8c7
--- a/daemon/gdm-launch-environment.c
39d8c7
+++ b/daemon/gdm-launch-environment.c
39d8c7
@@ -134,60 +134,61 @@ static GHashTable *
39d8c7
 build_launch_environment (GdmLaunchEnvironment *launch_environment,
39d8c7
                           gboolean              start_session)
39d8c7
 {
39d8c7
         GHashTable    *hash;
39d8c7
         struct passwd *pwent;
39d8c7
         static const char *const optional_environment[] = {
39d8c7
                 "GI_TYPELIB_PATH",
39d8c7
                 "LANG",
39d8c7
                 "LANGUAGE",
39d8c7
                 "LC_ADDRESS",
39d8c7
                 "LC_ALL",
39d8c7
                 "LC_COLLATE",
39d8c7
                 "LC_CTYPE",
39d8c7
                 "LC_IDENTIFICATION",
39d8c7
                 "LC_MEASUREMENT",
39d8c7
                 "LC_MESSAGES",
39d8c7
                 "LC_MONETARY",
39d8c7
                 "LC_NAME",
39d8c7
                 "LC_NUMERIC",
39d8c7
                 "LC_PAPER",
39d8c7
                 "LC_TELEPHONE",
39d8c7
                 "LC_TIME",
39d8c7
                 "LD_LIBRARY_PATH",
39d8c7
                 "PATH",
39d8c7
                 "WINDOWPATH",
39d8c7
                 "XCURSOR_PATH",
39d8c7
                 "XDG_CONFIG_DIRS",
39d8c7
                 NULL
39d8c7
         };
39d8c7
         char *system_data_dirs;
39d8c7
+        g_auto (GStrv) supported_session_types = NULL;
39d8c7
         int i;
39d8c7
 
39d8c7
         /* create a hash table of current environment, then update keys has necessary */
39d8c7
         hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
39d8c7
 
39d8c7
         for (i = 0; optional_environment[i] != NULL; i++) {
39d8c7
                 if (g_getenv (optional_environment[i]) == NULL) {
39d8c7
                         continue;
39d8c7
                 }
39d8c7
 
39d8c7
                 g_hash_table_insert (hash,
39d8c7
                                      g_strdup (optional_environment[i]),
39d8c7
                                      g_strdup (g_getenv (optional_environment[i])));
39d8c7
         }
39d8c7
 
39d8c7
         if (launch_environment->priv->x11_authority_file != NULL)
39d8c7
                 g_hash_table_insert (hash, g_strdup ("XAUTHORITY"), g_strdup (launch_environment->priv->x11_authority_file));
39d8c7
 
39d8c7
         if (launch_environment->priv->session_mode != NULL) {
39d8c7
                 g_hash_table_insert (hash, g_strdup ("GNOME_SHELL_SESSION_MODE"), g_strdup (launch_environment->priv->session_mode));
39d8c7
 
39d8c7
 		if (strcmp (launch_environment->priv->session_mode, INITIAL_SETUP_SESSION_MODE) != 0) {
39d8c7
 			/* gvfs is needed for fetching remote avatars in the initial setup. Disable it otherwise. */
39d8c7
 			g_hash_table_insert (hash, g_strdup ("GVFS_DISABLE_FUSE"), g_strdup ("1"));
39d8c7
 			g_hash_table_insert (hash, g_strdup ("GIO_USE_VFS"), g_strdup ("local"));
39d8c7
 			g_hash_table_insert (hash, g_strdup ("GVFS_REMOTE_VOLUME_MONITOR_IGNORE"), g_strdup ("1"));
39d8c7
 
39d8c7
 			/* The locked down dconf profile should not be used for the initial setup session.
39d8c7
 			 * This allows overridden values from the user profile to take effect.
39d8c7
 			 */
39d8c7
@@ -217,60 +218,68 @@ build_launch_environment (GdmLaunchEnvironment *launch_environment,
39d8c7
         }
39d8c7
 
39d8c7
         if (start_session && launch_environment->priv->x11_display_seat_id != NULL) {
39d8c7
                 char *seat_id;
39d8c7
 
39d8c7
                 seat_id = launch_environment->priv->x11_display_seat_id;
39d8c7
 
39d8c7
                 g_hash_table_insert (hash, g_strdup ("GDM_SEAT_ID"), g_strdup (seat_id));
39d8c7
         }
39d8c7
 
39d8c7
         g_hash_table_insert (hash, g_strdup ("RUNNING_UNDER_GDM"), g_strdup ("true"));
39d8c7
 
39d8c7
         /* Now populate XDG_DATA_DIRS from env.d if we're running initial setup; this allows
39d8c7
          * e.g. Flatpak apps to be recognized by gnome-shell.
39d8c7
          */
39d8c7
         if (g_strcmp0 (launch_environment->priv->session_mode, INITIAL_SETUP_SESSION_MODE) == 0)
39d8c7
                 gdm_load_env_d (load_env_func, get_var_cb, hash);
39d8c7
 
39d8c7
         /* Prepend our own XDG_DATA_DIRS value */
39d8c7
         system_data_dirs = g_strdup (g_hash_table_lookup (hash, "XDG_DATA_DIRS"));
39d8c7
         if (!system_data_dirs)
39d8c7
                 system_data_dirs = g_strjoinv (":", (char **) g_get_system_data_dirs ());
39d8c7
 
39d8c7
         g_hash_table_insert (hash,
39d8c7
                              g_strdup ("XDG_DATA_DIRS"),
39d8c7
                              g_strdup_printf ("%s:%s",
39d8c7
                                               DATADIR "/gdm/greeter",
39d8c7
                                               system_data_dirs));
39d8c7
         g_free (system_data_dirs);
39d8c7
 
39d8c7
+        g_object_get (launch_environment->priv->session,
39d8c7
+                      "supported-session-types",
39d8c7
+                      &supported_session_types,
39d8c7
+                      NULL);
39d8c7
+        g_hash_table_insert (hash,
39d8c7
+                             g_strdup ("GDM_SUPPORTED_SESSION_TYPES"),
39d8c7
+                             g_strjoinv (":", supported_session_types));
39d8c7
+
39d8c7
         return hash;
39d8c7
 }
39d8c7
 
39d8c7
 static void
39d8c7
 on_session_setup_complete (GdmSession        *session,
39d8c7
                            const char        *service_name,
39d8c7
                            GdmLaunchEnvironment *launch_environment)
39d8c7
 {
39d8c7
         GHashTable       *hash;
39d8c7
         GHashTableIter    iter;
39d8c7
         gpointer          key, value;
39d8c7
 
39d8c7
         hash = build_launch_environment (launch_environment, TRUE);
39d8c7
 
39d8c7
         g_hash_table_iter_init (&iter, hash);
39d8c7
         while (g_hash_table_iter_next (&iter, &key, &value)) {
39d8c7
                 gdm_session_set_environment_variable (launch_environment->priv->session, key, value);
39d8c7
         }
39d8c7
         g_hash_table_destroy (hash);
39d8c7
 }
39d8c7
 
39d8c7
 static void
39d8c7
 on_session_opened (GdmSession           *session,
39d8c7
                    const char           *service_name,
39d8c7
                    const char           *session_id,
39d8c7
                    GdmLaunchEnvironment *launch_environment)
39d8c7
 {
39d8c7
         launch_environment->priv->session_id = g_strdup (session_id);
39d8c7
 
39d8c7
         g_signal_emit (G_OBJECT (launch_environment), signals [OPENED], 0);
39d8c7
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
39d8c7
index 8a4ef06cd..141d64c6b 100644
39d8c7
--- a/daemon/gdm-local-display-factory.c
39d8c7
+++ b/daemon/gdm-local-display-factory.c
39d8c7
@@ -156,126 +156,225 @@ take_next_display_number (GdmLocalDisplayFactory *factory)
39d8c7
 
39d8c7
         g_debug ("GdmLocalDisplayFactory: Found the following X displays:");
39d8c7
         for (l = list; l != NULL; l = l->next) {
39d8c7
                 g_debug ("GdmLocalDisplayFactory: %u", GPOINTER_TO_UINT (l->data));
39d8c7
         }
39d8c7
 
39d8c7
         for (l = list; l != NULL; l = l->next) {
39d8c7
                 guint32 num;
39d8c7
                 num = GPOINTER_TO_UINT (l->data);
39d8c7
 
39d8c7
                 /* always fill zero */
39d8c7
                 if (l->prev == NULL && num != 0) {
39d8c7
                         ret = 0;
39d8c7
                         break;
39d8c7
                 }
39d8c7
                 /* now find the first hole */
39d8c7
                 if (l->next == NULL || GPOINTER_TO_UINT (l->next->data) != (num + 1)) {
39d8c7
                         ret = num + 1;
39d8c7
                         break;
39d8c7
                 }
39d8c7
         }
39d8c7
  out:
39d8c7
 
39d8c7
         /* now reserve this number */
39d8c7
         g_debug ("GdmLocalDisplayFactory: Reserving X display: %u", ret);
39d8c7
         g_hash_table_insert (factory->used_display_numbers, GUINT_TO_POINTER (ret), NULL);
39d8c7
 
39d8c7
         return ret;
39d8c7
 }
39d8c7
 
39d8c7
+static char *
39d8c7
+get_preferred_display_server (GdmLocalDisplayFactory *factory)
39d8c7
+{
39d8c7
+        g_autofree gchar *preferred_display_server = NULL;
39d8c7
+        gboolean wayland_enabled = FALSE, xorg_enabled = FALSE;
39d8c7
+
39d8c7
+        gdm_settings_direct_get_boolean (GDM_KEY_WAYLAND_ENABLE, &wayland_enabled);
39d8c7
+        gdm_settings_direct_get_boolean (GDM_KEY_XORG_ENABLE, &xorg_enabled);
39d8c7
+
39d8c7
+        if (wayland_enabled && !xorg_enabled) {
39d8c7
+                return g_strdup ("wayland");
39d8c7
+        }
39d8c7
+
39d8c7
+        if (!wayland_enabled && !xorg_enabled) {
39d8c7
+                return g_strdup ("none");
39d8c7
+        }
39d8c7
+
39d8c7
+        gdm_settings_direct_get_string (GDM_KEY_PREFERRED_DISPLAY_SERVER, &preferred_display_server);
39d8c7
+
39d8c7
+        if (g_strcmp0 (preferred_display_server, "wayland") == 0) {
39d8c7
+                if (wayland_enabled)
39d8c7
+                        return g_strdup (preferred_display_server);
39d8c7
+                else
39d8c7
+                        return g_strdup ("xorg");
39d8c7
+        }
39d8c7
+
39d8c7
+        if (g_strcmp0 (preferred_display_server, "xorg") == 0) {
39d8c7
+                if (xorg_enabled)
39d8c7
+                        return g_strdup (preferred_display_server);
39d8c7
+                else
39d8c7
+                        return g_strdup ("wayland");
39d8c7
+        }
39d8c7
+
39d8c7
+        if (g_strcmp0 (preferred_display_server, "legacy-xorg") == 0) {
39d8c7
+                if (xorg_enabled)
39d8c7
+                        return g_strdup (preferred_display_server);
39d8c7
+        }
39d8c7
+
39d8c7
+        return g_strdup ("none");
39d8c7
+}
39d8c7
+
39d8c7
+static const char *
39d8c7
+gdm_local_display_factory_get_session_type (GdmLocalDisplayFactory *factory,
39d8c7
+                                            gboolean                should_fall_back)
39d8c7
+{
39d8c7
+        const char *session_types[3] = { NULL };
39d8c7
+        gsize i, session_type_index = 0;
39d8c7
+        g_autofree gchar *preferred_display_server = NULL;
39d8c7
+
39d8c7
+        preferred_display_server = get_preferred_display_server (factory);
39d8c7
+
39d8c7
+        if (g_strcmp0 (preferred_display_server, "wayland") != 0 &&
39d8c7
+            g_strcmp0 (preferred_display_server, "xorg") != 0)
39d8c7
+              return NULL;
39d8c7
+
39d8c7
+        for (i = 0; i < G_N_ELEMENTS (session_types) - 1; i++) {
39d8c7
+#ifdef ENABLE_WAYLAND_SUPPORT
39d8c7
+            if (i > 0 ||
39d8c7
+                g_strcmp0 (preferred_display_server, "wayland") == 0) {
39d8c7
+                    gboolean wayland_enabled = FALSE;
39d8c7
+                    if (gdm_settings_direct_get_boolean (GDM_KEY_WAYLAND_ENABLE, &wayland_enabled)) {
39d8c7
+                            if (wayland_enabled && g_file_test ("/usr/bin/Xwayland", G_FILE_TEST_IS_EXECUTABLE)) {
39d8c7
+                                    session_types[i] = "wayland";
39d8c7
+                                    continue;
39d8c7
+                            }
39d8c7
+                    }
39d8c7
+            }
39d8c7
+#endif
39d8c7
+
39d8c7
+            if (i > 0 ||
39d8c7
+                g_strcmp0 (preferred_display_server, "xorg") == 0) {
39d8c7
+                    gboolean xorg_enabled = FALSE;
39d8c7
+                    if (gdm_settings_direct_get_boolean (GDM_KEY_XORG_ENABLE, &xorg_enabled)) {
39d8c7
+                            if (xorg_enabled && g_file_test ("/usr/bin/Xorg", G_FILE_TEST_IS_EXECUTABLE)) {
39d8c7
+                                    session_types[i] = "x11";
39d8c7
+                                    continue;
39d8c7
+                            }
39d8c7
+                    }
39d8c7
+            }
39d8c7
+        }
39d8c7
+
39d8c7
+        if (should_fall_back)
39d8c7
+                session_type_index++;
39d8c7
+
39d8c7
+        return session_types[session_type_index];
39d8c7
+}
39d8c7
+
39d8c7
 static void
39d8c7
 on_display_disposed (GdmLocalDisplayFactory *factory,
39d8c7
                      GdmDisplay             *display)
39d8c7
 {
39d8c7
         g_debug ("GdmLocalDisplayFactory: Display %p disposed", display);
39d8c7
 }
39d8c7
 
39d8c7
 static void
39d8c7
 store_display (GdmLocalDisplayFactory *factory,
39d8c7
                GdmDisplay             *display)
39d8c7
 {
39d8c7
         GdmDisplayStore *store;
39d8c7
 
39d8c7
         store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
39d8c7
         gdm_display_store_add (store, display);
39d8c7
 }
39d8c7
 
39d8c7
-static gboolean
39d8c7
-gdm_local_display_factory_use_wayland (void)
39d8c7
-{
39d8c7
-#ifdef ENABLE_WAYLAND_SUPPORT
39d8c7
-        gboolean wayland_enabled = FALSE;
39d8c7
-        if (gdm_settings_direct_get_boolean (GDM_KEY_WAYLAND_ENABLE, &wayland_enabled)) {
39d8c7
-                if (wayland_enabled && g_file_test ("/usr/bin/Xwayland", G_FILE_TEST_IS_EXECUTABLE) )
39d8c7
-                        return TRUE;
39d8c7
-        }
39d8c7
-#endif
39d8c7
-        return FALSE;
39d8c7
-}
39d8c7
-
39d8c7
 /*
39d8c7
   Example:
39d8c7
   dbus-send --system --dest=org.gnome.DisplayManager \
39d8c7
   --type=method_call --print-reply --reply-timeout=2000 \
39d8c7
   /org/gnome/DisplayManager/Manager \
39d8c7
   org.gnome.DisplayManager.Manager.GetDisplays
39d8c7
 */
39d8c7
 gboolean
39d8c7
 gdm_local_display_factory_create_transient_display (GdmLocalDisplayFactory *factory,
39d8c7
                                                     char                  **id,
39d8c7
                                                     GError                **error)
39d8c7
 {
39d8c7
         gboolean         ret;
39d8c7
         GdmDisplay      *display = NULL;
39d8c7
         gboolean         is_initial = FALSE;
39d8c7
+        const char      *session_type;
39d8c7
+        g_autofree gchar *preferred_display_server = NULL;
39d8c7
 
39d8c7
         g_return_val_if_fail (GDM_IS_LOCAL_DISPLAY_FACTORY (factory), FALSE);
39d8c7
 
39d8c7
         ret = FALSE;
39d8c7
 
39d8c7
         g_debug ("GdmLocalDisplayFactory: Creating transient display");
39d8c7
 
39d8c7
-#ifdef ENABLE_USER_DISPLAY_SERVER
39d8c7
-        display = gdm_local_display_new ();
39d8c7
-        if (gdm_local_display_factory_use_wayland ())
39d8c7
-                g_object_set (G_OBJECT (display), "session-type", "wayland", NULL);
39d8c7
-        is_initial = TRUE;
39d8c7
-#else
39d8c7
-        if (display == NULL) {
39d8c7
-                guint32 num;
39d8c7
+        preferred_display_server = get_preferred_display_server (factory);
39d8c7
 
39d8c7
-                num = take_next_display_number (factory);
39d8c7
+#ifdef ENABLE_USER_DISPLAY_SERVER
39d8c7
+        if (g_strcmp0 (preferred_display_server, "wayland") == 0 ||
39d8c7
+            g_strcmp0 (preferred_display_server, "xorg") == 0) {
39d8c7
+                session_type = gdm_local_display_factory_get_session_type (factory, FALSE);
39d8c7
+
39d8c7
+                if (session_type == NULL) {
39d8c7
+                        g_set_error_literal (error,
39d8c7
+                                             GDM_DISPLAY_ERROR,
39d8c7
+                                             GDM_DISPLAY_ERROR_GENERAL,
39d8c7
+                                             "Both Wayland and Xorg are unavailable");
39d8c7
+                        return FALSE;
39d8c7
+                }
39d8c7
 
39d8c7
-                display = gdm_legacy_display_new (num);
39d8c7
+                display = gdm_local_display_new ();
39d8c7
+                g_object_set (G_OBJECT (display), "session-type", session_type, NULL);
39d8c7
+                is_initial = TRUE;
39d8c7
         }
39d8c7
 #endif
39d8c7
+        if (g_strcmp0 (preferred_display_server, "legacy-xorg") == 0) {
39d8c7
+                if (display == NULL) {
39d8c7
+                        guint32 num;
39d8c7
+
39d8c7
+                        num = take_next_display_number (factory);
39d8c7
+
39d8c7
+                        display = gdm_legacy_display_new (num);
39d8c7
+                }
39d8c7
+        }
39d8c7
+
39d8c7
+        if (display == NULL) {
39d8c7
+                g_set_error_literal (error,
39d8c7
+                                     GDM_DISPLAY_ERROR,
39d8c7
+                                     GDM_DISPLAY_ERROR_GENERAL,
39d8c7
+                                     "Invalid preferred display server configured");
39d8c7
+                return FALSE;
39d8c7
+        }
39d8c7
 
39d8c7
         g_object_set (display,
39d8c7
                       "seat-id", "seat0",
39d8c7
                       "allow-timed-login", FALSE,
39d8c7
                       "is-initial", is_initial,
39d8c7
                       NULL);
39d8c7
 
39d8c7
         store_display (factory, display);
39d8c7
 
39d8c7
         if (! gdm_display_manage (display)) {
39d8c7
                 display = NULL;
39d8c7
                 goto out;
39d8c7
         }
39d8c7
 
39d8c7
         if (! gdm_display_get_id (display, id, NULL)) {
39d8c7
                 display = NULL;
39d8c7
                 goto out;
39d8c7
         }
39d8c7
 
39d8c7
         ret = TRUE;
39d8c7
  out:
39d8c7
         /* ref either held by store or not at all */
39d8c7
         g_object_unref (display);
39d8c7
 
39d8c7
         return ret;
39d8c7
 }
39d8c7
 
39d8c7
 static void
39d8c7
 finish_display_on_seat_if_waiting (GdmDisplayStore *display_store,
39d8c7
                                    GdmDisplay      *display,
39d8c7
@@ -454,190 +553,239 @@ lookup_prepared_display_by_seat_id (const char *id,
39d8c7
         return lookup_by_seat_id (id, display, user_data);
39d8c7
 }
39d8c7
 
39d8c7
 static int
39d8c7
 on_seat0_graphics_check_timeout (gpointer user_data)
39d8c7
 {
39d8c7
         GdmLocalDisplayFactory *factory = user_data;
39d8c7
 
39d8c7
         factory->seat0_graphics_check_timeout_id = 0;
39d8c7
 
39d8c7
         /* Simply try to re-add seat0. If it is there already (i.e. CanGraphical
39d8c7
          * turned TRUE, then we'll find it and it will not be created again).
39d8c7
          */
39d8c7
         factory->seat0_graphics_check_timed_out = TRUE;
39d8c7
         ensure_display_for_seat (factory, "seat0");
39d8c7
 
39d8c7
         return G_SOURCE_REMOVE;
39d8c7
 }
39d8c7
 
39d8c7
 static void
39d8c7
 ensure_display_for_seat (GdmLocalDisplayFactory *factory,
39d8c7
                          const char             *seat_id)
39d8c7
 {
39d8c7
         int ret;
39d8c7
         gboolean seat_supports_graphics;
39d8c7
         gboolean is_seat0;
39d8c7
         const char *session_type = "wayland";
39d8c7
         GdmDisplayStore *store;
39d8c7
         GdmDisplay      *display = NULL;
39d8c7
         g_autofree char *login_session_id = NULL;
39d8c7
+        gboolean wayland_enabled = FALSE, xorg_enabled = FALSE;
39d8c7
+        g_autofree gchar *preferred_display_server = NULL;
39d8c7
+        gboolean falling_back;
39d8c7
+
39d8c7
+        gdm_settings_direct_get_boolean (GDM_KEY_WAYLAND_ENABLE, &wayland_enabled);
39d8c7
+        gdm_settings_direct_get_boolean (GDM_KEY_XORG_ENABLE, &xorg_enabled);
39d8c7
+
39d8c7
+        preferred_display_server = get_preferred_display_server (factory);
39d8c7
+
39d8c7
+        if (g_strcmp0 (preferred_display_server, "none") == 0) {
39d8c7
+               g_debug ("GdmLocalDisplayFactory: Preferred display server is none, so not creating display");
39d8c7
+               return;
39d8c7
+        }
39d8c7
 
39d8c7
         ret = sd_seat_can_graphical (seat_id);
39d8c7
 
39d8c7
         if (ret < 0) {
39d8c7
                 g_critical ("Failed to query CanGraphical information for seat %s", seat_id);
39d8c7
                 return;
39d8c7
         }
39d8c7
 
39d8c7
         if (ret == 0) {
39d8c7
                 g_debug ("GdmLocalDisplayFactory: System doesn't currently support graphics");
39d8c7
                 seat_supports_graphics = FALSE;
39d8c7
         } else {
39d8c7
                 g_debug ("GdmLocalDisplayFactory: System supports graphics");
39d8c7
                 seat_supports_graphics = TRUE;
39d8c7
         }
39d8c7
 
39d8c7
         if (g_strcmp0 (seat_id, "seat0") == 0) {
39d8c7
                 is_seat0 = TRUE;
39d8c7
 
39d8c7
-                /* If we've failed, or are explicitly told to, fall back to legacy X11 support
39d8c7
-                 */
39d8c7
-                if (factory->num_failures > 0 || !gdm_local_display_factory_use_wayland ()) {
39d8c7
-                        session_type = NULL;
39d8c7
-                        g_debug ("GdmLocalDisplayFactory: New displays on seat0 will use X11 fallback");
39d8c7
-                } else {
39d8c7
-                        g_debug ("GdmLocalDisplayFactory: New displays on seat0 will use wayland");
39d8c7
-                }
39d8c7
+                falling_back = factory->num_failures > 0;
39d8c7
+                session_type = gdm_local_display_factory_get_session_type (factory, falling_back);
39d8c7
+
39d8c7
+                g_debug ("GdmLocalDisplayFactory: New displays on seat0 will use %s%s",
39d8c7
+                         session_type, falling_back? " fallback" : "");
39d8c7
         } else {
39d8c7
                 is_seat0 = FALSE;
39d8c7
 
39d8c7
                 g_debug ("GdmLocalDisplayFactory: New displays on seat %s will use X11 fallback", seat_id);
39d8c7
                 /* Force legacy X11 for all auxiliary seats */
39d8c7
                 seat_supports_graphics = TRUE;
39d8c7
-                session_type = NULL;
39d8c7
+                session_type = "x11";
39d8c7
         }
39d8c7
 
39d8c7
         /* For seat0, we have a fallback logic to still try starting it after
39d8c7
          * SEAT0_GRAPHICS_CHECK_TIMEOUT seconds. i.e. we simply continue even if
39d8c7
          * CanGraphical is unset.
39d8c7
          * This is ugly, but it means we'll come up eventually in some
39d8c7
          * scenarios where no master device is present.
39d8c7
          * Note that we'll force an X11 fallback even though there might be
39d8c7
          * cases where an wayland capable device is present and simply not marked as
39d8c7
          * master-of-seat. In these cases, this should likely be fixed in the
39d8c7
          * udev rules.
39d8c7
          *
39d8c7
          * At the moment, systemd always sets CanGraphical for non-seat0 seats.
39d8c7
          * This is because non-seat0 seats are defined by having master-of-seat
39d8c7
          * set. This means we can avoid the fallback check for non-seat0 seats,
39d8c7
          * which simplifies the code.
39d8c7
          */
39d8c7
         if (is_seat0) {
39d8c7
                 if (!seat_supports_graphics) {
39d8c7
                         if (!factory->seat0_graphics_check_timed_out) {
39d8c7
                                 if (factory->seat0_graphics_check_timeout_id == 0) {
39d8c7
                                         g_debug ("GdmLocalDisplayFactory: seat0 doesn't yet support graphics.  Waiting %d seconds to try again.", SEAT0_GRAPHICS_CHECK_TIMEOUT);
39d8c7
                                         factory->seat0_graphics_check_timeout_id = g_timeout_add_seconds (SEAT0_GRAPHICS_CHECK_TIMEOUT,
39d8c7
                                                                                                           on_seat0_graphics_check_timeout,
39d8c7
                                                                                                           factory);
39d8c7
 
39d8c7
                                 } else {
39d8c7
                                         /* It is not yet time to force X11 fallback. */
39d8c7
                                         g_debug ("GdmLocalDisplayFactory: seat0 display requested when there is no graphics support before graphics check timeout.");
39d8c7
                                 }
39d8c7
 
39d8c7
                                 return;
39d8c7
                         }
39d8c7
 
39d8c7
                         g_debug ("GdmLocalDisplayFactory: Assuming we can use seat0 for X11 even though system says it doesn't support graphics!");
39d8c7
                         g_debug ("GdmLocalDisplayFactory: This might indicate an issue where the framebuffer device is not tagged as master-of-seat in udev.");
39d8c7
                         seat_supports_graphics = TRUE;
39d8c7
-                        session_type = NULL;
39d8c7
+                        session_type = "x11";
39d8c7
+                        wayland_enabled = FALSE;
39d8c7
                 } else {
39d8c7
                         g_clear_handle_id (&factory->seat0_graphics_check_timeout_id, g_source_remove);
39d8c7
                 }
39d8c7
         }
39d8c7
 
39d8c7
         if (!seat_supports_graphics)
39d8c7
                 return;
39d8c7
 
39d8c7
-        g_debug ("GdmLocalDisplayFactory: %s login display for seat %s requested",
39d8c7
-                 session_type? : "X11", seat_id);
39d8c7
+        if (session_type != NULL)
39d8c7
+                g_debug ("GdmLocalDisplayFactory: %s login display for seat %s requested",
39d8c7
+                         session_type, seat_id);
39d8c7
+        else if (g_strcmp0 (preferred_display_server, "legacy-xorg") == 0)
39d8c7
+                g_debug ("GdmLocalDisplayFactory: Legacy Xorg login display for seat %s requested",
39d8c7
+                         seat_id);
39d8c7
+
39d8c7
         store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
39d8c7
 
39d8c7
         if (is_seat0)
39d8c7
                 display = gdm_display_store_find (store, lookup_prepared_display_by_seat_id, (gpointer) seat_id);
39d8c7
         else
39d8c7
                 display = gdm_display_store_find (store, lookup_by_seat_id, (gpointer) seat_id);
39d8c7
 
39d8c7
         /* Ensure we don't create the same display more than once */
39d8c7
         if (display != NULL) {
39d8c7
                 g_debug ("GdmLocalDisplayFactory: display already created");
39d8c7
                 return;
39d8c7
         }
39d8c7
 
39d8c7
         /* If we already have a login window, switch to it */
39d8c7
         if (gdm_get_login_window_session_id (seat_id, &login_session_id)) {
39d8c7
                 GdmDisplay *display;
39d8c7
 
39d8c7
                 display = gdm_display_store_find (store,
39d8c7
                                                   lookup_by_session_id,
39d8c7
                                                   (gpointer) login_session_id);
39d8c7
                 if (display != NULL &&
39d8c7
                     (gdm_display_get_status (display) == GDM_DISPLAY_MANAGED ||
39d8c7
                      gdm_display_get_status (display) == GDM_DISPLAY_WAITING_TO_FINISH)) {
39d8c7
                         g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_MANAGED, NULL);
39d8c7
                         g_debug ("GdmLocalDisplayFactory: session %s found, activating.",
39d8c7
                                  login_session_id);
39d8c7
                         gdm_activate_session_by_id (factory->connection, seat_id, login_session_id);
39d8c7
                         return;
39d8c7
                 }
39d8c7
         }
39d8c7
 
39d8c7
         g_debug ("GdmLocalDisplayFactory: Adding display on seat %s", seat_id);
39d8c7
 
39d8c7
 #ifdef ENABLE_USER_DISPLAY_SERVER
39d8c7
-        if (is_seat0) {
39d8c7
-                display = gdm_local_display_new ();
39d8c7
-                if (session_type != NULL) {
39d8c7
+        if (g_strcmp0 (preferred_display_server, "wayland") == 0 ||
39d8c7
+            g_strcmp0 (preferred_display_server, "xorg") == 0) {
39d8c7
+                if (is_seat0) {
39d8c7
+                        g_autoptr (GPtrArray) supported_session_types = NULL;
39d8c7
+
39d8c7
+                        if (session_type == NULL) {
39d8c7
+                                g_warning ("GdmLocalDisplayFactory: Both Wayland and Xorg sessions are unavailable");
39d8c7
+                                return;
39d8c7
+                        }
39d8c7
+
39d8c7
+                        supported_session_types = g_ptr_array_new ();
39d8c7
+
39d8c7
+                        if (g_strcmp0 (preferred_display_server, "wayland") == 0) {
39d8c7
+                                if (wayland_enabled)
39d8c7
+                                        g_ptr_array_add (supported_session_types, "wayland");
39d8c7
+                        } else {
39d8c7
+                                if (xorg_enabled)
39d8c7
+                                        g_ptr_array_add (supported_session_types, "x11");
39d8c7
+                        }
39d8c7
+
39d8c7
+                        if (!falling_back) {
39d8c7
+                                if (g_strcmp0 (preferred_display_server, "wayland") == 0) {
39d8c7
+                                        if (xorg_enabled)
39d8c7
+                                                g_ptr_array_add (supported_session_types, "x11");
39d8c7
+                                } else {
39d8c7
+                                        if (wayland_enabled)
39d8c7
+                                                g_ptr_array_add (supported_session_types, "wayland");
39d8c7
+                                }
39d8c7
+                        }
39d8c7
+
39d8c7
+                        g_ptr_array_add (supported_session_types, NULL);
39d8c7
+
39d8c7
+                        display = gdm_local_display_new ();
39d8c7
                         g_object_set (G_OBJECT (display), "session-type", session_type, NULL);
39d8c7
+                        g_object_set (G_OBJECT (display), "supported-session-types", supported_session_types->pdata, NULL);
39d8c7
                 }
39d8c7
         }
39d8c7
 #endif
39d8c7
 
39d8c7
         if (display == NULL) {
39d8c7
                 guint32 num;
39d8c7
+                const char *supported_session_types[] = { "x11", NULL };
39d8c7
 
39d8c7
                 num = take_next_display_number (factory);
39d8c7
 
39d8c7
                 display = gdm_legacy_display_new (num);
39d8c7
+                g_object_set (G_OBJECT (display), "supported-session-types", supported_session_types, NULL);
39d8c7
         }
39d8c7
 
39d8c7
         g_object_set (display, "seat-id", seat_id, NULL);
39d8c7
         g_object_set (display, "is-initial", is_seat0, NULL);
39d8c7
 
39d8c7
         store_display (factory, display);
39d8c7
 
39d8c7
         /* let store own the ref */
39d8c7
         g_object_unref (display);
39d8c7
 
39d8c7
         if (! gdm_display_manage (display)) {
39d8c7
                 gdm_display_unmanage (display);
39d8c7
         }
39d8c7
 
39d8c7
         return;
39d8c7
 }
39d8c7
 
39d8c7
 static void
39d8c7
 delete_display (GdmLocalDisplayFactory *factory,
39d8c7
                 const char             *seat_id) {
39d8c7
 
39d8c7
         GdmDisplayStore *store;
39d8c7
 
39d8c7
         g_debug ("GdmLocalDisplayFactory: Removing used_display_numbers on seat %s", seat_id);
39d8c7
 
39d8c7
         store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
39d8c7
         gdm_display_store_foreach_remove (store, lookup_by_seat_id, (gpointer) seat_id);
39d8c7
 }
39d8c7
 
39d8c7
 static gboolean
39d8c7
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
39d8c7
index 9c10adff3..4c2752fee 100644
39d8c7
--- a/daemon/gdm-manager.c
39d8c7
+++ b/daemon/gdm-manager.c
39d8c7
@@ -1306,74 +1306,75 @@ get_automatic_login_details (GdmManager *manager,
39d8c7
                 *usernamep = username;
39d8c7
         } else {
39d8c7
                 g_free (username);
39d8c7
         }
39d8c7
 
39d8c7
         return enabled;
39d8c7
 }
39d8c7
 
39d8c7
 static const char *
39d8c7
 get_username_for_greeter_display (GdmManager *manager,
39d8c7
                                   GdmDisplay *display)
39d8c7
 {
39d8c7
         gboolean doing_initial_setup = FALSE;
39d8c7
 
39d8c7
         g_object_get (G_OBJECT (display),
39d8c7
                       "doing-initial-setup", &doing_initial_setup,
39d8c7
                       NULL);
39d8c7
 
39d8c7
         if (doing_initial_setup) {
39d8c7
                 return INITIAL_SETUP_USERNAME;
39d8c7
         } else {
39d8c7
                 return GDM_USERNAME;
39d8c7
         }
39d8c7
 }
39d8c7
 
39d8c7
 static void
39d8c7
 set_up_automatic_login_session (GdmManager *manager,
39d8c7
                                 GdmDisplay *display)
39d8c7
 {
39d8c7
         GdmSession *session;
39d8c7
-        char       *display_session_type = NULL;
39d8c7
+        g_auto (GStrv) supported_session_types = NULL;
39d8c7
 
39d8c7
         /* 0 is root user; since the daemon talks to the session object
39d8c7
          * directly, itself, for automatic login
39d8c7
          */
39d8c7
         create_user_session_for_display (manager, display, 0);
39d8c7
         session = get_user_session_for_display (display);
39d8c7
 
39d8c7
         g_object_get (G_OBJECT (display),
39d8c7
-                      "session-type", &display_session_type,
39d8c7
+                      "supported-session-types", &supported_session_types,
39d8c7
                       NULL);
39d8c7
 
39d8c7
         g_object_set (G_OBJECT (session),
39d8c7
                       "display-is-initial", FALSE,
39d8c7
+                      "supported-session-types", supported_session_types,
39d8c7
                       NULL);
39d8c7
 
39d8c7
         g_debug ("GdmManager: Starting automatic login conversation");
39d8c7
         gdm_session_start_conversation (session, "gdm-autologin");
39d8c7
 }
39d8c7
 
39d8c7
 static void
39d8c7
 set_up_chooser_session (GdmManager *manager,
39d8c7
                         GdmDisplay *display)
39d8c7
 {
39d8c7
         const char *allowed_user;
39d8c7
         struct passwd *passwd_entry;
39d8c7
 
39d8c7
         allowed_user = get_username_for_greeter_display (manager, display);
39d8c7
 
39d8c7
         if (!gdm_get_pwent_for_name (allowed_user, &passwd_entry)) {
39d8c7
                 g_warning ("GdmManager: couldn't look up username %s",
39d8c7
                            allowed_user);
39d8c7
                 gdm_display_unmanage (display);
39d8c7
                 gdm_display_finish (display);
39d8c7
                 return;
39d8c7
         }
39d8c7
 
39d8c7
         gdm_display_start_greeter_session (display);
39d8c7
 }
39d8c7
 
39d8c7
 static void
39d8c7
 set_up_greeter_session (GdmManager *manager,
39d8c7
                         GdmDisplay *display)
39d8c7
 {
39d8c7
@@ -2278,87 +2279,85 @@ on_session_reauthentication_started (GdmSession *session,
39d8c7
 
39d8c7
         if (invocation != NULL) {
39d8c7
                 g_hash_table_steal (manager->priv->open_reauthentication_requests,
39d8c7
                                     source_tag);
39d8c7
                 gdm_dbus_manager_complete_open_reauthentication_channel (GDM_DBUS_MANAGER (manager),
39d8c7
                                                                          invocation,
39d8c7
                                                                          address);
39d8c7
         }
39d8c7
 }
39d8c7
 
39d8c7
 static void
39d8c7
 clean_user_session (GdmSession *session)
39d8c7
 {
39d8c7
         g_object_set_data (G_OBJECT (session), "gdm-display", NULL);
39d8c7
         g_object_unref (session);
39d8c7
 }
39d8c7
 
39d8c7
 static void
39d8c7
 create_user_session_for_display (GdmManager *manager,
39d8c7
                                  GdmDisplay *display,
39d8c7
                                  uid_t       allowed_user)
39d8c7
 {
39d8c7
         GdmSession *session;
39d8c7
         gboolean    display_is_local = FALSE;
39d8c7
         char       *display_name = NULL;
39d8c7
         char       *display_device = NULL;
39d8c7
         char       *remote_hostname = NULL;
39d8c7
         char       *display_auth_file = NULL;
39d8c7
         char       *display_seat_id = NULL;
39d8c7
         char       *display_id = NULL;
39d8c7
-#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
39d8c7
-        g_autofree char *display_session_type = NULL;
39d8c7
-        gboolean    greeter_is_wayland;
39d8c7
-#endif
39d8c7
+        g_auto (GStrv) supported_session_types = NULL;
39d8c7
 
39d8c7
         g_object_get (G_OBJECT (display),
39d8c7
                       "id", &display_id,
39d8c7
                       "x11-display-name", &display_name,
39d8c7
                       "is-local", &display_is_local,
39d8c7
                       "remote-hostname", &remote_hostname,
39d8c7
                       "x11-authority-file", &display_auth_file,
39d8c7
                       "seat-id", &display_seat_id,
39d8c7
-#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
39d8c7
-                      "session-type", &display_session_type,
39d8c7
-#endif
39d8c7
+                      "supported-session-types", &supported_session_types,
39d8c7
                       NULL);
39d8c7
         display_device = get_display_device (manager, display);
39d8c7
 
39d8c7
         session = gdm_session_new (GDM_SESSION_VERIFICATION_MODE_LOGIN,
39d8c7
                                    allowed_user,
39d8c7
                                    display_name,
39d8c7
                                    remote_hostname,
39d8c7
                                    display_device,
39d8c7
                                    display_seat_id,
39d8c7
                                    display_auth_file,
39d8c7
                                    display_is_local,
39d8c7
                                    NULL);
39d8c7
+        g_object_set (G_OBJECT (session),
39d8c7
+                      "supported-session-types", supported_session_types,
39d8c7
+                      NULL);
39d8c7
 
39d8c7
         g_debug ("GdmSession: Created user session for user %d on display %s (seat %s)",
39d8c7
                  (int) allowed_user,
39d8c7
                  display_id,
39d8c7
                  display_seat_id);
39d8c7
 
39d8c7
         g_free (display_name);
39d8c7
         g_free (remote_hostname);
39d8c7
         g_free (display_auth_file);
39d8c7
         g_free (display_seat_id);
39d8c7
 
39d8c7
         g_signal_connect (session,
39d8c7
                           "reauthentication-started",
39d8c7
                           G_CALLBACK (on_session_reauthentication_started),
39d8c7
                           manager);
39d8c7
         g_signal_connect (session,
39d8c7
                           "reauthenticated",
39d8c7
                           G_CALLBACK (on_session_reauthenticated),
39d8c7
                           manager);
39d8c7
         g_signal_connect (session,
39d8c7
                           "client-ready-for-session-to-start",
39d8c7
                           G_CALLBACK (on_session_client_ready_for_session_to_start),
39d8c7
                           manager);
39d8c7
         g_signal_connect (session,
39d8c7
                           "client-connected",
39d8c7
                           G_CALLBACK (on_session_client_connected),
39d8c7
                           manager);
39d8c7
         g_signal_connect (session,
39d8c7
                           "client-disconnected",
39d8c7
                           G_CALLBACK (on_session_client_disconnected),
39d8c7
@@ -2378,65 +2377,60 @@ create_user_session_for_display (GdmManager *manager,
39d8c7
         g_signal_connect (session,
39d8c7
                           "authentication-failed",
39d8c7
                           G_CALLBACK (on_session_authentication_failed),
39d8c7
                           manager);
39d8c7
         g_signal_connect (session,
39d8c7
                           "session-opened",
39d8c7
                           G_CALLBACK (on_user_session_opened),
39d8c7
                           manager);
39d8c7
         g_signal_connect (session,
39d8c7
                           "session-started",
39d8c7
                           G_CALLBACK (on_user_session_started),
39d8c7
                           manager);
39d8c7
         g_signal_connect (session,
39d8c7
                           "session-start-failed",
39d8c7
                           G_CALLBACK (on_session_start_failed),
39d8c7
                           manager);
39d8c7
         g_signal_connect (session,
39d8c7
                           "session-exited",
39d8c7
                           G_CALLBACK (on_user_session_exited),
39d8c7
                           manager);
39d8c7
         g_signal_connect (session,
39d8c7
                           "session-died",
39d8c7
                           G_CALLBACK (on_user_session_died),
39d8c7
                           manager);
39d8c7
         g_object_set_data (G_OBJECT (session), "gdm-display", display);
39d8c7
         g_object_set_data_full (G_OBJECT (display),
39d8c7
                                 "gdm-user-session",
39d8c7
                                 session,
39d8c7
                                 (GDestroyNotify)
39d8c7
                                 clean_user_session);
39d8c7
-
39d8c7
-#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
39d8c7
-        greeter_is_wayland = g_strcmp0 (display_session_type, "wayland") == 0;
39d8c7
-        g_object_set (G_OBJECT (session), "ignore-wayland", !greeter_is_wayland, NULL);
39d8c7
-#endif
39d8c7
 }
39d8c7
 
39d8c7
 static void
39d8c7
 on_display_added (GdmDisplayStore *display_store,
39d8c7
                   const char      *id,
39d8c7
                   GdmManager      *manager)
39d8c7
 {
39d8c7
         GdmDisplay *display;
39d8c7
 
39d8c7
         display = gdm_display_store_lookup (display_store, id);
39d8c7
 
39d8c7
         if (display != NULL) {
39d8c7
                 g_dbus_object_manager_server_export (manager->priv->object_manager,
39d8c7
                                                      gdm_display_get_object_skeleton (display));
39d8c7
 
39d8c7
                 g_signal_connect (display, "notify::status",
39d8c7
                                   G_CALLBACK (on_display_status_changed),
39d8c7
                                   manager);
39d8c7
                 g_signal_emit (manager, signals[DISPLAY_ADDED], 0, id);
39d8c7
         }
39d8c7
 }
39d8c7
 
39d8c7
 GQuark
39d8c7
 gdm_manager_error_quark (void)
39d8c7
 {
39d8c7
         static GQuark ret = 0;
39d8c7
         if (ret == 0) {
39d8c7
                 ret = g_quark_from_static_string ("gdm_manager_error");
39d8c7
         }
39d8c7
 
39d8c7
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
39d8c7
index a010cecf5..2b941e5e1 100644
39d8c7
--- a/daemon/gdm-session.c
39d8c7
+++ b/daemon/gdm-session.c
39d8c7
@@ -106,84 +106,81 @@ struct _GdmSession
39d8c7
         GdmDBusUserVerifier   *user_verifier_interface;
39d8c7
         GHashTable            *user_verifier_extensions;
39d8c7
         GdmDBusGreeter        *greeter_interface;
39d8c7
         GdmDBusRemoteGreeter  *remote_greeter_interface;
39d8c7
         GdmDBusChooser        *chooser_interface;
39d8c7
 
39d8c7
         GList               *pending_worker_connections;
39d8c7
         GList               *outside_connections;
39d8c7
 
39d8c7
         GPid                 session_pid;
39d8c7
 
39d8c7
         /* object lifetime scope */
39d8c7
         char                *session_type;
39d8c7
         char                *display_name;
39d8c7
         char                *display_hostname;
39d8c7
         char                *display_device;
39d8c7
         char                *display_seat_id;
39d8c7
         char                *display_x11_authority_file;
39d8c7
         gboolean             display_is_local;
39d8c7
 
39d8c7
         GdmSessionVerificationMode verification_mode;
39d8c7
 
39d8c7
         uid_t                allowed_user;
39d8c7
 
39d8c7
         char                *fallback_session_name;
39d8c7
 
39d8c7
         GDBusServer         *worker_server;
39d8c7
         GDBusServer         *outside_server;
39d8c7
         GHashTable          *environment;
39d8c7
 
39d8c7
+        GStrv                supported_session_types;
39d8c7
+
39d8c7
         guint32              is_program_session : 1;
39d8c7
         guint32              display_is_initial : 1;
39d8c7
-#ifdef ENABLE_WAYLAND_SUPPORT
39d8c7
-        guint32              ignore_wayland : 1;
39d8c7
-#endif
39d8c7
 };
39d8c7
 
39d8c7
 enum {
39d8c7
         PROP_0,
39d8c7
         PROP_VERIFICATION_MODE,
39d8c7
         PROP_ALLOWED_USER,
39d8c7
         PROP_DISPLAY_NAME,
39d8c7
         PROP_DISPLAY_HOSTNAME,
39d8c7
         PROP_DISPLAY_IS_LOCAL,
39d8c7
         PROP_DISPLAY_IS_INITIAL,
39d8c7
         PROP_SESSION_TYPE,
39d8c7
         PROP_DISPLAY_DEVICE,
39d8c7
         PROP_DISPLAY_SEAT_ID,
39d8c7
         PROP_DISPLAY_X11_AUTHORITY_FILE,
39d8c7
         PROP_USER_X11_AUTHORITY_FILE,
39d8c7
         PROP_CONVERSATION_ENVIRONMENT,
39d8c7
-#ifdef ENABLE_WAYLAND_SUPPORT
39d8c7
-        PROP_IGNORE_WAYLAND,
39d8c7
-#endif
39d8c7
+        PROP_SUPPORTED_SESSION_TYPES,
39d8c7
 };
39d8c7
 
39d8c7
 enum {
39d8c7
         CONVERSATION_STARTED = 0,
39d8c7
         CONVERSATION_STOPPED,
39d8c7
         SETUP_COMPLETE,
39d8c7
         CANCELLED,
39d8c7
         HOSTNAME_SELECTED,
39d8c7
         CLIENT_REJECTED,
39d8c7
         CLIENT_CONNECTED,
39d8c7
         CLIENT_DISCONNECTED,
39d8c7
         CLIENT_READY_FOR_SESSION_TO_START,
39d8c7
         DISCONNECTED,
39d8c7
         AUTHENTICATION_FAILED,
39d8c7
         VERIFICATION_COMPLETE,
39d8c7
         SESSION_OPENED,
39d8c7
         SESSION_OPENED_FAILED,
39d8c7
         SESSION_STARTED,
39d8c7
         SESSION_START_FAILED,
39d8c7
         SESSION_EXITED,
39d8c7
         SESSION_DIED,
39d8c7
         REAUTHENTICATION_STARTED,
39d8c7
         REAUTHENTICATED,
39d8c7
         LAST_SIGNAL
39d8c7
 };
39d8c7
 
39d8c7
 #ifdef ENABLE_WAYLAND_SUPPORT
39d8c7
 static gboolean gdm_session_is_wayland_session (GdmSession *self);
39d8c7
 #endif
39d8c7
 static void update_session_type (GdmSession *self);
39d8c7
@@ -320,109 +317,117 @@ on_establish_credentials_cb (GdmDBusWorker *proxy,
39d8c7
             g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
39d8c7
                 return;
39d8c7
 
39d8c7
         self = g_object_ref (conversation->session);
39d8c7
         service_name = g_strdup (conversation->service_name);
39d8c7
 
39d8c7
         if (worked) {
39d8c7
                 switch (self->verification_mode) {
39d8c7
                 case GDM_SESSION_VERIFICATION_MODE_LOGIN:
39d8c7
                 case GDM_SESSION_VERIFICATION_MODE_CHOOSER:
39d8c7
                         gdm_session_open_session (self, service_name);
39d8c7
                         break;
39d8c7
                 case GDM_SESSION_VERIFICATION_MODE_REAUTHENTICATE:
39d8c7
                         if (self->user_verifier_interface != NULL) {
39d8c7
                                 gdm_dbus_user_verifier_emit_verification_complete (self->user_verifier_interface,
39d8c7
                                                                                    service_name);
39d8c7
                                 g_signal_emit (self, signals[VERIFICATION_COMPLETE], 0, service_name);
39d8c7
                         }
39d8c7
                         break;
39d8c7
                 default:
39d8c7
                         break;
39d8c7
                 }
39d8c7
         } else {
39d8c7
                 report_and_stop_conversation (self, service_name, error);
39d8c7
         }
39d8c7
 
39d8c7
         g_free (service_name);
39d8c7
         g_object_unref (self);
39d8c7
 }
39d8c7
 
39d8c7
+static gboolean
39d8c7
+supports_session_type (GdmSession *self,
39d8c7
+                       const char *session_type)
39d8c7
+{
39d8c7
+        if (session_type == NULL)
39d8c7
+                return TRUE;
39d8c7
+
39d8c7
+        return g_strv_contains ((const char * const *) self->supported_session_types,
39d8c7
+                                session_type);
39d8c7
+}
39d8c7
+
39d8c7
 static char **
39d8c7
 get_system_session_dirs (GdmSession *self,
39d8c7
                          const char *type)
39d8c7
 {
39d8c7
         GArray *search_array = NULL;
39d8c7
         char **search_dirs;
39d8c7
-        int i;
39d8c7
+        int i, j;
39d8c7
         const gchar * const *system_data_dirs = g_get_system_data_dirs ();
39d8c7
 
39d8c7
         static const char *x_search_dirs[] = {
39d8c7
                 "/etc/X11/sessions/",
39d8c7
                 DMCONFDIR "/Sessions/",
39d8c7
                 DATADIR "/gdm/BuiltInSessions/",
39d8c7
                 DATADIR "/xsessions/",
39d8c7
         };
39d8c7
 
39d8c7
         static const char *wayland_search_dir = DATADIR "/wayland-sessions/";
39d8c7
 
39d8c7
         search_array = g_array_new (TRUE, TRUE, sizeof (char *));
39d8c7
 
39d8c7
-        if (type == NULL || g_str_equal (type, "x11")) {
39d8c7
-                for (i = 0; system_data_dirs[i]; i++) {
39d8c7
-                        gchar *dir = g_build_filename (system_data_dirs[i], "xsessions", NULL);
39d8c7
-                        g_array_append_val (search_array, dir);
39d8c7
+        for (j = 0; self->supported_session_types[j] != NULL; j++) {
39d8c7
+                const char *supported_type = self->supported_session_types[j];
39d8c7
+
39d8c7
+                if (g_str_equal (supported_type, "x11") &&
39d8c7
+                    (type == NULL || g_str_equal (type, supported_type))) {
39d8c7
+                        for (i = 0; system_data_dirs[i]; i++) {
39d8c7
+                                gchar *dir = g_build_filename (system_data_dirs[i], "xsessions", NULL);
39d8c7
+                                g_array_append_val (search_array, dir);
39d8c7
+                        }
39d8c7
+
39d8c7
+                        g_array_append_vals (search_array, x_search_dirs, G_N_ELEMENTS (x_search_dirs));
39d8c7
                 }
39d8c7
 
39d8c7
-                g_array_append_vals (search_array, x_search_dirs, G_N_ELEMENTS (x_search_dirs));
39d8c7
-        }
39d8c7
 
39d8c7
 #ifdef ENABLE_WAYLAND_SUPPORT
39d8c7
-        if (!self->ignore_wayland &&
39d8c7
-            (type == NULL || g_str_equal (type, "wayland"))) {
39d8c7
-#ifdef ENABLE_USER_DISPLAY_SERVER
39d8c7
-                g_array_prepend_val (search_array, wayland_search_dir);
39d8c7
+                if (g_str_equal (supported_type, "wayland") &&
39d8c7
+                    (type == NULL || g_str_equal (type, supported_type))) {
39d8c7
+                        for (i = 0; system_data_dirs[i]; i++) {
39d8c7
+                                gchar *dir = g_build_filename (system_data_dirs[i], "wayland-sessions", NULL);
39d8c7
+                                g_array_append_val (search_array, dir);
39d8c7
+                        }
39d8c7
 
39d8c7
-                for (i = 0; system_data_dirs[i]; i++) {
39d8c7
-                        gchar *dir = g_build_filename (system_data_dirs[i], "wayland-sessions", NULL);
39d8c7
-                        g_array_insert_val (search_array, i, dir);
39d8c7
+                        g_array_append_val (search_array, wayland_search_dir);
39d8c7
                 }
39d8c7
-#else
39d8c7
-                for (i = 0; system_data_dirs[i]; i++) {
39d8c7
-                        gchar *dir = g_build_filename (system_data_dirs[i], "wayland-sessions", NULL);
39d8c7
-                        g_array_append_val (search_array, dir);
39d8c7
-                }
39d8c7
-
39d8c7
-                g_array_append_val (search_array, wayland_search_dir);
39d8c7
 #endif
39d8c7
         }
39d8c7
-#endif
39d8c7
 
39d8c7
         search_dirs = g_strdupv ((char **) search_array->data);
39d8c7
 
39d8c7
         g_array_free (search_array, TRUE);
39d8c7
 
39d8c7
         return search_dirs;
39d8c7
 }
39d8c7
 
39d8c7
 static gboolean
39d8c7
 is_prog_in_path (const char *prog)
39d8c7
 {
39d8c7
         char    *f;
39d8c7
         gboolean ret;
39d8c7
 
39d8c7
         f = g_find_program_in_path (prog);
39d8c7
         ret = (f != NULL);
39d8c7
         g_free (f);
39d8c7
         return ret;
39d8c7
 }
39d8c7
 
39d8c7
 static GKeyFile *
39d8c7
 load_key_file_for_file (GdmSession   *self,
39d8c7
                         const char   *file,
39d8c7
                         const char   *type,
39d8c7
                         char        **full_path)
39d8c7
 {
39d8c7
         GKeyFile   *key_file;
39d8c7
         GError     *error = NULL;
39d8c7
         gboolean    res;
39d8c7
         char      **search_dirs;
39d8c7
@@ -444,60 +449,66 @@ load_key_file_for_file (GdmSession   *self,
39d8c7
                         g_debug ("GdmSession: %s", error->message);
39d8c7
                         g_error_free (error);
39d8c7
                 }
39d8c7
                 g_key_file_free (key_file);
39d8c7
                 key_file = NULL;
39d8c7
         }
39d8c7
 
39d8c7
         g_strfreev (search_dirs);
39d8c7
 
39d8c7
         return key_file;
39d8c7
 }
39d8c7
 
39d8c7
 static gboolean
39d8c7
 get_session_command_for_file (GdmSession  *self,
39d8c7
                               const char  *file,
39d8c7
                               const char  *type,
39d8c7
                               char       **command)
39d8c7
 {
39d8c7
         GKeyFile   *key_file;
39d8c7
         GError     *error;
39d8c7
         char       *exec;
39d8c7
         gboolean    ret;
39d8c7
         gboolean    res;
39d8c7
 
39d8c7
         exec = NULL;
39d8c7
         ret = FALSE;
39d8c7
         if (command != NULL) {
39d8c7
                 *command = NULL;
39d8c7
         }
39d8c7
 
39d8c7
+        if (!supports_session_type (self, type)) {
39d8c7
+                g_debug ("GdmSession: ignoring %s session command request for file '%s'",
39d8c7
+                         type, file);
39d8c7
+                goto out;
39d8c7
+        }
39d8c7
+
39d8c7
         g_debug ("GdmSession: getting session command for file '%s'", file);
39d8c7
         key_file = load_key_file_for_file (self, file, type, NULL);
39d8c7
         if (key_file == NULL) {
39d8c7
                 goto out;
39d8c7
         }
39d8c7
 
39d8c7
         error = NULL;
39d8c7
         res = g_key_file_get_boolean (key_file,
39d8c7
                                       G_KEY_FILE_DESKTOP_GROUP,
39d8c7
                                       G_KEY_FILE_DESKTOP_KEY_HIDDEN,
39d8c7
                                       &error);
39d8c7
         if (error == NULL && res) {
39d8c7
                 g_debug ("GdmSession: Session %s is marked as hidden", file);
39d8c7
                 goto out;
39d8c7
         }
39d8c7
 
39d8c7
         exec = g_key_file_get_string (key_file,
39d8c7
                                       G_KEY_FILE_DESKTOP_GROUP,
39d8c7
                                       G_KEY_FILE_DESKTOP_KEY_TRY_EXEC,
39d8c7
                                       NULL);
39d8c7
         if (exec != NULL) {
39d8c7
                 res = is_prog_in_path (exec);
39d8c7
                 g_free (exec);
39d8c7
                 exec = NULL;
39d8c7
 
39d8c7
                 if (! res) {
39d8c7
                         g_debug ("GdmSession: Command not found: %s",
39d8c7
                                  G_KEY_FILE_DESKTOP_KEY_TRY_EXEC);
39d8c7
                         goto out;
39d8c7
                 }
39d8c7
@@ -2230,68 +2241,72 @@ close_conversation (GdmSessionConversation *conversation)
39d8c7
 
39d8c7
         if (conversation->worker_manager_interface != NULL) {
39d8c7
                 unexport_worker_manager_interface (self, conversation->worker_manager_interface);
39d8c7
                 g_clear_object (&conversation->worker_manager_interface);
39d8c7
         }
39d8c7
 
39d8c7
         if (conversation->worker_proxy != NULL) {
39d8c7
                 GDBusConnection *connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (conversation->worker_proxy));
39d8c7
                 g_dbus_connection_close_sync (connection, NULL, NULL);
39d8c7
         }
39d8c7
 }
39d8c7
 
39d8c7
 static void
39d8c7
 stop_conversation (GdmSessionConversation *conversation)
39d8c7
 {
39d8c7
         close_conversation (conversation);
39d8c7
 
39d8c7
         conversation->is_stopping = TRUE;
39d8c7
         gdm_session_worker_job_stop (conversation->job);
39d8c7
 }
39d8c7
 
39d8c7
 static void
39d8c7
 stop_conversation_now (GdmSessionConversation *conversation)
39d8c7
 {
39d8c7
         close_conversation (conversation);
39d8c7
 
39d8c7
         gdm_session_worker_job_stop_now (conversation->job);
39d8c7
         g_clear_object (&conversation->job);
39d8c7
 }
39d8c7
 
39d8c7
-#ifdef ENABLE_WAYLAND_SUPPORT
39d8c7
 void
39d8c7
-gdm_session_set_ignore_wayland (GdmSession *self,
39d8c7
-                                gboolean    ignore_wayland)
39d8c7
+gdm_session_set_supported_session_types (GdmSession         *self,
39d8c7
+                                         const char * const *supported_session_types)
39d8c7
 {
39d8c7
-        self->ignore_wayland = ignore_wayland;
39d8c7
+        const char * const session_types[] = { "wayland", "x11", NULL };
39d8c7
+        g_strfreev (self->supported_session_types);
39d8c7
+
39d8c7
+        if (supported_session_types == NULL)
39d8c7
+                self->supported_session_types = g_strdupv ((GStrv) session_types);
39d8c7
+        else
39d8c7
+                self->supported_session_types = g_strdupv ((GStrv) supported_session_types);
39d8c7
 }
39d8c7
-#endif
39d8c7
 
39d8c7
 gboolean
39d8c7
 gdm_session_start_conversation (GdmSession *self,
39d8c7
                                 const char *service_name)
39d8c7
 {
39d8c7
         GdmSessionConversation *conversation;
39d8c7
 
39d8c7
         g_return_val_if_fail (GDM_IS_SESSION (self), FALSE);
39d8c7
 
39d8c7
         conversation = g_hash_table_lookup (self->conversations,
39d8c7
                                             service_name);
39d8c7
 
39d8c7
         if (conversation != NULL) {
39d8c7
                 if (!conversation->is_stopping) {
39d8c7
                         g_warning ("GdmSession: conversation %s started more than once", service_name);
39d8c7
                         return FALSE;
39d8c7
                 }
39d8c7
                 g_debug ("GdmSession: stopping old conversation %s", service_name);
39d8c7
                 gdm_session_worker_job_stop_now (conversation->job);
39d8c7
                 g_object_unref (conversation->job);
39d8c7
                 conversation->job = NULL;
39d8c7
         }
39d8c7
 
39d8c7
         g_debug ("GdmSession: starting conversation %s for session (%p)", service_name, self);
39d8c7
 
39d8c7
         conversation = start_conversation (self, service_name);
39d8c7
 
39d8c7
         g_hash_table_insert (self->conversations,
39d8c7
                              g_strdup (service_name), conversation);
39d8c7
         return TRUE;
39d8c7
@@ -3162,69 +3177,69 @@ gdm_session_get_session_id (GdmSession *self)
39d8c7
 
39d8c7
 const char *
39d8c7
 gdm_session_get_conversation_session_id (GdmSession *self,
39d8c7
                                          const char *service_name)
39d8c7
 {
39d8c7
         GdmSessionConversation *conversation;
39d8c7
 
39d8c7
         g_return_val_if_fail (GDM_IS_SESSION (self), NULL);
39d8c7
 
39d8c7
         conversation = find_conversation_by_name (self, service_name);
39d8c7
 
39d8c7
         if (conversation == NULL) {
39d8c7
                 return NULL;
39d8c7
         }
39d8c7
 
39d8c7
         return conversation->session_id;
39d8c7
 }
39d8c7
 
39d8c7
 static char *
39d8c7
 get_session_filename (GdmSession *self)
39d8c7
 {
39d8c7
         return g_strdup_printf ("%s.desktop", get_session_name (self));
39d8c7
 }
39d8c7
 
39d8c7
 #ifdef ENABLE_WAYLAND_SUPPORT
39d8c7
 static gboolean
39d8c7
 gdm_session_is_wayland_session (GdmSession *self)
39d8c7
 {
39d8c7
         GKeyFile   *key_file;
39d8c7
         gboolean    is_wayland_session = FALSE;
39d8c7
-        char       *filename;
39d8c7
-        char       *full_path = NULL;
39d8c7
+        char            *filename;
39d8c7
+        g_autofree char *full_path = NULL;
39d8c7
 
39d8c7
         g_return_val_if_fail (self != NULL, FALSE);
39d8c7
         g_return_val_if_fail (GDM_IS_SESSION (self), FALSE);
39d8c7
 
39d8c7
         filename = get_session_filename (self);
39d8c7
 
39d8c7
-        key_file = load_key_file_for_file (self, filename, "wayland", &full_path);
39d8c7
+        key_file = load_key_file_for_file (self, filename, NULL, &full_path);
39d8c7
 
39d8c7
         if (key_file == NULL) {
39d8c7
                 goto out;
39d8c7
         }
39d8c7
 
39d8c7
         if (full_path != NULL && strstr (full_path, "/wayland-sessions/") != NULL) {
39d8c7
                 is_wayland_session = TRUE;
39d8c7
         }
39d8c7
         g_debug ("GdmSession: checking if file '%s' is wayland session: %s", filename, is_wayland_session? "yes" : "no");
39d8c7
 
39d8c7
 out:
39d8c7
         g_clear_pointer (&key_file, g_key_file_free);
39d8c7
         g_free (filename);
39d8c7
         return is_wayland_session;
39d8c7
 }
39d8c7
 #endif
39d8c7
 
39d8c7
 static void
39d8c7
 update_session_type (GdmSession *self)
39d8c7
 {
39d8c7
 #ifdef ENABLE_WAYLAND_SUPPORT
39d8c7
         gboolean is_wayland_session = FALSE;
39d8c7
 
39d8c7
         is_wayland_session = gdm_session_is_wayland_session (self);
39d8c7
 
39d8c7
         if (is_wayland_session) {
39d8c7
                 set_session_type (self, "wayland");
39d8c7
         } else {
39d8c7
                 set_session_type (self, NULL);
39d8c7
         }
39d8c7
@@ -3513,140 +3528,138 @@ gdm_session_set_property (GObject      *object,
39d8c7
         case PROP_DISPLAY_HOSTNAME:
39d8c7
                 set_display_hostname (self, g_value_get_string (value));
39d8c7
                 break;
39d8c7
         case PROP_DISPLAY_DEVICE:
39d8c7
                 set_display_device (self, g_value_get_string (value));
39d8c7
                 break;
39d8c7
         case PROP_DISPLAY_SEAT_ID:
39d8c7
                 set_display_seat_id (self, g_value_get_string (value));
39d8c7
                 break;
39d8c7
         case PROP_USER_X11_AUTHORITY_FILE:
39d8c7
                 set_user_x11_authority_file (self, g_value_get_string (value));
39d8c7
                 break;
39d8c7
         case PROP_DISPLAY_X11_AUTHORITY_FILE:
39d8c7
                 set_display_x11_authority_file (self, g_value_get_string (value));
39d8c7
                 break;
39d8c7
         case PROP_DISPLAY_IS_LOCAL:
39d8c7
                 set_display_is_local (self, g_value_get_boolean (value));
39d8c7
                 break;
39d8c7
         case PROP_DISPLAY_IS_INITIAL:
39d8c7
                 set_display_is_initial (self, g_value_get_boolean (value));
39d8c7
                 break;
39d8c7
         case PROP_VERIFICATION_MODE:
39d8c7
                 set_verification_mode (self, g_value_get_enum (value));
39d8c7
                 break;
39d8c7
         case PROP_ALLOWED_USER:
39d8c7
                 set_allowed_user (self, g_value_get_uint (value));
39d8c7
                 break;
39d8c7
         case PROP_CONVERSATION_ENVIRONMENT:
39d8c7
                 set_conversation_environment (self, g_value_get_pointer (value));
39d8c7
                 break;
39d8c7
-#ifdef ENABLE_WAYLAND_SUPPORT
39d8c7
-        case PROP_IGNORE_WAYLAND:
39d8c7
-                gdm_session_set_ignore_wayland (self, g_value_get_boolean (value));
39d8c7
+        case PROP_SUPPORTED_SESSION_TYPES:
39d8c7
+                gdm_session_set_supported_session_types (self, g_value_get_boxed (value));
39d8c7
                 break;
39d8c7
-#endif
39d8c7
         default:
39d8c7
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
39d8c7
                 break;
39d8c7
         }
39d8c7
 }
39d8c7
 
39d8c7
 static void
39d8c7
 gdm_session_get_property (GObject    *object,
39d8c7
                           guint       prop_id,
39d8c7
                           GValue     *value,
39d8c7
                           GParamSpec *pspec)
39d8c7
 {
39d8c7
         GdmSession *self;
39d8c7
 
39d8c7
         self = GDM_SESSION (object);
39d8c7
 
39d8c7
         switch (prop_id) {
39d8c7
         case PROP_SESSION_TYPE:
39d8c7
                 g_value_set_string (value, self->session_type);
39d8c7
                 break;
39d8c7
         case PROP_DISPLAY_NAME:
39d8c7
                 g_value_set_string (value, self->display_name);
39d8c7
                 break;
39d8c7
         case PROP_DISPLAY_HOSTNAME:
39d8c7
                 g_value_set_string (value, self->display_hostname);
39d8c7
                 break;
39d8c7
         case PROP_DISPLAY_DEVICE:
39d8c7
                 g_value_set_string (value, self->display_device);
39d8c7
                 break;
39d8c7
         case PROP_DISPLAY_SEAT_ID:
39d8c7
                 g_value_set_string (value, self->display_seat_id);
39d8c7
                 break;
39d8c7
         case PROP_USER_X11_AUTHORITY_FILE:
39d8c7
                 g_value_set_string (value, self->user_x11_authority_file);
39d8c7
                 break;
39d8c7
         case PROP_DISPLAY_X11_AUTHORITY_FILE:
39d8c7
                 g_value_set_string (value, self->display_x11_authority_file);
39d8c7
                 break;
39d8c7
         case PROP_DISPLAY_IS_LOCAL:
39d8c7
                 g_value_set_boolean (value, self->display_is_local);
39d8c7
                 break;
39d8c7
         case PROP_DISPLAY_IS_INITIAL:
39d8c7
                 g_value_set_boolean (value, self->display_is_initial);
39d8c7
                 break;
39d8c7
         case PROP_VERIFICATION_MODE:
39d8c7
                 g_value_set_enum (value, self->verification_mode);
39d8c7
                 break;
39d8c7
         case PROP_ALLOWED_USER:
39d8c7
                 g_value_set_uint (value, self->allowed_user);
39d8c7
                 break;
39d8c7
         case PROP_CONVERSATION_ENVIRONMENT:
39d8c7
                 g_value_set_pointer (value, self->environment);
39d8c7
                 break;
39d8c7
-#ifdef ENABLE_WAYLAND_SUPPORT
39d8c7
-        case PROP_IGNORE_WAYLAND:
39d8c7
-                g_value_set_boolean (value, self->ignore_wayland);
39d8c7
+        case PROP_SUPPORTED_SESSION_TYPES:
39d8c7
+                g_value_set_boxed (value, self->supported_session_types);
39d8c7
                 break;
39d8c7
-#endif
39d8c7
         default:
39d8c7
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
39d8c7
                 break;
39d8c7
         }
39d8c7
 }
39d8c7
 
39d8c7
 static void
39d8c7
 gdm_session_dispose (GObject *object)
39d8c7
 {
39d8c7
         GdmSession *self;
39d8c7
 
39d8c7
         self = GDM_SESSION (object);
39d8c7
 
39d8c7
         g_debug ("GdmSession: Disposing session");
39d8c7
 
39d8c7
         gdm_session_close (self);
39d8c7
 
39d8c7
+        g_clear_pointer (&self->supported_session_types,
39d8c7
+                         g_strfreev);
39d8c7
         g_clear_pointer (&self->conversations,
39d8c7
                          g_hash_table_unref);
39d8c7
 
39d8c7
         g_clear_object (&self->user_verifier_interface);
39d8c7
         g_clear_pointer (&self->user_verifier_extensions,
39d8c7
                          g_hash_table_unref);
39d8c7
         g_clear_object (&self->greeter_interface);
39d8c7
         g_clear_object (&self->remote_greeter_interface);
39d8c7
         g_clear_object (&self->chooser_interface);
39d8c7
 
39d8c7
         g_free (self->display_name);
39d8c7
         self->display_name = NULL;
39d8c7
 
39d8c7
         g_free (self->display_hostname);
39d8c7
         self->display_hostname = NULL;
39d8c7
 
39d8c7
         g_free (self->display_device);
39d8c7
         self->display_device = NULL;
39d8c7
 
39d8c7
         g_free (self->display_seat_id);
39d8c7
         self->display_seat_id = NULL;
39d8c7
 
39d8c7
         g_free (self->display_x11_authority_file);
39d8c7
         self->display_x11_authority_file = NULL;
39d8c7
 
39d8c7
         g_strfreev (self->conversation_environment);
39d8c7
         self->conversation_environment = NULL;
39d8c7
 
39d8c7
         if (self->worker_server != NULL) {
39d8c7
                 g_dbus_server_stop (self->worker_server);
39d8c7
@@ -4007,69 +4020,67 @@ gdm_session_class_init (GdmSessionClass *session_class)
39d8c7
                                          PROP_DISPLAY_X11_AUTHORITY_FILE,
39d8c7
                                          g_param_spec_string ("display-x11-authority-file",
39d8c7
                                                               "display x11 authority file",
39d8c7
                                                               "display x11 authority file",
39d8c7
                                                               NULL,
39d8c7
                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
39d8c7
         /* not construct only */
39d8c7
         g_object_class_install_property (object_class,
39d8c7
                                          PROP_USER_X11_AUTHORITY_FILE,
39d8c7
                                          g_param_spec_string ("user-x11-authority-file",
39d8c7
                                                               "",
39d8c7
                                                               "",
39d8c7
                                                               NULL,
39d8c7
                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
39d8c7
         g_object_class_install_property (object_class,
39d8c7
                                          PROP_DISPLAY_DEVICE,
39d8c7
                                          g_param_spec_string ("display-device",
39d8c7
                                                               "display device",
39d8c7
                                                               "display device",
39d8c7
                                                               NULL,
39d8c7
                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
39d8c7
 
39d8c7
         g_object_class_install_property (object_class,
39d8c7
                                          PROP_DISPLAY_SEAT_ID,
39d8c7
                                          g_param_spec_string ("display-seat-id",
39d8c7
                                                               "display seat id",
39d8c7
                                                               "display seat id",
39d8c7
                                                               NULL,
39d8c7
                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
39d8c7
 
39d8c7
-#ifdef ENABLE_WAYLAND_SUPPORT
39d8c7
         g_object_class_install_property (object_class,
39d8c7
-                                         PROP_IGNORE_WAYLAND,
39d8c7
-                                         g_param_spec_boolean ("ignore-wayland",
39d8c7
-                                                               "ignore wayland",
39d8c7
-                                                               "ignore wayland",
39d8c7
-                                                               FALSE,
39d8c7
-                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
39d8c7
-#endif
39d8c7
+                                         PROP_SUPPORTED_SESSION_TYPES,
39d8c7
+                                         g_param_spec_boxed ("supported-session-types",
39d8c7
+                                                             "supported session types",
39d8c7
+                                                             "supported session types",
39d8c7
+                                                             G_TYPE_STRV,
39d8c7
+                                                             G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
39d8c7
 
39d8c7
         /* Ensure we can resolve errors */
39d8c7
         gdm_dbus_error_ensure (GDM_SESSION_WORKER_ERROR);
39d8c7
 }
39d8c7
 
39d8c7
 GdmSession *
39d8c7
 gdm_session_new (GdmSessionVerificationMode  verification_mode,
39d8c7
                  uid_t                       allowed_user,
39d8c7
                  const char                 *display_name,
39d8c7
                  const char                 *display_hostname,
39d8c7
                  const char                 *display_device,
39d8c7
                  const char                 *display_seat_id,
39d8c7
                  const char                 *display_x11_authority_file,
39d8c7
                  gboolean                    display_is_local,
39d8c7
                  const char * const         *environment)
39d8c7
 {
39d8c7
         GdmSession *self;
39d8c7
 
39d8c7
         self = g_object_new (GDM_TYPE_SESSION,
39d8c7
                              "verification-mode", verification_mode,
39d8c7
                              "allowed-user", (guint) allowed_user,
39d8c7
                              "display-name", display_name,
39d8c7
                              "display-hostname", display_hostname,
39d8c7
                              "display-device", display_device,
39d8c7
                              "display-seat-id", display_seat_id,
39d8c7
                              "display-x11-authority-file", display_x11_authority_file,
39d8c7
                              "display-is-local", display_is_local,
39d8c7
                              "conversation-environment", environment,
39d8c7
                              NULL);
39d8c7
 
39d8c7
diff --git a/data/gdm.schemas.in b/data/gdm.schemas.in
39d8c7
index 255bff023..a1035f95e 100644
39d8c7
--- a/data/gdm.schemas.in
39d8c7
+++ b/data/gdm.schemas.in
39d8c7
@@ -25,65 +25,75 @@
39d8c7
     <schema>
39d8c7
       <key>daemon/AutomaticLoginEnable</key>
39d8c7
       <signature>b</signature>
39d8c7
       <default>false</default>
39d8c7
     </schema>
39d8c7
     <schema>
39d8c7
       <key>daemon/AutomaticLogin</key>
39d8c7
       <signature>s</signature>
39d8c7
       <default></default>
39d8c7
     </schema>
39d8c7
     <schema>
39d8c7
       <key>daemon/TimedLoginEnable</key>
39d8c7
       <signature>b</signature>
39d8c7
       <default>false</default>
39d8c7
     </schema>
39d8c7
     <schema>
39d8c7
       <key>daemon/TimedLogin</key>
39d8c7
       <signature>s</signature>
39d8c7
       <default></default>
39d8c7
     </schema>
39d8c7
     <schema>
39d8c7
       <key>daemon/TimedLoginDelay</key>
39d8c7
       <signature>i</signature>
39d8c7
       <default>30</default>
39d8c7
     </schema>
39d8c7
     <schema>
39d8c7
       <key>daemon/InitialSetupEnable</key>
39d8c7
       <signature>b</signature>
39d8c7
       <default>true</default>
39d8c7
     </schema>
39d8c7
+    <schema>
39d8c7
+      <key>daemon/PreferredDisplayServer</key>
39d8c7
+      <signature>s</signature>
39d8c7
+      <default>wayland</default>
39d8c7
+    </schema>
39d8c7
     <schema>
39d8c7
       <key>daemon/WaylandEnable</key>
39d8c7
       <signature>b</signature>
39d8c7
       <default>true</default>
39d8c7
     </schema>
39d8c7
+    <schema>
39d8c7
+      <key>daemon/XorgEnable</key>
39d8c7
+      <signature>b</signature>
39d8c7
+      <default>true</default>
39d8c7
+    </schema>
39d8c7
     <schema>
39d8c7
       <key>security/AllowRemoteAutoLogin</key>
39d8c7
       <signature>b</signature>
39d8c7
       <default>false</default>
39d8c7
     </schema>
39d8c7
 
39d8c7
     <schema>
39d8c7
       <key>debug/Enable</key>
39d8c7
       <signature>b</signature>
39d8c7
       <default>false</default>
39d8c7
     </schema>
39d8c7
 
39d8c7
     <schema>
39d8c7
       <key>security/DisallowTCP</key>
39d8c7
       <signature>b</signature>
39d8c7
       <default>true</default>
39d8c7
     </schema>
39d8c7
     <schema>
39d8c7
       <key>xdmcp/Enable</key>
39d8c7
       <signature>b</signature>
39d8c7
       <default>false</default>
39d8c7
     </schema>
39d8c7
     <schema>
39d8c7
       <key>xdmcp/ShowLocalGreeter</key>
39d8c7
       <signature>b</signature>
39d8c7
       <default>true</default>
39d8c7
     </schema>
39d8c7
     <schema>
39d8c7
       <key>xdmcp/MaxPending</key>
39d8c7
       <signature>i</signature>
39d8c7
diff --git a/libgdm/gdm-sessions.c b/libgdm/gdm-sessions.c
39d8c7
index a13225050..f078e04b8 100644
39d8c7
--- a/libgdm/gdm-sessions.c
39d8c7
+++ b/libgdm/gdm-sessions.c
39d8c7
@@ -163,171 +163,203 @@ load_session_file (const char              *id,
39d8c7
 
39d8c7
 static gboolean
39d8c7
 remove_duplicate_sessions (gpointer key,
39d8c7
                            gpointer value,
39d8c7
                            gpointer user_data)
39d8c7
 {
39d8c7
         gboolean already_known;
39d8c7
         GHashTable *names_seen_before;
39d8c7
         GdmSessionFile *session;
39d8c7
 
39d8c7
         names_seen_before = (GHashTable *) user_data;
39d8c7
         session = (GdmSessionFile *) value;
39d8c7
         already_known = !g_hash_table_add (names_seen_before, session->translated_name);
39d8c7
 
39d8c7
         if (already_known)
39d8c7
                 g_debug ("GdmSession: Removing %s (%s) as we already have a session by this name",
39d8c7
                          session->id,
39d8c7
                          session->path);
39d8c7
 
39d8c7
         return already_known;
39d8c7
 }
39d8c7
 
39d8c7
 static void
39d8c7
 collect_sessions_from_directory (const char *dirname)
39d8c7
 {
39d8c7
         GDir       *dir;
39d8c7
         const char *filename;
39d8c7
 
39d8c7
         gboolean is_x11 = g_getenv ("WAYLAND_DISPLAY") == NULL &&
39d8c7
                           g_getenv ("RUNNING_UNDER_GDM") != NULL;
39d8c7
+        gboolean is_wayland = g_getenv ("WAYLAND_DISPLAY") != NULL &&
39d8c7
+                              g_getenv ("RUNNING_UNDER_GDM") != NULL;
39d8c7
 
39d8c7
         /* FIXME: add file monitor to directory */
39d8c7
 
39d8c7
         dir = g_dir_open (dirname, 0, NULL);
39d8c7
         if (dir == NULL) {
39d8c7
                 return;
39d8c7
         }
39d8c7
 
39d8c7
         while ((filename = g_dir_read_name (dir))) {
39d8c7
                 char *id;
39d8c7
                 char *full_path;
39d8c7
 
39d8c7
                 if (! g_str_has_suffix (filename, ".desktop")) {
39d8c7
                         continue;
39d8c7
                 }
39d8c7
 
39d8c7
-                if (is_x11 && g_str_has_suffix (filename, "-xorg.desktop")) {
39d8c7
-                        char *base_name = g_strndup (filename, strlen (filename) - strlen ("-xorg.desktop"));
39d8c7
-                        char *fallback_name = g_strconcat (base_name, ".desktop", NULL);
39d8c7
-                        g_free (base_name);
39d8c7
-                        char *fallback_path = g_build_filename (dirname, fallback_name, NULL);
39d8c7
-                        g_free (fallback_name);
39d8c7
-                        if (g_file_test (fallback_path, G_FILE_TEST_EXISTS)) {
39d8c7
-                                g_free (fallback_path);
39d8c7
-                                g_debug ("Running under X11, ignoring %s", filename);
39d8c7
-                                continue;
39d8c7
+                if (is_wayland) {
39d8c7
+                        if (g_str_has_suffix (filename, "-wayland.desktop")) {
39d8c7
+                                g_autofree char *base_name = g_strndup (filename, strlen (filename) - strlen ("-wayland.desktop"));
39d8c7
+                                g_autofree char *other_name = g_strconcat (base_name, ".desktop", NULL);
39d8c7
+                                g_autofree char *other_path = g_build_filename (dirname, other_name, NULL);
39d8c7
+
39d8c7
+                                if (g_file_test (other_path, G_FILE_TEST_EXISTS)) {
39d8c7
+                                        g_debug ("Running under Wayland, ignoring %s", filename);
39d8c7
+                                        continue;
39d8c7
+                                }
39d8c7
+                        } else {
39d8c7
+                                g_autofree char *base_name = g_strndup (filename, strlen (filename) - strlen (".desktop"));
39d8c7
+                                g_autofree char *other_name = g_strdup_printf ("%s-xorg.desktop", base_name);
39d8c7
+                                g_autofree char *other_path = g_build_filename (dirname, other_name, NULL);
39d8c7
+
39d8c7
+                                if (g_file_test (other_path, G_FILE_TEST_EXISTS)) {
39d8c7
+                                        g_debug ("Running under Wayland, ignoring %s", filename);
39d8c7
+                                        continue;
39d8c7
+                                }
39d8c7
+                        }
39d8c7
+                } else if (is_x11) {
39d8c7
+                        if (g_str_has_suffix (filename, "-xorg.desktop")) {
39d8c7
+                                g_autofree char *base_name = g_strndup (filename, strlen (filename) - strlen ("-xorg.desktop"));
39d8c7
+                                g_autofree char *other_name = g_strconcat (base_name, ".desktop", NULL);
39d8c7
+                                g_autofree char *other_path = g_build_filename (dirname, other_name, NULL);
39d8c7
+
39d8c7
+                                if (g_file_test (other_path, G_FILE_TEST_EXISTS)) {
39d8c7
+                                        g_debug ("Running under X11, ignoring %s", filename);
39d8c7
+                                        continue;
39d8c7
+                                }
39d8c7
+                        } else {
39d8c7
+                                g_autofree char *base_name = g_strndup (filename, strlen (filename) - strlen (".desktop"));
39d8c7
+                                g_autofree char *other_name = g_strdup_printf ("%s-wayland.desktop", base_name);
39d8c7
+                                g_autofree char *other_path = g_build_filename (dirname, other_name, NULL);
39d8c7
+
39d8c7
+                                if (g_file_test (other_path, G_FILE_TEST_EXISTS)) {
39d8c7
+                                        g_debug ("Running under X11, ignoring %s", filename);
39d8c7
+                                        continue;
39d8c7
+                                }
39d8c7
                         }
39d8c7
-                        g_free (fallback_path);
39d8c7
                 }
39d8c7
 
39d8c7
                 id = g_strndup (filename, strlen (filename) - strlen (".desktop"));
39d8c7
 
39d8c7
                 full_path = g_build_filename (dirname, filename, NULL);
39d8c7
 
39d8c7
                 load_session_file (id, full_path);
39d8c7
 
39d8c7
                 g_free (id);
39d8c7
                 g_free (full_path);
39d8c7
         }
39d8c7
 
39d8c7
         g_dir_close (dir);
39d8c7
 }
39d8c7
 
39d8c7
 static void
39d8c7
 collect_sessions (void)
39d8c7
 {
39d8c7
         g_autoptr(GHashTable) names_seen_before = NULL;
39d8c7
         g_autoptr(GPtrArray) xorg_search_array = NULL;
39d8c7
         g_autoptr(GPtrArray) wayland_search_array = NULL;
39d8c7
         gchar      *session_dir = NULL;
39d8c7
         int         i;
39d8c7
         const char *xorg_search_dirs[] = {
39d8c7
                 "/etc/X11/sessions/",
39d8c7
                 DMCONFDIR "/Sessions/",
39d8c7
                 DATADIR "/gdm/BuiltInSessions/",
39d8c7
                 DATADIR "/xsessions/",
39d8c7
         };
39d8c7
+        g_auto (GStrv) supported_session_types = NULL;
39d8c7
+
39d8c7
+        supported_session_types = g_strsplit (g_getenv ("GDM_SUPPORTED_SESSION_TYPES"), ":", -1);
39d8c7
 
39d8c7
         names_seen_before = g_hash_table_new (g_str_hash, g_str_equal);
39d8c7
         xorg_search_array = g_ptr_array_new_with_free_func (g_free);
39d8c7
 
39d8c7
         const gchar * const *system_data_dirs = g_get_system_data_dirs ();
39d8c7
 
39d8c7
         for (i = 0; system_data_dirs[i]; i++) {
39d8c7
                 session_dir = g_build_filename (system_data_dirs[i], "xsessions", NULL);
39d8c7
                 g_ptr_array_add (xorg_search_array, session_dir);
39d8c7
         }
39d8c7
 
39d8c7
         for (i = 0; i < G_N_ELEMENTS (xorg_search_dirs); i++) {
39d8c7
                 g_ptr_array_add (xorg_search_array, g_strdup (xorg_search_dirs[i]));
39d8c7
         }
39d8c7
 
39d8c7
 #ifdef ENABLE_WAYLAND_SUPPORT
39d8c7
         const char *wayland_search_dirs[] = {
39d8c7
                 DATADIR "/wayland-sessions/",
39d8c7
         };
39d8c7
 
39d8c7
         wayland_search_array = g_ptr_array_new_with_free_func (g_free);
39d8c7
 
39d8c7
         for (i = 0; system_data_dirs[i]; i++) {
39d8c7
                 session_dir = g_build_filename (system_data_dirs[i], "wayland-sessions", NULL);
39d8c7
                 g_ptr_array_add (wayland_search_array, session_dir);
39d8c7
         }
39d8c7
 
39d8c7
         for (i = 0; i < G_N_ELEMENTS (wayland_search_dirs); i++) {
39d8c7
                 g_ptr_array_add (wayland_search_array, g_strdup (wayland_search_dirs[i]));
39d8c7
         }
39d8c7
 #endif
39d8c7
 
39d8c7
         if (gdm_available_sessions_map == NULL) {
39d8c7
                 gdm_available_sessions_map = g_hash_table_new_full (g_str_hash, g_str_equal,
39d8c7
                                                                     g_free, (GDestroyNotify)gdm_session_file_free);
39d8c7
         }
39d8c7
 
39d8c7
-        for (i = 0; i < xorg_search_array->len; i++) {
39d8c7
-                collect_sessions_from_directory (g_ptr_array_index (xorg_search_array, i));
39d8c7
+        if (!supported_session_types || g_strv_contains ((const char * const *) supported_session_types, "x11")) {
39d8c7
+                for (i = 0; i < xorg_search_array->len; i++) {
39d8c7
+                        collect_sessions_from_directory (g_ptr_array_index (xorg_search_array, i));
39d8c7
+                }
39d8c7
         }
39d8c7
 
39d8c7
 #ifdef ENABLE_WAYLAND_SUPPORT
39d8c7
 #ifdef ENABLE_USER_DISPLAY_SERVER
39d8c7
-        if (g_getenv ("WAYLAND_DISPLAY") == NULL && g_getenv ("RUNNING_UNDER_GDM") != NULL) {
39d8c7
-                goto out;
39d8c7
+        if (!supported_session_types  || g_strv_contains ((const char * const *) supported_session_types, "wayland")) {
39d8c7
+                for (i = 0; i < wayland_search_array->len; i++) {
39d8c7
+                        collect_sessions_from_directory (g_ptr_array_index (wayland_search_array, i));
39d8c7
+                }
39d8c7
         }
39d8c7
 #endif
39d8c7
-
39d8c7
-        for (i = 0; i < wayland_search_array->len; i++) {
39d8c7
-                collect_sessions_from_directory (g_ptr_array_index (wayland_search_array, i));
39d8c7
-        }
39d8c7
 #endif
39d8c7
 
39d8c7
-out:
39d8c7
         g_hash_table_foreach_remove (gdm_available_sessions_map,
39d8c7
                                      remove_duplicate_sessions,
39d8c7
                                      names_seen_before);
39d8c7
 }
39d8c7
 
39d8c7
 static gint
39d8c7
 compare_session_ids (gconstpointer  a,
39d8c7
                      gconstpointer  b)
39d8c7
 {
39d8c7
         GdmSessionFile *session_a, *session_b;
39d8c7
         session_a = (GdmSessionFile *) g_hash_table_lookup (gdm_available_sessions_map, a);
39d8c7
         session_b = (GdmSessionFile *) g_hash_table_lookup (gdm_available_sessions_map, b);
39d8c7
 
39d8c7
         if (session_a == NULL)
39d8c7
                 return -1;
39d8c7
 
39d8c7
         if (session_b == NULL)
39d8c7
                 return 1;
39d8c7
 
39d8c7
         return g_strcmp0 (session_a->translated_name, session_b->translated_name);
39d8c7
 }
39d8c7
 
39d8c7
 /**
39d8c7
  * gdm_get_session_ids:
39d8c7
  *
39d8c7
  * Reads /usr/share/xsessions and other relevant places for possible sessions
39d8c7
  * to log into and returns the complete list.
39d8c7
  *
39d8c7
  * Returns: (transfer full): a %NULL terminated list of session ids
39d8c7
  */
39d8c7
-- 
39d8c7
2.31.1
39d8c7