Add environment {} config section

This commit is contained in:
Ivan Molodetskikh
2024-02-24 10:08:56 +04:00
parent e278e871c3
commit ec156a8587
5 changed files with 59 additions and 2 deletions
+28
View File
@@ -39,6 +39,8 @@ pub struct Config {
pub hotkey_overlay: HotkeyOverlay, pub hotkey_overlay: HotkeyOverlay,
#[knuffel(child, default)] #[knuffel(child, default)]
pub animations: Animations, pub animations: Animations,
#[knuffel(child, default)]
pub environment: Environment,
#[knuffel(children(name = "window-rule"))] #[knuffel(children(name = "window-rule"))]
pub window_rules: Vec<WindowRule>, pub window_rules: Vec<WindowRule>,
#[knuffel(child, default)] #[knuffel(child, default)]
@@ -572,6 +574,17 @@ pub enum AnimationCurve {
EaseOutExpo, EaseOutExpo,
} }
#[derive(knuffel::Decode, Debug, Default, Clone, PartialEq, Eq)]
pub struct Environment(#[knuffel(children)] pub Vec<EnvironmentVariable>);
#[derive(knuffel::Decode, Debug, Clone, PartialEq, Eq)]
pub struct EnvironmentVariable {
#[knuffel(node_name)]
pub name: String,
#[knuffel(argument)]
pub value: Option<String>,
}
#[derive(knuffel::Decode, Debug, Default, Clone, PartialEq)] #[derive(knuffel::Decode, Debug, Default, Clone, PartialEq)]
pub struct WindowRule { pub struct WindowRule {
#[knuffel(children(name = "match"))] #[knuffel(children(name = "match"))]
@@ -1061,6 +1074,11 @@ mod tests {
} }
} }
environment {
QT_QPA_PLATFORM "wayland"
DISPLAY null
}
window-rule { window-rule {
match app-id=".*alacritty" match app-id=".*alacritty"
exclude title="~" exclude title="~"
@@ -1217,6 +1235,16 @@ mod tests {
}, },
..Default::default() ..Default::default()
}, },
environment: Environment(vec![
EnvironmentVariable {
name: String::from("QT_QPA_PLATFORM"),
value: Some(String::from("wayland")),
},
EnvironmentVariable {
name: String::from("DISPLAY"),
value: None,
},
]),
window_rules: vec![WindowRule { window_rules: vec![WindowRule {
matches: vec![Match { matches: vec![Match {
app_id: Some(Regex::new(".*alacritty").unwrap()), app_id: Some(Regex::new(".*alacritty").unwrap()),
+9
View File
@@ -199,6 +199,15 @@ layout {
// which may be more convenient to use. // which may be more convenient to use.
// spawn-at-startup "alacritty" "-e" "fish" // spawn-at-startup "alacritty" "-e" "fish"
// You can override environment variables for processes spawned by niri.
environment {
// Set a variable like this:
// QT_QPA_PLATFORM "wayland"
// Remove a variable by using null as the value:
// DISPLAY null
}
cursor { cursor {
// Change the theme and size of the cursor as well as set the // Change the theme and size of the cursor as well as set the
// `XCURSOR_THEME` and `XCURSOR_SIZE` env variables. // `XCURSOR_THEME` and `XCURSOR_SIZE` env variables.
+4 -1
View File
@@ -15,7 +15,9 @@ use niri::cli::{Cli, Sub};
use niri::dbus; use niri::dbus;
use niri::ipc::client::handle_msg; use niri::ipc::client::handle_msg;
use niri::niri::State; use niri::niri::State;
use niri::utils::spawning::{spawn, REMOVE_ENV_RUST_BACKTRACE, REMOVE_ENV_RUST_LIB_BACKTRACE}; use niri::utils::spawning::{
spawn, CHILD_ENV, REMOVE_ENV_RUST_BACKTRACE, REMOVE_ENV_RUST_LIB_BACKTRACE,
};
use niri::utils::watcher::Watcher; use niri::utils::watcher::Watcher;
use niri::utils::{cause_panic, version, IS_SYSTEMD_SERVICE}; use niri::utils::{cause_panic, version, IS_SYSTEMD_SERVICE};
use niri_config::Config; use niri_config::Config;
@@ -161,6 +163,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
animation::ANIMATION_SLOWDOWN.store(slowdown, Ordering::Relaxed); animation::ANIMATION_SLOWDOWN.store(slowdown, Ordering::Relaxed);
let spawn_at_startup = mem::take(&mut config.spawn_at_startup); let spawn_at_startup = mem::take(&mut config.spawn_at_startup);
*CHILD_ENV.write().unwrap() = mem::take(&mut config.environment);
// Create the compositor. // Create the compositor.
let mut event_loop = EventLoop::try_new().unwrap(); let mut event_loop = EventLoop::try_new().unwrap();
+4 -1
View File
@@ -104,6 +104,7 @@ use crate::ui::config_error_notification::ConfigErrorNotification;
use crate::ui::exit_confirm_dialog::ExitConfirmDialog; use crate::ui::exit_confirm_dialog::ExitConfirmDialog;
use crate::ui::hotkey_overlay::HotkeyOverlay; use crate::ui::hotkey_overlay::HotkeyOverlay;
use crate::ui::screenshot_ui::{ScreenshotUi, ScreenshotUiRenderElement}; use crate::ui::screenshot_ui::{ScreenshotUi, ScreenshotUiRenderElement};
use crate::utils::spawning::CHILD_ENV;
use crate::utils::{ use crate::utils::{
center, get_monotonic_time, make_screenshot_path, output_size, write_png_rgba8, center, get_monotonic_time, make_screenshot_path, output_size, write_png_rgba8,
}; };
@@ -577,7 +578,7 @@ impl State {
pub fn reload_config(&mut self, path: PathBuf) { pub fn reload_config(&mut self, path: PathBuf) {
let _span = tracy_client::span!("State::reload_config"); let _span = tracy_client::span!("State::reload_config");
let config = match Config::load(&path) { let mut config = match Config::load(&path) {
Ok(config) => config, Ok(config) => config,
Err(err) => { Err(err) => {
warn!("{:?}", err.context("error loading config")); warn!("{:?}", err.context("error loading config"));
@@ -598,6 +599,8 @@ impl State {
}; };
animation::ANIMATION_SLOWDOWN.store(slowdown, Ordering::Relaxed); animation::ANIMATION_SLOWDOWN.store(slowdown, Ordering::Relaxed);
*CHILD_ENV.write().unwrap() = mem::take(&mut config.environment);
let mut reload_xkb = None; let mut reload_xkb = None;
let mut libinput_config_changed = false; let mut libinput_config_changed = false;
let mut output_config_changed = false; let mut output_config_changed = false;
+14
View File
@@ -4,9 +4,11 @@ use std::os::unix::process::CommandExt;
use std::path::Path; use std::path::Path;
use std::process::{Command, Stdio}; use std::process::{Command, Stdio};
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::RwLock;
use std::{io, thread}; use std::{io, thread};
use libc::close_range; use libc::close_range;
use niri_config::Environment;
use smithay::reexports::rustix; use smithay::reexports::rustix;
use smithay::reexports::rustix::io::{close, read, retry_on_intr, write}; use smithay::reexports::rustix::io::{close, read, retry_on_intr, write};
use smithay::reexports::rustix::pipe::{pipe_with, PipeFlags}; use smithay::reexports::rustix::pipe::{pipe_with, PipeFlags};
@@ -15,6 +17,7 @@ use crate::utils::expand_home;
pub static REMOVE_ENV_RUST_BACKTRACE: AtomicBool = AtomicBool::new(false); pub static REMOVE_ENV_RUST_BACKTRACE: AtomicBool = AtomicBool::new(false);
pub static REMOVE_ENV_RUST_LIB_BACKTRACE: AtomicBool = AtomicBool::new(false); pub static REMOVE_ENV_RUST_LIB_BACKTRACE: AtomicBool = AtomicBool::new(false);
pub static CHILD_ENV: RwLock<Environment> = RwLock::new(Environment(Vec::new()));
/// Spawns the command to run independently of the compositor. /// Spawns the command to run independently of the compositor.
pub fn spawn<T: AsRef<OsStr> + Send + 'static>(command: Vec<T>) { pub fn spawn<T: AsRef<OsStr> + Send + 'static>(command: Vec<T>) {
@@ -67,6 +70,17 @@ fn spawn_sync(command: impl AsRef<OsStr>, args: impl IntoIterator<Item = impl As
process.env_remove("RUST_LIB_BACKTRACE"); process.env_remove("RUST_LIB_BACKTRACE");
} }
// Set configured environment.
let env = CHILD_ENV.read().unwrap();
for var in &env.0 {
if let Some(value) = &var.value {
process.env(&var.name, value);
} else {
process.env_remove(&var.name);
}
}
drop(env);
// When running as a systemd session, we want to put children into their own transient scopes // When running as a systemd session, we want to put children into their own transient scopes
// in order to separate them from the niri process. This is helpful for example to prevent the // in order to separate them from the niri process. This is helpful for example to prevent the
// OOM killer from taking down niri together with a misbehaving client. // OOM killer from taking down niri together with a misbehaving client.