mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-07-11 07:32:51 +02: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
|
layouts
|
||||||
}
|
}
|
||||||
Self::UltrawideVerticalStack => {
|
Self::UltrawideVerticalStack => ultrawide(area, len, layout_flip, resize_dimensions),
|
||||||
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
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
dimensions
|
dimensions
|
||||||
@@ -586,3 +508,190 @@ fn recursive_fibonacci(
|
|||||||
res
|
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,
|
sizing: Sizing,
|
||||||
delta: i32,
|
delta: i32,
|
||||||
) -> Option<Rect> {
|
) -> Option<Rect> {
|
||||||
if !matches!(self, Self::BSP) {
|
if !matches!(self, Self::BSP) && !matches!(self, Self::UltrawideVerticalStack) {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -775,6 +775,16 @@ impl Workspace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn enforce_resize_constraints(&mut self) {
|
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() {
|
for (i, rect) in self.resize_dimensions_mut().iter_mut().enumerate() {
|
||||||
if let Some(rect) = rect {
|
if let Some(rect) = rect {
|
||||||
// Even containers can't be resized to the bottom
|
// 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<()> {
|
pub fn new_monocle_container(&mut self) -> Result<()> {
|
||||||
let focused_idx = self.focused_container_idx();
|
let focused_idx = self.focused_container_idx();
|
||||||
let container = self
|
let container = self
|
||||||
|
|||||||
Reference in New Issue
Block a user