[gdm/better-nvidia-wayland-support: 4/6] daemon: Provide more flexibility for configuring display server




commit 04853a3b8c17712cc7f74c3c405ef47af53151c1
Author: Ray Strode <rstrode redhat com>
Date:   Fri Jul 16 12:34:57 2021 -0400

    daemon: Provide more flexibility for configuring display server
    
    There's currently a way to disable wayland, but no way to disable Xorg.
    We currently prefer wayland if it's not disabled, but have no way to
    prefer Xorg without disabling wayland entirely.
    
    There's currently no way use legacy Xorg support at all if user display
    server support is enabled at a build time.
    
    This commit adds more flexibility to display server selection. It adds
    two new keys: XorgEnable and and PreferredDisplayServer.
    
    XorgEnable=false disables Xorg support entirely on seat 0.
    
    PreferredDisplayServer can be set to "wayland", "xorg", "legacy-xorg" or
    "none" to select which display server is used by default. If it's set to
    "wayland", it will fall back to "xorg". If it's set to "xorg" it will
    fall back to "wayland".

 common/gdm-settings-keys.h         |   2 +
 daemon/gdm-display.c               |  36 ++++++
 daemon/gdm-launch-environment.c    |   9 ++
 daemon/gdm-local-display-factory.c | 220 ++++++++++++++++++++++++++++++-------
 daemon/gdm-manager.c               |   6 -
 daemon/gdm-session.c               | 109 +++++++++---------
 data/gdm.schemas.in                |  10 ++
 libgdm/gdm-sessions.c              |  72 ++++++++----
 8 files changed, 349 insertions(+), 115 deletions(-)
---
diff --git a/common/gdm-settings-keys.h b/common/gdm-settings-keys.h
index f0059b5cf..87685d3cd 100644
--- a/common/gdm-settings-keys.h
+++ b/common/gdm-settings-keys.h
@@ -33,7 +33,9 @@ G_BEGIN_DECLS
 #define GDM_KEY_TIMED_LOGIN_USER "daemon/TimedLogin"
 #define GDM_KEY_TIMED_LOGIN_DELAY "daemon/TimedLoginDelay"
 #define GDM_KEY_INITIAL_SETUP_ENABLE "daemon/InitialSetupEnable"
+#define GDM_KEY_PREFERRED_DISPLAY_SERVER "daemon/PreferredDisplayServer"
 #define GDM_KEY_WAYLAND_ENABLE "daemon/WaylandEnable"
+#define GDM_KEY_XORG_ENABLE "daemon/XorgEnable"
 
 #define GDM_KEY_DEBUG "debug/Enable"
 
diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c
index 3a260923a..46d5a7732 100644
--- a/daemon/gdm-display.c
+++ b/daemon/gdm-display.c
@@ -93,6 +93,8 @@ typedef struct _GdmDisplayPrivate
         guint                 have_existing_user_accounts : 1;
         guint                 doing_initial_setup : 1;
         guint                 session_registered : 1;
