diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/input/mod.rs | 6 | ||||
| -rw-r--r-- | src/main.rs | 8 | ||||
| -rw-r--r-- | src/ui/hotkey_overlay.rs | 7 | ||||
| -rw-r--r-- | src/utils/spawning.rs | 10 |
4 files changed, 27 insertions, 4 deletions
diff --git a/src/input/mod.rs b/src/input/mod.rs index cc07aed3..711a09dd 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -44,7 +44,7 @@ use crate::layout::scrolling::ScrollDirection; use crate::layout::{ActivateWindow, LayoutElement as _}; use crate::niri::{CastTarget, PointerVisibility, State}; use crate::ui::screenshot_ui::ScreenshotUi; -use crate::utils::spawning::spawn; +use crate::utils::spawning::{spawn, spawn_sh}; use crate::utils::{center, get_monotonic_time, ResizeEdge}; pub mod backend_ext; @@ -595,6 +595,10 @@ impl State { let (token, _) = self.niri.activation_state.create_external_token(None); spawn(command, Some(token.clone())); } + Action::SpawnSh(command) => { + let (token, _) = self.niri.activation_state.create_external_token(None); + spawn_sh(command, Some(token.clone())); + } Action::DoScreenTransition(delay_ms) => { self.backend.with_primary_renderer(|renderer| { self.niri.do_screen_transition(renderer, delay_ms); diff --git a/src/main.rs b/src/main.rs index 9654f7e9..c17e2f39 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,8 +20,8 @@ use niri::dbus; use niri::ipc::client::handle_msg; use niri::niri::State; use niri::utils::spawning::{ - spawn, store_and_increase_nofile_rlimit, CHILD_DISPLAY, CHILD_ENV, REMOVE_ENV_RUST_BACKTRACE, - REMOVE_ENV_RUST_LIB_BACKTRACE, + spawn, spawn_sh, store_and_increase_nofile_rlimit, CHILD_DISPLAY, CHILD_ENV, + REMOVE_ENV_RUST_BACKTRACE, REMOVE_ENV_RUST_LIB_BACKTRACE, }; use niri::utils::{cause_panic, version, watcher, xwayland, IS_SYSTEMD_SERVICE}; use niri_config::ConfigPath; @@ -151,6 +151,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> { .unwrap_or_default(); let spawn_at_startup = mem::take(&mut config.spawn_at_startup); + let spawn_at_startup_sh = mem::take(&mut config.spawn_at_startup_sh); *CHILD_ENV.write().unwrap() = mem::take(&mut config.environment); store_and_increase_nofile_rlimit(); @@ -237,6 +238,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> { for elem in spawn_at_startup { spawn(elem.command, None); } + for elem in spawn_at_startup_sh { + spawn_sh(elem.command, None); + } // Show the config error notification right away if needed. if config_errored { diff --git a/src/ui/hotkey_overlay.rs b/src/ui/hotkey_overlay.rs index 7042d2c0..d30d500d 100644 --- a/src/ui/hotkey_overlay.rs +++ b/src/ui/hotkey_overlay.rs @@ -270,7 +270,7 @@ fn render( // Add the spawn actions. for bind in binds.iter().filter(|bind| { - matches!(bind.action, Action::Spawn(_)) + matches!(bind.action, Action::Spawn(_) | Action::SpawnSh(_)) // Only show binds with Mod or Super to filter out stuff like volume up/down. && (bind.key.modifiers.contains(Modifiers::COMPOSITOR) || bind.key.modifiers.contains(Modifiers::SUPER)) @@ -447,6 +447,11 @@ fn action_name(action: &Action) -> String { "Spawn <span face='monospace' bgcolor='#000000'>{}</span>", args.first().unwrap_or(&String::new()) ), + Action::SpawnSh(command) => format!( + "Spawn <span face='monospace' bgcolor='#000000'>{}</span>", + // Fairly crude but should get the job done in most cases. + command.split_ascii_whitespace().next().unwrap_or("") + ), _ => String::from("FIXME: Unknown"), } } diff --git a/src/utils/spawning.rs b/src/utils/spawning.rs index a6f516db..61912eae 100644 --- a/src/utils/spawning.rs +++ b/src/utils/spawning.rs @@ -83,6 +83,16 @@ pub fn spawn<T: AsRef<OsStr> + Send + 'static>(command: Vec<T>, token: Option<Xd } } +/// Spawns the command through the shell. +/// +/// We hardcode `sh -c`, consistent with other compositors: +/// +/// - https://github.com/swaywm/sway/blob/b3dcde8d69c3f1304b076968a7a64f54d0c958be/sway/commands/exec_always.c#L64 +/// - https://github.com/hyprwm/Hyprland/blob/1ac1ff457ab8ef1ae6a8f2ab17ee7965adfa729f/src/managers/KeybindManager.cpp#L987 +pub fn spawn_sh(command: String, token: Option<XdgActivationToken>) { + spawn(vec![String::from("sh"), String::from("-c"), command], token); +} + fn spawn_sync( command: impl AsRef<OsStr>, args: impl IntoIterator<Item = impl AsRef<OsStr>>, |
