mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-23 02:05:33 +07:00
ipc: Add screencast request and events for PipeWire casts
Allows desktop bars to show when screen recording is active.
This commit is contained in:
@@ -117,6 +117,8 @@ pub enum Request {
|
||||
ReturnError,
|
||||
/// Request information about the overview.
|
||||
OverviewState,
|
||||
/// Request information about screencasts.
|
||||
Casts,
|
||||
}
|
||||
|
||||
/// Reply from niri to client.
|
||||
@@ -161,6 +163,8 @@ pub enum Response {
|
||||
OutputConfigChanged(OutputConfigChanged),
|
||||
/// Information about the overview.
|
||||
OverviewState(Overview),
|
||||
/// Information about screencasts.
|
||||
Casts(Vec<Cast>),
|
||||
}
|
||||
|
||||
/// Overview information.
|
||||
@@ -1473,6 +1477,52 @@ pub struct LayerSurface {
|
||||
pub keyboard_interactivity: LayerSurfaceKeyboardInteractivity,
|
||||
}
|
||||
|
||||
/// A screencast.
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
|
||||
pub struct Cast {
|
||||
/// Stream ID of the screencast that uniquely identifies it.
|
||||
pub stream_id: u64,
|
||||
/// Session ID of the screencast.
|
||||
///
|
||||
/// A session can have multiple screencast streams. Then multiple `Cast`s will have the same
|
||||
/// `session_id`. Though, usually there's only one stream per session.
|
||||
///
|
||||
/// Do not confuse `session_id` with [`stream_id`](Self::stream_id).
|
||||
pub session_id: u64,
|
||||
/// Target being captured.
|
||||
pub target: CastTarget,
|
||||
/// Whether this is a Dynamic Cast Target screencast.
|
||||
///
|
||||
/// Meaning that actions like `SetDynamicCastWindow` will act on this screencast.
|
||||
///
|
||||
/// Keep in mind that the target can change even if this is `false`.
|
||||
pub is_dynamic_target: bool,
|
||||
/// Whether the cast is currently streaming frames.
|
||||
///
|
||||
/// This can be `false` for example when switching away to a different scene in OBS, which
|
||||
/// pauses the stream.
|
||||
pub is_active: bool,
|
||||
}
|
||||
|
||||
/// Target of a screencast.
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
|
||||
pub enum CastTarget {
|
||||
/// The target is not yet set, or was cleared.
|
||||
Nothing {},
|
||||
/// Casting an output.
|
||||
Output {
|
||||
/// Name of the screencasted output.
|
||||
name: String,
|
||||
},
|
||||
/// Casting a window.
|
||||
Window {
|
||||
/// ID of the screencasted window.
|
||||
id: u64,
|
||||
},
|
||||
}
|
||||
|
||||
/// A compositor event.
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
|
||||
@@ -1595,6 +1645,24 @@ pub enum Event {
|
||||
/// be converted to a `String` (e.g. contained invalid UTF-8 bytes).
|
||||
path: Option<String>,
|
||||
},
|
||||
/// The screencasts have changed.
|
||||
CastsChanged {
|
||||
/// The new screencast information.
|
||||
///
|
||||
/// This configuration completely replaces the previous configuration. I.e. if any casts
|
||||
/// are missing from here, then they were stopped.
|
||||
casts: Vec<Cast>,
|
||||
},
|
||||
/// A screencast started, or an existing cast changed.
|
||||
CastStartedOrChanged {
|
||||
/// The cast that started or changed.
|
||||
cast: Cast,
|
||||
},
|
||||
/// A screencast stopped.
|
||||
CastStopped {
|
||||
/// Stream ID of the stopped screencast.
|
||||
stream_id: u64,
|
||||
},
|
||||
}
|
||||
|
||||
impl From<Duration> for Timestamp {
|
||||
|
||||
+37
-1
@@ -9,7 +9,7 @@
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::{Event, KeyboardLayouts, Window, Workspace};
|
||||
use crate::{Cast, Event, KeyboardLayouts, Window, Workspace};
|
||||
|
||||
/// Part of the state communicated via the event stream.
|
||||
pub trait EventStreamStatePart {
|
||||
@@ -46,6 +46,9 @@ pub struct EventStreamState {
|
||||
|
||||
/// State of the config.
|
||||
pub config: ConfigState,
|
||||
|
||||
/// State of screencasts.
|
||||
pub casts: CastsState,
|
||||
}
|
||||
|
||||
/// The workspaces state communicated over the event stream.
|
||||
@@ -83,6 +86,13 @@ pub struct ConfigState {
|
||||
pub failed: bool,
|
||||
}
|
||||
|
||||
/// The casts state communicated over the event stream.
|
||||
#[derive(Debug, Default)]
|
||||
pub struct CastsState {
|
||||
/// Map from a stream id to the screencast.
|
||||
pub casts: HashMap<u64, Cast>,
|
||||
}
|
||||
|
||||
impl EventStreamStatePart for EventStreamState {
|
||||
fn replicate(&self) -> Vec<Event> {
|
||||
let mut events = Vec::new();
|
||||
@@ -91,6 +101,7 @@ impl EventStreamStatePart for EventStreamState {
|
||||
events.extend(self.keyboard_layouts.replicate());
|
||||
events.extend(self.overview.replicate());
|
||||
events.extend(self.config.replicate());
|
||||
events.extend(self.casts.replicate());
|
||||
events
|
||||
}
|
||||
|
||||
@@ -100,6 +111,7 @@ impl EventStreamStatePart for EventStreamState {
|
||||
let event = self.keyboard_layouts.apply(event)?;
|
||||
let event = self.overview.apply(event)?;
|
||||
let event = self.config.apply(event)?;
|
||||
let event = self.casts.apply(event)?;
|
||||
Some(event)
|
||||
}
|
||||
}
|
||||
@@ -285,3 +297,27 @@ impl EventStreamStatePart for ConfigState {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl EventStreamStatePart for CastsState {
|
||||
fn replicate(&self) -> Vec<Event> {
|
||||
let casts = self.casts.values().cloned().collect();
|
||||
vec![Event::CastsChanged { casts }]
|
||||
}
|
||||
|
||||
fn apply(&mut self, event: Event) -> Option<Event> {
|
||||
match event {
|
||||
Event::CastsChanged { casts } => {
|
||||
self.casts = casts.into_iter().map(|c| (c.stream_id, c)).collect();
|
||||
}
|
||||
Event::CastStartedOrChanged { cast } => {
|
||||
self.casts.insert(cast.stream_id, cast);
|
||||
}
|
||||
Event::CastStopped { stream_id } => {
|
||||
let cast = self.casts.remove(&stream_id);
|
||||
cast.expect("stopped cast was missing from the map");
|
||||
}
|
||||
event => return Some(event),
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user