diff --git a/docs/cli/cancel-preselect.md b/docs/cli/cancel-preselect.md new file mode 100644 index 00000000..f0770633 --- /dev/null +++ b/docs/cli/cancel-preselect.md @@ -0,0 +1,12 @@ +# cancel-preselect + +``` +Cancel a workspace preselect set by the preselect-direction command, if one exists + +Usage: komorebic.exe cancel-preselect + +Options: + -h, --help + Print help + +``` diff --git a/komorebi/src/container.rs b/komorebi/src/container.rs index 2cd4651b..c2e5dd14 100644 --- a/komorebi/src/container.rs +++ b/komorebi/src/container.rs @@ -41,6 +41,18 @@ impl Lockable for Container { } impl Container { + pub fn preselect() -> Self { + Self { + id: "PRESELECT".to_string(), + locked: false, + windows: Default::default(), + } + } + + pub fn is_preselect(&self) -> bool { + self.id == "PRESELECT" + } + pub fn hide(&self, omit: Option) { for window in self.windows().iter().rev() { let mut should_hide = omit.is_none(); diff --git a/komorebi/src/core/mod.rs b/komorebi/src/core/mod.rs index 5cec545c..ff6eddf4 100644 --- a/komorebi/src/core/mod.rs +++ b/komorebi/src/core/mod.rs @@ -56,6 +56,7 @@ pub enum SocketMessage { FocusWindow(OperationDirection), MoveWindow(OperationDirection), PreselectDirection(OperationDirection), + CancelPreselect, CycleFocusWindow(CycleDirection), CycleMoveWindow(CycleDirection), StackWindow(OperationDirection), diff --git a/komorebi/src/process_command.rs b/komorebi/src/process_command.rs index fecc843e..b68eac28 100644 --- a/komorebi/src/process_command.rs +++ b/komorebi/src/process_command.rs @@ -305,9 +305,25 @@ impl WindowManager { } SocketMessage::PreselectDirection(direction) => { let focused_workspace = self.focused_workspace()?; - if matches!(focused_workspace.layer, WorkspaceLayer::Tiling) { + let mut update = false; + + if focused_workspace.preselected_container_idx.is_some() { + tracing::warn!( + "ignoring command as this workspace already has a direction preselect set" + ); + } else if matches!(focused_workspace.layer, WorkspaceLayer::Tiling) { self.preselect_container_in_direction(direction)?; + update = true; } + + if update { + self.focused_workspace_mut()?.update()?; + } + } + SocketMessage::CancelPreselect => { + let focused_workspace = self.focused_workspace_mut()?; + focused_workspace.cancel_preselect(); + focused_workspace.update()?; } SocketMessage::MoveWindow(direction) => { let focused_workspace = self.focused_workspace()?; diff --git a/komorebi/src/window_manager.rs b/komorebi/src/window_manager.rs index 7732781b..295294eb 100644 --- a/komorebi/src/window_manager.rs +++ b/komorebi/src/window_manager.rs @@ -2077,7 +2077,7 @@ impl WindowManager { _ => new_idx, }; - workspace.preselect_container_index(adjusted_idx); + workspace.preselect_container_idx(adjusted_idx); } None => { tracing::debug!( diff --git a/komorebi/src/workspace.rs b/komorebi/src/workspace.rs index 75049454..525f401d 100644 --- a/komorebi/src/workspace.rs +++ b/komorebi/src/workspace.rs @@ -449,7 +449,8 @@ impl Workspace { } // make sure we are never holding on to empty containers - self.containers_mut().retain(|c| !c.windows().is_empty()); + self.containers_mut() + .retain(|c| c.is_preselect() || !c.windows().is_empty()); let container_padding = self .container_padding @@ -979,8 +980,16 @@ impl Workspace { container } - pub fn preselect_container_index(&mut self, insertion_index: usize) { - self.preselected_container_idx = Some(insertion_index); + pub fn preselect_container_idx(&mut self, insertion_idx: usize) { + self.preselected_container_idx = Some(insertion_idx); + self.insert_container_at_idx(insertion_idx, Container::preselect()); + } + + pub fn cancel_preselect(&mut self) { + if let Some(idx) = self.preselected_container_idx { + self.containers_mut().remove_respecting_locks(idx); + self.preselected_container_idx = None; + } } pub fn new_idx_for_direction(&self, direction: OperationDirection) -> Option { @@ -1084,9 +1093,8 @@ impl Workspace { pub fn new_container_for_window(&mut self, window: Window) { let next_idx = if let Some(idx) = self.preselected_container_idx { let next = idx; - self.preselected_container_idx = None; - + self.remove_container_by_idx(next); next } else if self.containers().is_empty() { 0 diff --git a/komorebic/src/main.rs b/komorebic/src/main.rs index 060b0204..f8ec7ca9 100644 --- a/komorebic/src/main.rs +++ b/komorebic/src/main.rs @@ -1099,6 +1099,8 @@ enum SubCommand { /// Preselect the specified direction for the next window to be spawned on supported layouts #[clap(arg_required_else_help = true)] PreselectDirection(PreselectDirection), + /// Cancel a workspace preselect set by the preselect-direction command, if one exists + CancelPreselect, /// Minimize the focused window Minimize, /// Close the focused window @@ -2045,6 +2047,9 @@ fn main() -> eyre::Result<()> { SubCommand::PreselectDirection(arg) => { send_message(&SocketMessage::PreselectDirection(arg.operation_direction))?; } + SubCommand::CancelPreselect => { + send_message(&SocketMessage::CancelPreselect)?; + } SubCommand::CycleFocus(arg) => { send_message(&SocketMessage::CycleFocusWindow(arg.cycle_direction))?; } diff --git a/mkdocs.yml b/mkdocs.yml index 990546fd..8aaf7b1a 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -112,6 +112,7 @@ nav: - cli/focus.md - cli/move.md - cli/preselect-direction.md + - cli/cancel-preselect.md - cli/minimize.md - cli/close.md - cli/force-focus.md