+
+        GStrv                 supported_session_types;
 } GdmDisplayPrivate;
 
 enum {
@@ -116,6 +118,7 @@ enum {
         PROP_HAVE_EXISTING_USER_ACCOUNTS,
         PROP_DOING_INITIAL_SETUP,
         PROP_SESSION_REGISTERED,
+        PROP_SUPPORTED_SESSION_TYPES,
 };
 
 static void     gdm_display_class_init  (GdmDisplayClass *klass);
@@ -910,6 +913,23 @@ _gdm_display_set_allow_timed_login (GdmDisplay     *self,
         priv->allow_timed_login = allow_timed_login;
 }
 
+static void
+_gdm_display_set_supported_session_types (GdmDisplay         *self,
+                                          const char * const *supported_session_types)
+
+{
+        GdmDisplayPrivate *priv;
+        g_autofree char *supported_session_types_string = NULL;
+
+       if (supported_session_types != NULL)
+          supported_session_types_string = g_strjoinv (":", (GStrv) supported_session_types);
+
+        priv = gdm_display_get_instance_private (self);
+        g_debug ("GdmDisplay: supported session types: %s", supported_session_types_string);
+        g_strfreev (priv->supported_session_types);
+        priv->supported_session_types = g_strdupv ((GStrv) supported_session_types);
+}
+
 static void
 gdm_display_set_property (GObject        *object,
                           guint           prop_id,
@@ -966,6 +986,9 @@ gdm_display_set_property (GObject        *object,
         case PROP_SESSION_REGISTERED:
                 _gdm_display_set_session_registered (self, g_value_get_boolean (value));
                 break;
+        case PROP_SUPPORTED_SESSION_TYPES:
+                _gdm_display_set_supported_session_types (self, g_value_get_boxed (value));
+                break;
         default:
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                 break;
@@ -1044,6 +1067,9 @@ gdm_display_get_property (GObject        *object,
         case PROP_ALLOW_TIMED_LOGIN:
                 g_value_set_boolean (value, priv->allow_timed_login);
                 break;
+        case PROP_SUPPORTED_SESSION_TYPES:
+                g_value_set_boxed (value, priv->supported_session_types);
+                break;
         default:
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                 break;
@@ -1229,6 +1255,7 @@ gdm_display_dispose (GObject *object)
                 priv->finish_idle_id = 0;
         }
         g_clear_object (&priv->launch_environment);
+        g_clear_pointer (&priv->supported_session_types, g_strfreev);
 
         g_warn_if_fail (priv->status != GDM_DISPLAY_MANAGED);
         g_warn_if_fail (priv->user_access_file == NULL);
@@ -1389,6 +1416,14 @@ gdm_display_class_init (GdmDisplayClass *klass)
                                                            G_MAXINT,
                                                            GDM_DISPLAY_UNMANAGED,
                                                            G_PARAM_READWRITE | G_PARAM_CONSTRUCT | 
G_PARAM_STATIC_STRINGS));
+
+        g_object_class_install_property (object_class,
+                                         PROP_SUPPORTED_SESSION_TYPES,
+                                         g_param_spec_boxed ("supported-session-types",
+                                                             "supported session types",
+                                                             "supported session types",
+                                                             G_TYPE_STRV,
+                                                             G_PARAM_READWRITE | G_PARAM_CONSTRUCT | 
G_PARAM_STATIC_STRINGS));
 }
 
 static void
@@ -1721,6 +1756,7 @@ gdm_display_start_greeter_session (GdmDisplay *self)
         session = gdm_launch_environment_get_session (priv->launch_environment);
         g_object_set (G_OBJECT (session),
                       "display-is-initial", priv->is_initial,
+                      "supported-session-types", priv->supported_session_types,
                       NULL);
 
         g_free (display_name);
diff --git a/daemon/gdm-launch-environment.c b/daemon/gdm-launch-environment.c
index 87a1c5ffe..14ecfac2d 100644
--- a/daemon/gdm-launch-environment.c
+++ b/daemon/gdm-launch-environment.c
@@ -161,6 +161,7 @@ build_launch_environment (GdmLaunchEnvironment *launch_environment,
                 NULL
         };
         char *system_data_dirs;
+        g_auto (GStrv) supported_session_types = NULL;
         int i;
 
         /* create a hash table of current environment, then update keys has necessary */
@@ -244,6 +245,14 @@ build_launch_environment (GdmLaunchEnvironment *launch_environment,
                                               system_data_dirs));
         g_free (system_data_dirs);
 
+        g_object_get (launch_environment->priv->session,
+                      "supported-session-types",
+                      &supported_session_types,
+                      NULL);
+        g_hash_table_insert (hash,
+                             g_strdup ("GDM_SUPPORTED_SESSION_TYPES"),
+                             g_strjoinv (":", supported_session_types));
+
         return hash;
 }
 
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index 8a4ef06cd..0bb3851f1 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -183,6 +183,89 @@ take_next_display_number (GdmLocalDisplayFactory *factory)
         return ret;
 }
 
