aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorrustysec <russ@infocyte.com>2024-05-16 14:30:52 -0700
committerIvan Molodetskikh <yalterz@gmail.com>2024-05-17 10:33:00 +0300
commit36d3e70f11bde96eb67d157b22ebcdf4767af0c2 (patch)
treef03cad743d95094e0d3eb37b26568006c5298806 /src
parenta2f74c9bff953c9f3318cb642785f02c6f5fe5d3 (diff)
downloadniri-36d3e70f11bde96eb67d157b22ebcdf4767af0c2.tar.gz
niri-36d3e70f11bde96eb67d157b22ebcdf4767af0c2.tar.bz2
niri-36d3e70f11bde96eb67d157b22ebcdf4767af0c2.zip
Implement niri msg workspaces
Diffstat (limited to 'src')
-rw-r--r--src/cli.rs2
-rw-r--r--src/ipc/client.rs49
-rw-r--r--src/ipc/server.rs10
-rw-r--r--src/layout/mod.rs35
-rw-r--r--src/niri.rs5
5 files changed, 101 insertions, 0 deletions
diff --git a/src/cli.rs b/src/cli.rs
index 65e2fd14..b6284559 100644
--- a/src/cli.rs
+++ b/src/cli.rs
@@ -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 {