Compare commits

...

6 Commits

Author SHA1 Message Date
dependabot[bot]
705f6bcca7 chore(deps): bump actions/upload-artifact from 6 to 7
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 6 to 7.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-02 15:58:54 +00:00
LGUG2Z
0f1854db8b ci(github): re-enable sunday cron jobs 2026-03-01 21:33:51 -08:00
Csaba
8889c3ca93 fix(wm): correct layout rounding for uneven integer division
The grid layout calculates row heights using integer division, which
truncates the result when the area height is not evenly divisible by the
number of rows in a column. Since every row received this truncated
height, columns with an odd row count (e.g. 3 rows in 800px: 266*3=798)
would fall short of the full area height, leaving a visible gap at the
bottom compared to columns with an even row count (e.g. 2 rows:
400*2=800).

The last row in each column now absorbs the remainder pixels from the
integer division. The vertical flip position calculation was also
updated so that the last row, which becomes the topmost window when
flipped, starts at the area top edge instead of being offset by the
truncation error.

The same integer division truncation also affected column widths in the
grid layout when the area width is not evenly divisible by the number of
columns. The last column now absorbs the width remainder using the same
pattern, and this correction is applied before the flipped column
positions are calculated so that horizontal flips also tile correctly.

The two shared helper functions columns_with_ratios and rows_with_ratios
had the same issue, which propagated to every layout that delegates to
them: Columns, Rows, VerticalStack stack rows, RightMainVerticalStack
stack rows, HorizontalStack stack columns, and UltrawideVerticalStack
tertiary rows. Both functions now correct the last element after the
sizing loop so that the total tiled dimension matches the area exactly.

The Scrolling layout computes a uniform column width by dividing the
area width by the visible column count, which can also leave a remainder
gap on the right edge. The last visible column in the current viewport
now absorbs this remainder. Since the layout is recalculated on every
scroll event, the correction stays accurate regardless of which column
is rightmost.
2026-03-01 21:31:36 -08:00
LGUG2Z
6ca49d4301 chore(deps): cargo update 2026-02-20 16:58:40 -08:00
Csaba
634a3e7f3b fix(wm): correct bsp/grid container positioning when flipped
The recursive_fibonacci function used formulas for main_x and main_y
that mixed unresized area dimensions with resized dimensions when
calculating flipped positions.

This caused a gap between containers proportional to resize_delta * (2 *
ratio - 1), meaning any column_ratios or row_ratios value other than the
default 0.5 would produce visible gaps or overlaps between containers
when the layout was both flipped and resized.

The fix replaces the flipped position formulas with ones that derive
main_x and main_y directly from the alt area width and height
expressions used by the recursive child call, ensuring the main
container is always positioned immediately adjacent to the alt area
regardless of ratio or resize delta.

The horizontal flip for grid layouts swapped column left positions
directly from the unflipped layout. With non-default column ratios this
caused narrow columns to receive wide column positions, producing
overlapping containers.

Precompute flipped column left positions by laying out the original
column widths in reverse order from the area left edge, ensuring
containers tile without overlap regardless of column ratio.

Separated all unit test for arrangements into a new file.

Added 4 BSP-specific regression tests (horizontal flip, vertical flip,
both axes, sweep across multiple ratios/deltas).

Added 7 adjacency tests covering ALL other layouts (Columns, Rows,
VerticalStack, RightMainVerticalStack, HorizontalStack,
UltrawideVerticalStack, Scrolling) confirming they don't have the gap
issue.

Added 2 Grid tests that verify containers don't overlap and tile the
full area when column ratios are non-default. The first test checks a
horizontal flip specifically, confirming 2 columns form with no gaps
edge-to-edge. The second test runs all three flip axes and asserts no
overlaps and full area coverage for each.
2026-02-20 16:57:21 -08:00
LGUG2Z
5b6fab0044 chore(dev): begin v0.1.41-dev 2026-02-20 16:56:51 -08:00
16 changed files with 2071 additions and 823 deletions

View File

