feat(headless-kde): reliable bring-up — readiness probe, fix portal ordering/env (roadmap #1 phase 1)
ci / rust (push) Has been cancelled
ci / rust (push) Has been cancelled
Headless KDE startup was a chain of timing-sensitive handoffs gated by a blind `sleep 2`, the dominant source of black screens. Phase-1 fixes: - New `punktfunk-host probe-compositor` subcommand: exits 0 iff the detected compositor is up AND ready to create a virtual output now. KWin gets a real check (connect + registry roundtrip + the privileged zkde_screencast global must be advertised — what the backend needs); gamescope/Mutter/wlroots create on demand so the probe just confirms Linux. (vdisplay::probe dispatcher + kwin::probe; reuses kwin.rs's existing roundtrip path.) - run-headless-kde.sh: replace `sleep 2` with an active readiness wait (poll probe-compositor until ready, 30s deadline, and bail with kwin's log if kwin_wayland exits during init). Move the portal restart to AFTER readiness, and precede it with `systemctl --user import-environment` + `dbus-update-activation-environment` (the missing env import — the Sway script does this; without it a restarted portal inherits a stale/empty WAYLAND_DISPLAY, which is the "streams but eats no input/audio" failure). kwin's stderr → a log file. Validated: probe-compositor exits 0 "Kwin ready" against the live session, exit 1 with a clear diagnostic when the compositor is absent. 114 tests green, clippy/fmt clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -111,6 +111,30 @@ pub fn open(compositor: Compositor) -> Result<Box<dyn VirtualDisplay>> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Readiness probe for `compositor`: is it up and able to create a virtual output *right
|
||||
/// now*? A session-bringup script polls this (via `punktfunk-host probe-compositor`) to gate
|
||||
/// on actual readiness instead of racing the compositor with a blind sleep.
|
||||
///
|
||||
/// KWin gets a real check (the privileged `zkde_screencast` global must be advertised). The
|
||||
/// others are spawn/D-Bus/portal-based and have no equivalent pre-flight global, so a probe
|
||||
/// just confirms the backend opens — `Ok(())` means "go ahead and try `create`".
|
||||
pub fn probe(compositor: Compositor) -> Result<()> {
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
match compositor {
|
||||
Compositor::Kwin => kwin::probe(),
|
||||
// gamescope spawns its own nested session per `create`; Mutter is D-Bus on demand;
|
||||
// wlroots creates the output on demand — nothing to pre-check beyond "Linux".
|
||||
Compositor::Gamescope | Compositor::Mutter | Compositor::Wlroots => Ok(()),
|
||||
}
|
||||
}
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
{
|
||||
let _ = compositor;
|
||||
anyhow::bail!("virtual displays require Linux (Wayland compositor)")
|
||||
}
|
||||
}
|
||||
|
||||
/// Path of the file where the gamescope backend relays the nested session's `LIBEI_SOCKET`
|
||||
/// (gamescope's EIS server) for the input injector.
|
||||
#[cfg(target_os = "linux")]
|
||||
|
||||
Reference in New Issue
Block a user