From 07f83eb641b9aa74a9d05ed2dc134a00de5d6d3e Mon Sep 17 00:00:00 2001 From: Mariano Abad Date: Sat, 8 Aug 2026 14:07:43 -0300 Subject: [PATCH] fix(linux): a Wayland greeter the DRM backend can serve is not headless fufesou reported the login screen still failing on Ubuntu 24.04 with gdm3, with the client asking for OS credentials to start an X session instead of showing the greeter. Reproduced on a real gdm greeter here. Same premise as the rest of the branch, one more consumer. `DesktopManager::new` reads seat0 through `get_values_of_seat0`, which skips a gdm/sddm Wayland session by construction, so at a greeter it finds no session at all and `get_supported_display_seat0_username` returns None from its empty-username arm. That makes `is_headless()` true, so the service advertises headless and `try_start_desktop` answers `LOGIN_MSG_DESKTOP_SESSION_NOT_READY`. The corrected `IS_X11` does not reach this one: it asks who owns seat0, not which display server is running. So ask again, with the greeter visible, when the DRM backend can capture and inject into it. At query time rather than in `new()`, because the DRM probe has not necessarily settled when the desktop manager is constructed, and the answer would latch for the process lifetime. In a normal session the latched username is a real user and the extra read is skipped. --- src/platform/linux_desktop_manager.rs | 27 +++++++++++++++++++++++++++ src/server/drm_capturer.rs | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/platform/linux_desktop_manager.rs b/src/platform/linux_desktop_manager.rs index 4cfde61a2..ba3da2d1a 100644 --- a/src/platform/linux_desktop_manager.rs +++ b/src/platform/linux_desktop_manager.rs @@ -229,6 +229,24 @@ pub fn is_headless() -> bool { }) } +/// The Wayland greeter on seat0, if the DRM backend can capture and inject into it. +/// +/// The cached probe, to match the routing gate in `Connection`: not yet settled answers false, +/// which is what upstream does today. +#[cfg(feature = "drm")] +fn drm_login_screen_seat0_username() -> Option { + if !crate::server::drm_capturer::is_available_cached() { + return None; + } + let values = get_values_of_seat0_with_gdm_wayland(&[0, 2]); + if !is_gdm_user(&values[1]) + || get_display_server_of_session(&values[0]) != DISPLAY_SERVER_WAYLAND + { + return None; + } + Some(values[1].clone()) +} + pub fn get_username() -> String { match &*DESKTOP_MANAGER.lock().unwrap() { Some(manager) => { @@ -275,6 +293,15 @@ impl DesktopManager { } fn get_supported_display_seat0_username(&self) -> Option { + // A Wayland greeter the DRM backend can serve is a supported display. Asked here and not in + // `new()` because the seat0 read there hides greeters, and because the DRM probe has not + // settled at startup. + #[cfg(feature = "drm")] + if self.seat0_username.is_empty() || is_gdm_user(&self.seat0_username) { + if let Some(username) = drm_login_screen_seat0_username() { + return Some(username); + } + } if is_gdm_user(&self.seat0_username) && self.seat0_display_server == DISPLAY_SERVER_WAYLAND { None diff --git a/src/server/drm_capturer.rs b/src/server/drm_capturer.rs index 8b56c58d8..5001a763f 100644 --- a/src/server/drm_capturer.rs +++ b/src/server/drm_capturer.rs @@ -823,7 +823,7 @@ impl Drop for UinputRefreshGuard { /// Never probes, never blocks: the form the ROUTING gates must use. Seconds of IPC inside /// `wayland::clear()`, `is_inited()` or the display enumeration trips "deadline has elapsed". -pub(super) fn is_available_cached() -> bool { +pub(crate) fn is_available_cached() -> bool { matches!(&*DRM_STATE.lock().unwrap(), ProbeState::Available(..)) }