Skip to content

Commit

Permalink
feat(wm): add right-main-vertical-stack layout
Browse files Browse the repository at this point in the history
This commit adds a new RightMainVerticalStack layout, adapting code from
the similarly named LeftWM layout.

It turns out that the horizontal axis flip on the VerticalStack does not
play well with resize offsets.

It was ultimately easier to implement this layout and the logic for
resizing both VerticalStack and RightMainVerticalStack independently
than to make resize offsets and horizontal axis flips work together.

I still have no idea why resize offsets and horizontal axis flips aren't
working properly together.

Horizontal axis flips have been disabled for both the VerticalStack and
RightMainVerticalStack layouts.

re #789
  • Loading branch information
LGUG2Z committed Apr 28, 2024
1 parent 0b04e3e commit 383533e
Show file tree
Hide file tree
Showing 4 changed files with 252 additions and 17 deletions.
163 changes: 153 additions & 10 deletions komorebi-core/src/arrangement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,8 @@ impl Arrangement for DefaultLayout {
_ => area.right / 2,
};

let mut main_left = area.left;
let mut stack_left = area.left + primary_right;

match layout_flip {
Some(Axis::Horizontal | Axis::HorizontalAndVertical) if len > 1 => {
main_left = main_left + area.right - primary_right;
stack_left = area.left;
}
_ => {}
}
let main_left = area.left;
let stack_left = area.left + primary_right;

