Env variable passing

This commit is contained in:
Stephen Hellings 2026-03-10 17:38:36 -04:00
parent 0a1c22035b
commit ca8c1246ce
4 changed files with 44 additions and 0 deletions

View file

@ -8,6 +8,12 @@ portal_socket = "$XDG_RUNTIME_DIR/wo-portal.sock"
enable_syscalls = true enable_syscalls = true
focus_notify = true focus_notify = true
# Environment variables passed to all spawned child processes.
# DISPLAY defaults to ":0" so X11 apps (e.g. Steam) work even before
# XWayland is ready. XWayland overrides DISPLAY with the actual value.
[compositor.environment]
DISPLAY = ":0"
[[root]] [[root]]
name = "main" name = "main"
url = "http://localhost:5173" url = "http://localhost:5173"

View file

@ -1,4 +1,5 @@
use serde::Deserialize; use serde::Deserialize;
use std::collections::HashMap;
use std::path::PathBuf; use std::path::PathBuf;
use anyhow::{Context, Result}; use anyhow::{Context, Result};
@ -89,6 +90,13 @@ pub struct CompositorConfig {
/// Cursor size in pixels (default: 24) /// Cursor size in pixels (default: 24)
#[serde(default = "default_cursor_size")] #[serde(default = "default_cursor_size")]
pub cursor_size: u32, pub cursor_size: u32,
/// Extra environment variables to set before spawning child processes.
/// Defaults include DISPLAY=":0" so X11 applications (e.g. Steam) can
/// fall back to a sensible value when XWayland hasn't started yet.
/// XWayland will override DISPLAY with the actual value once ready.
#[serde(default = "default_environment")]
pub environment: HashMap<String, String>,
} }
impl Default for CompositorConfig { impl Default for CompositorConfig {
@ -110,6 +118,7 @@ impl Default for CompositorConfig {
applications: vec![], applications: vec![],
cursor_theme: default_cursor_theme(), cursor_theme: default_cursor_theme(),
cursor_size: default_cursor_size(), cursor_size: default_cursor_size(),
environment: default_environment(),
} }
} }
} }
@ -278,6 +287,12 @@ fn default_true() -> bool { true }
fn default_cursor_theme() -> String { "breeze_cursors".into() } fn default_cursor_theme() -> String { "breeze_cursors".into() }
fn default_cursor_size() -> u32 { 24 } fn default_cursor_size() -> u32 { 24 }
fn default_environment() -> HashMap<String, String> {
let mut env = HashMap::new();
env.insert("DISPLAY".into(), ":0".into());
env
}
fn expand_path(s: &str) -> String { fn expand_path(s: &str) -> String {
shellexpand::full(s) shellexpand::full(s)
.map(|cow| cow.into_owned()) .map(|cow| cow.into_owned())
@ -320,6 +335,21 @@ impl Config {
pub fn config_dir() -> PathBuf { pub fn config_dir() -> PathBuf {
dirs_config() dirs_config()
} }
/// Apply configured environment variables to the current process so all
/// subsequently-spawned children inherit them. Existing env vars are
/// **not** overwritten so that, e.g., a DISPLAY already set by the
/// parent session or XWayland takes priority.
pub fn apply_environment(&self) {
for (key, value) in &self.compositor.environment {
if std::env::var(key).is_err() {
tracing::info!("Setting environment {key}={value} (from config default)");
std::env::set_var(key, value);
} else {
tracing::debug!("Environment {key} already set, skipping config default");
}
}
}
} }
fn config_path() -> PathBuf { fn config_path() -> PathBuf {

View file

@ -403,6 +403,10 @@ fn main() -> Result<(), anyhow::Error> {
let config = Config::load().context("loading config")?; let config = Config::load().context("loading config")?;
// Apply configured environment variables (e.g. DISPLAY=:0) so that all
// children inherit them. XWayland will override DISPLAY later if needed.
config.apply_environment();
// Determine backend priority: nested (gles) is prioritized with DRM fallback // Determine backend priority: nested (gles) is prioritized with DRM fallback
let force_drm = matches!(config.compositor.nested, Some(false)); let force_drm = matches!(config.compositor.nested, Some(false));

View file

@ -85,6 +85,10 @@ pub fn run_nested(config: Config) -> Result<()> {
info!("Starting nested compositor mode"); info!("Starting nested compositor mode");
// Apply configured environment variables (e.g. DISPLAY=:0) early so that
// all children inherit them. XWayland will override DISPLAY later.
config.apply_environment();
if config.compositor.exit_on_escape { if config.compositor.exit_on_escape {
info!("Press ESC to exit"); info!("Press ESC to exit");
} else { } else {