mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-03-23 09:51:16 +01:00
feat(wm): ultrawide layout resizing (#545)
* Allow different resize constraints for layouts Change Workspace::enforce_resize_constraints to enforce constraints differently for different layouts Add enforce_no_resize method for all but bsp layout resize_dimensions * Add resize constraints for UltrawideVerticalStack layout Add Workspace::enforce_resize_for_ultrawide method to apply resize constraints for ultrawide vertical stack layout. * feat(wm): Use resize_dimensions in calculate for ultrawide layout Add function calculate_ultrawide_adjustment to calculate adjustments for individual containers in ultrawide vertical stack layout Refactor ultrawide layout generation in separate function and use calculated adjustments * feat(wm): Enable ultrawide layout in DefaultLayout::resize * feat(wm): refactor ultrawide resize calculation Add some helper function and descriptive variable names in calculate_ultrawide_adjustment Apply clippy lints
This commit is contained in:
@@ -130,85 +130,7 @@ impl Arrangement for DefaultLayout {
|
||||
|
||||
layouts
|
||||
}
|
||||
Self::UltrawideVerticalStack => {
|
||||
let mut layouts: Vec<Rect> = vec![];
|
||||
|
||||
let primary_right = match len {
|
||||
1 => area.right,
|
||||
_ => area.right / 2,
|
||||
};
|
||||
|
||||
let secondary_right = match len {
|
||||
1 => 0,
|
||||
2 => area.right - primary_right,
|
||||
_ => (area.right - primary_right) / 2,
|
||||
};
|
||||
|
||||
let (primary_left, secondary_left, stack_left) = match len {
|
||||
1 => (area.left, 0, 0),
|
||||
2 => {
|
||||
let mut primary = area.left + secondary_right;
|
||||
let mut secondary = area.left;
|
||||
|
||||
match layout_flip {
|
||||
Some(Axis::Horizontal | Axis::HorizontalAndVertical) if len > 1 => {
|
||||
primary = area.left;
|
||||
secondary = area.left + primary_right;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
(primary, secondary, 0)
|
||||
}
|
||||
_ => {
|
||||
let primary = area.left + secondary_right;
|
||||
let mut secondary = area.left;
|
||||
let mut stack = area.left + primary_right + secondary_right;
|
||||
|
||||
match layout_flip {
|
||||
Some(Axis::Horizontal | Axis::HorizontalAndVertical) if len > 1 => {
|
||||
secondary = area.left + primary_right + secondary_right;
|
||||
stack = area.left;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
(primary, secondary, stack)
|
||||
}
|
||||
};
|
||||
|
||||
if len >= 1 {
|
||||
layouts.push(Rect {
|
||||
left: primary_left,
|
||||
top: area.top,
|
||||
right: primary_right,
|
||||
bottom: area.bottom,
|
||||
});
|
||||
|
||||
if len >= 2 {
|
||||
layouts.push(Rect {
|
||||
left: secondary_left,
|
||||
top: area.top,
|
||||
right: secondary_right,
|
||||
bottom: area.bottom,
|
||||
});
|
||||
|
||||
if len > 2 {
|
||||
layouts.append(&mut rows(
|
||||
&Rect {
|
||||
left: stack_left,
|
||||
top: area.top,
|
||||
right: secondary_right,
|
||||
bottom: area.bottom,
|
||||
},
|
||||
len - 2,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
layouts
|
||||
}
|
||||
Self::UltrawideVerticalStack => ultrawide(area, len, layout_flip, resize_dimensions),
|
||||
};
|
||||
|
||||
dimensions
|
||||
@@ -586,3 +508,190 @@ fn recursive_fibonacci(
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
fn calculate_ultrawide_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 => (),
|
||||
2 => {
|
||||
let (primary, secondary) = result.split_at_mut(1);
|
||||
let primary = &mut primary[0];
|
||||
let secondary = &mut secondary[0];
|
||||
// With two containers on screen container 0 is on the right
|
||||
if let Some(resize_primary) = resize_dimensions[0] {
|
||||
resize_left(primary, resize_primary.left);
|
||||
resize_right(secondary, resize_primary.left);
|
||||
}
|
||||
|
||||
if let Some(resize_secondary) = resize_dimensions[1] {
|
||||
resize_left(primary, resize_secondary.right);
|
||||
resize_right(secondary, resize_secondary.right);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let (primary, rest) = result.split_at_mut(1);
|
||||
let (secondary, tertiary) = rest.split_at_mut(1);
|
||||
let primary = &mut primary[0];
|
||||
let secondary = &mut secondary[0];
|
||||
// With three or more containers container 0 is in the center
|
||||
if let Some(resize_primary) = resize_dimensions[0] {
|
||||
resize_left(primary, resize_primary.left);
|
||||
resize_right(primary, resize_primary.right);
|
||||
|
||||
resize_right(secondary, resize_primary.left);
|
||||
|
||||
for vertical_element in &mut *tertiary {
|
||||
resize_left(vertical_element, resize_primary.right);
|
||||
}
|
||||
}
|
||||
|
||||
// Container 1 is on the left
|
||||
if let Some(resize_secondary) = resize_dimensions[1] {
|
||||
resize_left(primary, resize_secondary.right);
|
||||
resize_right(secondary, resize_secondary.right);
|
||||
}
|
||||
|
||||
// Handle stack on the right
|
||||
for (i, rect) in resize_dimensions[2..].iter().enumerate() {
|
||||
if let Some(rect) = rect {
|
||||
resize_right(primary, rect.left);
|
||||
tertiary
|
||||
.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 tertiary[i - 1], rect.top);
|
||||
resize_top(&mut tertiary[i], rect.top);
|
||||
}
|
||||
|
||||
// Containers in stack except last can be resized down displacing container
|
||||
// below them
|
||||
if i != tertiary.len() - 1 {
|
||||
resize_bottom(&mut tertiary[i], rect.bottom);
|
||||
resize_top(&mut tertiary[i + 1], rect.bottom);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
fn resize_left(rect: &mut Rect, resize: i32) {
|
||||
rect.left += resize / 2;
|
||||
rect.right += -resize / 2;
|
||||
}
|
||||
|
||||
fn resize_right(rect: &mut Rect, resize: i32) {
|
||||
rect.right += resize / 2;
|
||||
}
|
||||
|
||||
fn resize_top(rect: &mut Rect, resize: i32) {
|
||||
rect.top += resize / 2;
|
||||
rect.bottom += -resize / 2;
|
||||
}
|
||||
|
||||
fn resize_bottom(rect: &mut Rect, resize: i32) {
|
||||
rect.bottom += resize / 2;
|
||||
}
|
||||
|
||||
fn ultrawide(
|
||||
area: &Rect,
|
||||
len: usize,
|
||||
layout_flip: Option<Axis>,
|
||||
resize_dimensions: &[Option<Rect>],
|
||||
) -> Vec<Rect> {
|
||||
let mut layouts: Vec<Rect> = vec![];
|
||||
|
||||
let primary_right = match len {
|
||||
1 => area.right,
|
||||
_ => area.right / 2,
|
||||
};
|
||||
|
||||
let secondary_right = match len {
|
||||
1 => 0,
|
||||
2 => area.right - primary_right,
|
||||
_ => (area.right - primary_right) / 2,
|
||||
};
|
||||
|
||||
let (primary_left, secondary_left, stack_left) = match len {
|
||||
1 => (area.left, 0, 0),
|
||||
2 => {
|
||||
let mut primary = area.left + secondary_right;
|
||||
let mut secondary = area.left;
|
||||
|
||||
match layout_flip {
|
||||
Some(Axis::Horizontal | Axis::HorizontalAndVertical) if len > 1 => {
|
||||
primary = area.left;
|
||||
secondary = area.left + primary_right;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
(primary, secondary, 0)
|
||||
}
|
||||
_ => {
|
||||
let primary = area.left + secondary_right;
|
||||
let mut secondary = area.left;
|
||||
let mut stack = area.left + primary_right + secondary_right;
|
||||
|
||||
match layout_flip {
|
||||
Some(Axis::Horizontal | Axis::HorizontalAndVertical) if len > 1 => {
|
||||
secondary = area.left + primary_right + secondary_right;
|
||||
stack = area.left;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
(primary, secondary, stack)
|
||||
}
|
||||
};
|
||||
|
||||
if len >= 1 {
|
||||
layouts.push(Rect {
|
||||
left: primary_left,
|
||||
top: area.top,
|
||||
right: primary_right,
|
||||
bottom: area.bottom,
|
||||
});
|
||||
|
||||
if len >= 2 {
|
||||
layouts.push(Rect {
|
||||
left: secondary_left,
|
||||
top: area.top,
|
||||
right: secondary_right,
|
||||
bottom: area.bottom,
|
||||
});
|
||||
|
||||
if len > 2 {
|
||||
layouts.append(&mut rows(
|
||||
&Rect {
|
||||
left: stack_left,
|
||||
top: area.top,
|
||||
right: secondary_right,
|
||||
bottom: area.bottom,
|
||||
},
|
||||
len - 2,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let adjustment = calculate_ultrawide_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
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ impl DefaultLayout {
|
||||
sizing: Sizing,
|
||||
delta: i32,
|
||||
) -> Option<Rect> {
|
||||
if !matches!(self, Self::BSP) {
|
||||
if !matches!(self, Self::BSP) && !matches!(self, Self::UltrawideVerticalStack) {
|
||||
return None;
|
||||
};
|
||||
|
||||
|
||||
@@ -775,6 +775,16 @@ impl Workspace {
|
||||
}
|
||||
|
||||
fn enforce_resize_constraints(&mut self) {
|
||||
match self.layout {
|
||||
Layout::Default(DefaultLayout::BSP) => self.enforce_resize_constraints_for_bsp(),
|
||||
Layout::Default(DefaultLayout::UltrawideVerticalStack) => {
|
||||
self.enforce_resize_for_ultrawide();
|
||||
}
|
||||
_ => self.enforce_no_resize(),
|
||||
}
|
||||
}
|
||||
|
||||
fn enforce_resize_constraints_for_bsp(&mut self) {
|
||||
for (i, rect) in self.resize_dimensions_mut().iter_mut().enumerate() {
|
||||
if let Some(rect) = rect {
|
||||
// Even containers can't be resized to the bottom
|
||||
@@ -800,6 +810,72 @@ impl Workspace {
|
||||
}
|
||||
}
|
||||
|
||||
fn enforce_resize_for_ultrawide(&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(),
|
||||
// Two windows can only be resized in the middle
|
||||
2 => {
|
||||
// Zero is actually on the right
|
||||
if let Some(mut right) = resize_dimensions[0] {
|
||||
right.top = 0;
|
||||
right.bottom = 0;
|
||||
right.right = 0;
|
||||
}
|
||||
|
||||
// One is on the left
|
||||
if let Some(mut left) = resize_dimensions[1] {
|
||||
left.top = 0;
|
||||
left.bottom = 0;
|
||||
left.left = 0;
|
||||
}
|
||||
}
|
||||
// Three or more windows means 0 is in center, 1 is at the left, 2.. are a vertical
|
||||
// stack on the right
|
||||
_ => {
|
||||
// Central can be resized left or right
|
||||
if let Some(mut right) = resize_dimensions[0] {
|
||||
right.top = 0;
|
||||
right.bottom = 0;
|
||||
}
|
||||
|
||||
// Left one can only be resized to the right
|
||||
if let Some(mut left) = resize_dimensions[1] {
|
||||
left.top = 0;
|
||||
left.bottom = 0;
|
||||
left.left = 0;
|
||||
}
|
||||
|
||||
// Handle stack on the right
|
||||
let stack_size = resize_dimensions[2..].len();
|
||||
for (i, rect) in resize_dimensions[2..].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_no_resize(&mut self) {
|
||||
for rect in self.resize_dimensions_mut().iter_mut().flatten() {
|
||||
rect.left = 0;
|
||||
rect.right = 0;
|
||||
rect.top = 0;
|
||||
rect.bottom = 0;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_monocle_container(&mut self) -> Result<()> {
|
||||
let focused_idx = self.focused_container_idx();
|
||||
let container = self
|
||||
|
||||
Reference in New Issue
Block a user