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

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