From b98f4906da021c2d37729b73f0e8fc4f84a7bc4a Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Tue, 13 Jan 2026 13:49:52 +0300 Subject: [PATCH] ipc: Add CastKind --- niri-ipc/src/lib.rs | 17 +++++++++++++++++ src/ipc/client.rs | 8 +++++++- src/ipc/server.rs | 3 +++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/niri-ipc/src/lib.rs b/niri-ipc/src/lib.rs index 75285657..6041181f 100644 --- a/niri-ipc/src/lib.rs +++ b/niri-ipc/src/lib.rs @@ -1490,6 +1490,8 @@ pub struct Cast { /// /// Do not confuse `session_id` with [`stream_id`](Self::stream_id). pub session_id: u64, + /// Kind of this screencast. + pub kind: CastKind, /// Target being captured. pub target: CastTarget, /// Whether this is a Dynamic Cast Target screencast. @@ -1505,6 +1507,21 @@ pub struct Cast { pub is_active: bool, } +/// Kind of screencast. +#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)] +#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))] +pub enum CastKind { + /// PipeWire screencast, typically via xdg-desktop-portal-gnome. + PipeWire, + /// wlr-screencopy protocol screencast. + /// + /// Tools like wf-recorder, and the xdg-desktop-portal-wlr portal. + /// + /// Only wlr-screencopy with damage tracking is reported here. Screencopy without damage is + /// treated as a regular screenshot and not reported as a screencast. + WlrScreencopy, +} + /// Target of a screencast. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))] diff --git a/src/ipc/client.rs b/src/ipc/client.rs index 8372b1a6..22bf15cf 100644 --- a/src/ipc/client.rs +++ b/src/ipc/client.rs @@ -7,7 +7,7 @@ use anyhow::{anyhow, bail, Context}; use niri_config::OutputName; use niri_ipc::socket::Socket; use niri_ipc::{ - Action, Cast, CastTarget, Event, KeyboardLayouts, LogicalOutput, Mode, Output, + Action, Cast, CastKind, CastTarget, Event, KeyboardLayouts, LogicalOutput, Mode, Output, OutputConfigChanged, Overview, Request, Response, Transform, Window, WindowLayout, }; use serde_json::json; @@ -743,6 +743,12 @@ fn print_cast(cast: &Cast) { println!("Cast stream ID {}:{active}", cast.stream_id); println!(" Session ID: {}", cast.session_id); + let kind = match cast.kind { + CastKind::PipeWire => "PipeWire", + CastKind::WlrScreencopy => "wlr-screencopy", + }; + println!(" Kind: {kind}"); + match &cast.target { CastTarget::Nothing {} => { println!(" Target: nothing (cleared)"); diff --git a/src/ipc/server.rs b/src/ipc/server.rs index 07e68db9..4964ec2e 100644 --- a/src/ipc/server.rs +++ b/src/ipc/server.rs @@ -825,6 +825,7 @@ impl State { let cast = niri_ipc::Cast { session_id: pending.session_id.get(), stream_id, + kind: niri_ipc::CastKind::PipeWire, target: niri_ipc::CastTarget::Nothing {}, is_dynamic_target: true, is_active: false, @@ -845,6 +846,7 @@ impl State { let cast = niri_ipc::Cast { session_id: cast.session_id.get(), stream_id, + kind: niri_ipc::CastKind::PipeWire, target: cast.target.make_ipc(), is_dynamic_target: cast.dynamic_target, is_active: cast.is_active(), @@ -870,6 +872,7 @@ impl State { let cast = niri_ipc::Cast { session_id: cast_info.session_id.get(), stream_id, + kind: niri_ipc::CastKind::WlrScreencopy, target: niri_ipc::CastTarget::Output { name: cast_info.output_name.clone(), },