@@ -13,8 +13,8 @@ on:
- hotfix/*
tags:
- v*
# schedule:
# - cron: "30 0 * * 0" # Every day at 00:30 UTC
schedule:
- cron: "30 0 * * 0" # Every day at 00:30 UTC
workflow_dispatch:
jobs:
@@ -65,7 +65,7 @@ jobs:
- run: |
cargo install cargo-wix
cargo wix --no-build -p komorebi --nocapture -I .\wix\main.wxs --target ${{ matrix.platform.target }}
- uses: actions/upload-artifact@v6
- uses: actions/upload-artifact@v7
with:
name: komorebi-${{ matrix.platform.target }}-${{ github.sha }}
path: |

247
Cargo.lock generated
View File

@@ -284,9 +284,9 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.101"
version = "1.0.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f0e0fee31ef5ed1ba1316088939cea399010ed7731dba877ed44aeb407a75ea"
checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
[[package]]
name = "approx"
@@ -340,7 +340,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -405,9 +405,9 @@ dependencies = [
[[package]]
name = "async-executor"
version = "1.13.3"
version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "497c00e0fd83a72a79a39fcbd8e3e2f055d6f6c7e025f3b3d91f4f8e76527fb8"
checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a"
dependencies = [
"async-task",
"concurrent-queue",
@@ -472,7 +472,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -507,7 +507,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -800,9 +800,9 @@ checksum = "f4ad8f11f288f48ca24471bbd51ac257aaeaaa07adae295591266b792902ae64"
[[package]]
name = "bumpalo"
version = "3.19.1"
version = "3.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510"
checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb"
[[package]]
name = "bytemuck"
@@ -821,7 +821,7 @@ checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -1001,9 +1001,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.5.58"
version = "4.5.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63be97961acde393029492ce0be7a1af7e323e6bae9511ebfac33751be5e6806"
checksum = "2797f34da339ce31042b27d23607e051786132987f595b02ba4f6a6dffb7030a"
dependencies = [
"clap_builder",
"clap_derive",
@@ -1011,9 +1011,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.58"
version = "4.5.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f13174bda5dfd69d7e947827e5af4b0f2f94a4a3ee92912fba07a66150f21e2"
checksum = "24a241312cea5059b13574bb9b3861cabf758b879c15190b37b6d6fd63ab6876"
dependencies = [
"anstream",
"anstyle",
@@ -1031,7 +1031,7 @@ dependencies = [
"heck",
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -1366,7 +1366,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -1390,7 +1390,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -1401,7 +1401,7 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81"
dependencies = [
"darling_core",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -1520,7 +1520,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -1791,7 +1791,7 @@ checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -1812,7 +1812,7 @@ checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -1862,7 +1862,7 @@ checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -1966,7 +1966,7 @@ checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -2106,7 +2106,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -2161,9 +2161,9 @@ dependencies = [
[[package]]
name = "futures"
version = "0.3.31"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d"
dependencies = [
"futures-channel",
"futures-core",
@@ -2176,9 +2176,9 @@ dependencies = [
[[package]]
name = "futures-channel"
version = "0.3.31"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d"
dependencies = [
"futures-core",
"futures-sink",
@@ -2186,15 +2186,15 @@ dependencies = [
[[package]]
name = "futures-core"
version = "0.3.31"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
[[package]]
name = "futures-executor"
version = "0.3.31"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d"
dependencies = [
"futures-core",
"futures-task",
@@ -2203,9 +2203,9 @@ dependencies = [
[[package]]
name = "futures-io"
version = "0.3.31"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718"
[[package]]
name = "futures-lite"
@@ -2222,32 +2222,32 @@ dependencies = [
[[package]]
name = "futures-macro"
version = "0.3.31"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
name = "futures-sink"
version = "0.3.31"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893"
[[package]]
name = "futures-task"
version = "0.3.31"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393"
[[package]]
name = "futures-util"
version = "0.3.31"
version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6"
dependencies = [
"futures-channel",
"futures-core",
@@ -2257,7 +2257,6 @@ dependencies = [
"futures-task",
"memchr",
"pin-project-lite",
"pin-utils",
"slab",
]
@@ -2999,7 +2998,7 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -3113,9 +3112,9 @@ dependencies = [
[[package]]
name = "js-sys"
version = "0.3.85"
version = "0.3.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3"
checksum = "93f0862381daaec758576dcc22eb7bbf4d7efd67328553f3b45a412a51a3fb21"
dependencies = [
"once_cell",
"wasm-bindgen",
@@ -3140,7 +3139,7 @@ checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
[[package]]
name = "komorebi"
version = "0.1.40"
version = "0.1.41"
dependencies = [
"base64",
"bitflags 2.11.0",
@@ -3172,7 +3171,7 @@ dependencies = [
"serde_yaml 0.9.34+deprecated",
"shadow-rs",
"strum",
"sysinfo 0.38.1",
"sysinfo 0.38.2",
"tracing",
"tracing-appender",
"tracing-subscriber",
@@ -3191,7 +3190,7 @@ dependencies = [
[[package]]
name = "komorebi-bar"
version = "0.1.40"
version = "0.1.41"
dependencies = [
"chrono",
"chrono-tz",
@@ -3219,7 +3218,7 @@ dependencies = [
"serde",
"serde_json_lenient",
"starship-battery",
"sysinfo 0.38.1",
"sysinfo 0.38.2",
"tracing",
"tracing-subscriber",
"which",
@@ -3231,7 +3230,7 @@ dependencies = [
[[package]]
name = "komorebi-client"
version = "0.1.40"
version = "0.1.41"
dependencies = [
"komorebi",
"serde_json_lenient",
@@ -3240,7 +3239,7 @@ dependencies = [
[[package]]
name = "komorebi-gui"
version = "0.1.40"
version = "0.1.41"
dependencies = [
"eframe",
"egui_extras",
@@ -3253,7 +3252,7 @@ dependencies = [
[[package]]
name = "komorebi-layouts"
version = "0.1.40"
version = "0.1.41"
dependencies = [
"clap",
"color-eyre",
@@ -3279,7 +3278,7 @@ dependencies = [
[[package]]
name = "komorebi-themes"
version = "0.1.40"
version = "0.1.41"
dependencies = [
"base16-egui-themes",
"catppuccin-egui",
@@ -3294,7 +3293,7 @@ dependencies = [
[[package]]
name = "komorebic"
version = "0.1.40"
version = "0.1.41"
dependencies = [
"chrono",
"clap",
@@ -3313,7 +3312,7 @@ dependencies = [
"serde",
"serde_json_lenient",
"shadow-rs",
"sysinfo 0.38.1",
"sysinfo 0.38.2",
"thiserror 2.0.18",
"which",
"win-msgbox",
@@ -3322,7 +3321,7 @@ dependencies = [
[[package]]
name = "komorebic-no-console"
version = "0.1.40"
version = "0.1.41"
[[package]]
name = "kqueue"
@@ -3501,7 +3500,7 @@ dependencies = [
"proc-macro2",
"quote",
"regex-syntax",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -3573,9 +3572,9 @@ checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
[[package]]
name = "memmap2"
version = "0.9.9"
version = "0.9.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "744133e4a0e0a658e1374cf3bf8e415c4052a15a111acd372764c55b4177d490"
checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3"
dependencies = [
"libc",
]
@@ -3631,7 +3630,7 @@ checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -3766,9 +3765,9 @@ dependencies = [
[[package]]
name = "native-tls"
version = "0.2.16"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d5d26952a508f321b4d3d2e80e78fc2603eaefcdf0c30783867f19586518bdc"
checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2"
dependencies = [
"libc",
"log",
@@ -4022,7 +4021,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -4096,7 +4095,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -4565,7 +4564,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -4809,7 +4808,7 @@ dependencies = [
"phf_shared 0.11.3",
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
"unicase",
]
@@ -4858,7 +4857,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -5010,7 +5009,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
dependencies = [
"proc-macro2",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -5047,7 +5046,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b"
dependencies = [
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -5392,7 +5391,7 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -5651,7 +5650,7 @@ dependencies = [
"proc-macro2",
"quote",
"serde_derive_internals",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -5687,9 +5686,9 @@ dependencies = [
[[package]]
name = "security-framework"
version = "3.6.0"
version = "3.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d17b898a6d6948c3a8ee4372c17cb384f90d2e6e912ef00895b14fd7ab54ec38"
checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d"
dependencies = [
"bitflags 2.11.0",
"core-foundation 0.10.1",
@@ -5700,9 +5699,9 @@ dependencies = [
[[package]]
name = "security-framework-sys"
version = "2.16.0"
version = "2.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "321c8673b092a9a42605034a9879d73cb79101ed5fd117bc9a597b89b4e9e61a"
checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3"
dependencies = [
"core-foundation-sys",
"libc",
@@ -5741,7 +5740,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -5752,7 +5751,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -5789,7 +5788,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -5841,7 +5840,7 @@ dependencies = [
"darling",
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -6185,7 +6184,7 @@ dependencies = [
"heck",
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -6228,9 +6227,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.115"
version = "2.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e614ed320ac28113fa64972c4262d5dbc89deacdfd00c34a3e4cea073243c12"
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
dependencies = [
"proc-macro2",
"quote",
@@ -6254,7 +6253,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -6273,9 +6272,9 @@ dependencies = [
[[package]]
name = "sysinfo"
version = "0.38.1"
version = "0.38.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5792d209c2eac902426c0c4a166c9f72147db453af548cf9bf3242644c4d4fe3"
checksum = "1efc19935b4b66baa6f654ac7924c192f55b175c00a7ab72410fc24284dacda8"
dependencies = [
"libc",
"memchr",
@@ -6374,7 +6373,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -6385,7 +6384,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -6569,9 +6568,9 @@ dependencies = [
[[package]]
name = "toml_parser"
version = "1.0.8+spec-1.1.0"
version = "1.0.9+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0742ff5ff03ea7e67c8ae6c93cac239e0d9784833362da3f9a9c1da8dfefcbdc"
checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4"
dependencies = [
"winnow",
]
@@ -6653,7 +6652,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -6777,9 +6776,9 @@ checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142"
[[package]]
name = "unicode-ident"
version = "1.0.23"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "537dd038a89878be9b64dd4bd1b260315c1bb94f4d784956b81e27a088d9a09e"
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
[[package]]
name = "unicode-linebreak"
@@ -6949,9 +6948,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen"
version = "0.2.108"
version = "0.2.110"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566"
checksum = "1de241cdc66a9d91bd84f097039eb140cdc6eec47e0cdbaf9d932a1dd6c35866"
dependencies = [
"cfg-if 1.0.4",
"once_cell",
@@ -6962,9 +6961,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.58"
version = "0.4.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70a6e77fd0ae8029c9ea0063f87c46fde723e7d887703d74ad2616d792e51e6f"
checksum = "a42e96ea38f49b191e08a1bab66c7ffdba24b06f9995b39a9dd60222e5b6f1da"
dependencies = [
"cfg-if 1.0.4",
"futures-util",
@@ -6976,9 +6975,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.108"
version = "0.2.110"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608"
checksum = "e12fdf6649048f2e3de6d7d5ff3ced779cdedee0e0baffd7dff5cdfa3abc8a52"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -6986,22 +6985,22 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.108"
version = "0.2.110"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55"
checksum = "0e63d1795c565ac3462334c1e396fd46dbf481c40f51f5072c310717bc4fb309"
dependencies = [
"bumpalo",
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.108"
version = "0.2.110"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12"
checksum = "e9f9cdac23a5ce71f6bf9f8824898a501e511892791ea2a0c6b8568c68b9cb53"
dependencies = [
"unicode-ident",
]
@@ -7177,9 +7176,9 @@ dependencies = [
[[package]]
name = "web-sys"
version = "0.3.85"
version = "0.3.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "312e32e551d92129218ea9a2452120f4aabc03529ef03e4d0d82fb2780608598"
checksum = "f2c7c5718134e770ee62af3b6b4a84518ec10101aad610c024b64d6ff29bb1ff"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -7661,7 +7660,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -7672,7 +7671,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -7683,7 +7682,7 @@ checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -7694,7 +7693,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -7705,7 +7704,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -7716,7 +7715,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -7727,7 +7726,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -8287,7 +8286,7 @@ dependencies = [
"heck",
"indexmap 2.13.0",
"prettyplease",
"syn 2.0.115",
"syn 2.0.117",
"wasm-metadata",
"wit-bindgen-core",
"wit-component",
@@ -8303,7 +8302,7 @@ dependencies = [
"prettyplease",
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
"wit-bindgen-core",
"wit-bindgen-rust",
]
@@ -8463,7 +8462,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
"synstructure",
]
@@ -8520,7 +8519,7 @@ checksum = "10da05367f3a7b7553c8cdf8fa91aee6b64afebe32b51c95177957efc47ca3a0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
"zbus-lockstep",
"zbus_xml",
"zvariant",
@@ -8535,7 +8534,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
"zbus_names",
"zvariant",
"zvariant_utils",
@@ -8581,7 +8580,7 @@ checksum = "4122cd3169e94605190e77839c9a40d40ed048d305bfdc146e7df40ab0f3e517"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -8601,7 +8600,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
"synstructure",
]
@@ -8641,7 +8640,7 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
]
[[package]]
@@ -8712,7 +8711,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn 2.0.115",
"syn 2.0.117",
"zvariant_utils",
]
@@ -8725,6 +8724,6 @@ dependencies = [
"proc-macro2",
"quote",
"serde",
"syn 2.0.115",
"syn 2.0.117",
"winnow",
]

View File

@@ -1,5 +1,5 @@
{
"$schema": "https://raw.githubusercontent.com/LGUG2Z/komorebi/v0.1.40/schema.bar.json",
"$schema": "https://raw.githubusercontent.com/LGUG2Z/komorebi/v0.1.41/schema.bar.json",
"font_family": "JetBrains Mono",
"theme": {
"palette": "Base16",

View File

@@ -1,5 +1,5 @@
{
"$schema": "https://raw.githubusercontent.com/LGUG2Z/komorebi/v0.1.40/schema.json",
"$schema": "https://raw.githubusercontent.com/LGUG2Z/komorebi/v0.1.41/schema.json",
"app_specific_configuration_path": "$Env:USERPROFILE/applications.json",
"window_hiding_behaviour": "Cloak",
"cross_monitor_move_behaviour": "Insert",

View File

@@ -1,6 +1,6 @@
[package]
name = "komorebi-bar"
version = "0.1.40"
version = "0.1.41"
edition = "2024"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View File

@@ -15,7 +15,7 @@ use std::path::PathBuf;
#[derive(Clone, Debug, Serialize, Deserialize)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
/// The `komorebi.bar.json` configuration file reference for `v0.1.40`
/// The `komorebi.bar.json` configuration file reference for `v0.1.41`
pub struct KomobarConfig {
/// Bar height
#[cfg_attr(feature = "schemars", schemars(extend("default" = 50)))]

View File

@@ -1,6 +1,6 @@
[package]
name = "komorebi-client"
version = "0.1.40"
version = "0.1.41"
edition = "2024"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View File

@@ -1,6 +1,6 @@
[package]
name = "komorebi-gui"
version = "0.1.40"
version = "0.1.41"
edition = "2024"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View File

@@ -1,6 +1,6 @@
[package]
name = "komorebi-layouts"
version = "0.1.40"
version = "0.1.41"
edition = "2024"
[dependencies]

View File

@@ -141,6 +141,15 @@ impl Arrangement for DefaultLayout {
});
}
// Last visible column absorbs any remainder from integer division
// so that visible columns tile the full area width without gaps
let width_remainder = area.right - column_width * visible_columns;
if width_remainder > 0 {
let last_visible_idx =
(first_visible as usize + visible_columns as usize - 1).min(len - 1);
layouts[last_visible_idx].right += width_remainder;
}
let adjustment = calculate_scrolling_adjustment(resize_dimensions);
layouts
.iter_mut()
@@ -660,6 +669,34 @@ impl Arrangement for DefaultLayout {
current_left += width;
}
// Last column absorbs any remainder from integer division
// so that columns tile the full area width without gaps
let total_width: i32 = col_widths.iter().sum();
let width_remainder = area.right - total_width;
if width_remainder > 0
&& let Some(last) = col_widths.last_mut()
{
*last += width_remainder;
}
// Pre-calculate flipped column positions: same widths laid out
// in reverse order so that the last column sits at area.left
let flipped_col_lefts = if matches!(
layout_flip,
Some(Axis::Horizontal | Axis::HorizontalAndVertical)
) {
let n = num_cols as usize;
let mut flipped = vec![0i32; n];
let mut fl = area.left;
for i in (0..n).rev() {
flipped[i] = fl;
fl += col_widths[i];
}
flipped
} else {
vec![]
};
let mut iter = layouts.iter_mut().enumerate().peekable();
for col in 0..num_cols {
@@ -673,8 +710,10 @@ impl Arrangement for DefaultLayout {
remaining_windows / remaining_columns
};
// Rows within each column are equal height (no row_ratios support for Grid)
let win_height = area.bottom / num_rows_in_this_col;
// Rows within each column: base height from integer division,
// last row absorbs any remainder to cover the full area height
let base_height = area.bottom / num_rows_in_this_col;
let height_remainder = area.bottom - base_height * num_rows_in_this_col;
let col_idx = col as usize;
let win_width = col_widths[col_idx];
@@ -682,25 +721,36 @@ impl Arrangement for DefaultLayout {
for row in 0..num_rows_in_this_col {
if let Some((_idx, win)) = iter.next() {
let is_last_row = row == num_rows_in_this_col - 1;
let win_height = if is_last_row {
base_height + height_remainder
} else {
base_height
};
let mut left = col_left;
let mut top = area.top + win_height * row;
let mut top = area.top + base_height * row;
match layout_flip {
Some(Axis::Horizontal) => {
// Calculate flipped left position
let flipped_col = (num_cols - 1 - col) as usize;
left = col_lefts[flipped_col];
left = flipped_col_lefts[col_idx];
}
Some(Axis::Vertical) => {
// Calculate flipped top position
top = area.bottom - win_height * (row + 1) + area.top;
top = if is_last_row {
area.top
} else {
area.top + area.bottom - base_height * (row + 1)
};
}
Some(Axis::HorizontalAndVertical) => {
let flipped_col = (num_cols - 1 - col) as usize;
left = col_lefts[flipped_col];
top = area.bottom - win_height * (row + 1) + area.top;
left = flipped_col_lefts[col_idx];
top = if is_last_row {
area.top
} else {
area.top + area.bottom - base_height * (row + 1)
};
}
None => {} // No flip
None => {}
}
win.bottom = win_height;
@@ -934,6 +984,16 @@ fn columns_with_ratios(
left += right;
}
// Last column absorbs any remainder from integer division
// so that columns tile the full area width without gaps
let total_width: i32 = layouts.iter().map(|r| r.right).sum();
let remainder = area.right - total_width;
if remainder > 0
&& let Some(last) = layouts.last_mut()
{
last.right += remainder;
}
layouts
}
@@ -1005,6 +1065,16 @@ fn rows_with_ratios(
top += bottom;
}
// Last row absorbs any remainder from integer division
// so that rows tile the full area height without gaps
let total_height: i32 = layouts.iter().map(|r| r.bottom).sum();
let remainder = area.bottom - total_height;
if remainder > 0
&& let Some(last) = layouts.last_mut()
{
last.bottom += remainder;
}
layouts
}
@@ -1129,47 +1199,33 @@ fn recursive_fibonacci(
*area
};
#[allow(clippy::cast_possible_truncation)]
let primary_width = (area.right as f32 * column_split_ratio) as i32;
#[allow(clippy::cast_possible_truncation)]
let primary_height = (area.bottom as f32 * row_split_ratio) as i32;
#[allow(clippy::cast_possible_truncation)]
let primary_resized_width = (resized.right as f32 * column_split_ratio) as i32;
#[allow(clippy::cast_possible_truncation)]
let primary_resized_height = (resized.bottom as f32 * row_split_ratio) as i32;
let secondary_width = area.right - primary_width;
let secondary_resized_width = resized.right - primary_resized_width;
let secondary_resized_height = resized.bottom - primary_resized_height;
let (main_x, alt_x, alt_y, main_y);
if let Some(flip) = layout_flip {
match flip {
Axis::Horizontal => {
main_x =
resized.left + secondary_width + (secondary_width - secondary_resized_width);
main_x = resized.left + (area.right - primary_resized_width);
alt_x = resized.left;
alt_y = resized.top + primary_resized_height;
main_y = resized.top;
}
Axis::Vertical => {
main_y = resized.top
+ (area.bottom - primary_height)
+ ((area.bottom - primary_height) - secondary_resized_height);
main_y = resized.top + (area.bottom - primary_resized_height);
alt_y = resized.top;
main_x = resized.left;
alt_x = resized.left + primary_resized_width;
}
Axis::HorizontalAndVertical => {
main_x =
resized.left + secondary_width + (secondary_width - secondary_resized_width);
main_x = resized.left + (area.right - primary_resized_width);
alt_x = resized.left;
main_y = resized.top
+ (area.bottom - primary_height)
+ ((area.bottom - primary_height) - secondary_resized_height);
main_y = resized.top + (area.bottom - primary_resized_height);
alt_y = resized.top;
}
}
@@ -1541,657 +1597,5 @@ fn resize_bottom(rect: &mut Rect, resize: i32) {
}
#[cfg(test)]
mod tests {
use super::*;
use std::num::NonZeroUsize;
// Helper to create a test area
fn test_area() -> Rect {
Rect {
left: 0,
top: 0,
right: 1000,
bottom: 800,
}
}
// Helper to create LayoutOptions with column ratios
fn layout_options_with_column_ratios(ratios: &[f32]) -> LayoutOptions {
let mut arr = [None; MAX_RATIOS];
for (i, &r) in ratios.iter().take(MAX_RATIOS).enumerate() {
arr[i] = Some(r);
}
LayoutOptions {
scrolling: None,
grid: None,
column_ratios: Some(arr),
row_ratios: None,
}
}
// Helper to create LayoutOptions with row ratios
fn layout_options_with_row_ratios(ratios: &[f32]) -> LayoutOptions {
let mut arr = [None; MAX_RATIOS];
for (i, &r) in ratios.iter().take(MAX_RATIOS).enumerate() {
arr[i] = Some(r);
}
LayoutOptions {
scrolling: None,
grid: None,
column_ratios: None,
row_ratios: Some(arr),
}
}
// Helper to create LayoutOptions with both column and row ratios
fn layout_options_with_ratios(column_ratios: &[f32], row_ratios: &[f32]) -> LayoutOptions {
let mut col_arr = [None; MAX_RATIOS];
for (i, &r) in column_ratios.iter().take(MAX_RATIOS).enumerate() {
col_arr[i] = Some(r);
}
let mut row_arr = [None; MAX_RATIOS];
for (i, &r) in row_ratios.iter().take(MAX_RATIOS).enumerate() {
row_arr[i] = Some(r);
}
LayoutOptions {
scrolling: None,
grid: None,
column_ratios: Some(col_arr),
row_ratios: Some(row_arr),
}
}
mod columns_with_ratios_tests {
use super::*;
#[test]
fn test_columns_equal_width_no_ratios() {
let area = test_area();
let layouts = columns_with_ratios(&area, 4, None);
assert_eq!(layouts.len(), 4);
// Each column should be 250 pixels wide (1000 / 4)
for layout in &layouts {
assert_eq!(layout.right, 250);
assert_eq!(layout.bottom, 800);
}
}
#[test]
fn test_columns_with_single_ratio() {
let area = test_area();
let opts = layout_options_with_column_ratios(&[0.3]);
let layouts = columns_with_ratios(&area, 3, opts.column_ratios);
assert_eq!(layouts.len(), 3);
// First column: 30% of 1000 = 300
assert_eq!(layouts[0].right, 300);
// Remaining 700 split between 2 columns = 350 each
assert_eq!(layouts[1].right, 350);
assert_eq!(layouts[2].right, 350);
}
#[test]
fn test_columns_with_multiple_ratios() {
let area = test_area();
let opts = layout_options_with_column_ratios(&[0.2, 0.3, 0.5]);
let layouts = columns_with_ratios(&area, 4, opts.column_ratios);
assert_eq!(layouts.len(), 4);
// First column: 20% of 1000 = 200
assert_eq!(layouts[0].right, 200);
// Second column: 30% of 1000 = 300
assert_eq!(layouts[1].right, 300);
// Third column: 50% of 1000 = 500
// But wait - cumulative is 1.0, so third might be truncated
// Let's check what actually happens
// Actually, the sum 0.2 + 0.3 = 0.5 < 1.0, and 0.5 + 0.5 = 1.0
// So 0.5 won't be included because cumulative would reach 1.0
}
#[test]
fn test_columns_positions_are_correct() {
let area = test_area();
let opts = layout_options_with_column_ratios(&[0.3, 0.4]);
let layouts = columns_with_ratios(&area, 3, opts.column_ratios);
// First column starts at 0
assert_eq!(layouts[0].left, 0);
// Second column starts where first ends
assert_eq!(layouts[1].left, layouts[0].right);
// Third column starts where second ends
assert_eq!(layouts[2].left, layouts[1].left + layouts[1].right);
}
#[test]
fn test_columns_last_column_gets_remaining_space() {
let area = test_area();
let opts = layout_options_with_column_ratios(&[0.3]);
let layouts = columns_with_ratios(&area, 2, opts.column_ratios);
assert_eq!(layouts.len(), 2);
// First column: 30% = 300
assert_eq!(layouts[0].right, 300);
// Last column gets remaining space: 700
assert_eq!(layouts[1].right, 700);
}
#[test]
fn test_columns_single_column() {
let area = test_area();
let opts = layout_options_with_column_ratios(&[0.5]);
let layouts = columns_with_ratios(&area, 1, opts.column_ratios);
assert_eq!(layouts.len(), 1);
// Single column takes full width regardless of ratio
assert_eq!(layouts[0].right, 1000);
}
#[test]
fn test_columns_more_columns_than_ratios() {
let area = test_area();
let opts = layout_options_with_column_ratios(&[0.2]);
let layouts = columns_with_ratios(&area, 5, opts.column_ratios);
assert_eq!(layouts.len(), 5);
// First column: 20% = 200
assert_eq!(layouts[0].right, 200);
// Remaining 800 split among 4 columns = 200 each
for i in 1..5 {
assert_eq!(layouts[i].right, 200);
}
}
}
mod rows_with_ratios_tests {
use super::*;
#[test]
fn test_rows_equal_height_no_ratios() {
let area = test_area();
let layouts = rows_with_ratios(&area, 4, None);
assert_eq!(layouts.len(), 4);
// Each row should be 200 pixels tall (800 / 4)
for layout in &layouts {
assert_eq!(layout.bottom, 200);
assert_eq!(layout.right, 1000);
}
}
#[test]
fn test_rows_with_single_ratio() {
let area = test_area();
let opts = layout_options_with_row_ratios(&[0.5]);
let layouts = rows_with_ratios(&area, 3, opts.row_ratios);
assert_eq!(layouts.len(), 3);
// First row: 50% of 800 = 400
assert_eq!(layouts[0].bottom, 400);
// Remaining 400 split between 2 rows = 200 each
assert_eq!(layouts[1].bottom, 200);
assert_eq!(layouts[2].bottom, 200);
}
#[test]
fn test_rows_positions_are_correct() {
let area = test_area();
let opts = layout_options_with_row_ratios(&[0.25, 0.25]);
let layouts = rows_with_ratios(&area, 3, opts.row_ratios);
// First row starts at top
assert_eq!(layouts[0].top, 0);
// Second row starts where first ends
assert_eq!(layouts[1].top, layouts[0].bottom);
// Third row starts where second ends
assert_eq!(layouts[2].top, layouts[1].top + layouts[1].bottom);
}
#[test]
fn test_rows_last_row_gets_remaining_space() {
let area = test_area();
let opts = layout_options_with_row_ratios(&[0.25]);
let layouts = rows_with_ratios(&area, 2, opts.row_ratios);
assert_eq!(layouts.len(), 2);
// First row: 25% of 800 = 200
assert_eq!(layouts[0].bottom, 200);
// Last row gets remaining: 600
assert_eq!(layouts[1].bottom, 600);
}
}
mod vertical_stack_layout_tests {
use super::*;
#[test]
fn test_vertical_stack_default_ratio() {
let area = test_area();
let len = NonZeroUsize::new(3).unwrap();
let layouts =
DefaultLayout::VerticalStack.calculate(&area, len, None, None, &[], 0, None, &[]);
assert_eq!(layouts.len(), 3);
// Primary column should be 50% (default ratio)
assert_eq!(layouts[0].right, 500);
}
#[test]
fn test_vertical_stack_custom_ratio() {
let area = test_area();
let len = NonZeroUsize::new(3).unwrap();
let opts = layout_options_with_column_ratios(&[0.7]);
let layouts = DefaultLayout::VerticalStack.calculate(
&area,
len,
None,
None,
&[],
0,
Some(opts),
&[],
);
assert_eq!(layouts.len(), 3);
// Primary column should be 70%
assert_eq!(layouts[0].right, 700);
// Stack columns should share remaining 30%
assert_eq!(layouts[1].right, 300);
assert_eq!(layouts[2].right, 300);
}
#[test]
fn test_vertical_stack_with_row_ratios() {
let area = test_area();
let len = NonZeroUsize::new(4).unwrap();
let opts = layout_options_with_ratios(&[0.6], &[0.5, 0.3]);
let layouts = DefaultLayout::VerticalStack.calculate(
&area,
len,
None,
None,
&[],
0,
Some(opts),
&[],
);
assert_eq!(layouts.len(), 4);
// Primary column: 60%
assert_eq!(layouts[0].right, 600);
// Stack rows should use row_ratios
// First stack row: 50% of 800 = 400
assert_eq!(layouts[1].bottom, 400);
// Second stack row: 30% of 800 = 240
assert_eq!(layouts[2].bottom, 240);
}
#[test]
fn test_vertical_stack_single_window() {
let area = test_area();
let len = NonZeroUsize::new(1).unwrap();
let opts = layout_options_with_column_ratios(&[0.6]);
let layouts = DefaultLayout::VerticalStack.calculate(
&area,
len,
None,
None,
&[],
0,
Some(opts),
&[],
);
assert_eq!(layouts.len(), 1);
// Single window should take full width
assert_eq!(layouts[0].right, 1000);
}
}
mod horizontal_stack_layout_tests {
use super::*;
#[test]
fn test_horizontal_stack_default_ratio() {
let area = test_area();
let len = NonZeroUsize::new(3).unwrap();
let layouts =
DefaultLayout::HorizontalStack.calculate(&area, len, None, None, &[], 0, None, &[]);
assert_eq!(layouts.len(), 3);
// Primary row should be 50% height (default ratio)
assert_eq!(layouts[0].bottom, 400);
}
#[test]
fn test_horizontal_stack_custom_ratio() {
let area = test_area();
let len = NonZeroUsize::new(3).unwrap();
let opts = layout_options_with_row_ratios(&[0.7]);
let layouts = DefaultLayout::HorizontalStack.calculate(
&area,
len,
None,
None,
&[],
0,
Some(opts),
&[],
);
assert_eq!(layouts.len(), 3);
// Primary row should be 70% height
assert_eq!(layouts[0].bottom, 560);
}
}
mod ultrawide_layout_tests {
use super::*;
#[test]
fn test_ultrawide_default_ratios() {
let area = test_area();
let len = NonZeroUsize::new(3).unwrap();
let layouts = DefaultLayout::UltrawideVerticalStack.calculate(
&area,
len,
None,
None,
&[],
0,
None,
&[],
);
assert_eq!(layouts.len(), 3);
// Primary (center): 50% = 500
assert_eq!(layouts[0].right, 500);
// Secondary (left): 25% = 250
assert_eq!(layouts[1].right, 250);
// Tertiary gets remaining: 250
assert_eq!(layouts[2].right, 250);
}
#[test]
fn test_ultrawide_custom_ratios() {
let area = test_area();
let len = NonZeroUsize::new(4).unwrap();
let opts = layout_options_with_column_ratios(&[0.5, 0.2]);
let layouts = DefaultLayout::UltrawideVerticalStack.calculate(
&area,
len,
None,
None,
&[],
0,
Some(opts),
&[],
);
assert_eq!(layouts.len(), 4);
// Primary (center): 50% = 500
assert_eq!(layouts[0].right, 500);
// Secondary (left): 20% = 200
assert_eq!(layouts[1].right, 200);
// Tertiary column gets remaining: 300
assert_eq!(layouts[2].right, 300);
assert_eq!(layouts[3].right, 300);
}
#[test]
fn test_ultrawide_two_windows() {
let area = test_area();
let len = NonZeroUsize::new(2).unwrap();
let opts = layout_options_with_column_ratios(&[0.6]);
let layouts = DefaultLayout::UltrawideVerticalStack.calculate(
&area,
len,
None,
None,
&[],
0,
Some(opts),
&[],
);
assert_eq!(layouts.len(), 2);
// Primary: 60% = 600
assert_eq!(layouts[0].right, 600);
// Secondary gets remaining: 400
assert_eq!(layouts[1].right, 400);
}
}
mod bsp_layout_tests {
use super::*;
#[test]
fn test_bsp_default_ratio() {
let area = test_area();
let len = NonZeroUsize::new(2).unwrap();
let layouts = DefaultLayout::BSP.calculate(&area, len, None, None, &[], 0, None, &[]);
assert_eq!(layouts.len(), 2);
// First window should be 50% width
assert_eq!(layouts[0].right, 500);
}
#[test]
fn test_bsp_custom_column_ratio() {
let area = test_area();
let len = NonZeroUsize::new(2).unwrap();
let opts = layout_options_with_column_ratios(&[0.7]);
let layouts =
DefaultLayout::BSP.calculate(&area, len, None, None, &[], 0, Some(opts), &[]);
assert_eq!(layouts.len(), 2);
// First window should be 70% width
assert_eq!(layouts[0].right, 700);
}
#[test]
fn test_bsp_custom_row_ratio() {
let area = test_area();
let len = NonZeroUsize::new(3).unwrap();
let opts = layout_options_with_ratios(&[0.5], &[0.7]);
let layouts =
DefaultLayout::BSP.calculate(&area, len, None, None, &[], 0, Some(opts), &[]);
assert_eq!(layouts.len(), 3);
// Second window should be 70% of remaining height
assert_eq!(layouts[1].bottom, 560);
}
}
mod right_main_vertical_stack_tests {
use super::*;
#[test]
fn test_right_main_default_ratio() {
let area = test_area();
let len = NonZeroUsize::new(3).unwrap();
let layouts = DefaultLayout::RightMainVerticalStack.calculate(
&area,
len,
None,
None,
&[],
0,
None,
&[],
);
assert_eq!(layouts.len(), 3);
// Primary should be on the right, 50% width
assert_eq!(layouts[0].right, 500);
assert_eq!(layouts[0].left, 500); // Right side
}
#[test]
fn test_right_main_custom_ratio() {
let area = test_area();
let len = NonZeroUsize::new(3).unwrap();
let opts = layout_options_with_column_ratios(&[0.6]);
let layouts = DefaultLayout::RightMainVerticalStack.calculate(
&area,
len,
None,
None,
&[],
0,
Some(opts),
&[],
);
assert_eq!(layouts.len(), 3);
// Primary: 60% = 600
assert_eq!(layouts[0].right, 600);
// Should be positioned on the right
assert_eq!(layouts[0].left, 400);
}
}
mod columns_layout_tests {
use super::*;
#[test]
fn test_columns_layout_with_ratios() {
let area = test_area();
let len = NonZeroUsize::new(3).unwrap();
let opts = layout_options_with_column_ratios(&[0.2, 0.5]);
let layouts =
DefaultLayout::Columns.calculate(&area, len, None, None, &[], 0, Some(opts), &[]);
assert_eq!(layouts.len(), 3);
assert_eq!(layouts[0].right, 200); // 20%
assert_eq!(layouts[1].right, 500); // 50%
assert_eq!(layouts[2].right, 300); // remaining
}
}
mod rows_layout_tests {
use super::*;
#[test]
fn test_rows_layout_with_ratios() {
let area = test_area();
let len = NonZeroUsize::new(3).unwrap();
let opts = layout_options_with_row_ratios(&[0.25, 0.5]);
let layouts =
DefaultLayout::Rows.calculate(&area, len, None, None, &[], 0, Some(opts), &[]);
assert_eq!(layouts.len(), 3);
assert_eq!(layouts[0].bottom, 200); // 25%
assert_eq!(layouts[1].bottom, 400); // 50%
assert_eq!(layouts[2].bottom, 200); // remaining
}
}
mod grid_layout_tests {
use super::*;
#[test]
fn test_grid_with_column_ratios() {
let area = test_area();
let len = NonZeroUsize::new(4).unwrap();
let opts = layout_options_with_column_ratios(&[0.3]);
let layouts =
DefaultLayout::Grid.calculate(&area, len, None, None, &[], 0, Some(opts), &[]);
assert_eq!(layouts.len(), 4);
// Grid with 4 windows should be 2x2
// First column: 30% = 300
assert_eq!(layouts[0].right, 300);
assert_eq!(layouts[1].right, 300);
}
#[test]
fn test_grid_without_ratios() {
let area = test_area();
let len = NonZeroUsize::new(4).unwrap();
let layouts = DefaultLayout::Grid.calculate(&area, len, None, None, &[], 0, None, &[]);
assert_eq!(layouts.len(), 4);
// 2x2 grid, equal columns = 500 each
assert_eq!(layouts[0].right, 500);
assert_eq!(layouts[2].right, 500);
}
}
mod layout_flip_tests {
use super::*;
#[test]
fn test_columns_flip_horizontal() {
let area = test_area();
let len = NonZeroUsize::new(3).unwrap();
let opts = layout_options_with_column_ratios(&[0.2, 0.3]);
let layouts = DefaultLayout::Columns.calculate(
&area,
len,
None,
Some(Axis::Horizontal),
&[],
0,
Some(opts),
&[],
);
assert_eq!(layouts.len(), 3);
// Columns should be reversed
// Last column (originally 50%) should now be first
assert_eq!(layouts[2].left, 0);
}
#[test]
fn test_rows_flip_vertical() {
let area = test_area();
let len = NonZeroUsize::new(3).unwrap();
let opts = layout_options_with_row_ratios(&[0.25, 0.5]);
let layouts = DefaultLayout::Rows.calculate(
&area,
len,
None,
Some(Axis::Vertical),
&[],
0,
Some(opts),
&[],
);
assert_eq!(layouts.len(), 3);
// Rows should be reversed
// Last row should now be at top
assert_eq!(layouts[2].top, 0);
}
}
mod container_padding_tests {
use super::*;
#[test]
fn test_padding_applied_to_all_layouts() {
let area = test_area();
let len = NonZeroUsize::new(2).unwrap();
let padding = 10;
let layouts = DefaultLayout::Columns.calculate(
&area,
len,
Some(padding),
None,
&[],
0,
None,
&[],
);
assert_eq!(layouts.len(), 2);
// Each layout should have padding applied
// left increases, right decreases, top increases, bottom decreases
assert_eq!(layouts[0].left, padding);
assert_eq!(layouts[0].top, padding);
assert_eq!(layouts[0].right, 500 - padding * 2);
assert_eq!(layouts[0].bottom, 800 - padding * 2);
}
}
}
#[path = "arrangement_tests.rs"]
mod tests;

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
[package]
name = "komorebi-themes"
version = "0.1.40"
version = "0.1.41"
edition = "2024"
[dependencies]

View File

@@ -1,6 +1,6 @@
[package]
name = "komorebi"
version = "0.1.40"
version = "0.1.41"
description = "A tiling window manager for Windows"
repository = "https://github.com/LGUG2Z/komorebi"
edition = "2024"

View File

@@ -451,7 +451,7 @@ pub enum AppSpecificConfigurationPath {
#[serde_with::serde_as]
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
/// The `komorebi.json` static configuration file reference for `v0.1.40`
/// The `komorebi.json` static configuration file reference for `v0.1.41`
pub struct StaticConfig {
/// DEPRECATED from v0.1.22: no longer required
#[deprecated(note = "No longer required")]

View File

@@ -1,6 +1,6 @@
[package]
name = "komorebic-no-console"
version = "0.1.40"
version = "0.1.41"
description = "The command-line interface (without a console) for Komorebi, a tiling window manager for Windows"
repository = "https://github.com/LGUG2Z/komorebi"
edition = "2024"

View File

@@ -1,6 +1,6 @@
[package]
name = "komorebic"
version = "0.1.40"
version = "0.1.41"
description = "The command-line interface for Komorebi, a tiling window manager for Windows"
repository = "https://github.com/LGUG2Z/komorebi"
edition = "2024"