feat(host/linux): PUNKTFUNK_GAMESCOPE_STEAM opt-in for bare gamescope spawns
Adds --steam (before the -- terminator, where PUNKTFUNK_GAMESCOPE_APP cannot reach) to the bare headless gamescope spawn when the env var is truthy, enabling gamescope's Steam integration for steam -gamepadui dedicated sessions. Default off; managed gamescope-session-plus/SteamOS sessions own their own flags and are unaffected. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -71,6 +71,10 @@ pub struct HostConfig {
|
|||||||
/// backend (the legacy SudoVDA backend was removed), so this is currently informational — kept for the
|
/// backend (the legacy SudoVDA backend was removed), so this is currently informational — kept for the
|
||||||
/// shipped `host.env` and as a forward seam if a second backend is ever added.
|
/// shipped `host.env` and as a forward seam if a second backend is ever added.
|
||||||
pub vdisplay: Option<String>,
|
pub vdisplay: Option<String>,
|
||||||
|
/// `PUNKTFUNK_GAMESCOPE_STEAM` — opt the bare headless gamescope spawn into its Steam
|
||||||
|
/// integration mode (`--steam`). Managed gamescope-session-plus/SteamOS sessions own their
|
||||||
|
/// own flags and do not consult this.
|
||||||
|
pub gamescope_steam: bool,
|
||||||
/// `PUNKTFUNK_RECOVER_SESSION_CMD` — operator hook fired (debounced) when a client connects while NO
|
/// `PUNKTFUNK_RECOVER_SESSION_CMD` — operator hook fired (debounced) when a client connects while NO
|
||||||
/// graphical session is live for this uid: the state a compositor crash leaves behind (gnome-shell
|
/// graphical session is live for this uid: the state a compositor crash leaves behind (gnome-shell
|
||||||
/// SIGSEGV → GDM greeter, whose auto-login is once-per-boot, so the box would otherwise need a walk-up
|
/// SIGSEGV → GDM greeter, whose auto-login is once-per-boot, so the box would otherwise need a walk-up
|
||||||
@@ -120,6 +124,12 @@ impl HostConfig {
|
|||||||
compositor: val("PUNKTFUNK_COMPOSITOR"),
|
compositor: val("PUNKTFUNK_COMPOSITOR"),
|
||||||
gamepad: val("PUNKTFUNK_GAMEPAD"),
|
gamepad: val("PUNKTFUNK_GAMEPAD"),
|
||||||
vdisplay: val("PUNKTFUNK_VDISPLAY"),
|
vdisplay: val("PUNKTFUNK_VDISPLAY"),
|
||||||
|
gamescope_steam: val("PUNKTFUNK_GAMESCOPE_STEAM").is_some_and(|s| {
|
||||||
|
matches!(
|
||||||
|
s.trim().to_ascii_lowercase().as_str(),
|
||||||
|
"1" | "true" | "yes" | "on"
|
||||||
|
)
|
||||||
|
}),
|
||||||
recover_session_cmd: val("PUNKTFUNK_RECOVER_SESSION_CMD")
|
recover_session_cmd: val("PUNKTFUNK_RECOVER_SESSION_CMD")
|
||||||
.filter(|s| !s.trim().is_empty()),
|
.filter(|s| !s.trim().is_empty()),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1359,6 +1359,21 @@ fn shape_dedicated_command(app: &str) -> String {
|
|||||||
app.to_string()
|
app.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add the compositor-side arguments shared by every bare gamescope spawn. `steam_mode` belongs
|
||||||
|
/// before the `--` terminator; [`PUNKTFUNK_GAMESCOPE_APP`](spawn) configures the nested command
|
||||||
|
/// after it and therefore cannot enable gamescope's Steam integration itself.
|
||||||
|
fn add_bare_gamescope_args(command: &mut Command, w: u32, h: u32, hz: u32, steam_mode: bool) {
|
||||||
|
command
|
||||||
|
.args(["--backend", "headless"])
|
||||||
|
.args(["-W", &w.to_string()])
|
||||||
|
.args(["-H", &h.to_string()])
|
||||||
|
.args(["-r", &hz.to_string()]);
|
||||||
|
if steam_mode {
|
||||||
|
command.arg("--steam");
|
||||||
|
}
|
||||||
|
command.args(["--xwayland-count", "1", "--"]);
|
||||||
|
}
|
||||||
|
|
||||||
/// Spawn `gamescope --backend headless -W w -H h -r hz -- <app>`. The app comes from
|
/// Spawn `gamescope --backend headless -W w -H h -r hz -- <app>`. The app comes from
|
||||||
/// `PUNKTFUNK_GAMESCOPE_APP` (default a no-op that just keeps gamescope alive — set it to a real
|
/// `PUNKTFUNK_GAMESCOPE_APP` (default a no-op that just keeps gamescope alive — set it to a real
|
||||||
/// game/GL app for actual content, e.g. `steam -gamepadui` for the SteamOS-like session).
|
/// game/GL app for actual content, e.g. `steam -gamepadui` for the SteamOS-like session).
|
||||||
@@ -1385,13 +1400,10 @@ fn spawn(w: u32, h: u32, hz: u32, cmd: Option<&str>, log: &std::path::Path) -> R
|
|||||||
let app = shape_dedicated_command(&app);
|
let app = shape_dedicated_command(&app);
|
||||||
let relay = ei_socket_file();
|
let relay = ei_socket_file();
|
||||||
let _ = std::fs::remove_file(&relay); // stale socket path from a previous session
|
let _ = std::fs::remove_file(&relay); // stale socket path from a previous session
|
||||||
|
let steam_mode = crate::config::config().gamescope_steam;
|
||||||
let mut cmd = Command::new("gamescope");
|
let mut cmd = Command::new("gamescope");
|
||||||
cmd.args(["--backend", "headless"])
|
add_bare_gamescope_args(&mut cmd, w, h, hz, steam_mode);
|
||||||
.args(["-W", &w.to_string()])
|
cmd.args([
|
||||||
.args(["-H", &h.to_string()])
|
|
||||||
.args(["-r", &hz.to_string()])
|
|
||||||
.args(["--xwayland-count", "1", "--"])
|
|
||||||
.args([
|
|
||||||
"sh",
|
"sh",
|
||||||
"-c",
|
"-c",
|
||||||
&format!(
|
&format!(
|
||||||
@@ -1419,7 +1431,7 @@ fn spawn(w: u32, h: u32, hz: u32, cmd: Option<&str>, log: &std::path::Path) -> R
|
|||||||
} else {
|
} else {
|
||||||
cmd.stdout(Stdio::null()).stderr(Stdio::null());
|
cmd.stdout(Stdio::null()).stderr(Stdio::null());
|
||||||
}
|
}
|
||||||
tracing::info!(w, h, hz, %app, log = %log.display(), "spawning gamescope (headless)");
|
tracing::info!(w, h, hz, steam_mode, %app, log = %log.display(), "spawning gamescope (headless)");
|
||||||
cmd.spawn()
|
cmd.spawn()
|
||||||
.context("spawn gamescope (is it installed? `apt install gamescope`)")
|
.context("spawn gamescope (is it installed? `apt install gamescope`)")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user