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(