mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-04-25 10:08:33 +02:00
feat(wm): add vertical & horizontal stack layouts
This commit ports the CenterMain, MainAndVertStack, and MainAndHorizontalStack layouts from LeftWM to komorebi as UltrawideVerticalStack, VerticalStack and HorizontalStack. These layouts are fixed-size layouts, meaning that individual containers cannot be resized. The VerticalStack and UltrawideVerticalStack layouts support horizontal flipping, whereas the HorizontalStack layout supports vertical flipping. resolve #48
This commit is contained in:
24
Cargo.lock
generated
24
Cargo.lock
generated
@@ -199,9 +199,9 @@ checksum = "fb58b6451e8c2a812ad979ed1d83378caa5e927eef2622017a45f251457c2c9d"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "core-foundation-sys"
|
name = "core-foundation-sys"
|
||||||
version = "0.8.2"
|
version = "0.8.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b"
|
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-channel"
|
name = "crossbeam-channel"
|
||||||
@@ -425,9 +425,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hotwatch"
|
name = "hotwatch"
|
||||||
version = "0.4.5"
|
version = "0.4.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d61ee702e77f237b41761361a82e5c4bf6277dbb4bc8b6b7d745cb249cc82b31"
|
checksum = "39301670a6f5798b75f36a1b149a379a50df5aa7c71be50f4b41ec6eab445cb8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"notify",
|
"notify",
|
||||||
@@ -853,9 +853,9 @@ checksum = "36d62894f5590e88d99d0d82918742ba8e5bff1985af15d4906b6a65f635adb2"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ppv-lite86"
|
name = "ppv-lite86"
|
||||||
version = "0.2.10"
|
version = "0.2.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
|
checksum = "c3ca011bd0129ff4ae15cd04c4eef202cadf6c51c21e47aba319b4e0501db741"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-error"
|
name = "proc-macro-error"
|
||||||
@@ -883,9 +883,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.29"
|
version = "1.0.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d"
|
checksum = "edc3358ebc67bc8b7fa0c007f945b0b18226f78437d61bec735a9eb96b61ee70"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
@@ -1113,18 +1113,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sharded-slab"
|
name = "sharded-slab"
|
||||||
version = "0.1.3"
|
version = "0.1.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "740223c51853f3145fe7c90360d2d4232f2b62e3449489c207eccde818979982"
|
checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "slab"
|
name = "slab"
|
||||||
version = "0.4.4"
|
version = "0.4.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c307a32c1c5c437f38c7fd45d753050587732ba8628319fbdf12a7e289ccc590"
|
checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
|
|||||||
@@ -306,9 +306,13 @@ used [is available here](komorebi.sample.with.lib.ahk).
|
|||||||
- [x] Mouse drag to swap window container position
|
- [x] Mouse drag to swap window container position
|
||||||
- [x] Mouse drag to resize window container
|
- [x] Mouse drag to resize window container
|
||||||
- [x] Configurable workspace and container gaps
|
- [x] Configurable workspace and container gaps
|
||||||
- [x] BSP tree layout
|
- [x] BSP tree layout (`bsp`)
|
||||||
- [x] Flip BSP tree layout horizontally or vertically
|
- [x] Flip BSP tree layout horizontally or vertically
|
||||||
- [x] Equal-width, max-height column layout
|
- [x] Equal-width, max-height column layout (`columns`)
|
||||||
|
- [x] Equal-height, max-width row layout (`rows`)
|
||||||
|
- [x] Main half-height window with vertical stack layout (`horizontal-stack`)
|
||||||
|
- [x] Main half-width window with horizontal stack layout (`vertical-stack`)
|
||||||
|
- [x] 2x Main window (half and quarter-width) with horizontal stack layout (`ultrawide-vertical-stack`)
|
||||||
- [x] Floating rules based on exe name, window title and class
|
- [x] Floating rules based on exe name, window title and class
|
||||||
- [x] Workspace rules based on exe name and window class
|
- [x] Workspace rules based on exe name and window class
|
||||||
- [x] Additional manage rules based on exe name and window class
|
- [x] Additional manage rules based on exe name and window class
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ pub enum Layout {
|
|||||||
BSP,
|
BSP,
|
||||||
Columns,
|
Columns,
|
||||||
Rows,
|
Rows,
|
||||||
|
VerticalStack,
|
||||||
|
HorizontalStack,
|
||||||
|
UltrawideVerticalStack,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum)]
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum)]
|
||||||
@@ -131,7 +134,11 @@ impl Layout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap)]
|
#[allow(
|
||||||
|
clippy::cast_possible_truncation,
|
||||||
|
clippy::cast_possible_wrap,
|
||||||
|
clippy::too_many_lines
|
||||||
|
)]
|
||||||
pub fn calculate(
|
pub fn calculate(
|
||||||
&self,
|
&self,
|
||||||
area: &Rect,
|
area: &Rect,
|
||||||
@@ -185,6 +192,176 @@ impl Layout {
|
|||||||
|
|
||||||
layouts
|
layouts
|
||||||
}
|
}
|
||||||
|
Layout::VerticalStack => {
|
||||||
|
let mut layouts: Vec<Rect> = vec![];
|
||||||
|
layouts.resize(len, Rect::default());
|
||||||
|
|
||||||
|
let primary_right = match len {
|
||||||
|
1 => area.right,
|
||||||
|
_ => area.right / 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut main_left = area.left;
|
||||||
|
let mut stack_left = area.left + primary_right;
|
||||||
|
|
||||||
|
match layout_flip {
|
||||||
|
Some(Flip::Horizontal | Flip::HorizontalAndVertical) if len > 1 => {
|
||||||
|
main_left = main_left + area.right - primary_right;
|
||||||
|
stack_left = area.left;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut iter = layouts.iter_mut();
|
||||||
|
{
|
||||||
|
if let Some(first) = iter.next() {
|
||||||
|
first.left = main_left;
|
||||||
|
first.top = area.top;
|
||||||
|
first.right = primary_right;
|
||||||
|
first.bottom = area.bottom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let bottom = area.bottom / (len - 1) as i32;
|
||||||
|
let mut top = 0;
|
||||||
|
|
||||||
|
for next in iter {
|
||||||
|
next.left = stack_left;
|
||||||
|
next.top = area.top + top;
|
||||||
|
next.right = area.right - primary_right;
|
||||||
|
next.bottom = bottom;
|
||||||
|
|
||||||
|
top += bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
layouts
|
||||||
|
}
|
||||||
|
Layout::HorizontalStack => {
|
||||||
|
let mut layouts: Vec<Rect> = vec![];
|
||||||
|
layouts.resize(len, Rect::default());
|
||||||
|
|
||||||
|
let bottom = match len {
|
||||||
|
1 => area.bottom,
|
||||||
|
_ => area.bottom / 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut main_top = area.top;
|
||||||
|
let mut stack_top = area.top + bottom;
|
||||||
|
|
||||||
|
match layout_flip {
|
||||||
|
Some(Flip::Vertical | Flip::HorizontalAndVertical) if len > 1 => {
|
||||||
|
main_top = main_top + area.bottom - bottom;
|
||||||
|
stack_top = area.top;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut iter = layouts.iter_mut();
|
||||||
|
{
|
||||||
|
if let Some(first) = iter.next() {
|
||||||
|
first.left = area.left;
|
||||||
|
first.top = main_top;
|
||||||
|
first.right = area.right;
|
||||||
|
first.bottom = bottom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let right = area.right / (len - 1) as i32;
|
||||||
|
let mut left = 0;
|
||||||
|
|
||||||
|
for next in iter {
|
||||||
|
next.left = area.left + left;
|
||||||
|
next.top = stack_top;
|
||||||
|
next.right = right;
|
||||||
|
next.bottom = area.bottom - bottom;
|
||||||
|
|
||||||
|
left += right;
|
||||||
|
}
|
||||||
|
|
||||||
|
layouts
|
||||||
|
}
|
||||||
|
Layout::UltrawideVerticalStack => {
|
||||||
|
let mut layouts: Vec<Rect> = vec![];
|
||||||
|
layouts.resize(len, Rect::default());
|
||||||
|
|
||||||
|
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(Flip::Horizontal | Flip::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(Flip::Horizontal | Flip::HorizontalAndVertical) if len > 1 => {
|
||||||
|
secondary = area.left + primary_right + secondary_right;
|
||||||
|
stack = area.left;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
(primary, secondary, stack)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut iter = layouts.iter_mut();
|
||||||
|
|
||||||
|
{
|
||||||
|
if let Some(first) = iter.next() {
|
||||||
|
first.left = primary_left;
|
||||||
|
first.top = area.top;
|
||||||
|
first.right = primary_right;
|
||||||
|
first.bottom = area.bottom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
if let Some(second) = iter.next() {
|
||||||
|
second.left = secondary_left;
|
||||||
|
second.top = area.top;
|
||||||
|
second.right = secondary_right;
|
||||||
|
second.bottom = area.bottom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len > 2 {
|
||||||
|
let height = area.bottom / (len - 2) as i32;
|
||||||
|
let mut y = 0;
|
||||||
|
|
||||||
|
for next in iter {
|
||||||
|
next.left = stack_left;
|
||||||
|
next.top = area.top + y;
|
||||||
|
next.right = secondary_right;
|
||||||
|
next.bottom = height;
|
||||||
|
y += height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
layouts
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
dimensions
|
dimensions
|
||||||
|
|||||||
@@ -60,22 +60,36 @@ impl OperationDirection {
|
|||||||
Self::Up => match layout {
|
Self::Up => match layout {
|
||||||
Layout::BSP => len > 2 && idx != 0 && idx != 1,
|
Layout::BSP => len > 2 && idx != 0 && idx != 1,
|
||||||
Layout::Columns => false,
|
Layout::Columns => false,
|
||||||
Layout::Rows => idx != 0,
|
Layout::Rows | Layout::HorizontalStack => idx != 0,
|
||||||
|
Layout::VerticalStack => idx != 0 && idx != 1,
|
||||||
|
Layout::UltrawideVerticalStack => idx > 2,
|
||||||
},
|
},
|
||||||
Self::Down => match layout {
|
Self::Down => match layout {
|
||||||
Layout::BSP => len > 2 && idx != len - 1 && idx % 2 != 0,
|
Layout::BSP => len > 2 && idx != len - 1 && idx % 2 != 0,
|
||||||
Layout::Columns => false,
|
Layout::Columns => false,
|
||||||
Layout::Rows => idx != len - 1,
|
Layout::Rows => idx != len - 1,
|
||||||
|
Layout::VerticalStack => idx != 0 && idx != len - 1,
|
||||||
|
Layout::HorizontalStack => idx == 0,
|
||||||
|
Layout::UltrawideVerticalStack => idx > 1 && idx != len - 1,
|
||||||
},
|
},
|
||||||
Self::Left => match layout {
|
Self::Left => match layout {
|
||||||
Layout::BSP => len > 1 && idx != 0,
|
Layout::BSP => len > 1 && idx != 0,
|
||||||
Layout::Columns => idx != 0,
|
Layout::Columns | Layout::VerticalStack => idx != 0,
|
||||||
Layout::Rows => false,
|
Layout::Rows => false,
|
||||||
|
Layout::HorizontalStack => idx != 0 && idx != 1,
|
||||||
|
Layout::UltrawideVerticalStack => len > 1 && idx != 1,
|
||||||
},
|
},
|
||||||
Self::Right => match layout {
|
Self::Right => match layout {
|
||||||
Layout::BSP => len > 1 && idx % 2 == 0 && idx != len - 1,
|
Layout::BSP => len > 1 && idx % 2 == 0 && idx != len - 1,
|
||||||
Layout::Columns => idx != len - 1,
|
Layout::Columns => idx != len - 1,
|
||||||
Layout::Rows => false,
|
Layout::Rows => false,
|
||||||
|
Layout::VerticalStack => idx == 0,
|
||||||
|
Layout::HorizontalStack => idx != 0 && idx != len - 1,
|
||||||
|
Layout::UltrawideVerticalStack => match len {
|
||||||
|
0 | 1 => false,
|
||||||
|
2 => idx != 0,
|
||||||
|
_ => idx < 2,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -92,11 +106,16 @@ impl OperationDirection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Layout::Columns => unreachable!(),
|
Layout::Columns => unreachable!(),
|
||||||
Layout::Rows => idx - 1,
|
Layout::Rows | Layout::VerticalStack | Layout::UltrawideVerticalStack => idx - 1,
|
||||||
|
Layout::HorizontalStack => 0,
|
||||||
},
|
},
|
||||||
Self::Down => match layout {
|
Self::Down => match layout {
|
||||||
Layout::BSP | Layout::Rows => idx + 1,
|
Layout::BSP
|
||||||
|
| Layout::Rows
|
||||||
|
| Layout::VerticalStack
|
||||||
|
| Layout::UltrawideVerticalStack => idx + 1,
|
||||||
Layout::Columns => unreachable!(),
|
Layout::Columns => unreachable!(),
|
||||||
|
Layout::HorizontalStack => 1,
|
||||||
},
|
},
|
||||||
Self::Left => match layout {
|
Self::Left => match layout {
|
||||||
Layout::BSP => {
|
Layout::BSP => {
|
||||||
@@ -106,12 +125,24 @@ impl OperationDirection {
|
|||||||
idx - 1
|
idx - 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Layout::Columns => idx - 1,
|
Layout::Columns | Layout::HorizontalStack => idx - 1,
|
||||||
Layout::Rows => unreachable!(),
|
Layout::Rows => unreachable!(),
|
||||||
|
Layout::VerticalStack => 0,
|
||||||
|
Layout::UltrawideVerticalStack => match idx {
|
||||||
|
0 => 1,
|
||||||
|
1 => unreachable!(),
|
||||||
|
_ => 0,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Self::Right => match layout {
|
Self::Right => match layout {
|
||||||
Layout::BSP | Layout::Columns => idx + 1,
|
Layout::BSP | Layout::Columns | Layout::HorizontalStack => idx + 1,
|
||||||
Layout::Rows => unreachable!(),
|
Layout::Rows => unreachable!(),
|
||||||
|
Layout::VerticalStack => 1,
|
||||||
|
Layout::UltrawideVerticalStack => match idx {
|
||||||
|
1 => 0,
|
||||||
|
0 => 2,
|
||||||
|
_ => unreachable!(),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user