From e9fb9297e9e9e96e0bf789ea43b076d1b76dca82 Mon Sep 17 00:00:00 2001 From: Kushashwa Ravi Shrimali Date: Fri, 27 Oct 2023 05:03:27 +0530 Subject: [PATCH] feat(cli): add cycle-layout command (#556) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Command to ToggleLayout * Just improve logic of figuring out next layout * Addr review: rename to "Cycle" instead of toggle, and add a small comment * As per review comments, implement cycle method on DefaultLayout * I forgot to remove this, my bad * feat(cli): fixups for cycle-layout cmd * Update komorebic/src/main.rs Co-authored-by: Kushashwa Ravi Shrimali --------- Co-authored-by: LGUG2Z Co-authored-by: جاد --- komorebi-core/src/default_layout.rs | 25 +++++++++++++++++++++++++ komorebi-core/src/lib.rs | 1 + komorebi/src/process_command.rs | 2 ++ komorebi/src/window_manager.rs | 23 +++++++++++++++++++++++ komorebic.lib.ahk | 4 ++++ komorebic/src/main.rs | 7 +++++++ 6 files changed, 62 insertions(+) diff --git a/komorebi-core/src/default_layout.rs b/komorebi-core/src/default_layout.rs index b49bf7acc..635bc1c4e 100644 --- a/komorebi-core/src/default_layout.rs +++ b/komorebi-core/src/default_layout.rs @@ -20,6 +20,7 @@ pub enum DefaultLayout { VerticalStack, HorizontalStack, UltrawideVerticalStack, + // NOTE: If any new layout is added, please make sure to register the same in `DefaultLayout::cycle` } impl DefaultLayout { @@ -125,4 +126,28 @@ impl DefaultLayout { Option::from(r) } } + + #[must_use] + pub const fn cycle_next(self) -> Self { + match self { + Self::BSP => Self::Columns, + Self::Columns => Self::Rows, + Self::Rows => Self::VerticalStack, + Self::VerticalStack => Self::HorizontalStack, + Self::HorizontalStack => Self::UltrawideVerticalStack, + Self::UltrawideVerticalStack => Self::BSP, + } + } + + #[must_use] + pub const fn cycle_previous(self) -> Self { + match self { + Self::BSP => Self::UltrawideVerticalStack, + Self::UltrawideVerticalStack => Self::HorizontalStack, + Self::HorizontalStack => Self::VerticalStack, + Self::VerticalStack => Self::Rows, + Self::Rows => Self::Columns, + Self::Columns => Self::BSP, + } + } } diff --git a/komorebi-core/src/lib.rs b/komorebi-core/src/lib.rs index a06a73b3b..ef59e9b72 100644 --- a/komorebi-core/src/lib.rs +++ b/komorebi-core/src/lib.rs @@ -77,6 +77,7 @@ pub enum SocketMessage { AdjustContainerPadding(Sizing, i32), AdjustWorkspacePadding(Sizing, i32), ChangeLayout(DefaultLayout), + CycleLayout(CycleDirection), ChangeLayoutCustom(PathBuf), FlipLayout(Axis), // Monitor and Workspace Commands diff --git a/komorebi/src/process_command.rs b/komorebi/src/process_command.rs index 1a0539b1c..7588650d4 100644 --- a/komorebi/src/process_command.rs +++ b/komorebi/src/process_command.rs @@ -448,6 +448,7 @@ impl WindowManager { SocketMessage::Retile => self.retile_all(false)?, SocketMessage::FlipLayout(layout_flip) => self.flip_layout(layout_flip)?, SocketMessage::ChangeLayout(layout) => self.change_workspace_layout_default(layout)?, + SocketMessage::CycleLayout(direction) => self.cycle_layout(direction)?, SocketMessage::ChangeLayoutCustom(ref path) => { self.change_workspace_custom_layout(path.clone())?; } @@ -1254,6 +1255,7 @@ impl WindowManager { match message { SocketMessage::ChangeLayout(_) + | SocketMessage::CycleLayout(_) | SocketMessage::ChangeLayoutCustom(_) | SocketMessage::FlipLayout(_) | SocketMessage::ManageFocusedWindow diff --git a/komorebi/src/window_manager.rs b/komorebi/src/window_manager.rs index 87af1eb88..25cac399c 100644 --- a/komorebi/src/window_manager.rs +++ b/komorebi/src/window_manager.rs @@ -1705,6 +1705,29 @@ impl WindowManager { self.update_focused_workspace(self.mouse_follows_focus) } + #[tracing::instrument(skip(self))] + pub fn cycle_layout(&mut self, direction: CycleDirection) -> Result<()> { + tracing::info!("cycling layout"); + + let workspace = self.focused_workspace_mut()?; + let current_layout = workspace.layout(); + + match current_layout { + Layout::Default(current) => { + let new_layout = match direction { + CycleDirection::Previous => current.cycle_previous(), + CycleDirection::Next => current.cycle_next(), + }; + + tracing::info!("next layout: {new_layout}"); + workspace.set_layout(Layout::Default(new_layout)); + } + Layout::Custom(_) => {} + } + + self.update_focused_workspace(self.mouse_follows_focus) + } + #[tracing::instrument(skip(self))] pub fn change_workspace_custom_layout(&mut self, path: PathBuf) -> Result<()> { tracing::info!("changing layout"); diff --git a/komorebic.lib.ahk b/komorebic.lib.ahk index febeea996..e1e279b4a 100644 --- a/komorebic.lib.ahk +++ b/komorebic.lib.ahk @@ -196,6 +196,10 @@ ChangeLayout(default_layout) { RunWait("komorebic.exe change-layout " default_layout, , "Hide") } +CycleLayout(operation_direction) { + RunWait("komorebic.exe cycle-layout " operation_direction, , "Hide") +} + LoadCustomLayout(path) { RunWait("komorebic.exe load-custom-layout " path, , "Hide") } diff --git a/komorebic/src/main.rs b/komorebic/src/main.rs index f2c4ed12c..b0516f80a 100644 --- a/komorebic/src/main.rs +++ b/komorebic/src/main.rs @@ -125,6 +125,7 @@ gen_enum_subcommand_args! { CycleStack: CycleDirection, FlipLayout: Axis, ChangeLayout: DefaultLayout, + CycleLayout: CycleDirection, WatchConfiguration: BooleanState, MouseFollowsFocus: BooleanState, Query: StateQuery, @@ -865,6 +866,9 @@ enum SubCommand { /// Set the layout on the focused workspace #[clap(arg_required_else_help = true)] ChangeLayout(ChangeLayout), + /// Cycle between available layouts + #[clap(arg_required_else_help = true)] + CycleLayout(CycleLayout), /// Load a custom layout from file for the focused workspace #[clap(arg_required_else_help = true)] LoadCustomLayout(LoadCustomLayout), @@ -1678,6 +1682,9 @@ Stop-Process -Name:whkd -ErrorAction SilentlyContinue SubCommand::ChangeLayout(arg) => { send_message(&SocketMessage::ChangeLayout(arg.default_layout).as_bytes()?)?; } + SubCommand::CycleLayout(arg) => { + send_message(&SocketMessage::CycleLayout(arg.cycle_direction).as_bytes()?)?; + } SubCommand::LoadCustomLayout(arg) => { send_message( &SocketMessage::ChangeLayoutCustom(resolve_windows_path(&arg.path)?).as_bytes()?,