fix(windows/gamestream): create the virtual display on Windows (Moonlight black screen)
The GameStream video path (open_gs_virtual_source) ran the Linux compositor-
detection state machine on every platform. On Windows detect_active_session()
returns None and vdisplay::detect() bails ("could not detect compositor ...
XDG_CURRENT_DESKTOP=''"), killing the video thread right after RTSP PLAY — so a
Moonlight client paired, negotiated, then black-screened and dropped.
The native punktfunk/1 path already guards this (resolve_compositor returns a
placeholder Compositor on Windows, since vdisplay::open ignores the compositor
arg there and always uses the pf-vdisplay IddCx backend). Mirror that guard in
the GameStream path: short-circuit to a placeholder on Windows, keep the Linux
session detection (apply_session_env/apply_input_env) under cfg(not(windows)).
Validated live: Moonlight -> this box now creates the pf-vdisplay virtual
monitor, attaches the IDD-push ring, and NVENC streams 5120x1440@240.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -213,14 +213,26 @@ fn open_gs_virtual_source(
|
|||||||
let compositor = if let Some(c) = app.and_then(|a| a.compositor) {
|
let compositor = if let Some(c) = app.and_then(|a| a.compositor) {
|
||||||
c
|
c
|
||||||
} else {
|
} else {
|
||||||
let active = crate::vdisplay::detect_active_session();
|
// Windows has a single virtual-display backend (pf-vdisplay); `vdisplay::open` ignores the
|
||||||
crate::vdisplay::apply_session_env(&active);
|
// compositor arg there, so short-circuit the Linux session-detection state machine with a
|
||||||
let c = crate::vdisplay::compositor_for_kind(active.kind)
|
// placeholder — mirrors `punktfunk1::resolve_compositor`. Without this, the Linux `detect()`
|
||||||
.map(Ok)
|
// below bails on Windows ("could not detect compositor … XDG_CURRENT_DESKTOP=''"), which
|
||||||
.unwrap_or_else(crate::vdisplay::detect)
|
// killed the GameStream video thread → black screen (the native plane was already guarded).
|
||||||
.context("detect compositor")?;
|
#[cfg(target_os = "windows")]
|
||||||
crate::vdisplay::apply_input_env(c);
|
{
|
||||||
c
|
crate::vdisplay::Compositor::Kwin
|
||||||
|
}
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
{
|
||||||
|
let active = crate::vdisplay::detect_active_session();
|
||||||
|
crate::vdisplay::apply_session_env(&active);
|
||||||
|
let c = crate::vdisplay::compositor_for_kind(active.kind)
|
||||||
|
.map(Ok)
|
||||||
|
.unwrap_or_else(crate::vdisplay::detect)
|
||||||
|
.context("detect compositor")?;
|
||||||
|
crate::vdisplay::apply_input_env(c);
|
||||||
|
c
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let mut vd = crate::vdisplay::open(compositor).context("open virtual display")?;
|
let mut vd = crate::vdisplay::open(compositor).context("open virtual display")?;
|
||||||
// Carry the resolved launch command on the backend instance (per-session) rather than a
|
// Carry the resolved launch command on the backend instance (per-session) rather than a
|
||||||
|
|||||||
Reference in New Issue
Block a user