+static char *
+get_preferred_display_server (GdmLocalDisplayFactory *factory)
+{
+        g_autofree gchar *preferred_display_server = NULL;
+        gboolean wayland_enabled = FALSE, xorg_enabled = FALSE;
+
+        gdm_settings_direct_get_boolean (GDM_KEY_WAYLAND_ENABLE, &wayland_enabled);
+        gdm_settings_direct_get_boolean (GDM_KEY_XORG_ENABLE, &xorg_enabled);
+
+        if (wayland_enabled && !xorg_enabled) {
+                return g_strdup ("wayland");
+        }
+
+        if (!wayland_enabled && !xorg_enabled) {
+                return g_strdup ("none");
+        }
+
+        gdm_settings_direct_get_string (GDM_KEY_PREFERRED_DISPLAY_SERVER, &preferred_display_server);
+
+        if (g_strcmp0 (preferred_display_server, "wayland") == 0) {
+                if (wayland_enabled)
+                        return g_strdup (preferred_display_server);
+                else
+                        return g_strdup ("xorg");
+        }
+
+        if (g_strcmp0 (preferred_display_server, "xorg") == 0) {
+                if (xorg_enabled)
+                        return g_strdup (preferred_display_server);
+                else
+                        return g_strdup ("wayland");
+        }
+
+        if (g_strcmp0 (preferred_display_server, "legacy-xorg") == 0) {
+                if (xorg_enabled)
+                        return g_strdup (preferred_display_server);
+        }
+
+        return g_strdup ("none");
+}
+
+static const char *
+gdm_local_display_factory_get_session_type (GdmLocalDisplayFactory *factory,
+                                            gboolean                should_fall_back)
+{
+        const char *session_types[3] = { NULL };
+        gsize i, session_type_index = 0, number_of_session_types = 0;
+        g_autofree gchar *preferred_display_server = NULL;
+
+        preferred_display_server = get_preferred_display_server (factory);
+
+        if (g_strcmp0 (preferred_display_server, "wayland") != 0 &&
+            g_strcmp0 (preferred_display_server, "xorg") != 0)
+              return NULL;
+
+        for (i = 0; i < G_N_ELEMENTS (session_types) - 1; i++) {
+#ifdef ENABLE_WAYLAND_SUPPORT
+            if (number_of_session_types > 0 ||
+                g_strcmp0 (preferred_display_server, "wayland") == 0) {
+                    gboolean wayland_enabled = FALSE;
+                    if (gdm_settings_direct_get_boolean (GDM_KEY_WAYLAND_ENABLE, &wayland_enabled)) {
+                            if (wayland_enabled && g_file_test ("/usr/bin/Xwayland", 
G_FILE_TEST_IS_EXECUTABLE) )
+                                    session_types[number_of_session_types++] = "wayland";
+                    }
+            }
+#endif
+
+            if (number_of_session_types > 0 ||
+                g_strcmp0 (preferred_display_server, "xorg") == 0) {
+                    gboolean xorg_enabled = FALSE;
+                    if (gdm_settings_direct_get_boolean (GDM_KEY_XORG_ENABLE, &xorg_enabled)) {
+                            if (xorg_enabled && g_file_test ("/usr/bin/Xorg", G_FILE_TEST_IS_EXECUTABLE) )
+                                    session_types[number_of_session_types++] = "x11";
+                    }
+            }
+        }
+
+        if (should_fall_back)
+                session_type_index++;
+
+        return session_types[session_type_index];
+}
+
 static void
 on_display_disposed (GdmLocalDisplayFactory *factory,
                      GdmDisplay             *display)
@@ -200,19 +283,6 @@ store_display (GdmLocalDisplayFactory *factory,
         gdm_display_store_add (store, display);
 }
 
