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

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