From 849788bb2846fadada80bf73cb5238ae7f82c835 Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Thu, 15 Jan 2026 13:11:48 +0300 Subject: [PATCH] Add niri msg stop-cast --session-id --- niri-config/src/binds.rs | 3 +++ niri-ipc/src/lib.rs | 10 ++++++++++ src/input/mod.rs | 5 ++++- src/niri.rs | 3 +++ src/screencasting/mod.rs | 2 +- src/utils/mod.rs | 6 ++++++ 6 files changed, 27 insertions(+), 2 deletions(-) diff --git a/niri-config/src/binds.rs b/niri-config/src/binds.rs index fdb21afe..597c742e 100644 --- a/niri-config/src/binds.rs +++ b/niri-config/src/binds.rs @@ -356,6 +356,8 @@ pub enum Action { SetDynamicCastWindowById(u64), SetDynamicCastMonitor(#[knuffel(argument)] Option), ClearDynamicCastTarget, + #[knuffel(skip)] + StopCast(u64), ToggleOverview, OpenOverview, CloseOverview, @@ -690,6 +692,7 @@ impl From for Action { Self::SetDynamicCastMonitor(output) } niri_ipc::Action::ClearDynamicCastTarget {} => Self::ClearDynamicCastTarget, + niri_ipc::Action::StopCast { session_id } => Self::StopCast(session_id), niri_ipc::Action::ToggleOverview {} => Self::ToggleOverview, niri_ipc::Action::OpenOverview {} => Self::OpenOverview, niri_ipc::Action::CloseOverview {} => Self::CloseOverview, diff --git a/niri-ipc/src/lib.rs b/niri-ipc/src/lib.rs index 61b5578a..7785b902 100644 --- a/niri-ipc/src/lib.rs +++ b/niri-ipc/src/lib.rs @@ -898,6 +898,16 @@ pub enum Action { }, /// Clear the dynamic cast target, making it show nothing. ClearDynamicCastTarget {}, + /// Stop a PipeWire screencast. + /// + /// wlr-screencopy screencasts cannot currently be stopped via IPC. + StopCast { + /// Session ID of the screencast to stop. + /// + /// If the session has multiple screencast streams, this will stop all of them. + #[cfg_attr(feature = "clap", arg(long))] + session_id: u64, + }, /// Toggle (open/close) the Overview. ToggleOverview {}, /// Open the Overview. diff --git a/src/input/mod.rs b/src/input/mod.rs index aed2e9c5..011fd365 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -51,7 +51,7 @@ use crate::niri::{CastTarget, PointerVisibility, State}; use crate::ui::mru::{WindowMru, WindowMruUi}; use crate::ui::screenshot_ui::ScreenshotUi; use crate::utils::spawning::{spawn, spawn_sh}; -use crate::utils::{center, get_monotonic_time, ResizeEdge}; +use crate::utils::{center, get_monotonic_time, CastSessionId, ResizeEdge}; pub mod backend_ext; pub mod move_grab; @@ -2241,6 +2241,9 @@ impl State { Action::ClearDynamicCastTarget => { self.set_dynamic_cast_target(CastTarget::Nothing); } + Action::StopCast(session_id) => { + self.niri.stop_cast(CastSessionId::from(session_id)); + } Action::ToggleOverview => { self.niri.layout.toggle_overview(); self.niri.queue_redraw_all(); diff --git a/src/niri.rs b/src/niri.rs index c90a880e..1f6b632d 100644 --- a/src/niri.rs +++ b/src/niri.rs @@ -5086,6 +5086,9 @@ impl Niri { #[cfg(not(feature = "xdp-gnome-screencast"))] pub fn stop_casts_for_target(&mut self, _target: CastTarget) {} + #[cfg(not(feature = "xdp-gnome-screencast"))] + pub fn stop_cast(&mut self, _session_id: crate::utils::CastSessionId) {} + pub fn debug_toggle_damage(&mut self) { self.debug_draw_damage = !self.debug_draw_damage; diff --git a/src/screencasting/mod.rs b/src/screencasting/mod.rs index a5b4bcf2..d2e6ca3f 100644 --- a/src/screencasting/mod.rs +++ b/src/screencasting/mod.rs @@ -693,7 +693,7 @@ impl Niri { } } - fn stop_cast(&mut self, session_id: CastSessionId) { + pub fn stop_cast(&mut self, session_id: CastSessionId) { let _span = tracy_client::span!("Niri::stop_cast"); let _span = debug_span!("stop_cast", %session_id).entered(); diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 659c3823..84804a02 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -68,6 +68,12 @@ impl Display for CastSessionId { } } +impl From for CastSessionId { + fn from(value: u64) -> Self { + Self(value) + } +} + /// Unique ID for a screencast stream. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct CastStreamId(u64);