-static gboolean
-gdm_local_display_factory_use_wayland (void)
-{
-#ifdef ENABLE_WAYLAND_SUPPORT
-        gboolean wayland_enabled = FALSE;
-        if (gdm_settings_direct_get_boolean (GDM_KEY_WAYLAND_ENABLE, &wayland_enabled)) {
-                if (wayland_enabled && g_file_test ("/usr/bin/Xwayland", G_FILE_TEST_IS_EXECUTABLE) )
-                        return TRUE;
-        }
-#endif
-        return FALSE;
-}
-
 /*
   Example:
   dbus-send --system --dest=org.gnome.DisplayManager \
@@ -228,6 +298,8 @@ gdm_local_display_factory_create_transient_display (GdmLocalDisplayFactory *fact
         gboolean         ret;
         GdmDisplay      *display = NULL;
         gboolean         is_initial = FALSE;
+        const char      *session_type;
+        g_autofree gchar *preferred_display_server = NULL;
 
         g_return_val_if_fail (GDM_IS_LOCAL_DISPLAY_FACTORY (factory), FALSE);
 
@@ -235,20 +307,43 @@ gdm_local_display_factory_create_transient_display (GdmLocalDisplayFactory *fact
 
         g_debug ("GdmLocalDisplayFactory: Creating transient display");
 
-#ifdef ENABLE_USER_DISPLAY_SERVER
-        display = gdm_local_display_new ();
-        if (gdm_local_display_factory_use_wayland ())
-                g_object_set (G_OBJECT (display), "session-type", "wayland", NULL);
-        is_initial = TRUE;
-#else
-        if (display == NULL) {
-                guint32 num;
+        preferred_display_server = get_preferred_display_server (factory);
 
-                num = take_next_display_number (factory);
+#ifdef ENABLE_USER_DISPLAY_SERVER
+        if (g_strcmp0 (preferred_display_server, "wayland") == 0 ||
+            g_strcmp0 (preferred_display_server, "xorg") == 0) {
+                session_type = gdm_local_display_factory_get_session_type (factory, FALSE);
+
+                if (session_type == NULL) {
+                        g_set_error_literal (error,
+                                             GDM_DISPLAY_ERROR,
+                                             GDM_DISPLAY_ERROR_GENERAL,
+                                             "Both Wayland and Xorg are unavailable");
+                        return FALSE;
+                }
 
-                display = gdm_legacy_display_new (num);
+                display = gdm_local_display_new ();
+                g_object_set (G_OBJECT (display), "session-type", session_type, NULL);
+                is_initial = TRUE;
         }
 #endif
+        if (g_strcmp0 (preferred_display_server, "legacy-xorg") == 0) {
+                if (display == NULL) {
+                        guint32 num;
+
+                        num = take_next_display_number (factory);
+
+                        display = gdm_legacy_display_new (num);
+                }
+        }
+
+        if (display == NULL) {
+                g_set_error_literal (error,
+                                     GDM_DISPLAY_ERROR,
+                                     GDM_DISPLAY_ERROR_GENERAL,
+                                     "Invalid preferred display server configured");
+                return FALSE;
+        }
 
         g_object_set (display,
                       "seat-id", "seat0",
@@ -481,6 +576,19 @@ ensure_display_for_seat (GdmLocalDisplayFactory *factory,
         GdmDisplayStore *store;
         GdmDisplay      *display = NULL;
         g_autofree char *login_session_id = NULL;
+        gboolean wayland_enabled = FALSE, xorg_enabled = FALSE;
+        g_autofree gchar *preferred_display_server = NULL;
+        gboolean falling_back;
+
+        gdm_settings_direct_get_boolean (GDM_KEY_WAYLAND_ENABLE, &wayland_enabled);
+        gdm_settings_direct_get_boolean (GDM_KEY_XORG_ENABLE, &xorg_enabled);
+
+        preferred_display_server = get_preferred_display_server (factory);
+
+        if (g_strcmp0 (preferred_display_server, "none") == 0) {
+               g_debug ("GdmLocalDisplayFactory: Preferred display server is none, so not creating display");
+               return;
+        }
 
         ret = sd_seat_can_graphical (seat_id);
 
@@ -500,21 +608,18 @@ ensure_display_for_seat (GdmLocalDisplayFactory *factory,
         if (g_strcmp0 (seat_id, "seat0") == 0) {
                 is_seat0 = TRUE;
 
-                /* If we've failed, or are explicitly told to, fall back to legacy X11 support
-                 */
-                if (factory->num_failures > 0 || !gdm_local_display_factory_use_wayland ()) {
-                        session_type = NULL;
-                        g_debug ("GdmLocalDisplayFactory: New displays on seat0 will use X11 fallback");
-                } else {
-                        g_debug ("GdmLocalDisplayFactory: New displays on seat0 will use wayland");
-                }
+                falling_back = factory->num_failures > 0;
+                session_type = gdm_local_display_factory_get_session_type (factory, falling_back);
+
+                g_debug ("GdmLocalDisplayFactory: New displays on seat0 will use %s%s",
+                         session_type, falling_back? " fallback" : "");
         } else {
                 is_seat0 = FALSE;
 
                 g_debug ("GdmLocalDisplayFactory: New displays on seat %s will use X11 fallback", seat_id);
                 /* Force legacy X11 for all auxiliary seats */
                 seat_supports_graphics = TRUE;
-                session_type = NULL;
+                session_type = "x11";
         }
 
         /* For seat0, we have a fallback logic to still try starting it after
@@ -552,7 +657,8 @@ ensure_display_for_seat (GdmLocalDisplayFactory *factory,
                         g_debug ("GdmLocalDisplayFactory: Assuming we can use seat0 for X11 even though 
system says it doesn't support graphics!");
                         g_debug ("GdmLocalDisplayFactory: This might indicate an issue where the framebuffer 
device is not tagged as master-of-seat in udev.");
                         seat_supports_graphics = TRUE;
-                        session_type = NULL;
+                        session_type = "x11";
+                        wayland_enabled = FALSE;
                 } else {
                         g_clear_handle_id (&factory->seat0_graphics_check_timeout_id, g_source_remove);
                 }
@@ -561,8 +667,13 @@ ensure_display_for_seat (GdmLocalDisplayFactory *factory,
         if (!seat_supports_graphics)
                 return;
 
-        g_debug ("GdmLocalDisplayFactory: %s login display for seat %s requested",
-                 session_type? : "X11", seat_id);
+        if (session_type != NULL)
+                g_debug ("GdmLocalDisplayFactory: %s login display for seat %s requested",
+                         session_type, seat_id);
+        else if (g_strcmp0 (preferred_display_server, "legacy-xorg") == 0)
+                g_debug ("GdmLocalDisplayFactory: Legacy Xorg login display for seat %s requested",
+                         seat_id);
+
         store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
 
         if (is_seat0)
@@ -597,20 +708,53 @@ ensure_display_for_seat (GdmLocalDisplayFactory *factory,
         g_debug ("GdmLocalDisplayFactory: Adding display on seat %s", seat_id);
 
 #ifdef ENABLE_USER_DISPLAY_SERVER
-        if (is_seat0) {
-                display = gdm_local_display_new ();
-                if (session_type != NULL) {
+        if (g_strcmp0 (preferred_display_server, "wayland") == 0 ||
+            g_strcmp0 (preferred_display_server, "xorg") == 0) {
+                if (is_seat0) {
+                        g_autoptr (GPtrArray) supported_session_types = NULL;
+
+                        if (session_type == NULL) {
+                                g_warning ("GdmLocalDisplayFactory: Both Wayland and Xorg sessions are 
unavailable");
+                                return;
+                        }
+
+                        supported_session_types = g_ptr_array_new ();
+
+                        if (g_strcmp0 (preferred_display_server, "wayland") == 0) {
+                                if (wayland_enabled)
+                                        g_ptr_array_add (supported_session_types, "wayland");
+                        } else {
+                                if (xorg_enabled)
+                                        g_ptr_array_add (supported_session_types, "x11");
+                        }
+
+                        if (!falling_back) {
+                                if (g_strcmp0 (preferred_display_server, "wayland") == 0) {
+                                        if (xorg_enabled)
+                                                g_ptr_array_add (supported_session_types, "x11");
+                                } else {
+                                        if (wayland_enabled)
+                                                g_ptr_array_add (supported_session_types, "wayland");
+                                }
+                        }
+
+                        g_ptr_array_add (supported_session_types, NULL);
+
+                        display = gdm_local_display_new ();
                         g_object_set (G_OBJECT (display), "session-type", session_type, NULL);
+                        g_object_set (G_OBJECT (display), "supported-session-types", 
supported_session_types->pdata, NULL);
                 }
         }
 #endif
 
         if (display == NULL) {
                 guint32 num;
+                const char *supported_session_types[] = { "x11", NULL };
 
                 num = take_next_display_number (factory);
 
                 display = gdm_legacy_display_new (num);
+                g_object_set (G_OBJECT (display), "supported-session-types", supported_session_types, NULL);
         }
 
         g_object_set (display, "seat-id", seat_id, NULL);
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index 9c10adff3..e433acf3b 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -2307,7 +2307,6 @@ create_user_session_for_display (GdmManager *manager,
         char       *display_id = NULL;
 #if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
         g_autofree char *display_session_type = NULL;
-        gboolean    greeter_is_wayland;
 #endif
 
         g_object_get (G_OBJECT (display),
@@ -2405,11 +2404,6 @@ create_user_session_for_display (GdmManager *manager,
                                 session,
                                 (GDestroyNotify)
                                 clean_user_session);
-
-#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
-        greeter_is_wayland = g_strcmp0 (display_session_type, "wayland") == 0;
-        g_object_set (G_OBJECT (session), "ignore-wayland", !greeter_is_wayland, NULL);
-#endif
 }
 
 static void
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
index f705f0e07..ce49a8df4 100644
--- a/daemon/gdm-session.c
+++ b/daemon/gdm-session.c
@@ -132,11 +132,10 @@ struct _GdmSession
         GDBusServer         *outside_server;
         GHashTable          *environment;
 
+        GStrv                supported_session_types;
+
         guint32              is_program_session : 1;
         guint32              display_is_initial : 1;
-#ifdef ENABLE_WAYLAND_SUPPORT
-        guint32              ignore_wayland : 1;
-#endif
 };
 
 enum {
@@ -153,9 +152,7 @@ enum {
         PROP_DISPLAY_X11_AUTHORITY_FILE,
         PROP_USER_X11_AUTHORITY_FILE,
         PROP_CONVERSATION_ENVIRONMENT,
-#ifdef ENABLE_WAYLAND_SUPPORT
-        PROP_IGNORE_WAYLAND,
-#endif
+        PROP_SUPPORTED_SESSION_TYPES,
 };
 
 enum {
@@ -346,12 +343,23 @@ on_establish_credentials_cb (GdmDBusWorker *proxy,
         g_object_unref (self);
 }
 
+static gboolean
+supports_session_type (GdmSession *self,
+                       const char *session_type)
+{
+        if (session_type == NULL)
+                return TRUE;
+
+        return g_strv_contains ((const char * const *) self->supported_session_types,
+                                session_type);
+}
+
 static char **
 get_system_session_dirs (GdmSession *self)
 {
         GArray *search_array = NULL;
         char **search_dirs;
-        int i;
+        int i, j;
         const gchar * const *system_data_dirs = g_get_system_data_dirs ();
 
         static const char *x_search_dirs[] = {
@@ -365,32 +373,29 @@ get_system_session_dirs (GdmSession *self)
 
         search_array = g_array_new (TRUE, TRUE, sizeof (char *));
 
-        for (i = 0; system_data_dirs[i]; i++) {
-                gchar *dir = g_build_filename (system_data_dirs[i], "xsessions", NULL);
-                g_array_append_val (search_array, dir);
-        }
+        for (j = 0; self->supported_session_types[j] != NULL; j++) {
+                const char *supported_type = self->supported_session_types[j];
 
-        g_array_append_vals (search_array, x_search_dirs, G_N_ELEMENTS (x_search_dirs));
+                if (g_str_equal (supported_type, "x11")) {
+                        for (i = 0; system_data_dirs[i]; i++) {
+                                gchar *dir = g_build_filename (system_data_dirs[i], "xsessions", NULL);
+                                g_array_append_val (search_array, dir);
+                        }
+
+                        g_array_append_vals (search_array, x_search_dirs, G_N_ELEMENTS (x_search_dirs));
+                }
 
 #ifdef ENABLE_WAYLAND_SUPPORT
-        if (!self->ignore_wayland) {
-#ifdef ENABLE_USER_DISPLAY_SERVER
-                g_array_prepend_val (search_array, wayland_search_dir);
+                if (g_str_equal (supported_type, "wayland")) {
+                        g_array_prepend_val (search_array, wayland_search_dir);
 
-                for (i = 0; system_data_dirs[i]; i++) {
-                        gchar *dir = g_build_filename (system_data_dirs[i], "wayland-sessions", NULL);
-                        g_array_insert_val (search_array, i, dir);
-                }
-#else
-                for (i = 0; system_data_dirs[i]; i++) {
-                        gchar *dir = g_build_filename (system_data_dirs[i], "wayland-sessions", NULL);
-                        g_array_append_val (search_array, dir);
+                        for (i = 0; system_data_dirs[i]; i++) {
+                                gchar *dir = g_build_filename (system_data_dirs[i], "wayland-sessions", 
NULL);
+                                g_array_append_val (search_array, dir);
+                        }
                 }
-
-                g_array_append_val (search_array, wayland_search_dir);
 #endif
         }
-#endif
 
         search_dirs = g_strdupv ((char **) search_array->data);
 
@@ -2225,14 +2230,18 @@ stop_conversation_now (GdmSessionConversation *conversation)
         g_clear_object (&conversation->job);
 }
 
-#ifdef ENABLE_WAYLAND_SUPPORT
 void
-gdm_session_set_ignore_wayland (GdmSession *self,
-                                gboolean    ignore_wayland)
+gdm_session_set_supported_session_types (GdmSession         *self,
+                                         const char * const *supported_session_types)
 {
-        self->ignore_wayland = ignore_wayland;
+        const char * const session_types[] = { "wayland", "x11", NULL };
+        g_strfreev (self->supported_session_types);
+
+        if (supported_session_types == NULL)
+                self->supported_session_types = g_strdupv ((GStrv) session_types);
+        else
+                self->supported_session_types = g_strdupv ((GStrv) supported_session_types);
 }
-#endif
 
 gboolean
 gdm_session_start_conversation (GdmSession *self,
@@ -3165,11 +3174,13 @@ gdm_session_is_wayland_session (GdmSession *self)
 
         filename = get_session_filename (self);
 
-        key_file = load_key_file_for_file (self, filename, &full_path);
+        if (supports_session_type (self, "wayland")) {
+               key_file = load_key_file_for_file (self, filename, &full_path);
 
-        if (key_file == NULL) {
-                goto out;
-        }
+               if (key_file == NULL) {
+                       goto out;
+               }
+       }
 
         if (full_path != NULL && strstr (full_path, "/wayland-sessions/") != NULL) {
                 is_wayland_session = TRUE;
@@ -3507,11 +3518,9 @@ gdm_session_set_property (GObject      *object,
         case PROP_CONVERSATION_ENVIRONMENT:
                 set_conversation_environment (self, g_value_get_pointer (value));
                 break;
-#ifdef ENABLE_WAYLAND_SUPPORT
-        case PROP_IGNORE_WAYLAND:
-                gdm_session_set_ignore_wayland (self, g_value_get_boolean (value));
+        case PROP_SUPPORTED_SESSION_TYPES:
+                gdm_session_set_supported_session_types (self, g_value_get_boxed (value));
                 break;
-#endif
         default:
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                 break;
@@ -3565,11 +3574,9 @@ gdm_session_get_property (GObject    *object,
         case PROP_CONVERSATION_ENVIRONMENT:
                 g_value_set_pointer (value, self->environment);
                 break;
-#ifdef ENABLE_WAYLAND_SUPPORT
-        case PROP_IGNORE_WAYLAND:
-                g_value_set_boolean (value, self->ignore_wayland);
+        case PROP_SUPPORTED_SESSION_TYPES:
+                g_value_set_boxed (value, self->supported_session_types);
                 break;
-#endif
         default:
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                 break;
@@ -3587,6 +3594,8 @@ gdm_session_dispose (GObject *object)
 
         gdm_session_close (self);
 
+        g_clear_pointer (&self->supported_session_types,
+                         g_strfreev);
         g_clear_pointer (&self->conversations,
                          g_hash_table_unref);
 
@@ -4001,15 +4010,13 @@ gdm_session_class_init (GdmSessionClass *session_class)
                                                               NULL,
                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT | 
G_PARAM_STATIC_STRINGS));
 
-#ifdef ENABLE_WAYLAND_SUPPORT
         g_object_class_install_property (object_class,
-                                         PROP_IGNORE_WAYLAND,
-                                         g_param_spec_boolean ("ignore-wayland",
-                                                               "ignore wayland",
-                                                               "ignore wayland",
-                                                               FALSE,
-                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT | 
G_PARAM_STATIC_STRINGS));
-#endif
+                                         PROP_SUPPORTED_SESSION_TYPES,
+                                         g_param_spec_boxed ("supported-session-types",
+                                                             "supported session types",
+                                                             "supported session types",
+                                                             G_TYPE_STRV,
+                                                             G_PARAM_READWRITE | G_PARAM_CONSTRUCT | 
G_PARAM_STATIC_STRINGS));
 
         /* Ensure we can resolve errors */
         gdm_dbus_error_ensure (GDM_SESSION_WORKER_ERROR);
