From 21bd09e41937eff3a2dfb2651270ae54ab3cf9b0 Mon Sep 17 00:00:00 2001 From: LGUG2Z Date: Tue, 24 Sep 2024 10:07:51 -0700 Subject: [PATCH] fix(wm): add layout edge index awareness This commit builds on c3f135703eb4ea1263311e509af2afb897662030 and 1080159e6896bfffd2fc3782fdd175f5f56aa3f0 to add layout-specific edge index awareness to all default layouts. This is most useful for UltrawideVerticalStack and RightMostVerticalStack, which have a lot of edge cases due to the positioning of the 0th index changing with the number of containers on a workspace. --- komorebi/src/core/default_layout.rs | 31 +++++++ komorebi/src/monitor.rs | 52 +++++++++++- komorebi/src/window_manager.rs | 122 +++++++++++++++++++++++----- komorebi/src/workspace.rs | 1 + 4 files changed, 180 insertions(+), 26 deletions(-) diff --git a/komorebi/src/core/default_layout.rs b/komorebi/src/core/default_layout.rs index 58282791..3adef583 100644 --- a/komorebi/src/core/default_layout.rs +++ b/komorebi/src/core/default_layout.rs @@ -35,6 +35,37 @@ pub enum DefaultLayout { } impl DefaultLayout { + pub fn leftmost_index(&self, len: usize) -> usize { + match self { + Self::UltrawideVerticalStack | Self::RightMainVerticalStack => match len { + n if n > 1 => 1, + _ => 0, + }, + DefaultLayout::BSP + | DefaultLayout::Columns + | DefaultLayout::Rows + | DefaultLayout::VerticalStack + | DefaultLayout::HorizontalStack + | DefaultLayout::Grid => 0, + } + } + + pub fn rightmost_index(&self, len: usize) -> usize { + match self { + DefaultLayout::BSP + | DefaultLayout::Columns + | DefaultLayout::Rows + | DefaultLayout::VerticalStack + | DefaultLayout::HorizontalStack + | DefaultLayout::Grid => len.saturating_sub(1), + DefaultLayout::UltrawideVerticalStack => match len { + 2 => 0, + _ => len.saturating_sub(1), + }, + DefaultLayout::RightMainVerticalStack => 0, + } + } + #[must_use] #[allow(clippy::cast_precision_loss, clippy::only_used_in_recursion)] pub fn resize( diff --git a/komorebi/src/monitor.rs b/komorebi/src/monitor.rs index e7dee59e..090fe7ee 100644 --- a/komorebi/src/monitor.rs +++ b/komorebi/src/monitor.rs @@ -17,6 +17,8 @@ use crate::core::Rect; use crate::container::Container; use crate::ring::Ring; use crate::workspace::Workspace; +use crate::DefaultLayout; +use crate::Layout; use crate::OperationDirection; #[derive( @@ -191,10 +193,52 @@ impl Monitor { Some(workspace) => workspace, }; - if matches!(direction, Some(OperationDirection::Right)) { - target_workspace.add_container_to_front(container); - } else { - target_workspace.add_container_to_back(container); + match direction { + Some(OperationDirection::Left) => match target_workspace.layout() { + Layout::Default(layout) => match layout { + DefaultLayout::RightMainVerticalStack => { + target_workspace.add_container_to_front(container); + } + DefaultLayout::UltrawideVerticalStack => { + if target_workspace.containers().len() == 1 { + target_workspace.insert_container_at_idx(0, container); + } else { + target_workspace.add_container_to_back(container); + } + } + _ => { + target_workspace.add_container_to_back(container); + } + }, + Layout::Custom(_) => { + target_workspace.add_container_to_back(container); + } + }, + Some(OperationDirection::Right) => match target_workspace.layout() { + Layout::Default(layout) => { + let target_index = layout.leftmost_index(target_workspace.containers().len()); + + match layout { + DefaultLayout::RightMainVerticalStack + | DefaultLayout::UltrawideVerticalStack => { + if target_workspace.containers().len() == 1 { + target_workspace.add_container_to_back(container); + } else { + target_workspace.insert_container_at_idx(target_index, container); + } + } + _ => { + target_workspace.insert_container_at_idx(target_index, container); + } + } + } + Layout::Custom(_) => { + target_workspace.add_container_to_front(container); + } + }, + _ => { + target_workspace.add_container_to_back(container); + } } if follow { diff --git a/komorebi/src/window_manager.rs b/komorebi/src/window_manager.rs index 99d33079..02051002 100644 --- a/komorebi/src/window_manager.rs +++ b/komorebi/src/window_manager.rs @@ -1293,14 +1293,28 @@ impl WindowManager { if let Ok(focused_workspace) = self.focused_workspace_mut() { if focused_workspace.monocle_container().is_none() { match direction { - OperationDirection::Left => { - focused_workspace.focus_container( - focused_workspace.containers().len().saturating_sub(1), - ); - } - OperationDirection::Right => { - focused_workspace.focus_container(0); - } + OperationDirection::Left => match focused_workspace.layout() { + Layout::Default(layout) => { + let target_index = + layout.rightmost_index(focused_workspace.containers().len()); + focused_workspace.focus_container(target_index); + } + Layout::Custom(_) => { + focused_workspace.focus_container( + focused_workspace.containers().len().saturating_sub(1), + ); + } + }, + OperationDirection::Right => match focused_workspace.layout() { + Layout::Default(layout) => { + let target_index = + layout.leftmost_index(focused_workspace.containers().len()); + focused_workspace.focus_container(target_index); + } + Layout::Custom(_) => { + focused_workspace.focus_container(0); + } + }, _ => {} }; } @@ -1331,14 +1345,28 @@ impl WindowManager { } } else { match direction { - OperationDirection::Left => { - focused_workspace.focus_container( - focused_workspace.containers().len().saturating_sub(1), - ); - } - OperationDirection::Right => { - focused_workspace.focus_container(0); - } + OperationDirection::Left => match focused_workspace.layout() { + Layout::Default(layout) => { + let target_index = layout + .rightmost_index(focused_workspace.containers().len()); + focused_workspace.focus_container(target_index); + } + Layout::Custom(_) => { + focused_workspace.focus_container( + focused_workspace.containers().len().saturating_sub(1), + ); + } + }, + OperationDirection::Right => match focused_workspace.layout() { + Layout::Default(layout) => { + let target_index = + layout.leftmost_index(focused_workspace.containers().len()); + focused_workspace.focus_container(target_index); + } + Layout::Custom(_) => { + focused_workspace.focus_container(0); + } + }, _ => {} }; } @@ -1460,15 +1488,65 @@ impl WindowManager { match direction { OperationDirection::Left => { // insert the origin container into the focused workspace on the target monitor - // at the back if we are moving across a boundary to the left (back = right side - // of the target) - target_workspace.add_container_to_back(origin_container); + // at the back (or rightmost position) if we are moving across a boundary to + // the left (back = right side of the target) + match target_workspace.layout() { + Layout::Default(layout) => match layout { + DefaultLayout::RightMainVerticalStack => { + target_workspace.add_container_to_front(origin_container); + } + DefaultLayout::UltrawideVerticalStack => { + if target_workspace.containers().len() == 1 { + target_workspace + .insert_container_at_idx(0, origin_container); + } else { + target_workspace + .add_container_to_back(origin_container); + } + } + _ => { + target_workspace.add_container_to_back(origin_container); + } + }, + Layout::Custom(_) => { + target_workspace.add_container_to_back(origin_container); + } + } } OperationDirection::Right => { // insert the origin container into the focused workspace on the target monitor - // at the front if we are moving across a boundary to the right (front = left side - // of the target) - target_workspace.add_container_to_front(origin_container); + // at the front (or leftmost position) if we are moving across a boundary to the + // right (front = left side of the target) + match target_workspace.layout() { + Layout::Default(layout) => { + let target_index = + layout.leftmost_index(target_workspace.containers().len()); + + match layout { + DefaultLayout::RightMainVerticalStack + | DefaultLayout::UltrawideVerticalStack => { + if target_workspace.containers().len() == 1 { + target_workspace + .add_container_to_back(origin_container); + } else { + target_workspace.insert_container_at_idx( + target_index, + origin_container, + ); + } + } + _ => { + target_workspace.insert_container_at_idx( + target_index, + origin_container, + ); + } + } + } + Layout::Custom(_) => { + target_workspace.add_container_to_front(origin_container); + } + } } OperationDirection::Up | OperationDirection::Down => { // insert the origin container into the focused workspace on the target monitor diff --git a/komorebi/src/workspace.rs b/komorebi/src/workspace.rs index 63dc582d..37f1b01e 100644 --- a/komorebi/src/workspace.rs +++ b/komorebi/src/workspace.rs @@ -668,6 +668,7 @@ impl Workspace { pub fn insert_container_at_idx(&mut self, idx: usize, container: Container) { self.containers_mut().insert(idx, container); + self.focus_container(idx); } pub fn remove_container_by_idx(&mut self, idx: usize) -> Option {