diff options
| author | rustysec <russ@infocyte.com> | 2024-05-16 14:30:52 -0700 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2024-05-17 10:33:00 +0300 |
| commit | 36d3e70f11bde96eb67d157b22ebcdf4767af0c2 (patch) | |
| tree | f03cad743d95094e0d3eb37b26568006c5298806 /src | |
| parent | a2f74c9bff953c9f3318cb642785f02c6f5fe5d3 (diff) | |
| download | niri-36d3e70f11bde96eb67d157b22ebcdf4767af0c2.tar.gz niri-36d3e70f11bde96eb67d157b22ebcdf4767af0c2.tar.bz2 niri-36d3e70f11bde96eb67d157b22ebcdf4767af0c2.zip | |
Implement niri msg workspaces
Diffstat (limited to 'src')
| -rw-r--r-- | src/cli.rs | 2 | ||||
| -rw-r--r-- | src/ipc/client.rs | 49 | ||||
| -rw-r--r-- | src/ipc/server.rs | 10 | ||||
| -rw-r--r-- | src/layout/mod.rs | 35 | ||||
| -rw-r--r-- | src/niri.rs | 5 |
5 files changed, 101 insertions, 0 deletions
@@ -78,6 +78,8 @@ pub enum Msg { #[command(subcommand)] action: OutputAction, }, + /// List workspaces. + Workspaces, /// Request an error from the running niri instance. RequestError, } diff --git a/src/ipc/client.rs b/src/ipc/client.rs index ca472e11..f97cc80a 100644 --- a/src/ipc/client.rs +++ b/src/ipc/client.rs @@ -17,6 +17,7 @@ pub fn handle_msg(msg: Msg, json: bool) -> anyhow::Result<()> { output: output.clone(), action: action.clone(), }, + Msg::Workspaces => Request::Workspaces, Msg::RequestError => Request::ReturnError, }; @@ -260,6 +261,54 @@ pub fn handle_msg(msg: Msg, json: bool) -> anyhow::Result<()> { println!("The change will apply when it is connected."); } } + Msg::Workspaces => { + let Response::Workspaces(mut response) = response else { + bail!("unexpected response: expected Workspaces, got {response:?}"); + }; + + if json { + let response = + serde_json::to_string(&response).context("error formatting response")?; + println!("{response}"); + return Ok(()); + } + + if response.is_empty() { + println!("No workspaces."); + return Ok(()); + } + + response.sort_by_key(|ws| ws.idx); + response.sort_by(|a, b| a.output.cmp(&b.output)); + + let mut current_output = if let Some(output) = response[0].output.as_deref() { + println!("Output \"{output}\":"); + Some(output) + } else { + println!("No output:"); + None + }; + + for ws in &response { + if ws.output.as_deref() != current_output { + let output = ws.output.as_deref().context( + "invalid response: workspace with no output \ + following a workspace with an output", + )?; + current_output = Some(output); + println!("\nOutput \"{output}\":"); + } + + let is_active = if ws.is_active { " * " } else { " " }; + let idx = ws.idx; + let name = if let Some(name) = ws.name.as_deref() { + format!(" \"{name}\"") + } else { + String::new() + }; + println!("{is_active}{idx}{name}"); + } + } } Ok(()) diff --git a/src/ipc/server.rs b/src/ipc/server.rs index 5c3f27e6..26958a7f 100644 --- a/src/ipc/server.rs +++ b/src/ipc/server.rs @@ -198,6 +198,16 @@ async fn process(ctx: &ClientCtx, request: Request) -> Reply { Response::OutputConfigChanged(response) } + Request::Workspaces => { + let (tx, rx) = async_channel::bounded(1); + ctx.event_loop.insert_idle(move |state| { + let workspaces = state.niri.layout.ipc_workspaces(); + let _ = tx.send_blocking(workspaces); + }); + let result = rx.recv().await; + let workspaces = result.map_err(|_| String::from("error getting workspace info"))?; + Response::Workspaces(workspaces) + } }; Ok(response) diff --git a/src/layout/mod.rs b/src/layout/mod.rs index 544b2186..02eeda3b 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -2278,6 +2278,41 @@ impl<W: LayoutElement> Layout<W> { } } } + + pub fn ipc_workspaces(&self) -> Vec<niri_ipc::Workspace> { + match &self.monitor_set { + MonitorSet::Normal { + monitors, + primary_idx: _, + active_monitor_idx: _, + } => { + let mut workspaces = Vec::new(); + + for monitor in monitors { + for (idx, workspace) in monitor.workspaces.iter().enumerate() { + workspaces.push(niri_ipc::Workspace { + idx: u8::try_from(idx + 1).unwrap_or(u8::MAX), + name: workspace.name.clone(), + output: Some(monitor.output.name()), + is_active: monitor.active_workspace_idx == idx, + }) + } + } + + workspaces + } + MonitorSet::NoOutputs { workspaces } => workspaces + .iter() + .enumerate() + .map(|(idx, ws)| niri_ipc::Workspace { + idx: u8::try_from(idx + 1).unwrap_or(u8::MAX), + name: ws.name.clone(), + output: None, + is_active: false, + }) + .collect(), + } + } } impl<W: LayoutElement> Default for MonitorSet<W> { diff --git a/src/niri.rs b/src/niri.rs index 1c0ad3fc..d276a4e8 100644 --- a/src/niri.rs +++ b/src/niri.rs @@ -12,6 +12,7 @@ use _server_decoration::server::org_kde_kwin_server_decoration_manager::Mode as use anyhow::{ensure, Context}; use calloop::futures::Scheduler; use niri_config::{Config, Key, Modifiers, PreviewRender, TrackLayout, WorkspaceReference}; +use niri_ipc::Workspace; use smithay::backend::allocator::Fourcc; use smithay::backend::renderer::damage::OutputDamageTracker; use smithay::backend::renderer::element::memory::MemoryRenderBufferRenderElement; @@ -3934,6 +3935,10 @@ impl Niri { self.queue_redraw_all(); } } + + pub fn ipc_workspaces(&self) -> Vec<Workspace> { + self.layout.ipc_workspaces() + } } pub struct ClientState { |