diff --git a/data/gdm.schemas.in b/data/gdm.schemas.in
index 255bff023..a1035f95e 100644
--- a/data/gdm.schemas.in
+++ b/data/gdm.schemas.in
@@ -52,11 +52,21 @@
       <signature>b</signature>
       <default>true</default>
     </schema>
+    <schema>
+      <key>daemon/PreferredDisplayServer</key>
+      <signature>s</signature>
+      <default>wayland</default>
+    </schema>
     <schema>
       <key>daemon/WaylandEnable</key>
       <signature>b</signature>
       <default>true</default>
     </schema>
+    <schema>
+      <key>daemon/XorgEnable</key>
+      <signature>b</signature>
+      <default>true</default>
+    </schema>
     <schema>
       <key>security/AllowRemoteAutoLogin</key>
       <signature>b</signature>
diff --git a/libgdm/gdm-sessions.c b/libgdm/gdm-sessions.c
index 75d442eeb..97ed5ef3d 100644
--- a/libgdm/gdm-sessions.c
+++ b/libgdm/gdm-sessions.c
@@ -190,6 +190,8 @@ collect_sessions_from_directory (const char *dirname)
 
         gboolean is_x11 = g_getenv ("WAYLAND_DISPLAY") == NULL &&
                           g_getenv ("RUNNING_UNDER_GDM") != NULL;