if len >= 1 {
layouts.push(Rect {
Expand All @@ -86,6 +78,65 @@ impl Arrangement for DefaultLayout {
}
}

let adjustment = calculate_vertical_stack_adjustment(resize_dimensions);
layouts
.iter_mut()
.zip(adjustment.iter())
.for_each(|(layout, adjustment)| {
layout.top += adjustment.top;
layout.bottom += adjustment.bottom;
layout.left += adjustment.left;
layout.right += adjustment.right;
});

layouts
}
Self::RightMainVerticalStack => {
// Shamelessly borrowed from LeftWM: https://github.com/leftwm/leftwm/commit/f673851745295ae7584a102535566f559d96a941
let mut layouts: Vec<Rect> = vec![];

let primary_width = match len {
1 => area.right,
_ => area.right / 2,
};

let primary_left = match len {
1 => 0,
_ => area.right - primary_width,
};

if len >= 1 {
layouts.push(Rect {
left: area.left + primary_left,
top: area.top,
right: primary_width,
bottom: area.bottom,
});

if len > 1 {
layouts.append(&mut rows(
&Rect {
left: area.left,
top: area.top,
right: primary_left,
bottom: area.bottom,
},
len - 1,
));
}
}

let adjustment = calculate_right_vertical_stack_adjustment(resize_dimensions);
layouts
.iter_mut()
.zip(adjustment.iter())
.for_each(|(layout, adjustment)| {
layout.top += adjustment.top;
layout.bottom += adjustment.bottom;
layout.left += adjustment.left;
layout.right += adjustment.right;
});

layouts
}
Self::HorizontalStack => {
Expand Down Expand Up @@ -562,6 +613,98 @@ fn recursive_fibonacci(
}
}

fn calculate_vertical_stack_adjustment(resize_dimensions: &[Option<Rect>]) -> Vec<Rect> {
let len = resize_dimensions.len();
let mut result = vec![Rect::default(); len];
match len {
// One container can't be resized
0 | 1 => (),
_ => {
let (master, stack) = result.split_at_mut(1);
let primary = &mut master[0];

if let Some(resize) = resize_dimensions[0] {
resize_right(primary, resize.right);
for s in &mut *stack {
resize_left(s, resize.right);
}
}

// Handle stack on the right
for (i, rect) in resize_dimensions[1..].iter().enumerate() {
if let Some(rect) = rect {
resize_right(primary, rect.left);
stack
.iter_mut()
.for_each(|vertical_element| resize_left(vertical_element, rect.left));

// Containers in stack except first can be resized up displacing container
// above them
if i != 0 {
resize_bottom(&mut stack[i - 1], rect.top);
resize_top(&mut stack[i], rect.top);
}

// Containers in stack except last can be resized down displacing container
// below them
if i != stack.len() - 1 {
resize_bottom(&mut stack[i], rect.bottom);
resize_top(&mut stack[i + 1], rect.bottom);
}
}
}
}
};

result
}

fn calculate_right_vertical_stack_adjustment(resize_dimensions: &[Option<Rect>]) -> Vec<Rect> {
let len = resize_dimensions.len();
let mut result = vec![Rect::default(); len];
match len {
// One container can't be resized
0 | 1 => (),
_ => {
let (master, stack) = result.split_at_mut(1);
let primary = &mut master[0];

if let Some(resize) = resize_dimensions[0] {
resize_left(primary, resize.left);
for s in &mut *stack {
resize_right(s, resize.left);
}
}

// Handle stack on the left
for (i, rect) in resize_dimensions[1..].iter().enumerate() {
if let Some(rect) = rect {
resize_left(primary, rect.right);
stack
.iter_mut()
.for_each(|vertical_element| resize_right(vertical_element, rect.right));

// Containers in stack except first can be resized up displacing container
// above them
if i != 0 {
resize_bottom(&mut stack[i - 1], rect.top);
resize_top(&mut stack[i], rect.top);
}

// Containers in stack except last can be resized down displacing container
// below them
if i != stack.len() - 1 {
resize_bottom(&mut stack[i], rect.bottom);
resize_top(&mut stack[i + 1], rect.bottom);
}
}
}
}
};

result
}

fn calculate_ultrawide_adjustment(resize_dimensions: &[Option<Rect>]) -> Vec<Rect> {
let len = resize_dimensions.len();
let mut result = vec![Rect::default(); len];
Expand Down
15 changes: 12 additions & 3 deletions komorebi-core/src/default_layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pub enum DefaultLayout {
HorizontalStack,
UltrawideVerticalStack,
Grid,
RightMainVerticalStack,
// NOTE: If any new layout is added, please make sure to register the same in `DefaultLayout::cycle`
}

Expand All @@ -44,7 +45,13 @@ impl DefaultLayout {
sizing: Sizing,
delta: i32,
) -> Option<Rect> {
if !matches!(self, Self::BSP) && !matches!(self, Self::UltrawideVerticalStack) {
if !matches!(
self,
Self::BSP
| Self::UltrawideVerticalStack
| Self::VerticalStack
| Self::RightMainVerticalStack
) {
return None;
};

Expand Down Expand Up @@ -146,7 +153,8 @@ impl DefaultLayout {
Self::VerticalStack => Self::HorizontalStack,
Self::HorizontalStack => Self::UltrawideVerticalStack,
Self::UltrawideVerticalStack => Self::Grid,
Self::Grid => Self::BSP,
Self::Grid => Self::RightMainVerticalStack,
Self::RightMainVerticalStack => Self::BSP,
}
}

Expand All @@ -159,7 +167,8 @@ impl DefaultLayout {
Self::VerticalStack => Self::Rows,
Self::Rows => Self::Columns,
Self::Columns => Self::Grid,
Self::Grid => Self::BSP,
Self::Grid => Self::RightMainVerticalStack,
Self::RightMainVerticalStack => Self::BSP,
}
}
}
19 changes: 15 additions & 4 deletions komorebi-core/src/direction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,22 +95,23 @@ impl Direction for DefaultLayout {
Self::BSP => count > 2 && idx != 0 && idx != 1,
Self::Columns => false,
Self::Rows | Self::HorizontalStack => idx != 0,
Self::VerticalStack => idx != 0 && idx != 1,
Self::VerticalStack | Self::RightMainVerticalStack => idx != 0 && idx != 1,
Self::UltrawideVerticalStack => idx > 2,
Self::Grid => !is_grid_edge(op_direction, idx, count),
},
OperationDirection::Down => match self {
Self::BSP => count > 2 && idx != count - 1 && idx % 2 != 0,
Self::Columns => false,
Self::Rows => idx != count - 1,
Self::VerticalStack => idx != 0 && idx != count - 1,
Self::VerticalStack | Self::RightMainVerticalStack => idx != 0 && idx != count - 1,
Self::HorizontalStack => idx == 0,
Self::UltrawideVerticalStack => idx > 1 && idx != count - 1,
Self::Grid => !is_grid_edge(op_direction, idx, count),
},
OperationDirection::Left => match self {
Self::BSP => count > 1 && idx != 0,
Self::Columns | Self::VerticalStack => idx != 0,
Self::RightMainVerticalStack => idx == 0,
Self::Rows => false,
Self::HorizontalStack => idx != 0 && idx != 1,
Self::UltrawideVerticalStack => count > 1 && idx != 1,
Expand All @@ -121,6 +122,7 @@ impl Direction for DefaultLayout {
Self::Columns => idx != count - 1,
Self::Rows => false,
Self::VerticalStack => idx == 0,
Self::RightMainVerticalStack => idx != 0,
Self::HorizontalStack => idx != 0 && idx != count - 1,
Self::UltrawideVerticalStack => match count {
0 | 1 => false,
Expand All @@ -147,7 +149,10 @@ impl Direction for DefaultLayout {
}
}
Self::Columns => unreachable!(),
Self::Rows | Self::VerticalStack | Self::UltrawideVerticalStack => idx - 1,
Self::Rows
| Self::VerticalStack
| Self::UltrawideVerticalStack
| Self::RightMainVerticalStack => idx - 1,
Self::HorizontalStack => 0,
Self::Grid => grid_neighbor(op_direction, idx, count),
}
Expand All @@ -160,7 +165,11 @@ impl Direction for DefaultLayout {
count: Option<usize>,
) -> usize {
match self {
Self::BSP | Self::Rows | Self::VerticalStack | Self::UltrawideVerticalStack => idx + 1,
Self::BSP
| Self::Rows
| Self::VerticalStack
| Self::UltrawideVerticalStack
| Self::RightMainVerticalStack => idx + 1,
Self::Columns => unreachable!(),
Self::HorizontalStack => 1,
Self::Grid => grid_neighbor(op_direction, idx, count),
Expand All @@ -184,6 +193,7 @@ impl Direction for DefaultLayout {
Self::Columns | Self::HorizontalStack => idx - 1,
Self::Rows => unreachable!(),
Self::VerticalStack => 0,
Self::RightMainVerticalStack => 1,
Self::UltrawideVerticalStack => match idx {
0 => 1,
1 => unreachable!(),
Expand All @@ -203,6 +213,7 @@ impl Direction for DefaultLayout {
Self::BSP | Self::Columns | Self::HorizontalStack => idx + 1,
Self::Rows => unreachable!(),
Self::VerticalStack => 1,
Self::RightMainVerticalStack => 0,
Self::UltrawideVerticalStack => match idx {
1 => 0,
0 => 2,
Expand Down
72 changes: 72 additions & 0 deletions komorebi/src/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -894,6 +894,12 @@ impl Workspace {
fn enforce_resize_constraints(&mut self) {
match self.layout {
Layout::Default(DefaultLayout::BSP) => self.enforce_resize_constraints_for_bsp(),
Layout::Default(DefaultLayout::VerticalStack) => {
self.enforce_resize_for_vertical_stack()
}
Layout::Default(DefaultLayout::RightMainVerticalStack) => {
self.enforce_resize_for_right_vertical_stack()
}
Layout::Default(DefaultLayout::UltrawideVerticalStack) => {
self.enforce_resize_for_ultrawide();
}
Expand Down Expand Up @@ -927,6 +933,72 @@ impl Workspace {
}
}

fn enforce_resize_for_vertical_stack(&mut self) {
let resize_dimensions = self.resize_dimensions_mut();
match resize_dimensions.len() {
// Single window can not be resized at all
0 | 1 => self.enforce_no_resize(),
_ => {
// Zero is actually on the left
if let Some(mut left) = resize_dimensions[0] {
left.top = 0;
left.bottom = 0;
left.left = 0;
}

// Handle stack on the right
let stack_size = resize_dimensions[1..].len();
for (i, rect) in resize_dimensions[1..].iter_mut().enumerate() {
if let Some(rect) = rect {
// No containers can resize to the right
rect.right = 0;

// First container in stack cant resize up
if i == 0 {
rect.top = 0;
} else if i == stack_size - 1 {
// Last cant be resized to the bottom
rect.bottom = 0;
}
}
}
}
}
}

fn enforce_resize_for_right_vertical_stack(&mut self) {
let resize_dimensions = self.resize_dimensions_mut();
match resize_dimensions.len() {
// Single window can not be resized at all
0 | 1 => self.enforce_no_resize(),
_ => {
// Zero is actually on the right
if let Some(mut left) = resize_dimensions[1] {
left.top = 0;
left.bottom = 0;
left.right = 0;
}

// Handle stack on the right
let stack_size = resize_dimensions[1..].len();
for (i, rect) in resize_dimensions[1..].iter_mut().enumerate() {
if let Some(rect) = rect {
// No containers can resize to the left
rect.left = 0;

// First container in stack cant resize up
if i == 0 {
rect.top = 0;
} else if i == stack_size - 1 {
// Last cant be resized to the bottom
rect.bottom = 0;
}
}
}
}
}
}

fn enforce_resize_for_ultrawide(&mut self) {
let resize_dimensions = self.resize_dimensions_mut();
match resize_dimensions.len() {
Expand Down

0 comments on commit 383533e

Please sign in to comment.