From 04853a3b8c17712cc7f74c3c405ef47af53151c1 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Fri, 16 Jul 2021 12:34:57 -0400 Subject: 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 f0059b5c..87685d3c 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 3a260923..46d5a773 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 87a1c5ff..14ecfac2 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 8a4ef06c..0bb3851f 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 9c10adff..e433acf3 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 f705f0e0..ce49a8df 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 255bff02..a1035f95 100644 --- a/data/gdm.schemas.in +++ b/data/gdm.schemas.in @@ -52,11 +52,21 @@ b true + + daemon/PreferredDisplayServer + s + wayland + daemon/WaylandEnable b true + + daemon/XorgEnable + b + true + security/AllowRemoteAutoLogin b diff --git a/libgdm/gdm-sessions.c b/libgdm/gdm-sessions.c index 75d442ee..97ed5ef3 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); -- cgit v1.2.1