From f7181fb066e6390d516dfb4ee39e5812efad6f59 Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Mon, 2 Sep 2024 09:20:23 +0300 Subject: Implement by-id workspace action addressing It's not added to clap because there's no convenient mutually-exclusive argument enum derive yet (to have either the current or an --id ). It's not added to config parsing because I don't see how it could be useful there. As such, it's only accessible through raw IPC. --- niri-config/src/lib.rs | 2 ++ niri-ipc/src/lib.rs | 4 +++- src/layout/mod.rs | 26 ++++++++++++++++++++++++++ src/layout/workspace.rs | 4 ++++ src/niri.rs | 12 +++++++----- 5 files changed, 42 insertions(+), 6 deletions(-) diff --git a/niri-config/src/lib.rs b/niri-config/src/lib.rs index ff1fe365..9092cd21 100644 --- a/niri-config/src/lib.rs +++ b/niri-config/src/lib.rs @@ -1233,6 +1233,7 @@ impl From for Action { #[derive(Debug, PartialEq, Eq, Clone)] pub enum WorkspaceReference { + Id(u64), Index(u8), Name(String), } @@ -1240,6 +1241,7 @@ pub enum WorkspaceReference { impl From for WorkspaceReference { fn from(reference: WorkspaceReferenceArg) -> WorkspaceReference { match reference { + WorkspaceReferenceArg::Id(id) => Self::Id(id), WorkspaceReferenceArg::Index(i) => Self::Index(i), WorkspaceReferenceArg::Name(n) => Self::Name(n), } diff --git a/niri-ipc/src/lib.rs b/niri-ipc/src/lib.rs index 9ee0e5f8..22a1a63b 100644 --- a/niri-ipc/src/lib.rs +++ b/niri-ipc/src/lib.rs @@ -308,10 +308,12 @@ pub enum SizeChange { AdjustProportion(f64), } -/// Workspace reference (index or name) to operate on. +/// Workspace reference (id, index or name) to operate on. #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))] pub enum WorkspaceReferenceArg { + /// Id of the workspace. + Id(u64), /// Index of the workspace. Index(u8), /// Name of the workspace. diff --git a/src/layout/mod.rs b/src/layout/mod.rs index 20c63d28..9a9e084d 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -836,6 +836,32 @@ impl Layout { None } + pub fn find_workspace_by_id(&self, id: WorkspaceId) -> Option<(usize, &Workspace)> { + match &self.monitor_set { + MonitorSet::Normal { ref monitors, .. } => { + for mon in monitors { + if let Some((index, workspace)) = mon + .workspaces + .iter() + .enumerate() + .find(|(_, w)| w.id() == id) + { + return Some((index, workspace)); + } + } + } + MonitorSet::NoOutputs { workspaces } => { + if let Some((index, workspace)) = + workspaces.iter().enumerate().find(|(_, w)| w.id() == id) + { + return Some((index, workspace)); + } + } + } + + None + } + pub fn find_workspace_by_name(&self, workspace_name: &str) -> Option<(usize, &Workspace)> { match &self.monitor_set { MonitorSet::Normal { ref monitors, .. } => { diff --git a/src/layout/workspace.rs b/src/layout/workspace.rs index 26d6a785..f85ec622 100644 --- a/src/layout/workspace.rs +++ b/src/layout/workspace.rs @@ -133,6 +133,10 @@ impl WorkspaceId { pub fn get(self) -> u64 { self.0 } + + pub fn specific(id: u64) -> Self { + Self(id) + } } niri_render_elements! { diff --git a/src/niri.rs b/src/niri.rs index ab5049a8..edd56466 100644 --- a/src/niri.rs +++ b/src/niri.rs @@ -115,6 +115,7 @@ use crate::input::{ apply_libinput_settings, mods_with_finger_scroll_binds, mods_with_wheel_binds, TabletData, }; use crate::ipc::server::IpcServer; +use crate::layout::workspace::WorkspaceId; use crate::layout::{Layout, LayoutElement as _, MonitorRenderElement}; use crate::protocols::foreign_toplevel::{self, ForeignToplevelManagerState}; use crate::protocols::gamma_control::GammaControlManagerState; @@ -2422,16 +2423,17 @@ impl Niri { &self, workspace_reference: WorkspaceReference, ) -> Option<(Option, usize)> { - let workspace_name = match workspace_reference { + let (target_workspace_index, target_workspace) = match workspace_reference { WorkspaceReference::Index(index) => { return Some((None, index.saturating_sub(1) as usize)); } - WorkspaceReference::Name(name) => name, + WorkspaceReference::Name(name) => self.layout.find_workspace_by_name(&name)?, + WorkspaceReference::Id(id) => { + let id = WorkspaceId::specific(id); + self.layout.find_workspace_by_id(id)? + } }; - let (target_workspace_index, target_workspace) = - self.layout.find_workspace_by_name(&workspace_name)?; - // FIXME: when we do fixes for no connected outputs, this will need fixing too. let active_workspace = self.layout.active_workspace()?; -- cgit