From 18ca7939a1183a7558e3875dc8ea03bacb640bff Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Aug 24 2021 22:28:17 +0000 Subject: import gdm-40.0-12.el8 --- diff --git a/SOURCES/0001-Revert-gdm-wayland-x-session-don-t-overwrite-user-en.patch b/SOURCES/0001-Revert-gdm-wayland-x-session-don-t-overwrite-user-en.patch index b126eb0..4f36edc 100644 --- a/SOURCES/0001-Revert-gdm-wayland-x-session-don-t-overwrite-user-en.patch +++ b/SOURCES/0001-Revert-gdm-wayland-x-session-don-t-overwrite-user-en.patch @@ -1,7 +1,7 @@ -From 911780e9980fe16b18d139f757ff795da1d1882d Mon Sep 17 00:00:00 2001 +From 85951a0384cb7f37d99669575fad4aea155f25a8 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 5 May 2021 10:50:56 -0400 -Subject: [PATCH] Revert "gdm-{wayland,x}-session: don't overwrite user env +Subject: [PATCH 1/5] Revert "gdm-{wayland,x}-session: don't overwrite user env with fallback vars" This reverts commit ccecd9c975d04da80db4cd547b67a1a94fa83292. @@ -237,5 +237,5 @@ index 5962da572..b15483614 100644 state->session_command, NULL); -- -2.31.1 +2.30.1 diff --git a/SOURCES/0001-data-Disable-network-configuration-on-login-screen.patch b/SOURCES/0001-data-Disable-network-configuration-on-login-screen.patch index 7727a05..e87a1b7 100644 --- a/SOURCES/0001-data-Disable-network-configuration-on-login-screen.patch +++ b/SOURCES/0001-data-Disable-network-configuration-on-login-screen.patch @@ -1,7 +1,7 @@ -From b840bedd919eb321f2cefd8b9620af5bc28a28b6 Mon Sep 17 00:00:00 2001 +From cebcf2a4d29f01061dedf8714db2842b9582900c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Tue, 8 Jun 2021 20:45:00 +0200 -Subject: [PATCH] data: Disable network configuration on login screen +Subject: [PATCH 1/3] data: Disable network configuration on login screen --- data/meson.build | 10 ++++++++++ @@ -10,10 +10,37 @@ Subject: [PATCH] data: Disable network configuration on login screen create mode 100644 data/org.gnome.gdm.rules.in diff --git a/data/meson.build b/data/meson.build -index 7c5222ea..20d39a36 100644 +index 23e2d7f9f..cbd6a6a21 100644 --- a/data/meson.build +++ b/data/meson.build -@@ -157,6 +157,16 @@ gdm_rules = configure_file( +@@ -131,60 +131,70 @@ pam_data_files_map = { + 'arch': [ + 'gdm-autologin', + 'gdm-launch-environment', + 'gdm-fingerprint', + 'gdm-smartcard', + 'gdm-password', + 'gdm-pin', + ], + 'none': [], + # We should no longer have 'autodetect' at this point + } + + pam_data_files = pam_data_files_map[default_pam_config] + pam_prefix = (get_option('pam-prefix') != '')? get_option('pam-prefix') : get_option('sysconfdir') + foreach _pam_filename : pam_data_files + install_data('pam-@0@/@1@.pam'.format(default_pam_config, _pam_filename), + rename: _pam_filename, + install_dir: pam_prefix / 'pam.d', + ) + endforeach + + gdm_rules = configure_file( + input: '61-gdm.rules.in', + output: '@BASENAME@', + configuration: { + 'libexecdir': gdm_prefix / get_option('libexecdir'), + }, install_dir: udev_dir, ) @@ -30,9 +57,36 @@ index 7c5222ea..20d39a36 100644 # DBus service files service_config = configuration_data() service_config.set('sbindir', gdm_prefix / get_option('sbindir')) + service_config.set('GDM_INITIAL_VT', get_option('initial-vt')) + service_config.set('LANG_CONFIG_FILE', lang_config_file) + if plymouth_dep.found() + service_config.set('PLYMOUTH_QUIT_SERVICE', 'plymouth-quit.service') + else + service_config.set('PLYMOUTH_QUIT_SERVICE', '') + endif + + if get_option('systemdsystemunitdir') != '' + systemd_systemunitdir = get_option('systemdsystemunitdir') + else + systemd_systemunitdir = systemd_dep.get_pkgconfig_variable('systemdsystemunitdir') + endif + + if get_option('systemduserunitdir') != '' + systemd_userunitdir = get_option('systemduserunitdir') + else + systemd_userunitdir = systemd_dep.get_pkgconfig_variable('systemduserunitdir', + define_variable: ['prefix', get_option('prefix')]) + endif + + configure_file( + input: 'gdm.service.in', + output: '@BASENAME@', + configuration: service_config, + install_dir: systemd_systemunitdir, + format: 'cmake' diff --git a/data/org.gnome.gdm.rules.in b/data/org.gnome.gdm.rules.in new file mode 100644 -index 00000000..09544f11 +index 000000000..09544f11e --- /dev/null +++ b/data/org.gnome.gdm.rules.in @@ -0,0 +1,8 @@ @@ -45,5 +99,5 @@ index 00000000..09544f11 + return polkit.Result.NOT_HANDLED; +}); -- -2.31.1 +2.30.1 diff --git a/SOURCES/0001-data-add-system-dconf-databases-to-gdm-profile.patch b/SOURCES/0001-data-add-system-dconf-databases-to-gdm-profile.patch index 2985995..8fa2615 100644 --- a/SOURCES/0001-data-add-system-dconf-databases-to-gdm-profile.patch +++ b/SOURCES/0001-data-add-system-dconf-databases-to-gdm-profile.patch @@ -1,7 +1,7 @@ -From b1557adf711577c62609f8a784f11fad66eb54ef Mon Sep 17 00:00:00 2001 +From 8c9fe8ebd9e584adaec0a80ee4c4eaf5357422a5 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 31 Jul 2013 17:32:55 -0400 -Subject: [PATCH] data: add system dconf databases to gdm profile +Subject: [PATCH 1/2] data: add system dconf databases to gdm profile This way system settings can affect the login screen. --- @@ -20,5 +20,5 @@ index 4d8bf1748..9694078fb 100644 +system-db:distro file-db:@DATADIR@/@PACKAGE@/greeter-dconf-defaults -- -2.28.0 +2.30.1 diff --git a/SOURCES/0001-data-disable-wayland-on-certain-hardware.patch b/SOURCES/0001-data-disable-wayland-on-certain-hardware.patch index 0a82ff8..8aba1da 100644 --- a/SOURCES/0001-data-disable-wayland-on-certain-hardware.patch +++ b/SOURCES/0001-data-disable-wayland-on-certain-hardware.patch @@ -1,26 +1,48 @@ -From 53afc21a17f002730a53fe790de564f055c07352 Mon Sep 17 00:00:00 2001 +From afdaf0c31c7fb44e05a271a9047a0993ff1f4ef2 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Mon, 11 Feb 2019 18:14:07 -0500 Subject: [PATCH] data: disable wayland on certain hardware We're having issues with wayland on passthrough to virt -setups and with the vendor nvidia driver, so -disable it in those cases. +setups and with the vendor nvidia driver on hybrid graphics +setups, so disable it in those cases. + +Also disable it on server chips for performance reasons. --- - data/61-gdm.rules.in | 15 ++++++++++++--- - 1 file changed, 12 insertions(+), 3 deletions(-) + data/61-gdm.rules.in | 36 ++++++++++++++++++++++++++++++++---- + 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/data/61-gdm.rules.in b/data/61-gdm.rules.in -index b1da191f8..0230e5ca5 100644 +index b1da191f8..d863a4a4d 100644 --- a/data/61-gdm.rules.in +++ b/data/61-gdm.rules.in -@@ -1,6 +1,15 @@ +@@ -1,6 +1,34 @@ # disable Wayland on Hi1710 chipsets -ATTR{vendor}=="0x19e5", ATTR{device}=="0x1711", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false" -+ATTR{vendor}=="0x19e5", ATTR{device}=="0x1711", RUN+="@libexecdir@/gdm-disable-wayland" - # disable Wayland when using the proprietary nvidia driver +-# disable Wayland when using the proprietary nvidia driver -DRIVER=="nvidia", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false" -+DRIVER=="nvidia", RUN+="@libexecdir@/gdm-disable-wayland" ++ATTR{vendor}=="0x19e5", ATTR{device}=="0x1711", RUN+="@libexecdir@/gdm-disable-wayland" ++ ++# disable Wayland on Matrox chipsets ++ATTR{vendor}=="0x102b", ATTR{device}=="0x0522", RUN+="@libexecdir@/gdm-disable-wayland" ++ATTR{vendor}=="0x102b", ATTR{device}=="0x0524", RUN+="@libexecdir@/gdm-disable-wayland" ++ATTR{vendor}=="0x102b", ATTR{device}=="0x0530", RUN+="@libexecdir@/gdm-disable-wayland" ++ATTR{vendor}=="0x102b", ATTR{device}=="0x0532", RUN+="@libexecdir@/gdm-disable-wayland" ++ATTR{vendor}=="0x102b", ATTR{device}=="0x0533", RUN+="@libexecdir@/gdm-disable-wayland" ++ATTR{vendor}=="0x102b", ATTR{device}=="0x0534", RUN+="@libexecdir@/gdm-disable-wayland" ++ATTR{vendor}=="0x102b", ATTR{device}=="0x0536", RUN+="@libexecdir@/gdm-disable-wayland" ++ATTR{vendor}=="0x102b", ATTR{device}=="0x0538", RUN+="@libexecdir@/gdm-disable-wayland" ++ ++# disable Wayland on aspeed chipsets ++ATTR{vendor}=="0x1a03", ATTR{device}=="0x2010", RUN+="@libexecdir@/gdm-disable-wayland" ++ATTR{vendor}=="0x1a03", ATTR{device}=="0x2000", RUN+="@libexecdir@/gdm-disable-wayland" ++ ++# disable Wayland on hybrid systems with vendor nvidia driver ++# default to Xorg on single gpu vendor nvidia systems ++DRIVER=="nvidia", ENV{GDM_HAS_VENDOR_NVIDIA_DRIVER}="1" ++DRIVER=="nvidia", RUN+="@libexecdir@/gdm-runtime-config set daemon PreferredDisplayServer xorg" ++SUBSYSTEM=="drm", KERNEL=="card[1-9]*", ENV{GDM_HAS_NVIDIA_DRIVER}=="1", RUN+="@libexecdir@/gdm-disable-wayland" ++ACTION=="add", SUBSYSTEM=="module", KERNEL=="nvidia_drm", ATTR{parameters/modeset}=="N", RUN+="/usr/libexec/gdm-disable-wayland" + +# disable Wayland on passthrough graphics setups for now (assumes passthrough if +# there is more than one card, and one of the cards is virt: cirrus, bochs, qxl) diff --git a/SOURCES/0001-display-Handle-failure-before-display-registration.patch b/SOURCES/0001-display-Handle-failure-before-display-registration.patch index 3e9f2ea..219a865 100644 --- a/SOURCES/0001-display-Handle-failure-before-display-registration.patch +++ b/SOURCES/0001-display-Handle-failure-before-display-registration.patch @@ -1,7 +1,7 @@ -From f860f60771cd4f07ae1d06c56621a5aa8545e60b Mon Sep 17 00:00:00 2001 +From cbfb3ef99ecc9cbb4e6850e5dd0cc9fb65dd398a Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Tue, 1 Sep 2020 13:49:27 -0400 -Subject: [PATCH] display: Handle failure before display registration +Subject: [PATCH 1/3] display: Handle failure before display registration Normally, e.g., gdm-wayland-session would register its display before starting the session. This display registration is how diff --git a/SOURCES/0001-local-display-factory-Provide-more-flexibility-for-c.patch b/SOURCES/0001-local-display-factory-Provide-more-flexibility-for-c.patch new file mode 100644 index 0000000..2d93f69 --- /dev/null +++ b/SOURCES/0001-local-display-factory-Provide-more-flexibility-for-c.patch @@ -0,0 +1,2573 @@ +From 8c3a382416729296e1d9ba24af6832c354bd6fc4 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 16 Jul 2021 12:34:57 -0400 +Subject: [PATCH 1/2] local-display-factory: 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 | 20 +-- + daemon/gdm-session.c | 143 +++++++++++-------- + data/gdm.schemas.in | 10 ++ + libgdm/gdm-sessions.c | 72 +++++++--- + 8 files changed, 378 insertions(+), 134 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 +@@ -6,59 +6,61 @@ + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + #ifndef _GDM_SETTINGS_KEYS_H + #define _GDM_SETTINGS_KEYS_H + + #include + + G_BEGIN_DECLS + + #define GDM_KEY_USER "daemon/User" + #define GDM_KEY_GROUP "daemon/Group" + #define GDM_KEY_AUTO_LOGIN_ENABLE "daemon/AutomaticLoginEnable" + #define GDM_KEY_AUTO_LOGIN_USER "daemon/AutomaticLogin" + #define GDM_KEY_TIMED_LOGIN_ENABLE "daemon/TimedLoginEnable" + #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" + + #define GDM_KEY_INCLUDE "greeter/Include" + #define GDM_KEY_EXCLUDE "greeter/Exclude" + #define GDM_KEY_INCLUDE_ALL "greeter/IncludeAll" + + #define GDM_KEY_DISALLOW_TCP "security/DisallowTCP" + #define GDM_KEY_ALLOW_REMOTE_AUTOLOGIN "security/AllowRemoteAutoLogin" + + #define GDM_KEY_XDMCP_ENABLE "xdmcp/Enable" + #define GDM_KEY_SHOW_LOCAL_GREETER "xdmcp/ShowLocalGreeter" + #define GDM_KEY_MAX_PENDING "xdmcp/MaxPending" + #define GDM_KEY_MAX_SESSIONS "xdmcp/MaxSessions" + #define GDM_KEY_MAX_WAIT "xdmcp/MaxWait" + #define GDM_KEY_DISPLAYS_PER_HOST "xdmcp/DisplaysPerHost" + #define GDM_KEY_UDP_PORT "xdmcp/Port" + #define GDM_KEY_INDIRECT "xdmcp/HonorIndirect" + #define GDM_KEY_MAX_WAIT_INDIRECT "xdmcp/MaxWaitIndirect" + #define GDM_KEY_PING_INTERVAL "xdmcp/PingIntervalSeconds" + #define GDM_KEY_WILLING "xdmcp/Willing" + + #define GDM_KEY_MULTICAST "chooser/Multicast" + #define GDM_KEY_MULTICAST_ADDR "chooser/MulticastAddr" + + G_END_DECLS + + #endif /* _GDM_SETTINGS_KEYS_H */ +diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c +index 7c954ad24..874f9e6ba 100644 +--- a/daemon/gdm-display.c ++++ b/daemon/gdm-display.c +@@ -66,83 +66,86 @@ typedef struct _GdmDisplayPrivate + char *x11_display_name; + int status; + time_t creation_time; + + char *x11_cookie; + gsize x11_cookie_size; + GdmDisplayAccessFile *access_file; + + guint finish_idle_id; + + xcb_connection_t *xcb_connection; + int xcb_screen_number; + + GDBusConnection *connection; + GdmDisplayAccessFile *user_access_file; + + GdmDBusDisplay *display_skeleton; + GDBusObjectSkeleton *object_skeleton; + + GDBusProxy *accountsservice_proxy; + + /* this spawns and controls the greeter session */ + GdmLaunchEnvironment *launch_environment; + + guint is_local : 1; + guint is_initial : 1; + guint allow_timed_login : 1; + guint have_existing_user_accounts : 1; + guint doing_initial_setup : 1; + guint session_registered : 1; ++ ++ GStrv supported_session_types; + } GdmDisplayPrivate; + + enum { + PROP_0, + PROP_ID, + PROP_STATUS, + PROP_SEAT_ID, + PROP_SESSION_ID, + PROP_SESSION_CLASS, + PROP_SESSION_TYPE, + PROP_REMOTE_HOSTNAME, + PROP_X11_DISPLAY_NUMBER, + PROP_X11_DISPLAY_NAME, + PROP_X11_COOKIE, + PROP_X11_AUTHORITY_FILE, + PROP_IS_CONNECTED, + PROP_IS_LOCAL, + PROP_LAUNCH_ENVIRONMENT, + PROP_IS_INITIAL, + PROP_ALLOW_TIMED_LOGIN, + PROP_HAVE_EXISTING_USER_ACCOUNTS, + PROP_DOING_INITIAL_SETUP, + PROP_SESSION_REGISTERED, ++ PROP_SUPPORTED_SESSION_TYPES, + }; + + static void gdm_display_class_init (GdmDisplayClass *klass); + static void gdm_display_init (GdmDisplay *self); + static void gdm_display_finalize (GObject *object); + static void queue_finish (GdmDisplay *self); + static void _gdm_display_set_status (GdmDisplay *self, + int status); + static gboolean wants_initial_setup (GdmDisplay *self); + G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GdmDisplay, gdm_display, G_TYPE_OBJECT) + + GQuark + gdm_display_error_quark (void) + { + static GQuark ret = 0; + if (ret == 0) { + ret = g_quark_from_static_string ("gdm_display_error"); + } + + return ret; + } + + time_t + gdm_display_get_creation_time (GdmDisplay *self) + { + GdmDisplayPrivate *priv; + + g_return_val_if_fail (GDM_IS_DISPLAY (self), 0); + + priv = gdm_display_get_instance_private (self); +@@ -885,116 +888,136 @@ _gdm_display_set_launch_environment (GdmDisplay *self, + + priv = gdm_display_get_instance_private (self); + + g_clear_object (&priv->launch_environment); + + priv->launch_environment = g_object_ref (launch_environment); + } + + static void + _gdm_display_set_is_initial (GdmDisplay *self, + gboolean initial) + { + GdmDisplayPrivate *priv; + + priv = gdm_display_get_instance_private (self); + g_debug ("GdmDisplay: initial: %s", initial? "yes" : "no"); + priv->is_initial = initial; + } + + static void + _gdm_display_set_allow_timed_login (GdmDisplay *self, + gboolean allow_timed_login) + { + GdmDisplayPrivate *priv; + + priv = gdm_display_get_instance_private (self); + g_debug ("GdmDisplay: allow timed login: %s", allow_timed_login? "yes" : "no"); + 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, + const GValue *value, + GParamSpec *pspec) + { + GdmDisplay *self; + + self = GDM_DISPLAY (object); + + switch (prop_id) { + case PROP_ID: + _gdm_display_set_id (self, g_value_get_string (value)); + break; + case PROP_STATUS: + _gdm_display_set_status (self, g_value_get_int (value)); + break; + case PROP_SEAT_ID: + _gdm_display_set_seat_id (self, g_value_get_string (value)); + break; + case PROP_SESSION_ID: + _gdm_display_set_session_id (self, g_value_get_string (value)); + break; + case PROP_SESSION_CLASS: + _gdm_display_set_session_class (self, g_value_get_string (value)); + break; + case PROP_SESSION_TYPE: + _gdm_display_set_session_type (self, g_value_get_string (value)); + break; + case PROP_REMOTE_HOSTNAME: + _gdm_display_set_remote_hostname (self, g_value_get_string (value)); + break; + case PROP_X11_DISPLAY_NUMBER: + _gdm_display_set_x11_display_number (self, g_value_get_int (value)); + break; + case PROP_X11_DISPLAY_NAME: + _gdm_display_set_x11_display_name (self, g_value_get_string (value)); + break; + case PROP_X11_COOKIE: + _gdm_display_set_x11_cookie (self, g_value_get_string (value)); + break; + case PROP_IS_LOCAL: + _gdm_display_set_is_local (self, g_value_get_boolean (value)); + break; + case PROP_ALLOW_TIMED_LOGIN: + _gdm_display_set_allow_timed_login (self, g_value_get_boolean (value)); + break; + case PROP_LAUNCH_ENVIRONMENT: + _gdm_display_set_launch_environment (self, g_value_get_object (value)); + break; + case PROP_IS_INITIAL: + _gdm_display_set_is_initial (self, g_value_get_boolean (value)); + break; + 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; + } + } + + static void + gdm_display_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) + { + GdmDisplay *self; + GdmDisplayPrivate *priv; + + self = GDM_DISPLAY (object); + priv = gdm_display_get_instance_private (self); + + switch (prop_id) { + case PROP_ID: + g_value_set_string (value, priv->id); + break; + case PROP_STATUS: + g_value_set_int (value, priv->status); + break; + case PROP_SEAT_ID: + g_value_set_string (value, priv->seat_id); + break; + case PROP_SESSION_ID: + g_value_set_string (value, priv->session_id); +@@ -1019,60 +1042,63 @@ gdm_display_get_property (GObject *object, + break; + case PROP_X11_AUTHORITY_FILE: + g_value_take_string (value, + priv->access_file? + gdm_display_access_file_get_path (priv->access_file) : NULL); + break; + case PROP_IS_LOCAL: + g_value_set_boolean (value, priv->is_local); + break; + case PROP_IS_CONNECTED: + g_value_set_boolean (value, priv->xcb_connection != NULL); + break; + case PROP_LAUNCH_ENVIRONMENT: + g_value_set_object (value, priv->launch_environment); + break; + case PROP_IS_INITIAL: + g_value_set_boolean (value, priv->is_initial); + break; + case PROP_HAVE_EXISTING_USER_ACCOUNTS: + g_value_set_boolean (value, priv->have_existing_user_accounts); + break; + case PROP_DOING_INITIAL_SETUP: + g_value_set_boolean (value, priv->doing_initial_setup); + break; + case PROP_SESSION_REGISTERED: + g_value_set_boolean (value, priv->session_registered); + break; + 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; + } + } + + static gboolean + handle_get_id (GdmDBusDisplay *skeleton, + GDBusMethodInvocation *invocation, + GdmDisplay *self) + { + char *id; + + gdm_display_get_id (self, &id, NULL); + + gdm_dbus_display_complete_get_id (skeleton, invocation, id); + + g_free (id); + return TRUE; + } + + static gboolean + handle_get_remote_hostname (GdmDBusDisplay *skeleton, + GDBusMethodInvocation *invocation, + GdmDisplay *self) + { + char *hostname; + + gdm_display_get_remote_hostname (self, &hostname, NULL); + +@@ -1204,60 +1230,61 @@ gdm_display_constructor (GType type, + priv = gdm_display_get_instance_private (self); + + g_free (priv->id); + priv->id = g_strdup_printf ("/org/gnome/DisplayManager/Displays/%lu", + (gulong) self); + + res = register_display (self); + if (! res) { + g_warning ("Unable to register display with system bus"); + } + + return G_OBJECT (self); + } + + static void + gdm_display_dispose (GObject *object) + { + GdmDisplay *self; + GdmDisplayPrivate *priv; + + self = GDM_DISPLAY (object); + priv = gdm_display_get_instance_private (self); + + g_debug ("GdmDisplay: Disposing display"); + + if (priv->finish_idle_id != 0) { + g_source_remove (priv->finish_idle_id); + 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); + g_warn_if_fail (priv->access_file == NULL); + + G_OBJECT_CLASS (gdm_display_parent_class)->dispose (object); + } + + static void + gdm_display_class_init (GdmDisplayClass *klass) + { + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->get_property = gdm_display_get_property; + object_class->set_property = gdm_display_set_property; + object_class->constructor = gdm_display_constructor; + object_class->dispose = gdm_display_dispose; + object_class->finalize = gdm_display_finalize; + + klass->prepare = gdm_display_real_prepare; + + g_object_class_install_property (object_class, + PROP_ID, + g_param_spec_string ("id", + "id", + "id", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, + PROP_REMOTE_HOSTNAME, +@@ -1364,60 +1391,68 @@ gdm_display_class_init (GdmDisplayClass *klass) + PROP_DOING_INITIAL_SETUP, + g_param_spec_boolean ("doing-initial-setup", + NULL, + NULL, + FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, + PROP_SESSION_REGISTERED, + g_param_spec_boolean ("session-registered", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, + PROP_LAUNCH_ENVIRONMENT, + g_param_spec_object ("launch-environment", + NULL, + NULL, + GDM_TYPE_LAUNCH_ENVIRONMENT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, + PROP_STATUS, + g_param_spec_int ("status", + "status", + "status", + -1, + 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 + gdm_display_init (GdmDisplay *self) + { + GdmDisplayPrivate *priv; + + priv = gdm_display_get_instance_private (self); + + priv->creation_time = time (NULL); + } + + static void + gdm_display_finalize (GObject *object) + { + GdmDisplay *self; + GdmDisplayPrivate *priv; + + g_return_if_fail (object != NULL); + g_return_if_fail (GDM_IS_DISPLAY (object)); + + self = GDM_DISPLAY (object); + priv = gdm_display_get_instance_private (self); + + g_return_if_fail (priv != NULL); + + g_debug ("GdmDisplay: Finalizing display: %s", priv->id); + g_free (priv->id); + g_free (priv->seat_id); + g_free (priv->session_class); +@@ -1696,60 +1731,61 @@ gdm_display_start_greeter_session (GdmDisplay *self) + G_CALLBACK (on_launch_environment_session_opened), + self, 0); + g_signal_connect_object (priv->launch_environment, + "started", + G_CALLBACK (on_launch_environment_session_started), + self, 0); + g_signal_connect_object (priv->launch_environment, + "stopped", + G_CALLBACK (on_launch_environment_session_stopped), + self, 0); + g_signal_connect_object (priv->launch_environment, + "exited", + G_CALLBACK (on_launch_environment_session_exited), + self, 0); + g_signal_connect_object (priv->launch_environment, + "died", + G_CALLBACK (on_launch_environment_session_died), + self, 0); + + if (auth_file != NULL) { + g_object_set (priv->launch_environment, + "x11-authority-file", auth_file, + NULL); + } + + gdm_launch_environment_start (priv->launch_environment); + + 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); + g_free (seat_id); + g_free (hostname); + g_free (auth_file); + } + + void + gdm_display_stop_greeter_session (GdmDisplay *self) + { + GdmDisplayPrivate *priv; + + priv = gdm_display_get_instance_private (self); + + if (priv->launch_environment != NULL) { + + g_signal_handlers_disconnect_by_func (priv->launch_environment, + G_CALLBACK (on_launch_environment_session_opened), + self); + g_signal_handlers_disconnect_by_func (priv->launch_environment, + G_CALLBACK (on_launch_environment_session_started), + self); + g_signal_handlers_disconnect_by_func (priv->launch_environment, + G_CALLBACK (on_launch_environment_session_stopped), + self); + g_signal_handlers_disconnect_by_func (priv->launch_environment, + G_CALLBACK (on_launch_environment_session_exited), + self); + g_signal_handlers_disconnect_by_func (priv->launch_environment, +diff --git a/daemon/gdm-launch-environment.c b/daemon/gdm-launch-environment.c +index feccf057f..5044290cd 100644 +--- a/daemon/gdm-launch-environment.c ++++ b/daemon/gdm-launch-environment.c +@@ -117,60 +117,61 @@ static GHashTable * + build_launch_environment (GdmLaunchEnvironment *launch_environment, + gboolean start_session) + { + GHashTable *hash; + struct passwd *pwent; + static const char *const optional_environment[] = { + "GI_TYPELIB_PATH", + "LANG", + "LANGUAGE", + "LC_ADDRESS", + "LC_ALL", + "LC_COLLATE", + "LC_CTYPE", + "LC_IDENTIFICATION", + "LC_MEASUREMENT", + "LC_MESSAGES", + "LC_MONETARY", + "LC_NAME", + "LC_NUMERIC", + "LC_PAPER", + "LC_TELEPHONE", + "LC_TIME", + "LD_LIBRARY_PATH", + "PATH", + "WINDOWPATH", + "XCURSOR_PATH", + "XDG_CONFIG_DIRS", + 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 */ + hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + + for (i = 0; optional_environment[i] != NULL; i++) { + if (g_getenv (optional_environment[i]) == NULL) { + continue; + } + + g_hash_table_insert (hash, + g_strdup (optional_environment[i]), + g_strdup (g_getenv (optional_environment[i]))); + } + + system_data_dirs = g_strjoinv (":", (char **) g_get_system_data_dirs ()); + + g_hash_table_insert (hash, + g_strdup ("XDG_DATA_DIRS"), + g_strdup_printf ("%s:%s", + DATADIR "/gdm/greeter", + system_data_dirs)); + g_free (system_data_dirs); + + if (launch_environment->priv->x11_authority_file != NULL) + g_hash_table_insert (hash, g_strdup ("XAUTHORITY"), g_strdup (launch_environment->priv->x11_authority_file)); + + if (launch_environment->priv->session_mode != NULL) { + g_hash_table_insert (hash, g_strdup ("GNOME_SHELL_SESSION_MODE"), g_strdup (launch_environment->priv->session_mode)); + +@@ -191,60 +192,68 @@ build_launch_environment (GdmLaunchEnvironment *launch_environment, + g_hash_table_insert (hash, g_strdup ("USER"), g_strdup (launch_environment->priv->user_name)); + g_hash_table_insert (hash, g_strdup ("USERNAME"), g_strdup (launch_environment->priv->user_name)); + + g_hash_table_insert (hash, g_strdup ("GDM_VERSION"), g_strdup (VERSION)); + g_hash_table_remove (hash, "MAIL"); + + g_hash_table_insert (hash, g_strdup ("HOME"), g_strdup ("/")); + g_hash_table_insert (hash, g_strdup ("PWD"), g_strdup ("/")); + g_hash_table_insert (hash, g_strdup ("SHELL"), g_strdup ("/bin/sh")); + + gdm_get_pwent_for_name (launch_environment->priv->user_name, &pwent); + if (pwent != NULL) { + if (pwent->pw_dir != NULL && pwent->pw_dir[0] != '\0') { + g_hash_table_insert (hash, g_strdup ("HOME"), g_strdup (pwent->pw_dir)); + g_hash_table_insert (hash, g_strdup ("PWD"), g_strdup (pwent->pw_dir)); + } + + g_hash_table_insert (hash, g_strdup ("SHELL"), g_strdup (pwent->pw_shell)); + } + + if (start_session && launch_environment->priv->x11_display_seat_id != NULL) { + char *seat_id; + + seat_id = launch_environment->priv->x11_display_seat_id; + + g_hash_table_insert (hash, g_strdup ("GDM_SEAT_ID"), g_strdup (seat_id)); + } + + g_hash_table_insert (hash, g_strdup ("RUNNING_UNDER_GDM"), g_strdup ("true")); + ++ 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; + } + + static void + on_session_setup_complete (GdmSession *session, + const char *service_name, + GdmLaunchEnvironment *launch_environment) + { + GHashTable *hash; + GHashTableIter iter; + gpointer key, value; + + hash = build_launch_environment (launch_environment, TRUE); + + g_hash_table_iter_init (&iter, hash); + while (g_hash_table_iter_next (&iter, &key, &value)) { + gdm_session_set_environment_variable (launch_environment->priv->session, key, value); + } + g_hash_table_destroy (hash); + } + + static void + on_session_opened (GdmSession *session, + const char *service_name, + const char *session_id, + GdmLaunchEnvironment *launch_environment) + { + launch_environment->priv->session_id = g_strdup (session_id); + + g_signal_emit (G_OBJECT (launch_environment), signals [OPENED], 0); +diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c +index 8a4ef06cd..a8ca1d598 100644 +--- a/daemon/gdm-local-display-factory.c ++++ b/daemon/gdm-local-display-factory.c +@@ -156,126 +156,221 @@ take_next_display_number (GdmLocalDisplayFactory *factory) + + g_debug ("GdmLocalDisplayFactory: Found the following X displays:"); + for (l = list; l != NULL; l = l->next) { + g_debug ("GdmLocalDisplayFactory: %u", GPOINTER_TO_UINT (l->data)); + } + + for (l = list; l != NULL; l = l->next) { + guint32 num; + num = GPOINTER_TO_UINT (l->data); + + /* always fill zero */ + if (l->prev == NULL && num != 0) { + ret = 0; + break; + } + /* now find the first hole */ + if (l->next == NULL || GPOINTER_TO_UINT (l->next->data) != (num + 1)) { + ret = num + 1; + break; + } + } + out: + + /* now reserve this number */ + g_debug ("GdmLocalDisplayFactory: Reserving X display: %u", ret); + g_hash_table_insert (factory->used_display_numbers, GUINT_TO_POINTER (ret), NULL); + + 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[i] = "wayland"; ++ number_of_session_types++; ++ continue; ++ } ++ } ++ } ++#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[i] = "x11"; ++ number_of_session_types++; ++ continue; ++ } ++ } ++ } ++ } ++ if (should_fall_back) ++ session_type_index++; ++ return session_types[session_type_index]; ++} ++ + static void + on_display_disposed (GdmLocalDisplayFactory *factory, + GdmDisplay *display) + { + g_debug ("GdmLocalDisplayFactory: Display %p disposed", display); + } + + static void + store_display (GdmLocalDisplayFactory *factory, + GdmDisplay *display) + { + GdmDisplayStore *store; + + store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (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 \ + --type=method_call --print-reply --reply-timeout=2000 \ + /org/gnome/DisplayManager/Manager \ + org.gnome.DisplayManager.Manager.GetDisplays + */ + gboolean + gdm_local_display_factory_create_transient_display (GdmLocalDisplayFactory *factory, + char **id, + GError **error) + { + 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); + + ret = FALSE; + + 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", + "allow-timed-login", FALSE, + "is-initial", is_initial, + NULL); + + store_display (factory, display); + + if (! gdm_display_manage (display)) { + display = NULL; + goto out; + } + + if (! gdm_display_get_id (display, id, NULL)) { + display = NULL; + goto out; + } + + ret = TRUE; + out: + /* ref either held by store or not at all */ + g_object_unref (display); + + return ret; + } + + static void + finish_display_on_seat_if_waiting (GdmDisplayStore *display_store, + GdmDisplay *display, +@@ -454,190 +549,239 @@ lookup_prepared_display_by_seat_id (const char *id, + return lookup_by_seat_id (id, display, user_data); + } + + static int + on_seat0_graphics_check_timeout (gpointer user_data) + { + GdmLocalDisplayFactory *factory = user_data; + + factory->seat0_graphics_check_timeout_id = 0; + + /* Simply try to re-add seat0. If it is there already (i.e. CanGraphical + * turned TRUE, then we'll find it and it will not be created again). + */ + factory->seat0_graphics_check_timed_out = TRUE; + ensure_display_for_seat (factory, "seat0"); + + return G_SOURCE_REMOVE; + } + + static void + ensure_display_for_seat (GdmLocalDisplayFactory *factory, + const char *seat_id) + { + int ret; + gboolean seat_supports_graphics; + gboolean is_seat0; + const char *session_type = "wayland"; + 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 = FALSE; ++ ++ 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); + + if (ret < 0) { + g_critical ("Failed to query CanGraphical information for seat %s", seat_id); + return; + } + + if (ret == 0) { + g_debug ("GdmLocalDisplayFactory: System doesn't currently support graphics"); + seat_supports_graphics = FALSE; + } else { + g_debug ("GdmLocalDisplayFactory: System supports graphics"); + seat_supports_graphics = TRUE; + } + + 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 + * SEAT0_GRAPHICS_CHECK_TIMEOUT seconds. i.e. we simply continue even if + * CanGraphical is unset. + * This is ugly, but it means we'll come up eventually in some + * scenarios where no master device is present. + * Note that we'll force an X11 fallback even though there might be + * cases where an wayland capable device is present and simply not marked as + * master-of-seat. In these cases, this should likely be fixed in the + * udev rules. + * + * At the moment, systemd always sets CanGraphical for non-seat0 seats. + * This is because non-seat0 seats are defined by having master-of-seat + * set. This means we can avoid the fallback check for non-seat0 seats, + * which simplifies the code. + */ + if (is_seat0) { + if (!seat_supports_graphics) { + if (!factory->seat0_graphics_check_timed_out) { + if (factory->seat0_graphics_check_timeout_id == 0) { + g_debug ("GdmLocalDisplayFactory: seat0 doesn't yet support graphics. Waiting %d seconds to try again.", SEAT0_GRAPHICS_CHECK_TIMEOUT); + factory->seat0_graphics_check_timeout_id = g_timeout_add_seconds (SEAT0_GRAPHICS_CHECK_TIMEOUT, + on_seat0_graphics_check_timeout, + factory); + + } else { + /* It is not yet time to force X11 fallback. */ + g_debug ("GdmLocalDisplayFactory: seat0 display requested when there is no graphics support before graphics check timeout."); + } + + return; + } + + 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); + } + } + + 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) + display = gdm_display_store_find (store, lookup_prepared_display_by_seat_id, (gpointer) seat_id); + else + display = gdm_display_store_find (store, lookup_by_seat_id, (gpointer) seat_id); + + /* Ensure we don't create the same display more than once */ + if (display != NULL) { + g_debug ("GdmLocalDisplayFactory: display already created"); + return; + } + + /* If we already have a login window, switch to it */ + if (gdm_get_login_window_session_id (seat_id, &login_session_id)) { + GdmDisplay *display; + + display = gdm_display_store_find (store, + lookup_by_session_id, + (gpointer) login_session_id); + if (display != NULL && + (gdm_display_get_status (display) == GDM_DISPLAY_MANAGED || + gdm_display_get_status (display) == GDM_DISPLAY_WAITING_TO_FINISH)) { + g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_MANAGED, NULL); + g_debug ("GdmLocalDisplayFactory: session %s found, activating.", + login_session_id); + gdm_activate_session_by_id (factory->connection, seat_id, login_session_id); + return; + } + } + + 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); + g_object_set (display, "is-initial", is_seat0, NULL); + + store_display (factory, display); + + /* let store own the ref */ + g_object_unref (display); + + if (! gdm_display_manage (display)) { + gdm_display_unmanage (display); + } + + return; + } + + static void + delete_display (GdmLocalDisplayFactory *factory, + const char *seat_id) { + + GdmDisplayStore *store; + + g_debug ("GdmLocalDisplayFactory: Removing used_display_numbers on seat %s", seat_id); + + store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory)); + gdm_display_store_foreach_remove (store, lookup_by_seat_id, (gpointer) seat_id); + } + + static gboolean +diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c +index 9c10adff3..24219691c 100644 +--- a/daemon/gdm-manager.c ++++ b/daemon/gdm-manager.c +@@ -1306,74 +1306,75 @@ get_automatic_login_details (GdmManager *manager, + *usernamep = username; + } else { + g_free (username); + } + + return enabled; + } + + static const char * + get_username_for_greeter_display (GdmManager *manager, + GdmDisplay *display) + { + gboolean doing_initial_setup = FALSE; + + g_object_get (G_OBJECT (display), + "doing-initial-setup", &doing_initial_setup, + NULL); + + if (doing_initial_setup) { + return INITIAL_SETUP_USERNAME; + } else { + return GDM_USERNAME; + } + } + + static void + set_up_automatic_login_session (GdmManager *manager, + GdmDisplay *display) + { + GdmSession *session; +- char *display_session_type = NULL; ++ g_auto (GStrv) supported_session_types = NULL; + + /* 0 is root user; since the daemon talks to the session object + * directly, itself, for automatic login + */ + create_user_session_for_display (manager, display, 0); + session = get_user_session_for_display (display); + + g_object_get (G_OBJECT (display), +- "session-type", &display_session_type, ++ "supported-session-types", &supported_session_types, + NULL); + + g_object_set (G_OBJECT (session), + "display-is-initial", FALSE, ++ "supported-session-types", supported_session_types, + NULL); + + g_debug ("GdmManager: Starting automatic login conversation"); + gdm_session_start_conversation (session, "gdm-autologin"); + } + + static void + set_up_chooser_session (GdmManager *manager, + GdmDisplay *display) + { + const char *allowed_user; + struct passwd *passwd_entry; + + allowed_user = get_username_for_greeter_display (manager, display); + + if (!gdm_get_pwent_for_name (allowed_user, &passwd_entry)) { + g_warning ("GdmManager: couldn't look up username %s", + allowed_user); + gdm_display_unmanage (display); + gdm_display_finish (display); + return; + } + + gdm_display_start_greeter_session (display); + } + + static void + set_up_greeter_session (GdmManager *manager, + GdmDisplay *display) + { +@@ -2278,87 +2279,83 @@ on_session_reauthentication_started (GdmSession *session, + + if (invocation != NULL) { + g_hash_table_steal (manager->priv->open_reauthentication_requests, + source_tag); + gdm_dbus_manager_complete_open_reauthentication_channel (GDM_DBUS_MANAGER (manager), + invocation, + address); + } + } + + static void + clean_user_session (GdmSession *session) + { + g_object_set_data (G_OBJECT (session), "gdm-display", NULL); + g_object_unref (session); + } + + static void + create_user_session_for_display (GdmManager *manager, + GdmDisplay *display, + uid_t allowed_user) + { + GdmSession *session; + gboolean display_is_local = FALSE; + char *display_name = NULL; + char *display_device = NULL; + char *remote_hostname = NULL; + char *display_auth_file = NULL; + char *display_seat_id = NULL; + 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_auto (GStrv) supported_session_types = NULL; + + g_object_get (G_OBJECT (display), + "id", &display_id, + "x11-display-name", &display_name, + "is-local", &display_is_local, + "remote-hostname", &remote_hostname, + "x11-authority-file", &display_auth_file, + "seat-id", &display_seat_id, +-#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER) +- "session-type", &display_session_type, +-#endif ++ "supported-session-types", &supported_session_types, + NULL); + display_device = get_display_device (manager, display); + + session = gdm_session_new (GDM_SESSION_VERIFICATION_MODE_LOGIN, + allowed_user, + display_name, + remote_hostname, + display_device, + display_seat_id, + display_auth_file, + display_is_local, + NULL); ++ g_object_set (G_OBJECT (session), "supported-session-types", supported_session_types, NULL); + + g_debug ("GdmSession: Created user session for user %d on display %s (seat %s)", + (int) allowed_user, + display_id, + display_seat_id); + + g_free (display_name); + g_free (remote_hostname); + g_free (display_auth_file); + g_free (display_seat_id); + + g_signal_connect (session, + "reauthentication-started", + G_CALLBACK (on_session_reauthentication_started), + manager); + g_signal_connect (session, + "reauthenticated", + G_CALLBACK (on_session_reauthenticated), + manager); + g_signal_connect (session, + "client-ready-for-session-to-start", + G_CALLBACK (on_session_client_ready_for_session_to_start), + manager); + g_signal_connect (session, + "client-connected", + G_CALLBACK (on_session_client_connected), + manager); + g_signal_connect (session, + "client-disconnected", + G_CALLBACK (on_session_client_disconnected), +@@ -2378,65 +2375,60 @@ create_user_session_for_display (GdmManager *manager, + g_signal_connect (session, + "authentication-failed", + G_CALLBACK (on_session_authentication_failed), + manager); + g_signal_connect (session, + "session-opened", + G_CALLBACK (on_user_session_opened), + manager); + g_signal_connect (session, + "session-started", + G_CALLBACK (on_user_session_started), + manager); + g_signal_connect (session, + "session-start-failed", + G_CALLBACK (on_session_start_failed), + manager); + g_signal_connect (session, + "session-exited", + G_CALLBACK (on_user_session_exited), + manager); + g_signal_connect (session, + "session-died", + G_CALLBACK (on_user_session_died), + manager); + g_object_set_data (G_OBJECT (session), "gdm-display", display); + g_object_set_data_full (G_OBJECT (display), + "gdm-user-session", + 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 + on_display_added (GdmDisplayStore *display_store, + const char *id, + GdmManager *manager) + { + GdmDisplay *display; + + display = gdm_display_store_lookup (display_store, id); + + if (display != NULL) { + g_dbus_object_manager_server_export (manager->priv->object_manager, + gdm_display_get_object_skeleton (display)); + + g_signal_connect (display, "notify::status", + G_CALLBACK (on_display_status_changed), + manager); + g_signal_emit (manager, signals[DISPLAY_ADDED], 0, id); + } + } + + GQuark + gdm_manager_error_quark (void) + { + static GQuark ret = 0; + if (ret == 0) { + ret = g_quark_from_static_string ("gdm_manager_error"); + } + +diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c +index 5c5903a49..a53fb9804 100644 +--- a/daemon/gdm-session.c ++++ b/daemon/gdm-session.c +@@ -105,100 +105,98 @@ struct _GdmSession + GdmDBusUserVerifier *user_verifier_interface; + GHashTable *user_verifier_extensions; + GdmDBusGreeter *greeter_interface; + GdmDBusRemoteGreeter *remote_greeter_interface; + GdmDBusChooser *chooser_interface; + + GList *pending_worker_connections; + GList *outside_connections; + + GPid session_pid; + + /* object lifetime scope */ + char *session_type; + char *display_name; + char *display_hostname; + char *display_device; + char *display_seat_id; + char *display_x11_authority_file; + gboolean display_is_local; + + GdmSessionVerificationMode verification_mode; + + uid_t allowed_user; + + char *fallback_session_name; + + GDBusServer *worker_server; + 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 { + PROP_0, + PROP_VERIFICATION_MODE, + PROP_ALLOWED_USER, + PROP_DISPLAY_NAME, + PROP_DISPLAY_HOSTNAME, + PROP_DISPLAY_IS_LOCAL, + PROP_DISPLAY_IS_INITIAL, + PROP_SESSION_TYPE, + PROP_DISPLAY_DEVICE, + PROP_DISPLAY_SEAT_ID, + 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 { + CONVERSATION_STARTED = 0, + CONVERSATION_STOPPED, + SETUP_COMPLETE, + CANCELLED, + HOSTNAME_SELECTED, + CLIENT_REJECTED, + CLIENT_CONNECTED, + CLIENT_DISCONNECTED, + CLIENT_READY_FOR_SESSION_TO_START, + DISCONNECTED, + AUTHENTICATION_FAILED, + VERIFICATION_COMPLETE, + SESSION_OPENED, ++ SESSION_OPENED_FAILED, + SESSION_STARTED, + SESSION_START_FAILED, + SESSION_EXITED, + SESSION_DIED, + REAUTHENTICATION_STARTED, + REAUTHENTICATED, + LAST_SIGNAL + }; + + #ifdef ENABLE_WAYLAND_SUPPORT + static gboolean gdm_session_is_wayland_session (GdmSession *self); + #endif + static void update_session_type (GdmSession *self); + static void set_session_type (GdmSession *self, + const char *session_type); + static void close_conversation (GdmSessionConversation *conversation); + + static guint signals [LAST_SIGNAL] = { 0, }; + + G_DEFINE_TYPE (GdmSession, + gdm_session, + G_TYPE_OBJECT); + + static GdmSessionConversation * + find_conversation_by_name (GdmSession *self, + const char *service_name) + { + GdmSessionConversation *conversation; + + conversation = g_hash_table_lookup (self->conversations, service_name); +@@ -295,128 +293,136 @@ on_authorize_cb (GdmDBusWorker *proxy, + + if (worked) { + gdm_session_accredit (self, service_name); + } else { + report_and_stop_conversation (self, service_name, error); + } + } + + static void + on_establish_credentials_cb (GdmDBusWorker *proxy, + GAsyncResult *res, + gpointer user_data) + { + GdmSessionConversation *conversation = user_data; + GdmSession *self; + char *service_name; + + GError *error = NULL; + gboolean worked; + + worked = gdm_dbus_worker_call_establish_credentials_finish (proxy, res, &error); + + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED) || + g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + return; + + self = g_object_ref (conversation->session); + service_name = g_strdup (conversation->service_name); + + if (worked) { +- if (self->user_verifier_interface != NULL) { +- gdm_dbus_user_verifier_emit_verification_complete (self->user_verifier_interface, +- service_name); +- g_signal_emit (self, signals[VERIFICATION_COMPLETE], 0, service_name); +- } +- + switch (self->verification_mode) { + case GDM_SESSION_VERIFICATION_MODE_LOGIN: + case GDM_SESSION_VERIFICATION_MODE_CHOOSER: + gdm_session_open_session (self, service_name); + break; + case GDM_SESSION_VERIFICATION_MODE_REAUTHENTICATE: ++ if (self->user_verifier_interface != NULL) { ++ gdm_dbus_user_verifier_emit_verification_complete (self->user_verifier_interface, ++ service_name); ++ g_signal_emit (self, signals[VERIFICATION_COMPLETE], 0, service_name); ++ } ++ break; + default: + break; + } + } else { + report_and_stop_conversation (self, service_name, error); + } + + g_free (service_name); + 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[] = { + "/etc/X11/sessions/", + DMCONFDIR "/Sessions/", + DATADIR "/gdm/BuiltInSessions/", + DATADIR "/xsessions/", + }; + + static const char *wayland_search_dir = DATADIR "/wayland-sessions/"; + + 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]; ++ ++ 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)); ++ 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")) { ++ 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_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); ++ g_array_append_val (search_array, wayland_search_dir); + } +- +- g_array_append_val (search_array, wayland_search_dir); + #endif + } +-#endif + + search_dirs = g_strdupv ((char **) search_array->data); + + g_array_free (search_array, TRUE); + + return search_dirs; + } + + static gboolean + is_prog_in_path (const char *prog) + { + char *f; + gboolean ret; + + f = g_find_program_in_path (prog); + ret = (f != NULL); + g_free (f); + return ret; + } + + static GKeyFile * + load_key_file_for_file (GdmSession *self, + const char *file, + char **full_path) + { + GKeyFile *key_file; + GError *error; + gboolean res; + char **search_dirs; + +@@ -839,78 +845,78 @@ static void + on_opened (GdmDBusWorker *worker, + GAsyncResult *res, + gpointer user_data) + { + GdmSessionConversation *conversation = user_data; + GdmSession *self; + char *service_name; + + GError *error = NULL; + gboolean worked; + char *session_id; + + worked = gdm_dbus_worker_call_open_finish (worker, + &session_id, + res, + &error); + + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED) || + g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + return; + + self = conversation->session; + service_name = conversation->service_name; + + if (worked) { + g_clear_pointer (&conversation->session_id, + (GDestroyNotify) g_free); + + conversation->session_id = g_strdup (session_id); + +- if (self->greeter_interface != NULL) { +- gdm_dbus_greeter_emit_session_opened (self->greeter_interface, +- service_name); +- } +- + if (self->user_verifier_interface != NULL) { + gdm_dbus_user_verifier_emit_verification_complete (self->user_verifier_interface, + service_name); + g_signal_emit (self, signals[VERIFICATION_COMPLETE], 0, service_name); + } + ++ if (self->greeter_interface != NULL) { ++ gdm_dbus_greeter_emit_session_opened (self->greeter_interface, ++ service_name); ++ } ++ + g_debug ("GdmSession: Emitting 'session-opened' signal"); + g_signal_emit (self, signals[SESSION_OPENED], 0, service_name, session_id); + } else { + report_and_stop_conversation (self, service_name, error); + + g_debug ("GdmSession: Emitting 'session-start-failed' signal"); +- g_signal_emit (self, signals[SESSION_START_FAILED], 0, service_name, error->message); ++ g_signal_emit (self, signals[SESSION_OPENED_FAILED], 0, service_name, error->message); + } + } + + static void + worker_on_username_changed (GdmDBusWorker *worker, + const char *username, + GdmSessionConversation *conversation) + { + GdmSession *self = conversation->session; + + g_debug ("GdmSession: changing username from '%s' to '%s'", + self->selected_user != NULL ? self->selected_user : "", + (strlen (username)) ? username : ""); + + gdm_session_select_user (self, (strlen (username) > 0) ? g_strdup (username) : NULL); + gdm_session_defaults_changed (self); + } + + static void + worker_on_session_exited (GdmDBusWorker *worker, + const char *service_name, + int status, + GdmSessionConversation *conversation) + { + GdmSession *self = conversation->session; + + self->session_conversation = NULL; + + if (WIFEXITED (status)) { + g_debug ("GdmSession: Emitting 'session-exited' signal with exit code '%d'", +@@ -2197,68 +2203,72 @@ close_conversation (GdmSessionConversation *conversation) + + if (conversation->worker_manager_interface != NULL) { + unexport_worker_manager_interface (self, conversation->worker_manager_interface); + g_clear_object (&conversation->worker_manager_interface); + } + + if (conversation->worker_proxy != NULL) { + GDBusConnection *connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (conversation->worker_proxy)); + g_dbus_connection_close_sync (connection, NULL, NULL); + } + } + + static void + stop_conversation (GdmSessionConversation *conversation) + { + close_conversation (conversation); + + conversation->is_stopping = TRUE; + gdm_session_worker_job_stop (conversation->job); + } + + static void + stop_conversation_now (GdmSessionConversation *conversation) + { + close_conversation (conversation); + + gdm_session_worker_job_stop_now (conversation->job); + 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, + const char *service_name) + { + GdmSessionConversation *conversation; + + g_return_val_if_fail (GDM_IS_SESSION (self), FALSE); + + conversation = g_hash_table_lookup (self->conversations, + service_name); + + if (conversation != NULL) { + if (!conversation->is_stopping) { + g_warning ("GdmSession: conversation %s started more than once", service_name); + return FALSE; + } + g_debug ("GdmSession: stopping old conversation %s", service_name); + gdm_session_worker_job_stop_now (conversation->job); + g_object_unref (conversation->job); + conversation->job = NULL; + } + + g_debug ("GdmSession: starting conversation %s for session (%p)", service_name, self); + + conversation = start_conversation (self, service_name); + + g_hash_table_insert (self->conversations, + g_strdup (service_name), conversation); + return TRUE; +@@ -3137,64 +3147,66 @@ gdm_session_get_conversation_session_id (GdmSession *self, + + conversation = find_conversation_by_name (self, service_name); + + if (conversation == NULL) { + return NULL; + } + + return conversation->session_id; + } + + static char * + get_session_filename (GdmSession *self) + { + return g_strdup_printf ("%s.desktop", get_session_name (self)); + } + + #ifdef ENABLE_WAYLAND_SUPPORT + static gboolean + gdm_session_is_wayland_session (GdmSession *self) + { + GKeyFile *key_file; + gboolean is_wayland_session = FALSE; + char *filename; + char *full_path = NULL; + + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (GDM_IS_SESSION (self), FALSE); + + 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; + } + g_debug ("GdmSession: checking if file '%s' is wayland session: %s", filename, is_wayland_session? "yes" : "no"); + + out: + g_clear_pointer (&key_file, g_key_file_free); + g_free (filename); + return is_wayland_session; + } + #endif + + static void + update_session_type (GdmSession *self) + { + #ifdef ENABLE_WAYLAND_SUPPORT + gboolean is_wayland_session; + + is_wayland_session = gdm_session_is_wayland_session (self); + if (is_wayland_session) { + set_session_type (self, "wayland"); + } else { + set_session_type (self, NULL); + } + #endif + } + + gboolean +@@ -3479,140 +3491,138 @@ gdm_session_set_property (GObject *object, + case PROP_DISPLAY_HOSTNAME: + set_display_hostname (self, g_value_get_string (value)); + break; + case PROP_DISPLAY_DEVICE: + set_display_device (self, g_value_get_string (value)); + break; + case PROP_DISPLAY_SEAT_ID: + set_display_seat_id (self, g_value_get_string (value)); + break; + case PROP_USER_X11_AUTHORITY_FILE: + set_user_x11_authority_file (self, g_value_get_string (value)); + break; + case PROP_DISPLAY_X11_AUTHORITY_FILE: + set_display_x11_authority_file (self, g_value_get_string (value)); + break; + case PROP_DISPLAY_IS_LOCAL: + set_display_is_local (self, g_value_get_boolean (value)); + break; + case PROP_DISPLAY_IS_INITIAL: + set_display_is_initial (self, g_value_get_boolean (value)); + break; + case PROP_VERIFICATION_MODE: + set_verification_mode (self, g_value_get_enum (value)); + break; + case PROP_ALLOWED_USER: + set_allowed_user (self, g_value_get_uint (value)); + break; + 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; + } + } + + static void + gdm_session_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) + { + GdmSession *self; + + self = GDM_SESSION (object); + + switch (prop_id) { + case PROP_SESSION_TYPE: + g_value_set_string (value, self->session_type); + break; + case PROP_DISPLAY_NAME: + g_value_set_string (value, self->display_name); + break; + case PROP_DISPLAY_HOSTNAME: + g_value_set_string (value, self->display_hostname); + break; + case PROP_DISPLAY_DEVICE: + g_value_set_string (value, self->display_device); + break; + case PROP_DISPLAY_SEAT_ID: + g_value_set_string (value, self->display_seat_id); + break; + case PROP_USER_X11_AUTHORITY_FILE: + g_value_set_string (value, self->user_x11_authority_file); + break; + case PROP_DISPLAY_X11_AUTHORITY_FILE: + g_value_set_string (value, self->display_x11_authority_file); + break; + case PROP_DISPLAY_IS_LOCAL: + g_value_set_boolean (value, self->display_is_local); + break; + case PROP_DISPLAY_IS_INITIAL: + g_value_set_boolean (value, self->display_is_initial); + break; + case PROP_VERIFICATION_MODE: + g_value_set_enum (value, self->verification_mode); + break; + case PROP_ALLOWED_USER: + g_value_set_uint (value, self->allowed_user); + break; + 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; + } + } + + static void + gdm_session_dispose (GObject *object) + { + GdmSession *self; + + self = GDM_SESSION (object); + + g_debug ("GdmSession: Disposing session"); + + gdm_session_close (self); + ++ g_clear_pointer (&self->supported_session_types, ++ g_strfreev); + g_clear_pointer (&self->conversations, + g_hash_table_unref); + + g_clear_object (&self->user_verifier_interface); + g_clear_pointer (&self->user_verifier_extensions, + g_hash_table_unref); + g_clear_object (&self->greeter_interface); + g_clear_object (&self->remote_greeter_interface); + g_clear_object (&self->chooser_interface); + + g_free (self->display_name); + self->display_name = NULL; + + g_free (self->display_hostname); + self->display_hostname = NULL; + + g_free (self->display_device); + self->display_device = NULL; + + g_free (self->display_seat_id); + self->display_seat_id = NULL; + + g_free (self->display_x11_authority_file); + self->display_x11_authority_file = NULL; + + g_strfreev (self->conversation_environment); + self->conversation_environment = NULL; + + if (self->worker_server != NULL) { + g_dbus_server_stop (self->worker_server); +@@ -3719,60 +3729,71 @@ gdm_session_class_init (GdmSessionClass *session_class) + NULL, + NULL, + NULL, + G_TYPE_NONE, + 2, + G_TYPE_STRING, + G_TYPE_INT); + signals [VERIFICATION_COMPLETE] = + g_signal_new ("verification-complete", + GDM_TYPE_SESSION, + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 1, + G_TYPE_STRING); + signals [SESSION_OPENED] = + g_signal_new ("session-opened", + GDM_TYPE_SESSION, + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 2, + G_TYPE_STRING, + G_TYPE_STRING); ++ signals [SESSION_OPENED_FAILED] = ++ g_signal_new ("session-opened-failed", ++ GDM_TYPE_SESSION, ++ G_SIGNAL_RUN_FIRST, ++ 0, ++ NULL, ++ NULL, ++ g_cclosure_marshal_generic, ++ G_TYPE_NONE, ++ 2, ++ G_TYPE_STRING, G_TYPE_STRING); + signals [SESSION_STARTED] = + g_signal_new ("session-started", + GDM_TYPE_SESSION, + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + g_cclosure_marshal_generic, + G_TYPE_NONE, + 2, + G_TYPE_STRING, + G_TYPE_INT); + signals [SESSION_START_FAILED] = + g_signal_new ("session-start-failed", + GDM_TYPE_SESSION, + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + g_cclosure_marshal_generic, + G_TYPE_NONE, + 2, + G_TYPE_STRING, G_TYPE_STRING); + signals [SESSION_EXITED] = + g_signal_new ("session-exited", + GDM_TYPE_SESSION, + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, +@@ -3962,69 +3983,67 @@ gdm_session_class_init (GdmSessionClass *session_class) + PROP_DISPLAY_X11_AUTHORITY_FILE, + g_param_spec_string ("display-x11-authority-file", + "display x11 authority file", + "display x11 authority file", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + /* not construct only */ + g_object_class_install_property (object_class, + PROP_USER_X11_AUTHORITY_FILE, + g_param_spec_string ("user-x11-authority-file", + "", + "", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, + PROP_DISPLAY_DEVICE, + g_param_spec_string ("display-device", + "display device", + "display device", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, + PROP_DISPLAY_SEAT_ID, + g_param_spec_string ("display-seat-id", + "display seat id", + "display seat id", + 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); + } + + GdmSession * + gdm_session_new (GdmSessionVerificationMode verification_mode, + uid_t allowed_user, + const char *display_name, + const char *display_hostname, + const char *display_device, + const char *display_seat_id, + const char *display_x11_authority_file, + gboolean display_is_local, + const char * const *environment) + { + GdmSession *self; + + self = g_object_new (GDM_TYPE_SESSION, + "verification-mode", verification_mode, + "allowed-user", (guint) allowed_user, + "display-name", display_name, + "display-hostname", display_hostname, + "display-device", display_device, + "display-seat-id", display_seat_id, + "display-x11-authority-file", display_x11_authority_file, + "display-is-local", display_is_local, + "conversation-environment", environment, + NULL); + +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 +@@ -25,65 +25,75 @@ + + daemon/AutomaticLoginEnable + b + false + + + daemon/AutomaticLogin + s + + + + daemon/TimedLoginEnable + b + false + + + daemon/TimedLogin + s + + + + daemon/TimedLoginDelay + i + 30 + + + daemon/InitialSetupEnable + b + true + ++ ++ daemon/PreferredDisplayServer ++ s ++ wayland ++ + + daemon/WaylandEnable + b + true + ++ ++ daemon/XorgEnable ++ b ++ true ++ + + security/AllowRemoteAutoLogin + b + false + + + + debug/Enable + b + false + + + + security/DisallowTCP + b + true + + + xdmcp/Enable + b + false + + + xdmcp/ShowLocalGreeter + b + true + + + xdmcp/MaxPending + i +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 +@@ -163,171 +163,203 @@ load_session_file (const char *id, + + static gboolean + remove_duplicate_sessions (gpointer key, + gpointer value, + gpointer user_data) + { + gboolean already_known; + GHashTable *names_seen_before; + GdmSessionFile *session; + + names_seen_before = (GHashTable *) user_data; + session = (GdmSessionFile *) value; + already_known = !g_hash_table_add (names_seen_before, session->translated_name); + + if (already_known) + g_debug ("GdmSession: Removing %s (%s) as we already have a session by this name", + session->id, + session->path); + + return already_known; + } + + static void + collect_sessions_from_directory (const char *dirname) + { + GDir *dir; + const char *filename; + + 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 */ + + dir = g_dir_open (dirname, 0, NULL); + if (dir == NULL) { + return; + } + + while ((filename = g_dir_read_name (dir))) { + char *id; + char *full_path; + + if (! g_str_has_suffix (filename, ".desktop")) { + 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")); + + full_path = g_build_filename (dirname, filename, NULL); + + load_session_file (id, full_path); + + g_free (id); + g_free (full_path); + } + + g_dir_close (dir); + } + + static void + collect_sessions (void) + { + g_autoptr(GHashTable) names_seen_before = NULL; + g_autoptr(GPtrArray) xorg_search_array = NULL; + g_autoptr(GPtrArray) wayland_search_array = NULL; + gchar *session_dir = NULL; + int i; + const char *xorg_search_dirs[] = { + "/etc/X11/sessions/", + DMCONFDIR "/Sessions/", + 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); + + const gchar * const *system_data_dirs = g_get_system_data_dirs (); + + for (i = 0; system_data_dirs[i]; i++) { + session_dir = g_build_filename (system_data_dirs[i], "xsessions", NULL); + g_ptr_array_add (xorg_search_array, session_dir); + } + + for (i = 0; i < G_N_ELEMENTS (xorg_search_dirs); i++) { + g_ptr_array_add (xorg_search_array, g_strdup (xorg_search_dirs[i])); + } + + #ifdef ENABLE_WAYLAND_SUPPORT + const char *wayland_search_dirs[] = { + DATADIR "/wayland-sessions/", + }; + + wayland_search_array = g_ptr_array_new_with_free_func (g_free); + + for (i = 0; system_data_dirs[i]; i++) { + session_dir = g_build_filename (system_data_dirs[i], "wayland-sessions", NULL); + g_ptr_array_add (wayland_search_array, session_dir); + } + + for (i = 0; i < G_N_ELEMENTS (wayland_search_dirs); i++) { + g_ptr_array_add (wayland_search_array, g_strdup (wayland_search_dirs[i])); + } + #endif + + if (gdm_available_sessions_map == NULL) { + gdm_available_sessions_map = g_hash_table_new_full (g_str_hash, g_str_equal, + 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); + } + + /** + * gdm_get_session_ids: + * + * Reads /usr/share/xsessions and other relevant places for possible sessions + * to log into and returns the complete list. + * + * Returns: (transfer full): a %NULL terminated list of session ids + */ + char ** + gdm_get_session_ids (void) + { + GHashTableIter iter; + gpointer key, value; + GPtrArray *array; + + if (!gdm_sessions_map_is_initialized) { + collect_sessions (); + + gdm_sessions_map_is_initialized = TRUE; + } + + array = g_ptr_array_new (); + g_hash_table_iter_init (&iter, gdm_available_sessions_map); + while (g_hash_table_iter_next (&iter, &key, &value)) { + GdmSessionFile *session; +-- +2.31.1 + diff --git a/SOURCES/0001-local-display-factory-pause-for-a-few-seconds-before.patch b/SOURCES/0001-local-display-factory-pause-for-a-few-seconds-before.patch index ed5c469..81d88ac 100644 --- a/SOURCES/0001-local-display-factory-pause-for-a-few-seconds-before.patch +++ b/SOURCES/0001-local-display-factory-pause-for-a-few-seconds-before.patch @@ -1,4 +1,4 @@ -From 89ec6e57e452c04ffc43ae224052c7ddeea66676 Mon Sep 17 00:00:00 2001 +From 5c52259331ce0b37dd1b2b092ff41f96b0e5ce64 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Mon, 29 Oct 2018 06:57:59 -0400 Subject: [PATCH] local-display-factory: pause for a few seconds before falling @@ -12,14 +12,24 @@ back to X. http://bugzilla.redhat.com/1643874 --- - daemon/gdm-local-display-factory.c | 5 +++++ - 1 file changed, 5 insertions(+) + daemon/gdm-local-display-factory.c | 7 +++++++ + 1 file changed, 7 insertions(+) diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c -index 8a4ef06cd..8554a0442 100644 +index 0bb3851f1..297c3ac80 100644 --- a/daemon/gdm-local-display-factory.c +++ b/daemon/gdm-local-display-factory.c -@@ -488,60 +488,65 @@ ensure_display_for_seat (GdmLocalDisplayFactory *factory, +@@ -586,60 +586,67 @@ ensure_display_for_seat (GdmLocalDisplayFactory *factory, + 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); + + if (ret < 0) { g_critical ("Failed to query CanGraphical information for seat %s", seat_id); return; } @@ -35,26 +45,25 @@ index 8a4ef06cd..8554a0442 100644 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"); + 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" : ""); + -+ /* workaround logind race for now -+ * bug 1643874 -+ */ -+ g_usleep (2 * G_USEC_PER_SEC); - } else { - g_debug ("GdmLocalDisplayFactory: New displays on seat0 will use wayland"); - } ++ if (falling_back) { ++ /* workaround logind race for now ++ * bug 1643874 ++ */ ++ g_usleep (2 * G_USEC_PER_SEC); ++ } } 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 @@ -78,13 +87,6 @@ index 8a4ef06cd..8554a0442 100644 if (factory->seat0_graphics_check_timeout_id == 0) { g_debug ("GdmLocalDisplayFactory: seat0 doesn't yet support graphics. Waiting %d seconds to try again.", SEAT0_GRAPHICS_CHECK_TIMEOUT); factory->seat0_graphics_check_timeout_id = g_timeout_add_seconds (SEAT0_GRAPHICS_CHECK_TIMEOUT, - on_seat0_graphics_check_timeout, - factory); - - } else { - /* It is not yet time to force X11 fallback. */ - g_debug ("GdmLocalDisplayFactory: seat0 display requested when there is no graphics support before graphics check timeout."); - } -- -2.31.1 +2.30.1 diff --git a/SOURCES/0001-manager-allow-multiple-xdmcp-logins-for-the-same-use.patch b/SOURCES/0001-manager-allow-multiple-xdmcp-logins-for-the-same-use.patch index e67dcfc..718486c 100644 --- a/SOURCES/0001-manager-allow-multiple-xdmcp-logins-for-the-same-use.patch +++ b/SOURCES/0001-manager-allow-multiple-xdmcp-logins-for-the-same-use.patch @@ -1,4 +1,4 @@ -From d99f12385d6b04023cbe17f3f6fc2a917066c6e8 Mon Sep 17 00:00:00 2001 +From d80807171a457ff87bdc9bd861939161749a37a8 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Thu, 20 Dec 2018 14:51:38 -0500 Subject: [PATCH 1/3] manager: allow multiple xdmcp logins for the same user @@ -10,19 +10,19 @@ Subject: [PATCH 1/3] manager: allow multiple xdmcp logins for the same user 3 files changed, 59 insertions(+), 18 deletions(-) diff --git a/common/gdm-settings-keys.h b/common/gdm-settings-keys.h -index f0059b5cf..33676a851 100644 +index 87685d3cd..4b3a1ffeb 100644 --- a/common/gdm-settings-keys.h +++ b/common/gdm-settings-keys.h -@@ -28,37 +28,38 @@ G_BEGIN_DECLS - #define GDM_KEY_USER "daemon/User" - #define GDM_KEY_GROUP "daemon/Group" +@@ -30,37 +30,38 @@ G_BEGIN_DECLS #define GDM_KEY_AUTO_LOGIN_ENABLE "daemon/AutomaticLoginEnable" #define GDM_KEY_AUTO_LOGIN_USER "daemon/AutomaticLogin" #define GDM_KEY_TIMED_LOGIN_ENABLE "daemon/TimedLoginEnable" #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" @@ -53,7 +53,7 @@ index f0059b5cf..33676a851 100644 #endif /* _GDM_SETTINGS_KEYS_H */ diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c -index 9c10adff3..b96295ab6 100644 +index e433acf3b..ce8565bf9 100644 --- a/daemon/gdm-manager.c +++ b/daemon/gdm-manager.c @@ -566,93 +566,106 @@ get_display_and_details_for_bus_sender (GdmManager *self, @@ -297,10 +297,10 @@ index 9c10adff3..b96295ab6 100644 uid, is_remote); diff --git a/data/gdm.schemas.in b/data/gdm.schemas.in -index 255bff023..86059c02e 100644 +index a1035f95e..929d13d90 100644 --- a/data/gdm.schemas.in +++ b/data/gdm.schemas.in -@@ -102,33 +102,38 @@ +@@ -112,33 +112,38 @@ xdmcp/DisplaysPerHost i @@ -340,5 +340,5 @@ index 255bff023..86059c02e 100644 -- -2.31.1 +2.30.1 diff --git a/SOURCES/0001-worker-don-t-load-user-settings-for-program-sessions.patch b/SOURCES/0001-worker-don-t-load-user-settings-for-program-sessions.patch index fa74aae..f847682 100644 --- a/SOURCES/0001-worker-don-t-load-user-settings-for-program-sessions.patch +++ b/SOURCES/0001-worker-don-t-load-user-settings-for-program-sessions.patch @@ -1,7 +1,7 @@ -From 4fde9e7882e5d2e42a4ed5a0d71943d5ea966131 Mon Sep 17 00:00:00 2001 +From 7edce4ef248af01692758caf9dbb945bdd45cb0f Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 15 Aug 2018 10:48:16 -0400 -Subject: [PATCH 1/5] worker: don't load user settings for program sessions +Subject: [PATCH 1/4] worker: don't load user settings for program sessions We don't need or want the login greeter to access accountsservice for its session name diff --git a/SOURCES/0002-gdm-x-session-run-session-bus-on-non-seat0-seats.patch b/SOURCES/0002-gdm-x-session-run-session-bus-on-non-seat0-seats.patch index 6ca97fc..65e60ab 100644 --- a/SOURCES/0002-gdm-x-session-run-session-bus-on-non-seat0-seats.patch +++ b/SOURCES/0002-gdm-x-session-run-session-bus-on-non-seat0-seats.patch @@ -1,4 +1,4 @@ -From 81efb06506456a260d63b77e3dda1216041b5bb3 Mon Sep 17 00:00:00 2001 +From 874b26e3674d540df37d7f145df853bcf81e5a26 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 5 Feb 2020 15:20:48 -0500 Subject: [PATCH 2/3] gdm-x-session: run session bus on non-seat0 seats @@ -13,10 +13,10 @@ seats get their own session bus. 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c -index 5c5903a49..c891fb577 100644 +index 418240dc0..77d6b8ff0 100644 --- a/daemon/gdm-session.c +++ b/daemon/gdm-session.c -@@ -2811,119 +2811,128 @@ on_start_program_cb (GdmDBusWorker *worker, +@@ -2822,119 +2822,128 @@ on_start_program_cb (GdmDBusWorker *worker, if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED) || g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) return; @@ -78,7 +78,7 @@ index 5c5903a49..c891fb577 100644 register_session = !gdm_session_session_registers (self); -+ if (g_strcmp0 (priv->display_seat_id, "seat0") != 0 && !run_launcher) { ++ if (g_strcmp0 (self->display_seat_id, "seat0") != 0 && !run_launcher) { + run_separate_bus = TRUE; + } + @@ -147,5 +147,5 @@ index 5c5903a49..c891fb577 100644 self->selected_program); } -- -2.31.1 +2.30.1 diff --git a/SOURCES/0002-libgdm-Sort-session-list.patch b/SOURCES/0002-libgdm-Sort-session-list.patch new file mode 100644 index 0000000..abeb851 --- /dev/null +++ b/SOURCES/0002-libgdm-Sort-session-list.patch @@ -0,0 +1,131 @@ +From 6bdb7cf9e8ace0d9a42fd921d7192dcfece687fa Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 20 Jul 2021 13:36:45 -0400 +Subject: [PATCH 2/2] libgdm: Sort session list + +Right now the session list comes out in hash table order. + +This commit changes the code to sort by description. +--- + libgdm/gdm-sessions.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/libgdm/gdm-sessions.c b/libgdm/gdm-sessions.c +index 97ed5ef3d..f078e04b8 100644 +--- a/libgdm/gdm-sessions.c ++++ b/libgdm/gdm-sessions.c +@@ -311,92 +311,111 @@ collect_sessions (void) + g_ptr_array_add (wayland_search_array, g_strdup (wayland_search_dirs[i])); + } + #endif + + if (gdm_available_sessions_map == NULL) { + gdm_available_sessions_map = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, (GDestroyNotify)gdm_session_file_free); + } + + 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 (!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 + #endif + + g_hash_table_foreach_remove (gdm_available_sessions_map, + remove_duplicate_sessions, + names_seen_before); + } + ++static gint ++compare_session_ids (gconstpointer a, ++ gconstpointer b) ++{ ++ GdmSessionFile *session_a, *session_b; ++ session_a = (GdmSessionFile *) g_hash_table_lookup (gdm_available_sessions_map, a); ++ session_b = (GdmSessionFile *) g_hash_table_lookup (gdm_available_sessions_map, b); ++ ++ if (session_a == NULL) ++ return -1; ++ ++ if (session_b == NULL) ++ return 1; ++ ++ return g_strcmp0 (session_a->translated_name, session_b->translated_name); ++} ++ + /** + * gdm_get_session_ids: + * + * Reads /usr/share/xsessions and other relevant places for possible sessions + * to log into and returns the complete list. + * + * Returns: (transfer full): a %NULL terminated list of session ids + */ + char ** + gdm_get_session_ids (void) + { + GHashTableIter iter; + gpointer key, value; + GPtrArray *array; + + if (!gdm_sessions_map_is_initialized) { + collect_sessions (); + + gdm_sessions_map_is_initialized = TRUE; + } + + array = g_ptr_array_new (); + g_hash_table_iter_init (&iter, gdm_available_sessions_map); + while (g_hash_table_iter_next (&iter, &key, &value)) { + GdmSessionFile *session; + + session = (GdmSessionFile *) value; + + g_ptr_array_add (array, g_strdup (session->id)); + } + g_ptr_array_add (array, NULL); + ++ g_ptr_array_sort (array, compare_session_ids); ++ + return (char **) g_ptr_array_free (array, FALSE); + } + + /** + * gdm_get_session_name_and_description: + * @id: an id from gdm_get_session_ids() + * @description: (out): optional returned session description + * + * Takes an xsession id and returns the name and comment about it. + * + * Returns: The session name if found, or %NULL otherwise + */ + char * + gdm_get_session_name_and_description (const char *id, + char **description) + { + GdmSessionFile *session; + char *name; + + if (!gdm_sessions_map_is_initialized) { + collect_sessions (); + + gdm_sessions_map_is_initialized = TRUE; + } + + session = (GdmSessionFile *) g_hash_table_lookup (gdm_available_sessions_map, + id); + + if (session == NULL) { + return NULL; +-- +2.31.1 + diff --git a/SOURCES/0002-session-support-new-accountsservice-Session-and-Sess.patch b/SOURCES/0002-session-support-new-accountsservice-Session-and-Sess.patch index d6d5519..a4d8909 100644 --- a/SOURCES/0002-session-support-new-accountsservice-Session-and-Sess.patch +++ b/SOURCES/0002-session-support-new-accountsservice-Session-and-Sess.patch @@ -1,7 +1,7 @@ -From 83cdeb662961f8910e79c56f38d9e5e296ac93be Mon Sep 17 00:00:00 2001 +From c4716129cc3042ca9fa2ab7ee420800d85ec09db Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Tue, 14 Aug 2018 14:52:41 -0400 -Subject: [PATCH 2/5] session: support new accountsservice Session and +Subject: [PATCH 2/4] session: support new accountsservice Session and SessionType props At the moment the user's session is stored in a property called @@ -305,9 +305,9 @@ index 484a3b5b4..5b64cb65b 100644 - session_name = act_user_get_x_session (settings->priv->user); - g_debug ("GdmSessionSettings: saved session is %s", session_name); -+ /* if the user doesn't have saved state, they don't have any settings worth reading */ -+ if (!act_user_get_saved (settings->priv->user)) -+ goto out; ++ ++ ++ + + session_type = act_user_get_session_type (settings->priv->user); + session_name = act_user_get_session (settings->priv->user); @@ -754,7 +754,7 @@ index 4280fe095..a215779c8 100644 diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c -index d95cef905..2d471ec46 100644 +index 6e6326243..73ae5cbc5 100644 --- a/daemon/gdm-session.c +++ b/daemon/gdm-session.c @@ -61,60 +61,61 @@ @@ -819,25 +819,14 @@ index d95cef905..2d471ec46 100644 char *display_name; char *display_hostname; char *display_device; -@@ -319,312 +320,328 @@ on_establish_credentials_cb (GdmDBusWorker *proxy, - return; - - self = g_object_ref (conversation->session); - service_name = g_strdup (conversation->service_name); - - if (worked) { - if (self->user_verifier_interface != NULL) { - gdm_dbus_user_verifier_emit_verification_complete (self->user_verifier_interface, - service_name); - g_signal_emit (self, signals[VERIFICATION_COMPLETE], 0, service_name); - } - - switch (self->verification_mode) { - case GDM_SESSION_VERIFICATION_MODE_LOGIN: - case GDM_SESSION_VERIFICATION_MODE_CHOOSER: - gdm_session_open_session (self, service_name); - break; +@@ -328,309 +329,325 @@ on_establish_credentials_cb (GdmDBusWorker *proxy, case GDM_SESSION_VERIFICATION_MODE_REAUTHENTICATE: + if (self->user_verifier_interface != NULL) { + gdm_dbus_user_verifier_emit_verification_complete (self->user_verifier_interface, + service_name); + g_signal_emit (self, signals[VERIFICATION_COMPLETE], 0, service_name); + } + break; default: break; } @@ -849,6 +838,17 @@ index d95cef905..2d471ec46 100644 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) +get_system_session_dirs (GdmSession *self, @@ -856,7 +856,7 @@ index d95cef905..2d471ec46 100644 { 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[] = { @@ -870,40 +870,33 @@ index d95cef905..2d471ec46 100644 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); -- } -+ if (type == NULL || strcmp (type, "x11") == 0) { -+ 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)); -+ g_array_append_vals (search_array, x_search_dirs, G_N_ELEMENTS (x_search_dirs)); -+ } +- if (g_str_equal (supported_type, "x11")) { ++ if (g_str_equal (supported_type, "x11") || ++ (type == NULL || g_str_equal (type, supported_type))) { + 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); + } - #ifdef ENABLE_WAYLAND_SUPPORT -- if (!self->ignore_wayland) { -+ if ((!self->ignore_wayland && type == NULL) || g_strcmp0 (type, "wayland") == 0) { - #ifdef ENABLE_USER_DISPLAY_SERVER - 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); + g_array_append_vals (search_array, x_search_dirs, G_N_ELEMENTS (x_search_dirs)); } - g_array_append_val (search_array, wayland_search_dir); + #ifdef ENABLE_WAYLAND_SUPPORT +- if (g_str_equal (supported_type, "wayland")) { ++ if (g_str_equal (supported_type, "wayland") || ++ (type == NULL || g_str_equal (type, supported_type))) { + 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); @@ -983,9 +976,9 @@ index d95cef905..2d471ec46 100644 *command = NULL; } -+ if (self->ignore_wayland && g_strcmp0 (type, "wayland") == 0) { -+ g_debug ("GdmSession: ignoring wayland session command request for file '%s'", -+ file); ++ if (!supports_session_type (self, type)) { ++ g_debug ("GdmSession: ignoring %s session command request for file '%s'", ++ type, file); + goto out; + } + @@ -1165,7 +1158,7 @@ index d95cef905..2d471ec46 100644 out: return self->fallback_session_name; -@@ -643,60 +660,63 @@ get_default_session_name (GdmSession *self) +@@ -649,60 +666,63 @@ get_default_session_name (GdmSession *self) static void gdm_session_defaults_changed (GdmSession *self) { @@ -1229,7 +1222,7 @@ index d95cef905..2d471ec46 100644 static void set_pending_query (GdmSessionConversation *conversation, -@@ -963,80 +983,91 @@ worker_on_reauthenticated (GdmDBusWorker *worker, +@@ -969,80 +989,91 @@ worker_on_reauthenticated (GdmDBusWorker *worker, GdmSession *self = conversation->session; g_debug ("GdmSession: Emitting 'reauthenticated' signal "); g_signal_emit (self, signals[REAUTHENTICATED], 0, service_name); @@ -1322,7 +1315,7 @@ index d95cef905..2d471ec46 100644 uid_t connecting_user; connecting_user = g_credentials_get_unix_user (credentials, NULL); -@@ -1116,60 +1147,63 @@ register_worker (GdmDBusWorkerManager *worker_manager_interface, +@@ -1122,60 +1153,63 @@ register_worker (GdmDBusWorkerManager *worker_manager_interface, g_dbus_method_invocation_return_value (invocation, NULL); conversation->worker_proxy = gdm_dbus_worker_proxy_new_sync (connection, @@ -1386,7 +1379,7 @@ index d95cef905..2d471ec46 100644 g_debug ("GdmSession: Conversation started"); return TRUE; -@@ -1912,60 +1946,63 @@ free_conversation (GdmSessionConversation *conversation) +@@ -1918,60 +1952,63 @@ free_conversation (GdmSessionConversation *conversation) close_conversation (conversation); if (conversation->job != NULL) { @@ -1450,7 +1443,7 @@ index d95cef905..2d471ec46 100644 error = NULL; if (!g_file_get_contents (config_file, &contents, &length, &error)) { g_debug ("Failed to parse '%s': %s", -@@ -2520,83 +2557,83 @@ gdm_session_send_environment (GdmSession *self, +@@ -2530,83 +2567,83 @@ gdm_session_send_environment (GdmSession *self, g_return_if_fail (GDM_IS_SESSION (self)); conversation = find_conversation_by_name (self, service_name); @@ -1536,8 +1529,7 @@ index d95cef905..2d471ec46 100644 g_strdup (value)); } -@@ -3165,85 +3202,87 @@ gdm_session_get_conversation_session_id (GdmSession *self, - +@@ -3176,148 +3213,150 @@ gdm_session_get_conversation_session_id (GdmSession *self, conversation = find_conversation_by_name (self, service_name); if (conversation == NULL) { @@ -1567,11 +1559,16 @@ index d95cef905..2d471ec46 100644 filename = get_session_filename (self); -- key_file = load_key_file_for_file (self, filename, &full_path); -+ key_file = load_key_file_for_file (self, filename, "wayland", &full_path); + if (supports_session_type (self, "wayland")) { +- key_file = load_key_file_for_file (self, filename, &full_path); ++ key_file = load_key_file_for_file (self, filename, NULL, &full_path); - if (key_file == NULL) { - goto out; +- if (key_file == NULL) { +- goto out; +- } ++ if (key_file == NULL) { ++ goto out; ++ } } if (full_path != NULL && strstr (full_path, "/wayland-sessions/") != NULL) { @@ -1593,7 +1590,7 @@ index d95cef905..2d471ec46 100644 - gboolean is_wayland_session; + gboolean is_wayland_session = FALSE; + -+ if (!self->ignore_wayland) ++ if (supports_session_type (self, "wayland")) + is_wayland_session = gdm_session_is_wayland_session (self); - is_wayland_session = gdm_session_is_wayland_session (self); @@ -1618,7 +1615,8 @@ index d95cef905..2d471ec46 100644 filename = get_session_filename (self); - key_file = load_key_file_for_file (self, filename, NULL); +- key_file = load_key_file_for_file (self, filename, NULL); ++ key_file = load_key_file_for_file (self, filename, NULL, NULL); session_registers = g_key_file_get_boolean (key_file, G_KEY_FILE_DESKTOP_GROUP, @@ -1627,7 +1625,7 @@ index d95cef905..2d471ec46 100644 if (!session_registers && error != NULL && !g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND)) { -@@ -3251,61 +3290,61 @@ gdm_session_session_registers (GdmSession *self) + g_warning ("GdmSession: Couldn't read session file '%s'", filename); return FALSE; } diff --git a/SOURCES/0003-daemon-save-os-release-in-accountsservice.patch b/SOURCES/0003-daemon-save-os-release-in-accountsservice.patch index efba617..05682b9 100644 --- a/SOURCES/0003-daemon-save-os-release-in-accountsservice.patch +++ b/SOURCES/0003-daemon-save-os-release-in-accountsservice.patch @@ -1,7 +1,7 @@ -From 35e2d1d298607c3fdb2cbbfb1cf878dc9cbbf546 Mon Sep 17 00:00:00 2001 +From 09e4f57ea2525e48bd22a34cb0c9b917ce7565df Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Mon, 20 Aug 2018 14:30:59 -0400 -Subject: [PATCH 3/5] daemon: save os-release in accountsservice +Subject: [PATCH 3/4] daemon: save os-release in accountsservice It can be useful to know what OS a user was running when they logged in (to detect upgrades). @@ -10,8 +10,9 @@ This commit saves that information in accountsservice. --- .../com.redhat.AccountsServiceUser.System.xml | 10 ++ daemon/gdm-session-settings.c | 98 +++++++++++++++++++ + daemon/gdm-session.c | 4 +- daemon/meson.build | 8 ++ - 3 files changed, 116 insertions(+) + 4 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 daemon/com.redhat.AccountsServiceUser.System.xml diff --git a/daemon/com.redhat.AccountsServiceUser.System.xml b/daemon/com.redhat.AccountsServiceUser.System.xml @@ -232,9 +233,9 @@ index 5b64cb65b..5bcfdc14f 100644 + } + } + - /* if the user doesn't have saved state, they don't have any settings worth reading */ - if (!act_user_get_saved (settings->priv->user)) - goto out; + + + session_type = act_user_get_session_type (settings->priv->user); session_name = act_user_get_session (settings->priv->user); @@ -399,6 +400,85 @@ index 5b64cb65b..5bcfdc14f 100644 return TRUE; } +diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c +index 73ae5cbc5..ce6df14c6 100644 +--- a/daemon/gdm-session.c ++++ b/daemon/gdm-session.c +@@ -351,72 +351,72 @@ supports_session_type (GdmSession *self, + 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, + const char *type) + { + GArray *search_array = NULL; + char **search_dirs; + int i, j; + const gchar * const *system_data_dirs = g_get_system_data_dirs (); + + static const char *x_search_dirs[] = { + "/etc/X11/sessions/", + DMCONFDIR "/Sessions/", + DATADIR "/gdm/BuiltInSessions/", + DATADIR "/xsessions/", + }; + + static const char *wayland_search_dir = DATADIR "/wayland-sessions/"; + + search_array = g_array_new (TRUE, TRUE, sizeof (char *)); + + for (j = 0; self->supported_session_types[j] != NULL; j++) { + const char *supported_type = self->supported_session_types[j]; + +- if (g_str_equal (supported_type, "x11") || ++ if (g_str_equal (supported_type, "x11") && + (type == NULL || g_str_equal (type, supported_type))) { + 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 (g_str_equal (supported_type, "wayland") || ++ if (g_str_equal (supported_type, "wayland") && + (type == NULL || g_str_equal (type, supported_type))) { + 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 + } + + search_dirs = g_strdupv ((char **) search_array->data); + + g_array_free (search_array, TRUE); + + return search_dirs; + } + + static gboolean + is_prog_in_path (const char *prog) + { + char *f; + gboolean ret; + + f = g_find_program_in_path (prog); + ret = (f != NULL); + g_free (f); + return ret; + } + diff --git a/daemon/meson.build b/daemon/meson.build index 2e61b6447..71c650398 100644 --- a/daemon/meson.build diff --git a/SOURCES/0003-session-ensure-login-screen-over-XDMCP-connects-to-i.patch b/SOURCES/0003-session-ensure-login-screen-over-XDMCP-connects-to-i.patch index a9ef5f6..79b75d0 100644 --- a/SOURCES/0003-session-ensure-login-screen-over-XDMCP-connects-to-i.patch +++ b/SOURCES/0003-session-ensure-login-screen-over-XDMCP-connects-to-i.patch @@ -1,4 +1,4 @@ -From 9a2de416bc13fc40a6d7f2e4e6cb9cf64be2854f Mon Sep 17 00:00:00 2001 +From 64e8db8432158e5115df18a03bb87ecc1d58ae63 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Mon, 11 Feb 2019 10:32:55 -0500 Subject: [PATCH 3/3] session: ensure login screen over XDMCP connects to its @@ -17,10 +17,10 @@ the session is X11. 1 file changed, 19 insertions(+) diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c -index c891fb577..d95cef905 100644 +index 77d6b8ff0..357e4a297 100644 --- a/daemon/gdm-session.c +++ b/daemon/gdm-session.c -@@ -2686,60 +2686,79 @@ set_up_session_environment (GdmSession *self) +@@ -2697,60 +2697,79 @@ set_up_session_environment (GdmSession *self) } static void @@ -101,5 +101,5 @@ index c891fb577..d95cef905 100644 gpointer key, value; -- -2.31.1 +2.30.1 diff --git a/SOURCES/0004-daemon-handle-upgrades-from-RHEL-7.patch b/SOURCES/0004-daemon-handle-upgrades-from-RHEL-7.patch index 905f143..bb72e64 100644 --- a/SOURCES/0004-daemon-handle-upgrades-from-RHEL-7.patch +++ b/SOURCES/0004-daemon-handle-upgrades-from-RHEL-7.patch @@ -1,7 +1,7 @@ -From 234fdc6e4bd4d4c19fefba27495db5bdc9642217 Mon Sep 17 00:00:00 2001 +From de103948b84188cd2273c9aab904a633323a9479 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Mon, 20 Aug 2018 14:30:59 -0400 -Subject: [PATCH 4/5] daemon: handle upgrades from RHEL 7 +Subject: [PATCH 4/4] daemon: handle upgrades from RHEL 7 RHEL 7 users need to stay on X if they were using X, and they need to stay on gnome-classic if they were using @@ -12,7 +12,8 @@ or not they were using RHEL 7 and in the event they were try to get the right settings. --- daemon/gdm-session-settings.c | 19 +++++++++++++++++++ - 1 file changed, 19 insertions(+) + daemon/gdm-session.c | 19 ++++++++----------- + 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/daemon/gdm-session-settings.c b/daemon/gdm-session-settings.c index 5bcfdc14f..a7eaa8b2f 100644 @@ -79,9 +80,9 @@ index 5bcfdc14f..a7eaa8b2f 100644 } } - /* if the user doesn't have saved state, they don't have any settings worth reading */ - if (!act_user_get_saved (settings->priv->user)) - goto out; + + + session_type = act_user_get_session_type (settings->priv->user); session_name = act_user_get_session (settings->priv->user); @@ -133,6 +134,117 @@ index 5bcfdc14f..a7eaa8b2f 100644 G_CALLBACK (on_user_is_loaded_changed), settings); } +diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c +index ce6df14c6..6bda6d6e2 100644 +--- a/daemon/gdm-session.c ++++ b/daemon/gdm-session.c +@@ -3202,98 +3202,95 @@ gdm_session_get_session_id (GdmSession *self) + return conversation->session_id; + } + + const char * + gdm_session_get_conversation_session_id (GdmSession *self, + const char *service_name) + { + GdmSessionConversation *conversation; + + g_return_val_if_fail (GDM_IS_SESSION (self), NULL); + + conversation = find_conversation_by_name (self, service_name); + + if (conversation == NULL) { + return NULL; + } + + return conversation->session_id; + } + + static char * + get_session_filename (GdmSession *self) + { + return g_strdup_printf ("%s.desktop", get_session_name (self)); + } + + #ifdef ENABLE_WAYLAND_SUPPORT + static gboolean + gdm_session_is_wayland_session (GdmSession *self) + { +- GKeyFile *key_file; ++ g_autoptr (GKeyFile) key_file = NULL; + gboolean is_wayland_session = FALSE; +- char *filename; +- char *full_path = NULL; ++ g_autofree char *filename = NULL; ++ g_autofree char *full_path = NULL; + + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (GDM_IS_SESSION (self), FALSE); + + filename = get_session_filename (self); + + if (supports_session_type (self, "wayland")) { + key_file = load_key_file_for_file (self, filename, NULL, &full_path); + + if (key_file == NULL) { + goto out; + } +- } + +- if (full_path != NULL && strstr (full_path, "/wayland-sessions/") != NULL) { +- is_wayland_session = TRUE; ++ if (full_path != NULL && strstr (full_path, "/wayland-sessions/") != NULL) { ++ is_wayland_session = TRUE; ++ } + } +- g_debug ("GdmSession: checking if file '%s' is wayland session: %s", filename, is_wayland_session? "yes" : "no"); + + out: +- g_clear_pointer (&key_file, g_key_file_free); +- g_free (filename); ++ g_debug ("GdmSession: checking if file '%s' is wayland session: %s", filename, is_wayland_session? "yes" : "no"); + return is_wayland_session; + } + #endif + + static void + update_session_type (GdmSession *self) + { + #ifdef ENABLE_WAYLAND_SUPPORT + gboolean is_wayland_session = FALSE; + +- if (supports_session_type (self, "wayland")) +- is_wayland_session = gdm_session_is_wayland_session (self); ++ is_wayland_session = gdm_session_is_wayland_session (self); + + if (is_wayland_session) { + set_session_type (self, "wayland"); + } else { + set_session_type (self, NULL); + } + #endif + } + + gboolean + gdm_session_session_registers (GdmSession *self) + { + g_autoptr(GError) error = NULL; + g_autoptr(GKeyFile) key_file = NULL; + gboolean session_registers = FALSE; + g_autofree char *filename = NULL; + + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (GDM_IS_SESSION (self), FALSE); + + filename = get_session_filename (self); + + key_file = load_key_file_for_file (self, filename, NULL, NULL); + + session_registers = g_key_file_get_boolean (key_file, + G_KEY_FILE_DESKTOP_GROUP, + "X-GDM-SessionRegisters", + &error); + if (!session_registers && + error != NULL && -- 2.31.1 diff --git a/SOURCES/0005-daemon-fix-wayland-detection-when-deciding-to-bypass.patch b/SOURCES/0005-daemon-fix-wayland-detection-when-deciding-to-bypass.patch deleted file mode 100644 index e2c6879..0000000 --- a/SOURCES/0005-daemon-fix-wayland-detection-when-deciding-to-bypass.patch +++ /dev/null @@ -1,221 +0,0 @@ -From 4862efc8bb38e97a785bd9c368d9b701c2acba68 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Sun, 15 Dec 2019 14:51:44 -0500 -Subject: [PATCH 5/5] daemon: fix wayland detection when deciding to bypass - Xsession - -At the moment if there's a session file with the same name in -both /usr/share/xsessions and /usr/share/wayland-sessions, GDM -will think the wayland is getting used when deciding whether or -not to bypass the /etc/gdm/Xsession script, even if wayland is -explicitly being ignored. - -This commit fixes the check. ---- - daemon/gdm-session.c | 31 +++++++++++++++---------------- - 1 file changed, 15 insertions(+), 16 deletions(-) - -diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c -index 2d471ec46..38a32fdab 100644 ---- a/daemon/gdm-session.c -+++ b/daemon/gdm-session.c -@@ -2898,61 +2898,61 @@ gdm_session_start_session (GdmSession *self, - char *command; - char *program; - gboolean register_session; - - g_return_if_fail (GDM_IS_SESSION (self)); - g_return_if_fail (self->session_conversation == NULL); - - conversation = find_conversation_by_name (self, service_name); - - if (conversation == NULL) { - g_warning ("GdmSession: Tried to start session of " - "nonexistent conversation %s", service_name); - return; - } - - stop_all_other_conversations (self, conversation, FALSE); - - display_mode = gdm_session_get_display_mode (self); - - #ifdef ENABLE_WAYLAND_SUPPORT - is_x11 = g_strcmp0 (self->session_type, "wayland") != 0; - #endif - - if (display_mode == GDM_SESSION_DISPLAY_MODE_LOGIND_MANAGED || - display_mode == GDM_SESSION_DISPLAY_MODE_NEW_VT) { - run_launcher = TRUE; - } - - register_session = !gdm_session_session_registers (self); - -- if (g_strcmp0 (priv->display_seat_id, "seat0") != 0 && !run_launcher) { -+ if (g_strcmp0 (self->display_seat_id, "seat0") != 0 && !run_launcher) { - run_separate_bus = TRUE; - } - - if (self->selected_program == NULL) { - gboolean run_xsession_script; - - command = get_session_command (self); - - run_xsession_script = !gdm_session_bypasses_xsession (self); - - if (self->display_is_local) { - gboolean disallow_tcp = TRUE; - gdm_settings_direct_get_boolean (GDM_KEY_DISALLOW_TCP, &disallow_tcp); - allow_remote_connections = !disallow_tcp; - } else { - allow_remote_connections = TRUE; - } - - if (run_launcher) { - if (is_x11) { - program = g_strdup_printf (LIBEXECDIR "/gdm-x-session %s%s %s\"%s\"", - register_session ? "--register-session " : "", - run_xsession_script? "--run-script " : "", - allow_remote_connections? "--allow-remote-connections " : "", - command); - } else { - program = g_strdup_printf (LIBEXECDIR "/gdm-wayland-session %s\"%s\"", - register_session ? "--register-session " : "", - command); - } -@@ -3192,119 +3192,118 @@ gdm_session_get_session_id (GdmSession *self) - return conversation->session_id; - } - - const char * - gdm_session_get_conversation_session_id (GdmSession *self, - const char *service_name) - { - GdmSessionConversation *conversation; - - g_return_val_if_fail (GDM_IS_SESSION (self), NULL); - - conversation = find_conversation_by_name (self, service_name); - - if (conversation == NULL) { - return NULL; - } - - return conversation->session_id; - } - - static char * - get_session_filename (GdmSession *self) - { - return g_strdup_printf ("%s.desktop", get_session_name (self)); - } - - #ifdef ENABLE_WAYLAND_SUPPORT - static gboolean - gdm_session_is_wayland_session (GdmSession *self) - { -- GKeyFile *key_file; -+ g_autoptr (GKeyFile) key_file = NULL; - gboolean is_wayland_session = FALSE; -- char *filename; -- char *full_path = NULL; -+ g_autofree char *filename = NULL; -+ g_autofree char *full_path = NULL; - - g_return_val_if_fail (self != NULL, FALSE); - g_return_val_if_fail (GDM_IS_SESSION (self), FALSE); - - filename = get_session_filename (self); - -- key_file = load_key_file_for_file (self, filename, "wayland", &full_path); -+ if (!self->ignore_wayland) { -+ key_file = load_key_file_for_file (self, filename, "wayland", &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; -+ if (full_path != NULL && strstr (full_path, "/wayland-sessions/") != NULL) { -+ is_wayland_session = TRUE; -+ } - } -- g_debug ("GdmSession: checking if file '%s' is wayland session: %s", filename, is_wayland_session? "yes" : "no"); - - out: -- g_clear_pointer (&key_file, g_key_file_free); -- g_free (filename); -+ g_debug ("GdmSession: checking if file '%s' is wayland session: %s", filename, is_wayland_session? "yes" : "no"); - return is_wayland_session; - } - #endif - - static void - update_session_type (GdmSession *self) - { - #ifdef ENABLE_WAYLAND_SUPPORT - gboolean is_wayland_session = FALSE; - -- if (!self->ignore_wayland) -- is_wayland_session = gdm_session_is_wayland_session (self); -+ is_wayland_session = gdm_session_is_wayland_session (self); - - if (is_wayland_session) { - set_session_type (self, "wayland"); - } else { - set_session_type (self, NULL); - } - #endif - } - - gboolean - gdm_session_session_registers (GdmSession *self) - { - g_autoptr(GError) error = NULL; - g_autoptr(GKeyFile) key_file = NULL; - gboolean session_registers = FALSE; - g_autofree char *filename = NULL; - - g_return_val_if_fail (self != NULL, FALSE); - g_return_val_if_fail (GDM_IS_SESSION (self), FALSE); - - filename = get_session_filename (self); - -- key_file = load_key_file_for_file (self, filename, NULL); -+ key_file = load_key_file_for_file (self, filename, NULL, NULL); - - session_registers = g_key_file_get_boolean (key_file, - G_KEY_FILE_DESKTOP_GROUP, - "X-GDM-SessionRegisters", - &error); - if (!session_registers && - error != NULL && - !g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND)) { - g_warning ("GdmSession: Couldn't read session file '%s'", filename); - return FALSE; - } - - g_debug ("GdmSession: '%s' %s self", filename, - session_registers ? "registers" : "does not register"); - - return session_registers; - } - - gboolean - gdm_session_bypasses_xsession (GdmSession *self) - { - GError *error; - GKeyFile *key_file; - gboolean res; - gboolean bypasses_xsession = FALSE; - char *filename = NULL; - - g_return_val_if_fail (self != NULL, FALSE); - g_return_val_if_fail (GDM_IS_SESSION (self), FALSE); - --- -2.31.1 - diff --git a/SPECS/gdm.spec b/SPECS/gdm.spec index da3f7bc..b97a14a 100644 --- a/SPECS/gdm.spec +++ b/SPECS/gdm.spec @@ -12,7 +12,7 @@ Name: gdm Epoch: 1 Version: 40.0 -Release: 3%{?dist} +Release: 12%{?dist} Summary: The GNOME Display Manager License: GPLv2+ @@ -20,6 +20,10 @@ URL: https://wiki.gnome.org/Projects/GDM Source0: http://download.gnome.org/sources/gdm/40/gdm-%{version}.tar.xz Source1: org.gnome.login-screen.gschema.override +# Lets customers using vendor nvidia driver pick wayland sessions from the login screen +Patch10001: 0001-local-display-factory-Provide-more-flexibility-for-c.patch +Patch10002: 0002-libgdm-Sort-session-list.patch + # Race fix Patch40001: 0001-display-Handle-failure-before-display-registration.patch @@ -45,7 +49,6 @@ Patch99920001: 0001-worker-don-t-load-user-settings-for-program-sessions.patch Patch99920002: 0002-session-support-new-accountsservice-Session-and-Sess.patch Patch99920003: 0003-daemon-save-os-release-in-accountsservice.patch Patch99920004: 0004-daemon-handle-upgrades-from-RHEL-7.patch -Patch99920005: 0005-daemon-fix-wayland-detection-when-deciding-to-bypass.patch Patch99920006: 0001-data-Disable-network-configuration-on-login-screen.patch @@ -357,6 +360,21 @@ fi %{_libdir}/pkgconfig/gdm-pam-extensions.pc %changelog +* Thu Aug 19 2021 Ray Strode - 40.0-12 +- Redisable on server chips since rebase + Related: #1909300 + +* Wed Aug 04 2021 Ray Strode - 40.0-11 +- Read session settings from users even if they've never saved + before. Needed to support accountsservice templated user + defaults. + Related: #1812788 + +* Tue Jul 27 2021 Ray Strode - 40.0-10 +- Let customers using vendor nvidia driver choose wayland sessions + Resolves: #1962211 +- Drop unused patches + * Tue Jun 08 2021 Florian Müllner - 40.0-3 - Disable network items on login screen Resolves: #1935261