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.
This commit is contained in:
Mariano Abad
2026-08-08 14:07:43 -03:00
parent 4c7e85cfa6
commit 07f83eb641
2 changed files with 28 additions and 1 deletions
+27
View File
@@ -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<String> {
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<String> {
// 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
+1 -1
View File
@@ -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(..))
}