+        gboolean is_wayland = g_getenv ("WAYLAND_DISPLAY") != NULL &&
+                              g_getenv ("RUNNING_UNDER_GDM") != NULL;
 
         /* FIXME: add file monitor to directory */
 
@@ -206,18 +208,46 @@ collect_sessions_from_directory (const char *dirname)
                         continue;
                 }
 
-                if (is_x11 && g_str_has_suffix (filename, "-xorg.desktop")) {
-                        char *base_name = g_strndup (filename, strlen (filename) - strlen ("-xorg.desktop"));
-                        char *fallback_name = g_strconcat (base_name, ".desktop", NULL);
-                        g_free (base_name);
-                        char *fallback_path = g_build_filename (dirname, fallback_name, NULL);
-                        g_free (fallback_name);
-                        if (g_file_test (fallback_path, G_FILE_TEST_EXISTS)) {
-                                g_free (fallback_path);
-                                g_debug ("Running under X11, ignoring %s", filename);
-                                continue;
+                if (is_wayland) {
+                        if (g_str_has_suffix (filename, "-wayland.desktop")) {
+                                g_autofree char *base_name = g_strndup (filename, strlen (filename) - strlen 
("-wayland.desktop"));
+                                g_autofree char *other_name = g_strconcat (base_name, ".desktop", NULL);
+                                g_autofree char *other_path = g_build_filename (dirname, other_name, NULL);
+
+                                if (g_file_test (other_path, G_FILE_TEST_EXISTS)) {
+                                        g_debug ("Running under Wayland, ignoring %s", filename);
+                                        continue;
+                                }
+                        } else {
+                                g_autofree char *base_name = g_strndup (filename, strlen (filename) - strlen 
(".desktop"));
+                                g_autofree char *other_name = g_strdup_printf ("%s-xorg.desktop", base_name);
+                                g_autofree char *other_path = g_build_filename (dirname, other_name, NULL);
+
+                                if (g_file_test (other_path, G_FILE_TEST_EXISTS)) {
+                                        g_debug ("Running under Wayland, ignoring %s", filename);
+                                        continue;
+                                }
+                        }
+                } else if (is_x11) {
+                        if (g_str_has_suffix (filename, "-xorg.desktop")) {
+                                g_autofree char *base_name = g_strndup (filename, strlen (filename) - strlen 
("-xorg.desktop"));
+                                g_autofree char *other_name = g_strconcat (base_name, ".desktop", NULL);
+                                g_autofree char *other_path = g_build_filename (dirname, other_name, NULL);
+
+                                if (g_file_test (other_path, G_FILE_TEST_EXISTS)) {
+                                        g_debug ("Running under X11, ignoring %s", filename);
+                                        continue;
+                                }
+                        } else {
+                                g_autofree char *base_name = g_strndup (filename, strlen (filename) - strlen 
(".desktop"));
+                                g_autofree char *other_name = g_strdup_printf ("%s-wayland.desktop", 
base_name);
+                                g_autofree char *other_path = g_build_filename (dirname, other_name, NULL);
+
+                                if (g_file_test (other_path, G_FILE_TEST_EXISTS)) {
+                                        g_debug ("Running under X11, ignoring %s", filename);
+                                        continue;
+                                }
                         }
-                        g_free (fallback_path);
                 }
 
                 id = g_strndup (filename, strlen (filename) - strlen (".desktop"));
@@ -247,6 +277,9 @@ collect_sessions (void)
                 DATADIR "/gdm/BuiltInSessions/",
                 DATADIR "/xsessions/",
         };
+        g_auto (GStrv) supported_session_types = NULL;
+
+        supported_session_types = g_strsplit (g_getenv ("GDM_SUPPORTED_SESSION_TYPES"), ":", -1);
 
         names_seen_before = g_hash_table_new (g_str_hash, g_str_equal);
         xorg_search_array = g_ptr_array_new_with_free_func (g_free);
@@ -284,23 +317,22 @@ collect_sessions (void)
                                                                     g_free, 
(GDestroyNotify)gdm_session_file_free);
         }
 
