feat(vdisplay): wlroots/Sway backend — swaymsg headless output + xdpw chooser
The fourth VirtualDisplay backend: `swaymsg create_output` adds a HEADLESS-N output (name found by diffing get_outputs), `output <NAME> mode --custom WxH@HzHz` sets the client's exact mode (and the refresh clock a fresh headless output needs to produce frames at all), and the PipeWire node comes from the ScreenCast portal. Headless output selection is non-interactive via xdg-desktop-portal-wlr's chooser hook: a managed config (chooser_type=simple, chooser_cmd cats /tmp/punktfunk-xdpw-output; portal try-restarted when the config changes) plus a per-session `Monitor: <NAME>` written to that file. Teardown is RAII: drop ends the portal thread (zbus connection drop ends the cast) then `swaymsg output <NAME> unplug`. swaymsg commands go after `--` so tokens like `--custom` reach sway instead of swaymsg's getopt. Validated live on headless sway 1.11 (gles2-on-NVIDIA, xdpw 0.8.1), zero-copy dmabuf→CUDA on both runs: 720p60 257 frames p50 0.77 ms, 1080p60 480/480 frames p50 1.18 ms, output unplugged with the session both times. The checked-in xdpw.config sample now matches the managed config (the old chooser_type=none/HEADLESS-1 form would pin capture to the wrong output). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -6,8 +6,8 @@
|
||||
//! this trait:
|
||||
//!
|
||||
//! * **KWin** — privileged `zkde_screencast_unstable_v1::stream_virtual_output` ([`kwin`]).
|
||||
//! * **wlroots/Sway** — `swaymsg create_output` + `output mode --custom` (TODO).
|
||||
//! * **Mutter/GNOME** — D-Bus `RemoteDesktop` + `ScreenCast.RecordVirtual` (TODO).
|
||||
//! * **wlroots/Sway** — `swaymsg create_output` + `output mode --custom` ([`wlroots`]).
|
||||
//! * **Mutter/GNOME** — D-Bus `RemoteDesktop` + `ScreenCast.RecordVirtual` ([`mutter`]).
|
||||
//!
|
||||
//! [`VirtualDisplay::create`] returns a [`VirtualOutput`]: the PipeWire node to capture plus an
|
||||
//! owned keepalive whose `Drop` releases the output (RAII — no explicit `destroy`). Capture
|
||||
@@ -101,9 +101,7 @@ pub fn open(compositor: Compositor) -> Result<Box<dyn VirtualDisplay>> {
|
||||
Compositor::Kwin => Ok(Box::new(kwin::KwinDisplay::new()?)),
|
||||
Compositor::Gamescope => Ok(Box::new(gamescope::GamescopeDisplay::new()?)),
|
||||
Compositor::Mutter => Ok(Box::new(mutter::MutterDisplay::new()?)),
|
||||
Compositor::Wlroots => {
|
||||
anyhow::bail!("wlroots virtual-output backend not yet implemented")
|
||||
}
|
||||
Compositor::Wlroots => Ok(Box::new(wlroots::WlrootsDisplay::new()?)),
|
||||
}
|
||||
}
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
@@ -126,3 +124,5 @@ mod gamescope;
|
||||
mod kwin;
|
||||
#[cfg(target_os = "linux")]
|
||||
mod mutter;
|
||||
#[cfg(target_os = "linux")]
|
||||
mod wlroots;
|
||||
|
||||
Reference in New Issue
Block a user