mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-24 02:01:18 +07:00
Implement IPC for the overview state (#1526)
* Implement IPC for the overview state * Update Overview IPC to maintain naming consistency, renamed OverviewToggled to be more clear, simplify overview state request on the server, consolidate ipc refresh * Fix Overview is_open in IPC client * Change opened to is_open * Update niri-ipc/src/lib.rs Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com> * Update niri-ipc/src/state.rs Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com> * Update src/ipc/client.rs Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com> * Update src/ipc/client.rs Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com> * Add overview state to EventStreamStatePart replicate and apply * Fix formatting * Rename Overview to OverviewState --------- Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
This commit is contained in:
@@ -97,6 +97,8 @@ pub enum Request {
|
|||||||
EventStream,
|
EventStream,
|
||||||
/// Respond with an error (for testing error handling).
|
/// Respond with an error (for testing error handling).
|
||||||
ReturnError,
|
ReturnError,
|
||||||
|
/// Request information about the overview.
|
||||||
|
OverviewState,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reply from niri to client.
|
/// Reply from niri to client.
|
||||||
@@ -139,6 +141,16 @@ pub enum Response {
|
|||||||
PickedColor(Option<PickedColor>),
|
PickedColor(Option<PickedColor>),
|
||||||
/// Output configuration change result.
|
/// Output configuration change result.
|
||||||
OutputConfigChanged(OutputConfigChanged),
|
OutputConfigChanged(OutputConfigChanged),
|
||||||
|
/// Information about the overview.
|
||||||
|
OverviewState(Overview),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Overview information.
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
|
||||||
|
pub struct Overview {
|
||||||
|
/// Whether the overview is currently open.
|
||||||
|
pub is_open: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Color picked from the screen.
|
/// Color picked from the screen.
|
||||||
@@ -1269,6 +1281,11 @@ pub enum Event {
|
|||||||
/// Index of the newly active layout.
|
/// Index of the newly active layout.
|
||||||
idx: u8,
|
idx: u8,
|
||||||
},
|
},
|
||||||
|
/// The overview was opened or closed.
|
||||||
|
OverviewOpenedOrClosed {
|
||||||
|
/// The new state of the overview.
|
||||||
|
is_open: bool,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for WorkspaceReferenceArg {
|
impl FromStr for WorkspaceReferenceArg {
|
||||||
|
|||||||
@@ -40,6 +40,9 @@ pub struct EventStreamState {
|
|||||||
|
|
||||||
/// State of the keyboard layouts.
|
/// State of the keyboard layouts.
|
||||||
pub keyboard_layouts: KeyboardLayoutsState,
|
pub keyboard_layouts: KeyboardLayoutsState,
|
||||||
|
|
||||||
|
/// State of the overview.
|
||||||
|
pub overview: OverviewState,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The workspaces state communicated over the event stream.
|
/// The workspaces state communicated over the event stream.
|
||||||
@@ -63,12 +66,20 @@ pub struct KeyboardLayoutsState {
|
|||||||
pub keyboard_layouts: Option<KeyboardLayouts>,
|
pub keyboard_layouts: Option<KeyboardLayouts>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The overview state communicated over the event stream.
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct OverviewState {
|
||||||
|
/// Whether the overview is currently open.
|
||||||
|
pub is_open: bool,
|
||||||
|
}
|
||||||
|
|
||||||
impl EventStreamStatePart for EventStreamState {
|
impl EventStreamStatePart for EventStreamState {
|
||||||
fn replicate(&self) -> Vec<Event> {
|
fn replicate(&self) -> Vec<Event> {
|
||||||
let mut events = Vec::new();
|
let mut events = Vec::new();
|
||||||
events.extend(self.workspaces.replicate());
|
events.extend(self.workspaces.replicate());
|
||||||
events.extend(self.windows.replicate());
|
events.extend(self.windows.replicate());
|
||||||
events.extend(self.keyboard_layouts.replicate());
|
events.extend(self.keyboard_layouts.replicate());
|
||||||
|
events.extend(self.overview.replicate());
|
||||||
events
|
events
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,6 +87,7 @@ impl EventStreamStatePart for EventStreamState {
|
|||||||
let event = self.workspaces.apply(event)?;
|
let event = self.workspaces.apply(event)?;
|
||||||
let event = self.windows.apply(event)?;
|
let event = self.windows.apply(event)?;
|
||||||
let event = self.keyboard_layouts.apply(event)?;
|
let event = self.keyboard_layouts.apply(event)?;
|
||||||
|
let event = self.overview.apply(event)?;
|
||||||
Some(event)
|
Some(event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -192,3 +204,21 @@ impl EventStreamStatePart for KeyboardLayoutsState {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl EventStreamStatePart for OverviewState {
|
||||||
|
fn replicate(&self) -> Vec<Event> {
|
||||||
|
vec![Event::OverviewOpenedOrClosed {
|
||||||
|
is_open: self.is_open,
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply(&mut self, event: Event) -> Option<Event> {
|
||||||
|
match event {
|
||||||
|
Event::OverviewOpenedOrClosed { is_open } => {
|
||||||
|
self.is_open = is_open;
|
||||||
|
}
|
||||||
|
event => return Some(event),
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -105,4 +105,6 @@ pub enum Msg {
|
|||||||
Version,
|
Version,
|
||||||
/// Request an error from the running niri instance.
|
/// Request an error from the running niri instance.
|
||||||
RequestError,
|
RequestError,
|
||||||
|
/// Print the overview state.
|
||||||
|
OverviewState,
|
||||||
}
|
}
|
||||||
|
|||||||
+25
-2
@@ -5,8 +5,8 @@ use anyhow::{anyhow, bail, Context};
|
|||||||
use niri_config::OutputName;
|
use niri_config::OutputName;
|
||||||
use niri_ipc::socket::Socket;
|
use niri_ipc::socket::Socket;
|
||||||
use niri_ipc::{
|
use niri_ipc::{
|
||||||
Event, KeyboardLayouts, LogicalOutput, Mode, Output, OutputConfigChanged, Request, Response,
|
Event, KeyboardLayouts, LogicalOutput, Mode, Output, OutputConfigChanged, Overview, Request,
|
||||||
Transform, Window,
|
Response, Transform, Window,
|
||||||
};
|
};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
@@ -32,6 +32,7 @@ pub fn handle_msg(msg: Msg, json: bool) -> anyhow::Result<()> {
|
|||||||
Msg::KeyboardLayouts => Request::KeyboardLayouts,
|
Msg::KeyboardLayouts => Request::KeyboardLayouts,
|
||||||
Msg::EventStream => Request::EventStream,
|
Msg::EventStream => Request::EventStream,
|
||||||
Msg::RequestError => Request::ReturnError,
|
Msg::RequestError => Request::ReturnError,
|
||||||
|
Msg::OverviewState => Request::OverviewState,
|
||||||
};
|
};
|
||||||
|
|
||||||
let socket = Socket::connect().context("error connecting to the niri socket")?;
|
let socket = Socket::connect().context("error connecting to the niri socket")?;
|
||||||
@@ -435,10 +436,32 @@ pub fn handle_msg(msg: Msg, json: bool) -> anyhow::Result<()> {
|
|||||||
Event::KeyboardLayoutSwitched { idx } => {
|
Event::KeyboardLayoutSwitched { idx } => {
|
||||||
println!("Keyboard layout switched: {idx}");
|
println!("Keyboard layout switched: {idx}");
|
||||||
}
|
}
|
||||||
|
Event::OverviewOpenedOrClosed { is_open: opened } => {
|
||||||
|
println!("Overview toggled: {opened}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Msg::OverviewState => {
|
||||||
|
let Response::OverviewState(response) = response else {
|
||||||
|
bail!("unexpected response: expected Overview, got {response:?}");
|
||||||
|
};
|
||||||
|
|
||||||
|
if json {
|
||||||
|
let response =
|
||||||
|
serde_json::to_string(&response).context("error formatting response")?;
|
||||||
|
println!("{response}");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let Overview { is_open } = response;
|
||||||
|
if is_open {
|
||||||
|
println!("Overview is open.");
|
||||||
|
} else {
|
||||||
|
println!("Overview is closed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
+27
-1
@@ -16,7 +16,9 @@ use futures_util::io::{AsyncReadExt, BufReader};
|
|||||||
use futures_util::{select_biased, AsyncBufReadExt, AsyncWrite, AsyncWriteExt, FutureExt as _};
|
use futures_util::{select_biased, AsyncBufReadExt, AsyncWrite, AsyncWriteExt, FutureExt as _};
|
||||||
use niri_config::OutputName;
|
use niri_config::OutputName;
|
||||||
use niri_ipc::state::{EventStreamState, EventStreamStatePart as _};
|
use niri_ipc::state::{EventStreamState, EventStreamStatePart as _};
|
||||||
use niri_ipc::{Event, KeyboardLayouts, OutputConfigChanged, Reply, Request, Response, Workspace};
|
use niri_ipc::{
|
||||||
|
Event, KeyboardLayouts, OutputConfigChanged, Overview, Reply, Request, Response, Workspace,
|
||||||
|
};
|
||||||
use smithay::desktop::layer_map_for_output;
|
use smithay::desktop::layer_map_for_output;
|
||||||
use smithay::input::pointer::{
|
use smithay::input::pointer::{
|
||||||
CursorIcon, CursorImageStatus, Focus, GrabStartData as PointerGrabStartData,
|
CursorIcon, CursorImageStatus, Focus, GrabStartData as PointerGrabStartData,
|
||||||
@@ -428,6 +430,11 @@ async fn process(ctx: &ClientCtx, request: Request) -> Reply {
|
|||||||
Response::FocusedOutput(output)
|
Response::FocusedOutput(output)
|
||||||
}
|
}
|
||||||
Request::EventStream => Response::Handled,
|
Request::EventStream => Response::Handled,
|
||||||
|
Request::OverviewState => {
|
||||||
|
let state = ctx.event_stream_state.borrow();
|
||||||
|
let is_open = state.overview.is_open;
|
||||||
|
Response::OverviewState(Overview { is_open })
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(response)
|
Ok(response)
|
||||||
@@ -524,6 +531,7 @@ impl State {
|
|||||||
pub fn ipc_refresh_layout(&mut self) {
|
pub fn ipc_refresh_layout(&mut self) {
|
||||||
self.ipc_refresh_workspaces();
|
self.ipc_refresh_workspaces();
|
||||||
self.ipc_refresh_windows();
|
self.ipc_refresh_windows();
|
||||||
|
self.ipc_refresh_overview();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ipc_refresh_workspaces(&mut self) {
|
fn ipc_refresh_workspaces(&mut self) {
|
||||||
@@ -690,4 +698,22 @@ impl State {
|
|||||||
server.send_event(event);
|
server.send_event(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn ipc_refresh_overview(&mut self) {
|
||||||
|
let Some(server) = &self.niri.ipc_server else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut state = server.event_stream_state.borrow_mut();
|
||||||
|
let state = &mut state.overview;
|
||||||
|
let is_open = self.niri.layout.is_overview_open();
|
||||||
|
|
||||||
|
if state.is_open == is_open {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let event = Event::OverviewOpenedOrClosed { is_open };
|
||||||
|
state.apply(event.clone());
|
||||||
|
server.send_event(event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user