Skip to content

Commit

Permalink
fix(wm): add layout edge index awareness
Browse files Browse the repository at this point in the history
This commit builds on c3f1357 and
1080159 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.
  • Loading branch information
LGUG2Z committed Sep 24, 2024
1 parent 01ccf70 commit df7a1fd
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 26 deletions.
32 changes: 32 additions & 0 deletions komorebi/src/core/default_layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,38 @@ 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 | DefaultLayout::RightMainVerticalStack => {
match len {
2 => 0,
_ => len.saturating_sub(1),
}
}
}
}

#[must_use]
#[allow(clippy::cast_precision_loss, clippy::only_used_in_recursion)]
pub fn resize(
Expand Down
50 changes: 46 additions & 4 deletions komorebi/src/monitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -191,10 +193,50 @@ 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::UltrawideVerticalStack
| DefaultLayout::RightMainVerticalStack => {
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 {
Expand Down
120 changes: 98 additions & 22 deletions komorebi/src/window_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
},
_ => {}
};
}
Expand Down Expand Up @@ -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);
}
},
_ => {}
};
}
Expand Down Expand Up @@ -1460,15 +1488,63 @@ 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::UltrawideVerticalStack
| DefaultLayout::RightMainVerticalStack => {
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
Expand Down
1 change: 1 addition & 0 deletions komorebi/src/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Container> {
Expand Down

0 comments on commit df7a1fd

Please sign in to comment.