From 2814349228e40ceb5f0ea46458149c38ca6f3189 Mon Sep 17 00:00:00 2001 From: LGUG2Z Date: Mon, 1 Nov 2021 15:53:01 -0700 Subject: [PATCH] feat(wm): add cmd to resize by axis This commit adds a new command to resize by axis. Resizing is still limited to the BSP layout. This command is intended to be bound to mouse wheel up and down events, with different modified keys determining the axis to operate on. --- komorebi-core/src/arrangement.rs | 24 ++++----- komorebi-core/src/lib.rs | 7 +-- komorebi-core/src/operation_direction.rs | 22 ++++---- komorebi/src/process_command.rs | 65 +++++++++++++++++++++++- komorebi/src/process_event.rs | 2 +- komorebi/src/window_manager.rs | 50 ++++++++++-------- komorebi/src/workspace.rs | 4 +- komorebic.lib.sample.ahk | 8 ++- komorebic/src/main.rs | 24 +++++++-- 9 files changed, 147 insertions(+), 59 deletions(-) diff --git a/komorebi-core/src/arrangement.rs b/komorebi-core/src/arrangement.rs index 657267c2..50c50315 100644 --- a/komorebi-core/src/arrangement.rs +++ b/komorebi-core/src/arrangement.rs @@ -19,7 +19,7 @@ pub trait Arrangement { area: &Rect, len: NonZeroUsize, container_padding: Option, - layout_flip: Option, + layout_flip: Option, resize_dimensions: &[Option], ) -> Vec; } @@ -31,7 +31,7 @@ impl Arrangement for DefaultLayout { area: &Rect, len: NonZeroUsize, container_padding: Option, - layout_flip: Option, + layout_flip: Option, resize_dimensions: &[Option], ) -> Vec { let len = usize::from(len); @@ -57,7 +57,7 @@ impl Arrangement for DefaultLayout { let mut stack_left = area.left + primary_right; match layout_flip { - Some(Flip::Horizontal | Flip::HorizontalAndVertical) if len > 1 => { + Some(Axis::Horizontal | Axis::HorizontalAndVertical) if len > 1 => { main_left = main_left + area.right - primary_right; stack_left = area.left; } @@ -99,7 +99,7 @@ impl Arrangement for DefaultLayout { let mut stack_top = area.top + bottom; match layout_flip { - Some(Flip::Vertical | Flip::HorizontalAndVertical) if len > 1 => { + Some(Axis::Vertical | Axis::HorizontalAndVertical) if len > 1 => { main_top = main_top + area.bottom - bottom; stack_top = area.top; } @@ -150,7 +150,7 @@ impl Arrangement for DefaultLayout { let mut secondary = area.left; match layout_flip { - Some(Flip::Horizontal | Flip::HorizontalAndVertical) if len > 1 => { + Some(Axis::Horizontal | Axis::HorizontalAndVertical) if len > 1 => { primary = area.left; secondary = area.left + primary_right; } @@ -165,7 +165,7 @@ impl Arrangement for DefaultLayout { let mut stack = area.left + primary_right + secondary_right; match layout_flip { - Some(Flip::Horizontal | Flip::HorizontalAndVertical) if len > 1 => { + Some(Axis::Horizontal | Axis::HorizontalAndVertical) if len > 1 => { secondary = area.left + primary_right + secondary_right; stack = area.left; } @@ -224,7 +224,7 @@ impl Arrangement for CustomLayout { area: &Rect, len: NonZeroUsize, container_padding: Option, - _layout_flip: Option, + _layout_flip: Option, _resize_dimensions: &[Option], ) -> Vec { let mut dimensions = vec![]; @@ -343,7 +343,7 @@ impl Arrangement for CustomLayout { #[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum)] #[strum(serialize_all = "snake_case")] -pub enum Flip { +pub enum Axis { Horizontal, Vertical, HorizontalAndVertical, @@ -478,7 +478,7 @@ fn recursive_fibonacci( idx: usize, count: usize, area: &Rect, - layout_flip: Option, + layout_flip: Option, resize_adjustments: Vec>, ) -> Vec { let mut a = *area; @@ -502,21 +502,21 @@ fn recursive_fibonacci( if let Some(flip) = layout_flip { match flip { - Flip::Horizontal => { + Axis::Horizontal => { main_x = resized.left + half_width + (half_width - half_resized_width); alt_x = resized.left; alt_y = resized.top + half_resized_height; main_y = resized.top; } - Flip::Vertical => { + Axis::Vertical => { main_y = resized.top + half_height + (half_height - half_resized_height); alt_y = resized.top; main_x = resized.left; alt_x = resized.left + half_resized_width; } - Flip::HorizontalAndVertical => { + Axis::HorizontalAndVertical => { main_x = resized.left + half_width + (half_width - half_resized_width); alt_x = resized.left; main_y = resized.top + half_height + (half_height - half_resized_height); diff --git a/komorebi-core/src/lib.rs b/komorebi-core/src/lib.rs index 699c10f4..2dc38f7e 100644 --- a/komorebi-core/src/lib.rs +++ b/komorebi-core/src/lib.rs @@ -12,7 +12,7 @@ use strum::Display; use strum::EnumString; pub use arrangement::Arrangement; -pub use arrangement::Flip; +pub use arrangement::Axis; pub use custom_layout::CustomLayout; pub use cycle_direction::CycleDirection; pub use default_layout::DefaultLayout; @@ -39,7 +39,8 @@ pub enum SocketMessage { CycleFocusWindow(CycleDirection), CycleMoveWindow(CycleDirection), StackWindow(OperationDirection), - ResizeWindow(OperationDirection, Sizing), + ResizeWindowEdge(OperationDirection, Sizing), + ResizeWindowAxis(Axis, Sizing), UnstackWindow, CycleStack(CycleDirection), MoveContainerToMonitorNumber(usize), @@ -57,7 +58,7 @@ pub enum SocketMessage { AdjustWorkspacePadding(Sizing, i32), ChangeLayout(DefaultLayout), ChangeLayoutCustom(PathBuf), - FlipLayout(Flip), + FlipLayout(Axis), // Monitor and Workspace Commands EnsureWorkspaces(usize, usize), NewWorkspace, diff --git a/komorebi-core/src/operation_direction.rs b/komorebi-core/src/operation_direction.rs index e4979fa7..8b7d7391 100644 --- a/komorebi-core/src/operation_direction.rs +++ b/komorebi-core/src/operation_direction.rs @@ -7,7 +7,7 @@ use strum::Display; use strum::EnumString; use crate::direction::Direction; -use crate::Flip; +use crate::Axis; #[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum)] #[strum(serialize_all = "snake_case")] @@ -29,23 +29,23 @@ impl OperationDirection { } } - fn flip(self, layout_flip: Option) -> Self { + fn flip(self, layout_flip: Option) -> Self { layout_flip.map_or(self, |flip| match self { Self::Left => match flip { - Flip::Horizontal | Flip::HorizontalAndVertical => Self::Right, - Flip::Vertical => self, + Axis::Horizontal | Axis::HorizontalAndVertical => Self::Right, + Axis::Vertical => self, }, Self::Right => match flip { - Flip::Horizontal | Flip::HorizontalAndVertical => Self::Left, - Flip::Vertical => self, + Axis::Horizontal | Axis::HorizontalAndVertical => Self::Left, + Axis::Vertical => self, }, Self::Up => match flip { - Flip::Vertical | Flip::HorizontalAndVertical => Self::Down, - Flip::Horizontal => self, + Axis::Vertical | Axis::HorizontalAndVertical => Self::Down, + Axis::Horizontal => self, }, Self::Down => match flip { - Flip::Vertical | Flip::HorizontalAndVertical => Self::Up, - Flip::Horizontal => self, + Axis::Vertical | Axis::HorizontalAndVertical => Self::Up, + Axis::Horizontal => self, }, }) } @@ -54,7 +54,7 @@ impl OperationDirection { pub fn destination( self, layout: &dyn Direction, - layout_flip: Option, + layout_flip: Option, idx: usize, len: NonZeroUsize, ) -> Option { diff --git a/komorebi/src/process_command.rs b/komorebi/src/process_command.rs index e017e91e..e9e30992 100644 --- a/komorebi/src/process_command.rs +++ b/komorebi/src/process_command.rs @@ -15,7 +15,9 @@ use miow::pipe::connect; use parking_lot::Mutex; use uds_windows::UnixStream; +use komorebi_core::Axis; use komorebi_core::FocusFollowsMouseImplementation; +use komorebi_core::OperationDirection; use komorebi_core::Rect; use komorebi_core::SocketMessage; use komorebi_core::StateQuery; @@ -260,8 +262,67 @@ impl WindowManager { let mut stream = UnixStream::connect(&socket)?; stream.write_all(response.as_bytes())?; } - SocketMessage::ResizeWindow(direction, sizing) => { - self.resize_window(direction, sizing, Option::from(50))?; + SocketMessage::ResizeWindowEdge(direction, sizing) => { + self.resize_window(direction, sizing, Option::from(50), true)?; + } + SocketMessage::ResizeWindowAxis(axis, sizing) => { + match axis { + Axis::Horizontal => { + self.resize_window( + OperationDirection::Left, + sizing, + Option::from(50), + false, + )?; + self.resize_window( + OperationDirection::Right, + sizing, + Option::from(50), + false, + )?; + } + Axis::Vertical => { + self.resize_window( + OperationDirection::Up, + sizing, + Option::from(50), + false, + )?; + self.resize_window( + OperationDirection::Down, + sizing, + Option::from(50), + false, + )?; + } + Axis::HorizontalAndVertical => { + self.resize_window( + OperationDirection::Left, + sizing, + Option::from(50), + false, + )?; + self.resize_window( + OperationDirection::Right, + sizing, + Option::from(50), + false, + )?; + self.resize_window( + OperationDirection::Up, + sizing, + Option::from(50), + false, + )?; + self.resize_window( + OperationDirection::Down, + sizing, + Option::from(50), + false, + )?; + } + } + self.update_focused_workspace(false)?; } SocketMessage::FocusFollowsMouse(mut implementation, enable) => { if !CUSTOM_FFM.load(Ordering::SeqCst) { diff --git a/komorebi/src/process_event.rs b/komorebi/src/process_event.rs index 07394527..c24e8514 100644 --- a/komorebi/src/process_event.rs +++ b/komorebi/src/process_event.rs @@ -384,7 +384,7 @@ impl WindowManager { } for (edge, sizing, step) in ops { - self.resize_window(edge, sizing, Option::from(step))?; + self.resize_window(edge, sizing, Option::from(step), true)?; } self.update_focused_workspace(false)?; diff --git a/komorebi/src/window_manager.rs b/komorebi/src/window_manager.rs index e7c44d09..38ab0e57 100644 --- a/komorebi/src/window_manager.rs +++ b/komorebi/src/window_manager.rs @@ -16,9 +16,9 @@ use uds_windows::UnixListener; use komorebi_core::custom_layout::CustomLayout; use komorebi_core::Arrangement; +use komorebi_core::Axis; use komorebi_core::CycleDirection; use komorebi_core::DefaultLayout; -use komorebi_core::Flip; use komorebi_core::FocusFollowsMouseImplementation; use komorebi_core::Layout; use komorebi_core::OperationDirection; @@ -677,6 +677,7 @@ impl WindowManager { direction: OperationDirection, sizing: Sizing, step: Option, + update: bool, ) -> Result<()> { let work_area = self.focused_monitor_work_area()?; let workspace = self.focused_workspace_mut()?; @@ -715,21 +716,21 @@ impl WindowManager { // can flip them however they need to be flipped once the resizing has been done if let Some(flip) = workspace.layout_flip() { match flip { - Flip::Horizontal => { + Axis::Horizontal => { if matches!(direction, OperationDirection::Left) || matches!(direction, OperationDirection::Right) { direction = direction.opposite(); } } - Flip::Vertical => { + Axis::Vertical => { if matches!(direction, OperationDirection::Up) || matches!(direction, OperationDirection::Down) { direction = direction.opposite(); } } - Flip::HorizontalAndVertical => direction = direction.opposite(), + Axis::HorizontalAndVertical => direction = direction.opposite(), } } @@ -744,7 +745,12 @@ impl WindowManager { ); workspace.resize_dimensions_mut()[focused_idx] = resize; - return self.update_focused_workspace(false); + + return if update { + self.update_focused_workspace(false) + } else { + Ok(()) + }; } tracing::warn!("cannot resize container in this direction"); @@ -1085,7 +1091,7 @@ impl WindowManager { } #[tracing::instrument(skip(self))] - pub fn flip_layout(&mut self, layout_flip: Flip) -> Result<()> { + pub fn flip_layout(&mut self, layout_flip: Axis) -> Result<()> { tracing::info!("flipping layout"); let workspace = self.focused_workspace_mut()?; @@ -1097,28 +1103,28 @@ impl WindowManager { } Some(current_layout_flip) => { match current_layout_flip { - Flip::Horizontal => match layout_flip { - Flip::Horizontal => workspace.set_layout_flip(None), - Flip::Vertical => { - workspace.set_layout_flip(Option::from(Flip::HorizontalAndVertical)) + Axis::Horizontal => match layout_flip { + Axis::Horizontal => workspace.set_layout_flip(None), + Axis::Vertical => { + workspace.set_layout_flip(Option::from(Axis::HorizontalAndVertical)) } - Flip::HorizontalAndVertical => { - workspace.set_layout_flip(Option::from(Flip::HorizontalAndVertical)) + Axis::HorizontalAndVertical => { + workspace.set_layout_flip(Option::from(Axis::HorizontalAndVertical)) } }, - Flip::Vertical => match layout_flip { - Flip::Horizontal => { - workspace.set_layout_flip(Option::from(Flip::HorizontalAndVertical)) + Axis::Vertical => match layout_flip { + Axis::Horizontal => { + workspace.set_layout_flip(Option::from(Axis::HorizontalAndVertical)) } - Flip::Vertical => workspace.set_layout_flip(None), - Flip::HorizontalAndVertical => { - workspace.set_layout_flip(Option::from(Flip::HorizontalAndVertical)) + Axis::Vertical => workspace.set_layout_flip(None), + Axis::HorizontalAndVertical => { + workspace.set_layout_flip(Option::from(Axis::HorizontalAndVertical)) } }, - Flip::HorizontalAndVertical => match layout_flip { - Flip::Horizontal => workspace.set_layout_flip(Option::from(Flip::Vertical)), - Flip::Vertical => workspace.set_layout_flip(Option::from(Flip::Horizontal)), - Flip::HorizontalAndVertical => workspace.set_layout_flip(None), + Axis::HorizontalAndVertical => match layout_flip { + Axis::Horizontal => workspace.set_layout_flip(Option::from(Axis::Vertical)), + Axis::Vertical => workspace.set_layout_flip(Option::from(Axis::Horizontal)), + Axis::HorizontalAndVertical => workspace.set_layout_flip(None), }, }; } diff --git a/komorebi/src/workspace.rs b/komorebi/src/workspace.rs index 75ad8f7b..31661a98 100644 --- a/komorebi/src/workspace.rs +++ b/komorebi/src/workspace.rs @@ -9,9 +9,9 @@ use getset::MutGetters; use getset::Setters; use serde::Serialize; +use komorebi_core::Axis; use komorebi_core::CycleDirection; use komorebi_core::DefaultLayout; -use komorebi_core::Flip; use komorebi_core::Layout; use komorebi_core::OperationDirection; use komorebi_core::Rect; @@ -41,7 +41,7 @@ pub struct Workspace { #[getset(get = "pub", set = "pub")] layout: Layout, #[getset(get_copy = "pub", set = "pub")] - layout_flip: Option, + layout_flip: Option, #[getset(get_copy = "pub", set = "pub")] workspace_padding: Option, #[getset(get_copy = "pub", set = "pub")] diff --git a/komorebic.lib.sample.ahk b/komorebic.lib.sample.ahk index c43d873c..948ff544 100644 --- a/komorebic.lib.sample.ahk +++ b/komorebic.lib.sample.ahk @@ -68,6 +68,10 @@ Resize(edge, sizing) { Run, komorebic.exe resize %edge% %sizing%, , Hide } +ResizeAxis(axis, sizing) { + Run, komorebic.exe resize-axis %axis% %sizing%, , Hide +} + Unstack() { Run, komorebic.exe unstack, , Hide } @@ -136,8 +140,8 @@ LoadCustomLayout(path) { Run, komorebic.exe load-custom-layout %path%, , Hide } -FlipLayout(flip) { - Run, komorebic.exe flip-layout %flip%, , Hide +FlipLayout(axis) { + Run, komorebic.exe flip-layout %axis%, , Hide } Promote() { diff --git a/komorebic/src/main.rs b/komorebic/src/main.rs index 905e6817..117ef5fc 100644 --- a/komorebic/src/main.rs +++ b/komorebic/src/main.rs @@ -28,9 +28,9 @@ use windows::Win32::UI::WindowsAndMessaging::SW_RESTORE; use derive_ahk::AhkFunction; use derive_ahk::AhkLibrary; use komorebi_core::ApplicationIdentifier; +use komorebi_core::Axis; use komorebi_core::CycleDirection; use komorebi_core::DefaultLayout; -use komorebi_core::Flip; use komorebi_core::FocusFollowsMouseImplementation; use komorebi_core::OperationDirection; use komorebi_core::Rect; @@ -85,7 +85,7 @@ gen_enum_subcommand_args! { CycleWorkspace: CycleDirection, Stack: OperationDirection, CycleStack: CycleDirection, - FlipLayout: Flip, + FlipLayout: Axis, ChangeLayout: DefaultLayout, WatchConfiguration: BooleanState, MouseFollowsFocus: BooleanState, @@ -168,6 +168,14 @@ struct Resize { sizing: Sizing, } +#[derive(Parser, AhkFunction)] +struct ResizeAxis { + #[clap(arg_enum)] + axis: Axis, + #[clap(arg_enum)] + sizing: Sizing, +} + #[derive(Parser, AhkFunction)] struct InvisibleBorders { /// Size of the left invisible border @@ -381,6 +389,9 @@ enum SubCommand { /// Resize the focused window in the specified direction #[clap(setting = AppSettings::ArgRequiredElseHelp)] Resize(Resize), + /// Resize the focused window along the specified axis + #[clap(setting = AppSettings::ArgRequiredElseHelp)] + ResizeAxis(ResizeAxis), /// Unstack the focused window Unstack, /// Cycle the focused stack in the specified cycle direction @@ -757,7 +768,7 @@ fn main() -> Result<()> { )?; } SubCommand::FlipLayout(arg) => { - send_message(&*SocketMessage::FlipLayout(arg.flip).as_bytes()?)?; + send_message(&*SocketMessage::FlipLayout(arg.axis).as_bytes()?)?; } SubCommand::FocusMonitor(arg) => { send_message(&*SocketMessage::FocusMonitorNumber(arg.target).as_bytes()?)?; @@ -868,7 +879,12 @@ fn main() -> Result<()> { } } SubCommand::Resize(resize) => { - send_message(&*SocketMessage::ResizeWindow(resize.edge, resize.sizing).as_bytes()?)?; + send_message( + &*SocketMessage::ResizeWindowEdge(resize.edge, resize.sizing).as_bytes()?, + )?; + } + SubCommand::ResizeAxis(arg) => { + send_message(&*SocketMessage::ResizeWindowAxis(arg.axis, arg.sizing).as_bytes()?)?; } SubCommand::FocusFollowsMouse(arg) => { send_message(