-        for (i = 0; i < xorg_search_array->len; i++) {
-                collect_sessions_from_directory (g_ptr_array_index (xorg_search_array, i));
+        if (!supported_session_types || g_strv_contains ((const char * const *) supported_session_types, 
"x11")) {
+                for (i = 0; i < xorg_search_array->len; i++) {
+                        collect_sessions_from_directory (g_ptr_array_index (xorg_search_array, i));
+                }
         }
 
 #ifdef ENABLE_WAYLAND_SUPPORT
 #ifdef ENABLE_USER_DISPLAY_SERVER
-        if (g_getenv ("WAYLAND_DISPLAY") == NULL && g_getenv ("RUNNING_UNDER_GDM") != NULL) {
-                goto out;
+        if (!supported_session_types  || g_strv_contains ((const char * const *) supported_session_types, 
"wayland")) {
+                for (i = 0; i < wayland_search_array->len; i++) {
+                        collect_sessions_from_directory (g_ptr_array_index (wayland_search_array, i));
+                }
         }
 #endif
-
-        for (i = 0; i < wayland_search_array->len; i++) {
-                collect_sessions_from_directory (g_ptr_array_index (wayland_search_array, i));
-        }
 #endif
 
-out:
         g_hash_table_foreach_remove (gdm_available_sessions_map,
                                      remove_duplicate_sessions,
                                      names_seen_before);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]