Compare commits

..

1 Commits

Author SHA1 Message Date
LGUG2Z
557ef98ee5 feat(wm): add tiling and floating ws layers
This commit introduces an implementation of workspace layers to
komorebi.

Workspace layers change the kinds of windows that certain commands
operate on. This implementation features two variants,
WorkspaceLayer::Tiling and WorkspaceLayer::Floating.

The default behaviour until now has been WorkspaceLayer::Tiling.

When the user sets WorkspaceLayer::Floating, either through the
'toggle-workspace-layer' command or the new bar widget, the 'move',
'focus', 'cycle-focus' and 'resize-axis' commands will operate on
floating windows, if the currently focused window is a floating window.

As I don't have 'cycle-focus' bound to anything, 'focus up' and 'focus
down' double as incrementing and decrementing cycle focus commands,
iterating focus through the floating windows assigned to a workspace.

Floating windows in komorebi belong to specific workspaces, therefore
commands such as 'move' and 'resize-axis' will restrict movement and
resizing to the bounds of their workspace's work area (or more
accurately, the work area of the monitor that the workspace belongs to,
as floating windows are never constrained by workspace-specific work
area restrictions).
2025-02-22 12:54:33 -08:00
29 changed files with 678 additions and 1213 deletions

356
Cargo.lock generated
View File

@@ -285,14 +285,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df099ccb16cd014ff054ac1bf392c67feeef57164b05c42f037cd40f5d4357f4"
dependencies = [
"clipboard-win",
"core-graphics 0.23.2",
"image",
"log",
"objc2",
"objc2-app-kit",
"objc2-foundation",
"parking_lot",
"windows-sys 0.48.0",
"x11rb",
]
@@ -556,9 +553,9 @@ dependencies = [
[[package]]
name = "avif-serialize"
version = "0.8.3"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98922d6a4cfbcb08820c69d8eeccc05bb1f29bfa06b4f5b1dbfe9a868bd7608e"
checksum = "e335041290c43101ca215eed6f43ec437eb5a42125573f600fc3fa42b9bddd62"
dependencies = [
"arrayvec",
]
@@ -590,13 +587,13 @@ dependencies = [
[[package]]
name = "base16-egui-themes"
version = "0.1.0"
source = "git+https://github.com/LGUG2Z/base16-egui-themes?rev=96f26c88d83781f234d42222293ec73d23a39ad8#96f26c88d83781f234d42222293ec73d23a39ad8"
source = "git+https://github.com/LGUG2Z/base16-egui-themes?rev=911079d#911079d1ee7d60bbebf1f8e05d0e5a6bc596ad79"
dependencies = [
"egui",
"schemars",
"serde",
"strum 0.27.1",
"strum_macros 0.27.1",
"strum",
"strum_macros",
]
[[package]]
@@ -784,7 +781,7 @@ dependencies = [
[[package]]
name = "catppuccin-egui"
version = "5.3.1"
source = "git+https://github.com/LGUG2Z/catppuccin-egui?rev=bdaff30959512c4f7ee7304117076a48633d777f#bdaff30959512c4f7ee7304117076a48633d777f"
source = "git+https://github.com/LGUG2Z/catppuccin-egui?rev=f85cc3c#f85cc3ce187bab308bec7d50ca974d66578a5590"
dependencies = [
"egui",
]
@@ -828,6 +825,12 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cfg_aliases"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
[[package]]
name = "cfg_aliases"
version = "0.2.1"
@@ -845,9 +848,9 @@ dependencies = [
[[package]]
name = "chrono"
version = "0.4.40"
version = "0.4.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c"
checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825"
dependencies = [
"android-tzdata",
"iana-time-zone",
@@ -855,14 +858,14 @@ dependencies = [
"num-traits",
"serde",
"wasm-bindgen",
"windows-link",
"windows-targets 0.52.6",
]
[[package]]
name = "clap"
version = "4.5.31"
version = "4.5.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "027bb0d98429ae334a8698531da7077bdf906419543a35a55c2cb1b66437d767"
checksum = "92b7b18d71fad5313a1e320fa9897994228ce274b60faa4d694fe0ea89cd9e6d"
dependencies = [
"clap_builder",
"clap_derive",
@@ -870,9 +873,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.31"
version = "4.5.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5589e0cba072e0f3d23791efac0fd8627b49c829c196a492e88168e6a669d863"
checksum = "a35db2071778a7344791a4fb4f95308b5673d219dee3ae348b86642574ecc90c"
dependencies = [
"anstream",
"anstyle",
@@ -985,6 +988,12 @@ dependencies = [
"crossbeam-utils",
]
[[package]]
name = "const_fn"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f8a2ca5ac02d09563609681103aada9e1777d54fc57a5acd7a41404f9c93b6e"
[[package]]
name = "const_format"
version = "0.2.34"
@@ -1276,9 +1285,9 @@ checksum = "feeef44e73baff3a26d371801df019877a9866a8c493d315ab00177843314f35"
[[package]]
name = "ecolor"
version = "0.31.0"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "878e9005799dd739e5d5d89ff7480491c12d0af571d44399bcaefa1ee172dd76"
checksum = "7d72e9c39f6e11a2e922d04a34ec5e7ef522ea3f5a1acfca7a19d16ad5fe50f5"
dependencies = [
"bytemuck",
"emath",
@@ -1286,9 +1295,9 @@ dependencies = [
[[package]]
name = "eframe"
version = "0.31.0"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eba4c50d905804fe9ec4e159fde06b9d38f9440228617ab64a03d7a2091ece63"
checksum = "b2f2d9e7ea2d11ec9e98a8683b6eb99f9d7d0448394ef6e0d6d91bd4eb817220"
dependencies = [
"ahash",
"bytemuck",
@@ -1297,7 +1306,7 @@ dependencies = [
"egui-wgpu",
"egui-winit",
"egui_glow",
"glow",
"glow 0.16.0",
"glutin",
"glutin-winit",
"image",
@@ -1322,13 +1331,12 @@ dependencies = [
[[package]]
name = "egui"
version = "0.31.0"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d2768eaa6d5c80a6e2a008da1f0e062dff3c83eb2b28605ea2d0732d46e74d6"
checksum = "252d52224d35be1535d7fd1d6139ce071fb42c9097773e79f7665604f5596b5e"
dependencies = [
"accesskit",
"ahash",
"bitflags 2.8.0",
"emath",
"epaint",
"log",
@@ -1338,18 +1346,18 @@ dependencies = [
[[package]]
name = "egui-phosphor"
version = "0.9.0"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "171d57331491e92f0a7c73fad1088716e3200984309f4f8684731b750cee1378"
checksum = "ebe75c81cd796bfb6718df8a5339c47695bfb33e400fae03a77200305519f2c2"
dependencies = [
"egui",
]
[[package]]
name = "egui-wgpu"
version = "0.31.0"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d8151704bcef6271bec1806c51544d70e79ef20e8616e5eac01facfd9c8c54a"
checksum = "26c1e821d2d8921ef6ce98b258c7e24d9d6aab2ca1f9cdf374eca997e7f67f59"
dependencies = [
"ahash",
"bytemuck",
@@ -1367,14 +1375,13 @@ dependencies = [
[[package]]
name = "egui-winit"
version = "0.31.0"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ace791b367c1f63e6044aef2f3834904509d1d1a6912fd23ebf3f6a9af92cd84"
checksum = "1e84c2919cd9f3a38a91e8f84ac6a245c19251fd95226ed9fae61d5ea564fce3"
dependencies = [
"accesskit_winit",
"ahash",
"arboard",
"bytemuck",
"egui",
"log",
"profiling",
@@ -1387,9 +1394,9 @@ dependencies = [
[[package]]
name = "egui_extras"
version = "0.31.0"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b5cf69510eb3d19211fc0c062fb90524f43fe8e2c012967dcf0e2d81cb040f"
checksum = "3d7a8198c088b1007108cb2d403bc99a5e370999b200db4f14559610d7330126"
dependencies = [
"ahash",
"egui",
@@ -1401,14 +1408,14 @@ dependencies = [
[[package]]
name = "egui_glow"
version = "0.31.0"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a53e2374a964c3c793cb0b8ead81bca631f24974bc0b747d1a5622f4e39fdd0"
checksum = "3eaf6264cc7608e3e69a7d57a6175f438275f1b3889c1a551b418277721c95e6"
dependencies = [
"ahash",
"bytemuck",
"egui",
"glow",
"glow 0.16.0",
"log",
"memoffset",
"profiling",
@@ -1419,15 +1426,15 @@ dependencies = [
[[package]]
name = "either"
version = "1.14.0"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7914353092ddf589ad78f25c5c1c21b7f80b0ff8621e7c814c3485b5306da9d"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]]
name = "emath"
version = "0.31.0"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55b7b6be5ad1d247f11738b0e4699d9c20005ed366f2c29f5ec1f8e1de180bc2"
checksum = "c4fe73c1207b864ee40aa0b0c038d6092af1030744678c60188a05c28553515d"
dependencies = [
"bytemuck",
]
@@ -1497,9 +1504,9 @@ checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe"
[[package]]
name = "epaint"
version = "0.31.0"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "275b665a7b9611d8317485187e5458750850f9e64604d3c58434bb3fc1d22915"
checksum = "5666f8d25236293c966fbb3635eac18b04ad1914e3bab55bc7d44b9980cafcac"
dependencies = [
"ab_glyph",
"ahash",
@@ -1515,9 +1522,9 @@ dependencies = [
[[package]]
name = "epaint_default_fonts"
version = "0.31.0"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9343d356d7cac894dacafc161b4654e0881301097bdf32a122ed503d97cb94b6"
checksum = "66f6ddac3e6ac6fd4c3d48bb8b1943472f8da0f43a4303bcd8a18aa594401c80"
[[package]]
name = "equivalent"
@@ -1641,9 +1648,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
[[package]]
name = "flate2"
version = "1.1.0"
version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc"
checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c"
dependencies = [
"crc32fast",
"miniz_oxide 0.8.5",
@@ -1901,9 +1908,9 @@ dependencies = [
[[package]]
name = "getset"
version = "0.1.5"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3586f256131df87204eb733da72e3d3eb4f343c639f4b7be279ac7c48baeafe"
checksum = "eded738faa0e88d3abc9d1a13cb11adc2073c400969eeb8793cf7132589959fc"
dependencies = [
"proc-macro-error2",
"proc-macro2",
@@ -1951,6 +1958,18 @@ dependencies = [
"xml-rs",
]
[[package]]
name = "glow"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d51fa363f025f5c111e03f13eda21162faeacb6911fe8caa0c0349f9cf0c4483"
dependencies = [
"js-sys",
"slotmap",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "glow"
version = "0.16.0"
@@ -1970,7 +1989,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03642b8b0cce622392deb0ee3e88511f75df2daac806102597905c3ea1974848"
dependencies = [
"bitflags 2.8.0",
"cfg_aliases",
"cfg_aliases 0.2.1",
"cgl",
"core-foundation 0.9.4",
"dispatch",
@@ -1994,7 +2013,7 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85edca7075f8fc728f28cb8fbb111a96c3b89e930574369e3e9c27eb75d3788f"
dependencies = [
"cfg_aliases",
"cfg_aliases 0.2.1",
"glutin",
"raw-window-handle",
"winit",
@@ -2672,7 +2691,7 @@ dependencies = [
"serde_json_lenient",
"serde_yaml",
"shadow-rs",
"strum 0.27.1",
"strum",
"sysinfo",
"tracing",
"tracing-appender",
@@ -2756,7 +2775,7 @@ dependencies = [
"schemars",
"serde",
"serde_variant",
"strum 0.27.1",
"strum",
]
[[package]]
@@ -2829,9 +2848,9 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8"
[[package]]
name = "libc"
version = "0.2.170"
version = "0.2.169"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828"
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
[[package]]
name = "libfuzzer-sys"
@@ -2896,9 +2915,9 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
[[package]]
name = "litemap"
version = "0.7.5"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856"
checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104"
[[package]]
name = "litrs"
@@ -2994,9 +3013,9 @@ dependencies = [
[[package]]
name = "metal"
version = "0.31.0"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f569fb946490b5743ad69813cb19629130ce9374034abe31614a36402d18f99e"
checksum = "7ecfd3296f8c56b7c1f6fbac3c71cefa9d78ce009850c45000015f206dc7fa21"
dependencies = [
"bitflags 2.8.0",
"block",
@@ -3017,7 +3036,7 @@ dependencies = [
"backtrace-ext",
"cfg-if 1.0.0",
"miette-derive",
"owo-colors 4.2.0",
"owo-colors 4.1.0",
"supports-color",
"supports-hyperlinks",
"supports-unicode",
@@ -3113,23 +3132,22 @@ dependencies = [
[[package]]
name = "naga"
version = "24.0.0"
version = "23.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e380993072e52eef724eddfcde0ed013b0c023c3f0417336ed041aa9f076994e"
checksum = "364f94bc34f61332abebe8cad6f6cd82a5b65cff22c828d05d0968911462ca4f"
dependencies = [
"arrayvec",
"bit-set",
"bitflags 2.8.0",
"cfg_aliases",
"cfg_aliases 0.1.1",
"codespan-reporting",
"hexf-parse",
"indexmap",
"log",
"rustc-hash",
"spirv",
"strum 0.26.3",
"termcolor",
"thiserror 2.0.11",
"thiserror 1.0.69",
"unicode-xid",
]
@@ -3289,7 +3307,7 @@ checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
dependencies = [
"bitflags 2.8.0",
"cfg-if 1.0.0",
"cfg_aliases",
"cfg_aliases 0.2.1",
"libc",
"memoffset",
]
@@ -3773,15 +3791,6 @@ dependencies = [
"libredox",
]
[[package]]
name = "ordered-float"
version = "4.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951"
dependencies = [
"num-traits",
]
[[package]]
name = "ordered-stream"
version = "0.2.0"
@@ -3826,9 +3835,9 @@ checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
[[package]]
name = "owo-colors"
version = "4.2.0"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1036865bb9422d3300cf723f657c2851d0e9ab12567854b1f4eba3d77decf564"
checksum = "fb37767f6569cd834a413442455e0f066d0d522de8630436e2a1761d9726ba56"
[[package]]
name = "parking"
@@ -4358,9 +4367,9 @@ checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a"
[[package]]
name = "ring"
version = "0.17.11"
version = "0.17.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da5349ae27d3887ca812fb375b45a4fbb36d8d12d2df394968cd86e35683fe73"
checksum = "d34b5020fcdea098ef7d95e9f89ec15952123a4a039badd09fabebe9e963e839"
dependencies = [
"cc",
"cfg-if 1.0.0",
@@ -4466,9 +4475,9 @@ dependencies = [
[[package]]
name = "schemars"
version = "0.8.22"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615"
checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92"
dependencies = [
"dyn-clone",
"schemars_derive",
@@ -4478,9 +4487,9 @@ dependencies = [
[[package]]
name = "schemars_derive"
version = "0.8.22"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32e265784ad618884abaea0600a9adf15393368d840e0222d101a072f3f7534d"
checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e"
dependencies = [
"proc-macro2",
"quote",
@@ -4679,9 +4688,9 @@ dependencies = [
[[package]]
name = "shadow-rs"
version = "1.0.1"
version = "0.38.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3672eb035a31ac62bf171765d04e3f1f01659920847384d08ac979ca6bb56763"
checksum = "6ec14cc798c29f4bf74a6c4299c657c04d4e9fba03875c1f0eec569af03aed89"
dependencies = [
"const_format",
"git2",
@@ -4865,16 +4874,7 @@ version = "0.26.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
dependencies = [
"strum_macros 0.26.4",
]
[[package]]
name = "strum"
version = "0.27.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32"
dependencies = [
"strum_macros 0.27.1",
"strum_macros",
]
[[package]]
@@ -4890,19 +4890,6 @@ dependencies = [
"syn",
]
[[package]]
name = "strum_macros"
version = "0.27.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8"
dependencies = [
"heck",
"proc-macro2",
"quote",
"rustversion",
"syn",
]
[[package]]
name = "subtle"
version = "2.6.1"
@@ -5418,15 +5405,18 @@ checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
[[package]]
name = "tz-rs"
version = "0.7.0"
version = "0.6.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1450bf2b99397e72070e7935c89facaa80092ac812502200375f1f7d33c71a1"
checksum = "33851b15c848fad2cf4b105c6bb66eb9512b6f6c44a4b13f57c53c73c707e2b4"
dependencies = [
"const_fn",
]
[[package]]
name = "tzdb"
version = "0.7.2"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0be2ea5956f295449f47c0b825c5e109022ff1a6a53bb4f77682a87c2341fbf5"
checksum = "1b580f6b365fa89f5767cdb619a55d534d04a4e14c2d7e5b9a31e94598687fb1"
dependencies = [
"iana-time-zone",
"tz-rs",
@@ -5435,9 +5425,9 @@ dependencies = [
[[package]]
name = "tzdb_data"
version = "0.2.1"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0604b35c1f390a774fdb138cac75a99981078895d24bcab175987440bbff803b"
checksum = "d4471adcfcbd3052e8c5b5890a04a559837444b3be26b9cbbd622063171cec9d"
dependencies = [
"tz-rs",
]
@@ -5835,13 +5825,12 @@ checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082"
[[package]]
name = "wgpu"
version = "24.0.1"
version = "23.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47f55718f85c2fa756edffa0e7f0e0a60aba463d1362b57e23123c58f035e4b6"
checksum = "80f70000db37c469ea9d67defdc13024ddf9a5f1b89cb2941b812ad7cde1735a"
dependencies = [
"arrayvec",
"bitflags 2.8.0",
"cfg_aliases",
"cfg_aliases 0.1.1",
"document-features",
"js-sys",
"log",
@@ -5860,14 +5849,14 @@ dependencies = [
[[package]]
name = "wgpu-core"
version = "24.0.2"
version = "23.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "671c25545d479b47d3f0a8e373aceb2060b67c6eb841b24ac8c32348151c7a0c"
checksum = "d63c3c478de8e7e01786479919c8769f62a22eec16788d8c2ac77ce2c132778a"
dependencies = [
"arrayvec",
"bit-vec",
"bitflags 2.8.0",
"cfg_aliases",
"cfg_aliases 0.1.1",
"document-features",
"indexmap",
"log",
@@ -5878,25 +5867,25 @@ dependencies = [
"raw-window-handle",
"rustc-hash",
"smallvec",
"thiserror 2.0.11",
"thiserror 1.0.69",
"wgpu-hal",
"wgpu-types",
]
[[package]]
name = "wgpu-hal"
version = "24.0.2"
version = "23.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4317a17171dc20e6577bf606796794580accae0716a69edbc7388c86a3ec9f23"
checksum = "89364b8a0b211adc7b16aeaf1bd5ad4a919c1154b44c9ce27838213ba05fd821"
dependencies = [
"android_system_properties",
"arrayvec",
"ash",
"bitflags 2.8.0",
"bytemuck",
"cfg_aliases",
"cfg_aliases 0.1.1",
"core-graphics-types",
"glow",
"glow 0.14.2",
"glutin_wgl_sys",
"gpu-alloc",
"gpu-descriptor",
@@ -5910,14 +5899,13 @@ dependencies = [
"ndk-sys 0.5.0+25.2.9519653",
"objc",
"once_cell",
"ordered-float",
"parking_lot",
"profiling",
"raw-window-handle",
"renderdoc-sys",
"rustc-hash",
"smallvec",
"thiserror 2.0.11",
"thiserror 1.0.69",
"wasm-bindgen",
"web-sys",
"wgpu-types",
@@ -5926,13 +5914,12 @@ dependencies = [
[[package]]
name = "wgpu-types"
version = "24.0.0"
version = "23.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50ac044c0e76c03a0378e7786ac505d010a873665e2d51383dcff8dd227dc69c"
checksum = "610f6ff27778148c31093f3b03abc4840f9636d58d597ca2f5977433acfe0068"
dependencies = [
"bitflags 2.8.0",
"js-sys",
"log",
"web-sys",
]
@@ -5951,7 +5938,7 @@ dependencies = [
[[package]]
name = "win32-display-data"
version = "0.1.0"
source = "git+https://github.com/LGUG2Z/win32-display-data?rev=55cebdebfbd68dbd14945a1ba90f6b05b7be2893#55cebdebfbd68dbd14945a1ba90f6b05b7be2893"
source = "git+https://github.com/LGUG2Z/win32-display-data?rev=376523b9e1321e033b0b0ed0e6fa75a072b46ad9#376523b9e1321e033b0b0ed0e6fa75a072b46ad9"
dependencies = [
"itertools 0.14.0",
"serde",
@@ -6012,6 +5999,16 @@ dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f919aee0a93304be7f62e8e5027811bbba96bcb1de84d6618be56e43f8a32a1"
dependencies = [
"windows-core 0.59.0",
"windows-targets 0.53.0",
]
[[package]]
name = "windows"
version = "0.60.0"
@@ -6068,6 +6065,19 @@ dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-core"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "810ce18ed2112484b0d4e15d022e5f598113e220c53e373fb31e67e21670c1ce"
dependencies = [
"windows-implement 0.59.0",
"windows-interface 0.59.0",
"windows-result 0.3.1",
"windows-strings 0.3.1",
"windows-targets 0.53.0",
]
[[package]]
name = "windows-core"
version = "0.60.1"
@@ -6316,13 +6326,29 @@ dependencies = [
"windows_aarch64_gnullvm 0.52.6",
"windows_aarch64_msvc 0.52.6",
"windows_i686_gnu 0.52.6",
"windows_i686_gnullvm",
"windows_i686_gnullvm 0.52.6",
"windows_i686_msvc 0.52.6",
"windows_x86_64_gnu 0.52.6",
"windows_x86_64_gnullvm 0.52.6",
"windows_x86_64_msvc 0.52.6",
]
[[package]]
name = "windows-targets"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b"
dependencies = [
"windows_aarch64_gnullvm 0.53.0",
"windows_aarch64_msvc 0.53.0",
"windows_i686_gnu 0.53.0",
"windows_i686_gnullvm 0.53.0",
"windows_i686_msvc 0.53.0",
"windows_x86_64_gnu 0.53.0",
"windows_x86_64_gnullvm 0.53.0",
"windows_x86_64_msvc 0.53.0",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.2"
@@ -6341,6 +6367,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.2"
@@ -6359,6 +6391,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_aarch64_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
[[package]]
name = "windows_i686_gnu"
version = "0.42.2"
@@ -6377,12 +6415,24 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnu"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
[[package]]
name = "windows_i686_msvc"
version = "0.42.2"
@@ -6401,6 +6451,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_i686_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.2"
@@ -6419,6 +6475,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnu"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.2"
@@ -6437,6 +6499,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.2"
@@ -6455,6 +6523,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "windows_x86_64_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
[[package]]
name = "winit"
version = "0.30.9"
@@ -6468,7 +6542,7 @@ dependencies = [
"block2",
"bytemuck",
"calloop",
"cfg_aliases",
"cfg_aliases 0.2.1",
"concurrent-queue",
"core-foundation 0.9.4",
"core-graphics 0.23.2",
@@ -6552,17 +6626,17 @@ dependencies = [
[[package]]
name = "wmi"
version = "0.15.1"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae33d16f05f9b4b819abe7a9472bad4acb17f5b5d52d3f422762ebec613c65a6"
checksum = "58078b4e28f04064dae68f6e11a6b93133c83b88dfd5ae16738ded4942db6544"
dependencies = [
"chrono",
"futures",
"log",
"serde",
"thiserror 2.0.11",
"windows 0.60.0",
"windows-core 0.60.1",
"windows 0.59.0",
"windows-core 0.59.0",
]
[[package]]
@@ -6796,18 +6870,18 @@ dependencies = [
[[package]]
name = "zerofrom"
version = "0.1.6"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e"
dependencies = [
"zerofrom-derive",
]
[[package]]
name = "zerofrom-derive"
version = "0.1.6"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
dependencies = [
"proc-macro2",
"quote",

View File

@@ -17,8 +17,8 @@ chrono = "0.4"
crossbeam-channel = "0.5"
crossbeam-utils = "0.8"
color-eyre = "0.6"
eframe = "0.31"
egui_extras = "0.31"
eframe = "0.30"
egui_extras = "0.30"
dirs = "6"
dunce = "1"
hotwatch = "0.5"
@@ -27,19 +27,18 @@ lazy_static = "1"
serde = { version = "1", features = ["derive"] }
serde_json = { package = "serde_json_lenient", version = "0.2" }
serde_yaml = "0.9"
strum = { version = "0.27", features = ["derive"] }
tracing = "0.1"
tracing-appender = "0.2"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
paste = "1"
sysinfo = "0.33"
uds_windows = "1"
win32-display-data = { git = "https://github.com/LGUG2Z/win32-display-data", rev = "55cebdebfbd68dbd14945a1ba90f6b05b7be2893" }
win32-display-data = { git = "https://github.com/LGUG2Z/win32-display-data", rev = "376523b9e1321e033b0b0ed0e6fa75a072b46ad9" }
windows-numerics = { version = "0.1" }
windows-implement = { version = "0.59" }
windows-interface = { version = "0.59" }
windows-core = { version = "0.60" }
shadow-rs = "1"
shadow-rs = "0.38"
which = "7"
[workspace.dependencies.windows]
@@ -72,16 +71,3 @@ features = [
"Media",
"Media_Control"
]
[profile.dev-jeezy]
inherits = "dev"
debug = false
opt-level = 1
[profile.dev-jeezy.package."*"]
opt-level = 3
[profile.release-jeezy]
inherits = "release"
incremental = true
codegen-units = 256

View File

@@ -28,23 +28,11 @@ build-targets *targets:
"{{ targets }}" -split ' ' | ForEach-Object { just build-target $_ }
build-target target:
cargo +stable build --package {{ target }} --locked --profile release-jeezy
cargo +stable build --release --package {{ target }} --locked
build:
just build-targets komorebic komorebic-no-console komorebi komorebi-bar komorebi-gui
copy-target target:
cp .\target\release-jeezy\{{ target }}.exe $Env:USERPROFILE\.cargo\bin
copy-targets *targets:
"{{ targets }}" -split ' ' | ForEach-Object { just copy-target $_ }
wpm target:
just build-target {{ target }} && wpmctl stop {{ target }}; just copy-target {{ target }} && wpmctl start {{ target }}
copy:
just copy-targets komorebic komorebic-no-console komorebi komorebi-bar komorebi-gui
run target:
cargo +stable run --bin {{ target }} --locked

View File

@@ -16,7 +16,7 @@ crossbeam-channel = { workspace = true }
dirs = { workspace = true }
dunce = { workspace = true }
eframe = { workspace = true }
egui-phosphor = "0.9"
egui-phosphor = "0.8"
font-loader = "0.11"
hotwatch = { workspace = true }
image = "0.25"

View File

@@ -178,11 +178,11 @@ pub fn apply_theme(
{
if let Some(rounding) = config.rounding {
ctx.style_mut(|style| {
style.visuals.widgets.noninteractive.corner_radius = rounding.into();
style.visuals.widgets.inactive.corner_radius = rounding.into();
style.visuals.widgets.hovered.corner_radius = rounding.into();
style.visuals.widgets.active.corner_radius = rounding.into();
style.visuals.widgets.open.corner_radius = rounding.into();
style.visuals.widgets.noninteractive.rounding = rounding.into();
style.visuals.widgets.inactive.rounding = rounding.into();
style.visuals.widgets.hovered.rounding = rounding.into();
style.visuals.widgets.active.rounding = rounding.into();
style.visuals.widgets.open.rounding = rounding.into();
});
}
}
@@ -365,10 +365,10 @@ impl Komobar {
&SocketMessage::MonitorWorkAreaOffset(monitor_index, new_rect),
) {
tracing::error!(
"error applying work area offset to monitor '{monitor_index}': {error}"
"error applying work area offset to monitor '{}': {}",
monitor_index,
error,
);
} else {
tracing::info!("work area offset applied to monitor: {monitor_index}",);
}
}
}
@@ -502,12 +502,11 @@ impl Komobar {
{
if let Some(rounding) = config.rounding {
ctx.style_mut(|style| {
style.visuals.widgets.noninteractive.corner_radius =
rounding.into();
style.visuals.widgets.inactive.corner_radius = rounding.into();
style.visuals.widgets.hovered.corner_radius = rounding.into();
style.visuals.widgets.active.corner_radius = rounding.into();
style.visuals.widgets.open.corner_radius = rounding.into();
style.visuals.widgets.noninteractive.rounding = rounding.into();
style.visuals.widgets.inactive.rounding = rounding.into();
style.visuals.widgets.hovered.rounding = rounding.into();
style.visuals.widgets.active.rounding = rounding.into();
style.visuals.widgets.open.rounding = rounding.into();
});
}
}
@@ -624,13 +623,8 @@ impl Komobar {
pub fn position_bar(&self) {
if let Some(hwnd) = self.hwnd {
let window = komorebi_client::Window::from(hwnd);
match window.set_position(&self.size_rect, false) {
Ok(_) => {
tracing::info!("updated bar position");
}
Err(error) => {
tracing::error!("{error}")
}
if let Err(error) = window.set_position(&self.size_rect, false) {
tracing::error!("{}", error.to_string())
}
}
}
@@ -719,12 +713,6 @@ impl eframe::App for Komobar {
}
}
// Reset the current `work_area_offset` so that it gets recalculated and
// properly applied again, since if the monitor has connected for the first
// time it won't have the work_area_offset applied but the bar thinks it
// does.
self.work_area_offset = komorebi_client::Rect::default();
should_apply_config = true;
}
self.disabled = false;
@@ -840,26 +828,26 @@ impl eframe::App for Komobar {
let frame = match &self.config.padding {
None => {
if let Some(frame) = &self.config.frame {
Frame::NONE
Frame::none()
.inner_margin(Margin::symmetric(
frame.inner_margin.x as i8,
frame.inner_margin.y as i8,
frame.inner_margin.x,
frame.inner_margin.y,
))
.fill(*self.bg_color_with_alpha.borrow())
} else {
Frame::NONE
.inner_margin(Margin::same(0))
Frame::none()
.inner_margin(Margin::same(0.0))
.fill(*self.bg_color_with_alpha.borrow())
}
}
Some(padding) => {
let padding = padding.to_individual(DEFAULT_PADDING);
Frame::NONE
Frame::none()
.inner_margin(Margin {
top: padding.top as i8,
bottom: padding.bottom as i8,
left: padding.left as i8,
right: padding.right as i8,
top: padding.top,
bottom: padding.bottom,
left: padding.left,
right: padding.right,
})
.fill(*self.bg_color_with_alpha.borrow())
}
@@ -872,13 +860,13 @@ impl eframe::App for Komobar {
CentralPanel::default().frame(frame).show(ctx, |ui| {
// Apply grouping logic for the bar as a whole
let area_frame = if let Some(frame) = &self.config.frame {
Frame::NONE
.inner_margin(Margin::symmetric(0, frame.inner_margin.y as i8))
.outer_margin(Margin::same(0))
Frame::none()
.inner_margin(Margin::symmetric(0.0, frame.inner_margin.y))
.outer_margin(Margin::same(0.0))
} else {
Frame::NONE
.inner_margin(Margin::same(0))
.outer_margin(Margin::same(0))
Frame::none()
.inner_margin(Margin::same(0.0))
.outer_margin(Margin::same(0.0))
};
let available_height = ui.max_rect().max.y;
@@ -898,13 +886,13 @@ impl eframe::App for Komobar {
.as_ref()
.map(|s| s.to_individual(DEFAULT_PADDING))
{
left_area_frame.inner_margin.left = padding.left as i8;
left_area_frame.inner_margin.top = padding.top as i8;
left_area_frame.inner_margin.bottom = padding.bottom as i8;
left_area_frame.inner_margin.left = padding.left;
left_area_frame.inner_margin.top = padding.top;
left_area_frame.inner_margin.bottom = padding.bottom;
} else if let Some(frame) = &self.config.frame {
left_area_frame.inner_margin.left = frame.inner_margin.x as i8;
left_area_frame.inner_margin.top = frame.inner_margin.y as i8;
left_area_frame.inner_margin.bottom = frame.inner_margin.y as i8;
left_area_frame.inner_margin.left = frame.inner_margin.x;
left_area_frame.inner_margin.top = frame.inner_margin.y;
left_area_frame.inner_margin.bottom = frame.inner_margin.y;
}
left_area_frame.show(ui, |ui| {
@@ -934,13 +922,13 @@ impl eframe::App for Komobar {
.as_ref()
.map(|s| s.to_individual(DEFAULT_PADDING))
{
right_area_frame.inner_margin.right = padding.right as i8;
right_area_frame.inner_margin.top = padding.top as i8;
right_area_frame.inner_margin.bottom = padding.bottom as i8;
right_area_frame.inner_margin.right = padding.right;
right_area_frame.inner_margin.top = padding.top;
right_area_frame.inner_margin.bottom = padding.bottom;
} else if let Some(frame) = &self.config.frame {
right_area_frame.inner_margin.right = frame.inner_margin.x as i8;
right_area_frame.inner_margin.top = frame.inner_margin.y as i8;
right_area_frame.inner_margin.bottom = frame.inner_margin.y as i8;
right_area_frame.inner_margin.right = frame.inner_margin.x;
right_area_frame.inner_margin.top = frame.inner_margin.y;
right_area_frame.inner_margin.bottom = frame.inner_margin.y;
}
right_area_frame.show(ui, |ui| {
@@ -978,11 +966,11 @@ impl eframe::App for Komobar {
.as_ref()
.map(|s| s.to_individual(DEFAULT_PADDING))
{
center_area_frame.inner_margin.top = padding.top as i8;
center_area_frame.inner_margin.bottom = padding.bottom as i8;
center_area_frame.inner_margin.top = padding.top;
center_area_frame.inner_margin.bottom = padding.bottom;
} else if let Some(frame) = &self.config.frame {
center_area_frame.inner_margin.top = frame.inner_margin.y as i8;
center_area_frame.inner_margin.bottom = frame.inner_margin.y as i8;
center_area_frame.inner_margin.top = frame.inner_margin.y;
center_area_frame.inner_margin.bottom = frame.inner_margin.y;
}
center_area_frame.show(ui, |ui| {

View File

@@ -125,15 +125,6 @@ impl KomobarConfig {
}
}
}
pub fn show_all_icons_on_komorebi_workspace(widgets: &[WidgetConfig]) -> bool {
widgets
.iter()
.any(|w| matches!(w, WidgetConfig::Komorebi(config) if config.workspaces.is_some_and(|w| w.enable && w.display.is_some_and(|s| matches!(s,
WorkspacesDisplayFormat::AllIcons
| WorkspacesDisplayFormat::AllIconsAndText
| WorkspacesDisplayFormat::AllIconsAndTextOnSelected)))))
}
}
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
@@ -425,90 +416,3 @@ pub enum DisplayFormat {
/// Show an icon and text for the selected element, and icons on the rest
IconAndTextOnSelected,
}
macro_rules! extend_enum {
($existing_enum:ident, $new_enum:ident, { $($(#[$meta:meta])* $variant:ident),* $(,)? }) => {
#[derive(Copy, Clone, Debug, serde::Serialize, serde::Deserialize, schemars::JsonSchema, PartialEq)]
pub enum $new_enum {
// Add new variants
$(
$(#[$meta])*
$variant,
)*
// Include a variant that wraps the existing enum and flatten it when deserializing
#[serde(untagged)]
Existing($existing_enum),
}
// Implement From for the existing enum
impl From<$existing_enum> for $new_enum {
fn from(value: $existing_enum) -> Self {
$new_enum::Existing(value)
}
}
};
}
extend_enum!(DisplayFormat, WorkspacesDisplayFormat, {
/// Show all icons only
AllIcons,
/// Show both all icons and text
AllIconsAndText,
/// Show all icons and text for the selected element, and all icons on the rest
AllIconsAndTextOnSelected,
});
#[cfg(test)]
mod tests {
use schemars::JsonSchema;
use serde::Deserialize;
use serde::Serialize;
use serde_json::json;
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq)]
pub enum OriginalDisplayFormat {
/// Show None Of The Things
NoneOfTheThings,
}
extend_enum!(OriginalDisplayFormat, ExtendedDisplayFormat, {
/// Show Some Of The Things
SomeOfTheThings,
});
#[derive(serde::Deserialize)]
struct ExampleConfig {
#[allow(unused)]
format: ExtendedDisplayFormat,
}
#[test]
pub fn extend_new_variant() {
let raw = json!({
"format": "SomeOfTheThings",
})
.to_string();
assert!(serde_json::from_str::<ExampleConfig>(&raw).is_ok())
}
#[test]
pub fn extend_existing_variant() {
let raw = json!({
"format": "NoneOfTheThings",
})
.to_string();
assert!(serde_json::from_str::<ExampleConfig>(&raw).is_ok())
}
#[test]
pub fn extend_invalid_variant() {
let raw = json!({
"format": "ALLOFTHETHINGS",
})
.to_string();
assert!(serde_json::from_str::<ExampleConfig>(&raw).is_err())
}
}

View File

@@ -1,7 +1,6 @@
use crate::bar::apply_theme;
use crate::config::DisplayFormat;
use crate::config::KomobarTheme;
use crate::config::WorkspacesDisplayFormat;
use crate::komorebi_layout::KomorebiLayout;
use crate::render::Grouping;
use crate::render::RenderConfig;
@@ -15,15 +14,13 @@ use eframe::egui::vec2;
use eframe::egui::Color32;
use eframe::egui::ColorImage;
use eframe::egui::Context;
use eframe::egui::CornerRadius;
use eframe::egui::Frame;
use eframe::egui::Image;
use eframe::egui::Label;
use eframe::egui::Margin;
use eframe::egui::RichText;
use eframe::egui::Rounding;
use eframe::egui::Sense;
use eframe::egui::Stroke;
use eframe::egui::StrokeKind;
use eframe::egui::TextureHandle;
use eframe::egui::TextureOptions;
use eframe::egui::Ui;
@@ -68,7 +65,7 @@ pub struct KomorebiWorkspacesConfig {
/// Hide workspaces without any windows
pub hide_empty_workspaces: bool,
/// Display format of the workspace
pub display: Option<WorkspacesDisplayFormat>,
pub display: Option<DisplayFormat>,
}
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
@@ -159,92 +156,84 @@ impl BarWidget for Komorebi {
fn render(&mut self, ctx: &Context, ui: &mut Ui, config: &mut RenderConfig) {
let mut komorebi_notification_state = self.komorebi_notification_state.borrow_mut();
let icon_size = Vec2::splat(config.icon_font_id.size);
let text_size = Vec2::splat(config.text_font_id.size);
if let Some(workspaces) = self.workspaces {
if workspaces.enable {
let mut update = None;
if !komorebi_notification_state.workspaces.is_empty() {
let format = workspaces.display.unwrap_or(DisplayFormat::Text.into());
let format = workspaces.display.unwrap_or(DisplayFormat::Text);
config.apply_on_widget(false, ui, |ui| {
for (i, (ws, containers, _)) in
for (i, (ws, container_information, _)) in
komorebi_notification_state.workspaces.iter().enumerate()
{
let is_selected = komorebi_notification_state.selected_workspace.eq(ws);
if SelectableFrame::new(
is_selected,
komorebi_notification_state.selected_workspace.eq(ws),
)
.show(ui, |ui| {
let mut has_icon = false;
if format == WorkspacesDisplayFormat::AllIcons
|| format == WorkspacesDisplayFormat::AllIconsAndText
|| format == WorkspacesDisplayFormat::AllIconsAndTextOnSelected
|| format == DisplayFormat::Icon.into()
|| format == DisplayFormat::IconAndText.into()
|| format == DisplayFormat::IconAndTextOnSelected.into()
|| (format == DisplayFormat::TextAndIconOnSelected.into() && is_selected)
if format == DisplayFormat::Icon
|| format == DisplayFormat::IconAndText
|| format == DisplayFormat::IconAndTextOnSelected
|| (format == DisplayFormat::TextAndIconOnSelected
&& komorebi_notification_state.selected_workspace.eq(ws))
{
has_icon = containers.iter().any(|(_, container_info)| {
container_info.icons.iter().any(|icon| icon.is_some())
});
let icons: Vec<_> =
container_information.icons.iter().flatten().collect();
if has_icon {
Frame::NONE
if !icons.is_empty() {
Frame::none()
.inner_margin(Margin::same(
ui.style().spacing.button_padding.y as i8,
ui.style().spacing.button_padding.y,
))
.show(ui, |ui| {
for (is_focused, container) in containers {
for icon in container.icons.iter().flatten().collect::<Vec<_>>() {
ui.add(
Image::from(&img_to_texture(ctx, icon))
.maintain_aspect_ratio(true)
.fit_to_exact_size(if *is_focused { icon_size } else { text_size }),
);
for icon in icons {
ui.add(
Image::from(&img_to_texture(ctx, icon))
.maintain_aspect_ratio(true)
.fit_to_exact_size(icon_size),
);
if !has_icon {
has_icon = true;
}
}
});
}
}
// draw a custom icon when there is no app icon or text
if !has_icon && (matches!(format, WorkspacesDisplayFormat::AllIcons | WorkspacesDisplayFormat::Existing(DisplayFormat::Icon))
|| (!is_selected && matches!(format, WorkspacesDisplayFormat::AllIconsAndTextOnSelected | WorkspacesDisplayFormat::Existing(DisplayFormat::IconAndTextOnSelected)))) {
// draw a custom icon when there is no app icon
if match format {
DisplayFormat::Icon => !has_icon,
_ => false,
} {
let (response, painter) =
ui.allocate_painter(icon_size, Sense::hover());
let stroke = Stroke::new(
1.0,
if is_selected { ctx.style().visuals.selection.stroke.color} else { ui.style().visuals.text_color() },
ctx.style().visuals.selection.stroke.color,
);
let mut rect = response.rect;
let rounding = CornerRadius::same((rect.width() * 0.1) as u8);
let rounding = Rounding::same(rect.width() * 0.1);
rect = rect.shrink(stroke.width);
let c = rect.center();
let r = rect.width() / 2.0;
painter.rect_stroke(rect, rounding, stroke, StrokeKind::Outside);
painter.rect_stroke(rect, rounding, stroke);
painter.line_segment([c - vec2(r, r), c + vec2(r, r)], stroke);
response.on_hover_text(ws.to_string())
// add hover text when there are only icons
} else if match format {
WorkspacesDisplayFormat::AllIcons | WorkspacesDisplayFormat::Existing(DisplayFormat::Icon) => has_icon,
DisplayFormat::Icon => has_icon,
_ => false,
} {
ui.response().on_hover_text(ws.to_string())
// add label only
} else if (format != WorkspacesDisplayFormat::AllIconsAndTextOnSelected && format != DisplayFormat::IconAndTextOnSelected.into())
|| (is_selected && matches!(format, WorkspacesDisplayFormat::AllIconsAndTextOnSelected | WorkspacesDisplayFormat::Existing(DisplayFormat::IconAndTextOnSelected)))
} else if format != DisplayFormat::IconAndTextOnSelected
|| (format == DisplayFormat::IconAndTextOnSelected
&& komorebi_notification_state.selected_workspace.eq(ws))
{
if is_selected {
ui.add(Label::new(RichText::new(ws.to_string()).color(ctx.style().visuals.selection.stroke.color)).selectable(false))
}
else {
ui.add(Label::new(ws.to_string()).selectable(false))
}
ui.add(Label::new(ws.to_string()).selectable(false))
} else {
ui.response()
}
@@ -434,7 +423,6 @@ impl BarWidget for Komorebi {
for (i, (title, icon)) in iter.enumerate() {
let selected = i == focused_window_idx && len != 1;
let text_color = if selected { ctx.style().visuals.selection.stroke.color} else { ui.style().visuals.text_color() };
if SelectableFrame::new(selected)
.show(ui, |ui| {
@@ -454,9 +442,9 @@ impl BarWidget for Komorebi {
&& i == focused_window_idx)
{
if let Some(img) = icon {
Frame::NONE
Frame::none()
.inner_margin(Margin::same(
ui.style().spacing.button_padding.y as i8,
ui.style().spacing.button_padding.y,
))
.show(ui, |ui| {
let response = ui.add(
@@ -486,7 +474,7 @@ impl BarWidget for Komorebi {
MAX_LABEL_WIDTH.load(Ordering::SeqCst) as f32,
available_height,
),
Label::new(RichText::new( title).color(text_color)).selectable(false).truncate(),
Label::new(title).selectable(false).truncate(),
);
}
})
@@ -533,12 +521,11 @@ fn img_to_texture(ctx: &Context, rgba_image: &RgbaImage) -> TextureHandle {
ctx.load_texture("icon", color_image, TextureOptions::default())
}
#[allow(clippy::type_complexity)]
#[derive(Clone, Debug)]
pub struct KomorebiNotificationState {
pub workspaces: Vec<(
String,
Vec<(bool, KomorebiNotificationStateContainerInformation)>,
KomorebiNotificationStateContainerInformation,
WorkspaceLayer,
)>,
pub selected_workspace: String,
@@ -570,8 +557,6 @@ impl KomorebiNotificationState {
default_theme: Option<KomobarTheme>,
render_config: Rc<RefCell<RenderConfig>>,
) {
let show_all_icons = render_config.borrow().show_all_icons;
match notification.event {
NotificationEvent::WindowManager(_) => {}
NotificationEvent::Monitor(_) => {}
@@ -642,7 +627,6 @@ impl KomorebiNotificationState {
let focused_workspace_idx = monitor.focused_workspace_idx();
let mut workspaces = vec![];
self.selected_workspace = monitor.workspaces()[focused_workspace_idx]
.name()
.to_owned()
@@ -658,36 +642,7 @@ impl KomorebiNotificationState {
if should_show {
workspaces.push((
ws.name().to_owned().unwrap_or_else(|| format!("{}", i + 1)),
if show_all_icons {
let mut containers = vec![];
let mut has_monocle = false;
// add monocle container
if let Some(container) = ws.monocle_container() {
containers.push((true, container.into()));
has_monocle = true;
}
// add all tiled windows
for (i, container) in ws.containers().iter().enumerate() {
containers.push((
!has_monocle && i == ws.focused_container_idx(),
container.into(),
));
}
// add all floating windows
for floating_window in ws.floating_windows() {
containers.push((
!has_monocle && floating_window.is_focused(),
floating_window.into(),
));
}
containers
} else {
vec![(true, ws.into())]
},
ws.into(),
ws.layer().to_owned(),
));
}

View File

@@ -4,13 +4,12 @@ use crate::render::RenderConfig;
use crate::selected_frame::SelectableFrame;
use eframe::egui::vec2;
use eframe::egui::Context;
use eframe::egui::CornerRadius;
use eframe::egui::FontId;
use eframe::egui::Frame;
use eframe::egui::Label;
use eframe::egui::Rounding;
use eframe::egui::Sense;
use eframe::egui::Stroke;
use eframe::egui::StrokeKind;
use eframe::egui::Ui;
use eframe::egui::Vec2;
use komorebi_client::SocketMessage;
@@ -123,22 +122,18 @@ impl KomorebiLayout {
}
}
fn show_icon(&mut self, is_selected: bool, font_id: FontId, ctx: &Context, ui: &mut Ui) {
fn show_icon(&mut self, font_id: FontId, ctx: &Context, ui: &mut Ui) {
// paint custom icons for the layout
let size = Vec2::splat(font_id.size);
let (response, painter) = ui.allocate_painter(size, Sense::hover());
let color = if is_selected {
ctx.style().visuals.selection.stroke.color
} else {
ui.style().visuals.text_color()
};
let color = ctx.style().visuals.selection.stroke.color;
let stroke = Stroke::new(1.0, color);
let mut rect = response.rect;
let rounding = CornerRadius::same((rect.width() * 0.1) as u8);
let rounding = Rounding::same(rect.width() * 0.1);
rect = rect.shrink(stroke.width);
let c = rect.center();
let r = rect.width() / 2.0;
painter.rect_stroke(rect, rounding, stroke, StrokeKind::Outside);
painter.rect_stroke(rect, rounding, stroke);
match self {
KomorebiLayout::Default(layout) => match layout {
@@ -194,7 +189,7 @@ impl KomorebiLayout {
rect.width() * 0.35 + stroke.width,
));
painter.rect_filled(rect_left, rounding, color);
painter.rect_stroke(rect_right, rounding, stroke, StrokeKind::Outside);
painter.rect_stroke(rect_right, rounding, stroke);
}
KomorebiLayout::Paused => {
let mut rect_left = response.rect;
@@ -241,7 +236,7 @@ impl KomorebiLayout {
let layout_frame = SelectableFrame::new(false)
.show(ui, |ui| {
if let DisplayFormat::Icon | DisplayFormat::IconAndText = format {
self.show_icon(false, font_id.clone(), ctx, ui);
self.show_icon(font_id.clone(), ctx, ui);
}
if let DisplayFormat::Text | DisplayFormat::IconAndText = format {
@@ -256,7 +251,7 @@ impl KomorebiLayout {
if show_options {
if let Some(workspace_idx) = workspace_idx {
Frame::NONE.show(ui, |ui| {
Frame::none().show(ui, |ui| {
ui.add(
Label::new(egui_phosphor::regular::ARROW_FAT_LINES_RIGHT.to_string())
.selectable(false),
@@ -284,12 +279,8 @@ impl KomorebiLayout {
]);
for layout_option in &mut layout_options {
let is_selected = self == layout_option;
if SelectableFrame::new(is_selected)
.show(ui, |ui| {
layout_option.show_icon(is_selected, font_id.clone(), ctx, ui)
})
if SelectableFrame::new(self == layout_option)
.show(ui, |ui| layout_option.show_icon(font_id.clone(), ctx, ui))
.on_hover_text(match layout_option {
KomorebiLayout::Default(layout) => layout.to_string(),
KomorebiLayout::Monocle => "Toggle monocle".to_string(),

View File

@@ -3,14 +3,15 @@ use crate::config::KomobarConfig;
use crate::config::MonitorConfigOrIndex;
use eframe::egui::Color32;
use eframe::egui::Context;
use eframe::egui::CornerRadius;
use eframe::egui::FontId;
use eframe::egui::Frame;
use eframe::egui::InnerResponse;
use eframe::egui::Margin;
use eframe::egui::Rounding;
use eframe::egui::Shadow;
use eframe::egui::TextStyle;
use eframe::egui::Ui;
use eframe::egui::Vec2;
use schemars::JsonSchema;
use serde::Deserialize;
use serde::Serialize;
@@ -53,8 +54,6 @@ pub struct RenderConfig {
pub text_font_id: FontId,
/// FontId for icon (based on scaling the text font id)
pub icon_font_id: FontId,
/// Show all icons on the workspace section of the Komorebi widget
pub show_all_icons: bool,
}
pub trait RenderExt {
@@ -88,15 +87,6 @@ impl RenderExt for &KomobarConfig {
MonitorConfigOrIndex::Index(idx) => *idx,
};
// check if any of the alignments have a komorebi widget with the workspace set to show all icons
let show_all_icons =
KomobarConfig::show_all_icons_on_komorebi_workspace(&self.left_widgets)
|| self
.center_widgets
.as_ref()
.is_some_and(|list| KomobarConfig::show_all_icons_on_komorebi_workspace(list))
|| KomobarConfig::show_all_icons_on_komorebi_workspace(&self.right_widgets);
RenderConfig {
monitor_idx,
spacing: self.widget_spacing.unwrap_or(10.0),
@@ -107,7 +97,6 @@ impl RenderExt for &KomobarConfig {
applied_on_widget: false,
text_font_id,
icon_font_id,
show_all_icons,
}
}
}
@@ -132,7 +121,6 @@ impl RenderConfig {
applied_on_widget: false,
text_font_id: FontId::default(),
icon_font_id: FontId::default(),
show_all_icons: false,
}
}
@@ -147,10 +135,10 @@ impl RenderConfig {
return self.define_group_frame(
//TODO: this outer margin can be a config
Some(Margin {
left: 10,
right: 10,
top: 6,
bottom: 6,
left: 10.0,
right: 10.0,
top: 6.0,
bottom: 6.0,
}),
config,
ui_style,
@@ -203,11 +191,11 @@ impl RenderConfig {
ui: &mut Ui,
add_contents: impl FnOnce(&mut Ui) -> R,
) -> InnerResponse<R> {
Frame::NONE
Frame::none()
.outer_margin(outer_margin.unwrap_or(Margin::ZERO))
.inner_margin(match self.more_inner_margin {
true => Margin::symmetric(5, 0),
false => Margin::same(0),
true => Margin::symmetric(5.0, 0.0),
false => Margin::same(0.0),
})
.show(ui, add_contents)
}
@@ -232,13 +220,13 @@ impl RenderConfig {
Frame::group(ui_style)
.outer_margin(outer_margin.unwrap_or(Margin::ZERO))
.inner_margin(match self.more_inner_margin {
true => Margin::symmetric(6, 1),
false => Margin::symmetric(1, 1),
true => Margin::symmetric(6.0, 1.0),
false => Margin::symmetric(1.0, 1.0),
})
.stroke(ui_style.visuals.widgets.noninteractive.bg_stroke)
.corner_radius(match config.rounding {
.rounding(match config.rounding {
Some(rounding) => rounding.into(),
None => ui_style.visuals.widgets.noninteractive.corner_radius,
None => ui_style.visuals.widgets.noninteractive.rounding,
})
.fill(
self.background_color
@@ -249,27 +237,27 @@ impl RenderConfig {
// new styles can be added if needed here
GroupingStyle::Default => Shadow::NONE,
GroupingStyle::DefaultWithShadowB4O1S3 => Shadow {
blur: 4,
offset: [1, 1],
spread: 3,
blur: 4.0,
offset: Vec2::new(1.0, 1.0),
spread: 3.0,
color: Color32::BLACK.try_apply_alpha(config.transparency_alpha),
},
GroupingStyle::DefaultWithShadowB4O0S3 => Shadow {
blur: 4,
offset: [0, 0],
spread: 3,
blur: 4.0,
offset: Vec2::new(0.0, 0.0),
spread: 3.0,
color: Color32::BLACK.try_apply_alpha(config.transparency_alpha),
},
GroupingStyle::DefaultWithShadowB0O1S3 => Shadow {
blur: 0,
offset: [1, 1],
spread: 3,
blur: 0.0,
offset: Vec2::new(1.0, 1.0),
spread: 3.0,
color: Color32::BLACK.try_apply_alpha(config.transparency_alpha),
},
GroupingStyle::DefaultWithGlowB3O1S2 => Shadow {
blur: 3,
offset: [1, 1],
spread: 2,
blur: 3.0,
offset: Vec2::new(1.0, 1.0),
spread: 2.0,
color: ui_style
.visuals
.selection
@@ -278,9 +266,9 @@ impl RenderConfig {
.try_apply_alpha(config.transparency_alpha),
},
GroupingStyle::DefaultWithGlowB3O0S2 => Shadow {
blur: 3,
offset: [0, 0],
spread: 2,
blur: 3.0,
offset: Vec2::new(0.0, 0.0),
spread: 2.0,
color: ui_style
.visuals
.selection
@@ -289,9 +277,9 @@ impl RenderConfig {
.try_apply_alpha(config.transparency_alpha),
},
GroupingStyle::DefaultWithGlowB0O1S2 => Shadow {
blur: 0,
offset: [1, 1],
spread: 2,
blur: 0.0,
offset: Vec2::new(1.0, 1.0),
spread: 2.0,
color: ui_style
.visuals
.selection
@@ -307,9 +295,9 @@ impl RenderConfig {
fn widget_outer_margin(&mut self, ui: &mut Ui) -> Margin {
let spacing = if self.applied_on_widget {
// Remove the default item spacing from the margin
(self.spacing - ui.spacing().item_spacing.x) as i8
self.spacing - ui.spacing().item_spacing.x
} else {
0
0.0
};
if !self.applied_on_widget {
@@ -321,20 +309,20 @@ impl RenderConfig {
Some(align) => match align {
Alignment::Left => spacing,
Alignment::Center => spacing,
Alignment::Right => 0,
Alignment::Right => 0.0,
},
None => 0,
None => 0.0,
},
right: match self.alignment {
Some(align) => match align {
Alignment::Left => 0,
Alignment::Center => 0,
Alignment::Left => 0.0,
Alignment::Center => 0.0,
Alignment::Right => spacing,
},
None => 0,
None => 0.0,
},
top: 0,
bottom: 0,
top: 0.0,
bottom: 0.0,
}
}
}
@@ -378,19 +366,16 @@ pub enum RoundingConfig {
Individual([f32; 4]),
}
impl From<RoundingConfig> for CornerRadius {
impl From<RoundingConfig> for Rounding {
fn from(value: RoundingConfig) -> Self {
match value {
RoundingConfig::Same(value) => Self::same(value as u8),
RoundingConfig::Individual(values) => {
let values = values.map(|f| f as u8);
Self {
nw: values[0],
ne: values[1],
sw: values[2],
se: values[3],
}
}
RoundingConfig::Same(value) => Rounding::same(value),
RoundingConfig::Individual(values) => Self {
nw: values[0],
ne: values[1],
sw: values[2],
se: values[3],
},
}
}
}

View File

@@ -18,14 +18,14 @@ impl SelectableFrame {
pub fn show<R>(self, ui: &mut Ui, add_contents: impl FnOnce(&mut Ui) -> R) -> Response {
let Self { selected } = self;
Frame::NONE
Frame::none()
.show(ui, |ui| {
let response = ui.interact(ui.max_rect(), ui.unique_id(), Sense::click());
if ui.is_rect_visible(response.rect) {
let inner_margin = Margin::symmetric(
ui.style().spacing.button_padding.x as i8,
ui.style().spacing.button_padding.y as i8,
ui.style().spacing.button_padding.x,
ui.style().spacing.button_padding.y,
);
if selected
@@ -35,14 +35,14 @@ impl SelectableFrame {
{
let visuals = ui.style().interact_selectable(&response, selected);
Frame::NONE
Frame::none()
.stroke(visuals.bg_stroke)
.corner_radius(visuals.corner_radius)
.rounding(visuals.rounding)
.fill(visuals.bg_fill)
.inner_margin(inner_margin)
.show(ui, add_contents);
} else {
Frame::NONE
Frame::none()
.inner_margin(inner_margin)
.show(ui, add_contents);
}

View File

@@ -6,14 +6,13 @@ use crate::widget::BarWidget;
use eframe::egui::text::LayoutJob;
use eframe::egui::Align;
use eframe::egui::Context;
use eframe::egui::CornerRadius;
use eframe::egui::Label;
use eframe::egui::Rounding;
use eframe::egui::Sense;
use eframe::egui::Stroke;
use eframe::egui::TextFormat;
use eframe::egui::Ui;
use eframe::egui::Vec2;
use eframe::epaint::StrokeKind;
use schemars::JsonSchema;
use serde::Deserialize;
use serde::Serialize;
@@ -159,14 +158,14 @@ impl Time {
let color = ctx.style().visuals.text_color();
let stroke = Stroke::new(1.0, color);
let round_all = CornerRadius::same((response.rect.width() * 0.1) as u8);
let round_top = CornerRadius {
let round_all = Rounding::same(response.rect.width() * 0.1);
let round_top = Rounding {
nw: round_all.nw,
ne: round_all.ne,
..Default::default()
};
let round_none = CornerRadius::ZERO;
let round_bottom = CornerRadius {
let round_none = Rounding::ZERO;
let round_bottom = Rounding {
sw: round_all.nw,
se: round_all.ne,
..Default::default()
@@ -176,19 +175,14 @@ impl Time {
let mut rect = response.rect.shrink(stroke.width);
rect.set_height(rect.height() - height * 2.0);
rect = rect.translate(Vec2::new(0.0, height * 2.0));
painter.rect_stroke(rect, round_all, stroke, StrokeKind::Outside);
painter.rect_stroke(rect, round_all, stroke);
} else if max_power == 3 {
let mut rect = response.rect.shrink(stroke.width);
rect.set_height(rect.height() - height);
rect = rect.translate(Vec2::new(0.0, height));
painter.rect_stroke(rect, round_all, stroke, StrokeKind::Outside);
painter.rect_stroke(rect, round_all, stroke);
} else {
painter.rect_stroke(
response.rect.shrink(stroke.width),
round_all,
stroke,
StrokeKind::Outside,
);
painter.rect_stroke(response.rect.shrink(stroke.width), round_all, stroke);
}
let mut rect_bin = response.rect;

View File

@@ -48,7 +48,6 @@ pub use komorebi::ring::Ring;
pub use komorebi::window::Window;
pub use komorebi::window_manager_event::WindowManagerEvent;
pub use komorebi::workspace::Workspace;
pub use komorebi::workspace::WorkspaceGlobals;
pub use komorebi::workspace::WorkspaceLayer;
pub use komorebi::AnimationsConfig;
pub use komorebi::AspectRatio;

View File

@@ -4,11 +4,11 @@ version = "0.1.35"
edition = "2021"
[dependencies]
base16-egui-themes = { git = "https://github.com/LGUG2Z/base16-egui-themes", rev = "96f26c88d83781f234d42222293ec73d23a39ad8" }
catppuccin-egui = { git = "https://github.com/LGUG2Z/catppuccin-egui", rev = "bdaff30959512c4f7ee7304117076a48633d777f", default-features = false, features = ["egui31"] }
base16-egui-themes = { git = "https://github.com/LGUG2Z/base16-egui-themes", rev = "911079d" }
catppuccin-egui = { git = "https://github.com/LGUG2Z/catppuccin-egui", rev = "f85cc3c", default-features = false, features = ["egui30"] }
#catppuccin-egui = { version = "5", default-features = false, features = ["egui30"] }
eframe = { workspace = true }
schemars = { workspace = true }
serde = { workspace = true }
serde_variant = "0.1"
strum = { workspace = true }
strum = "0.26"

View File

@@ -34,7 +34,7 @@ serde = { workspace = true }
serde_json = { workspace = true }
serde_yaml = { workspace = true }
shadow-rs = { workspace = true }
strum = { workspace = true }
strum = { version = "0.26", features = ["derive"] }
sysinfo = { workspace = true }
tracing = { workspace = true }
tracing-appender = { workspace = true }

View File

@@ -475,11 +475,13 @@ impl Border {
});
// Get window kind and color
(*border_pointer).window_kind = FOCUS_STATE
.lock()
.get(&(window.0 as isize))
.copied()
.unwrap_or(WindowKind::Unfocused);
let window_kind = (*border_pointer).window_kind;
if let Some(brush) = (*border_pointer).brushes.get(&window_kind) {
render_target.BeginDraw();

View File

@@ -5,7 +5,6 @@ use crate::core::BorderImplementation;
use crate::core::BorderStyle;
use crate::core::WindowKind;
use crate::ring::Ring;
use crate::workspace::WorkspaceLayer;
use crate::workspace_reconciliator::ALT_TAB_HWND;
use crate::Colour;
use crate::Rgb;
@@ -113,7 +112,6 @@ pub fn destroy_all_borders() -> color_eyre::Result<()> {
borders.clear();
BORDERS_MONITORS.lock().clear();
WINDOWS_BORDERS.lock().clear();
FOCUS_STATE.lock().clear();
RENDER_TARGETS.lock().clear();
@@ -168,7 +166,6 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
let mut previous_pending_move_op = None;
let mut previous_is_paused = false;
let mut previous_notification: Option<Notification> = None;
let mut previous_layer = WorkspaceLayer::default();
'receiver: for notification in receiver {
// Check the wm state every time we receive a notification
@@ -185,9 +182,6 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
.iter()
.map(|w| w.hwnd)
.collect::<Vec<_>>();
let workspace_layer = *state.monitors.elements()[focused_monitor_idx].workspaces()
[focused_workspace_idx]
.layer();
let foreground_window = WindowsApi::foreground_window().unwrap_or_default();
drop(state);
@@ -301,7 +295,6 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
let mut borders = BORDER_STATE.lock();
let mut borders_monitors = BORDERS_MONITORS.lock();
let mut windows_borders = WINDOWS_BORDERS.lock();
let mut focus_state = FOCUS_STATE.lock();
// If borders are disabled
if !BORDER_ENABLED.load_consume()
@@ -316,9 +309,7 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
}
borders.clear();
borders_monitors.clear();
windows_borders.clear();
focus_state.clear();
previous_is_paused = is_paused;
continue 'receiver;
@@ -329,15 +320,19 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
if let Some(ws) = m.focused_workspace() {
// Workspaces with tiling disabled don't have borders
if !ws.tile() {
// Remove all borders on this monitor
remove_borders(
&mut borders,
&mut windows_borders,
&mut focus_state,
&mut borders_monitors,
monitor_idx,
|_, _| true,
)?;
let mut to_remove = vec![];
for (id, border) in borders.iter() {
if borders_monitors.get(id).copied().unwrap_or_default()
== monitor_idx
{
border.destroy()?;
to_remove.push(id.clone());
}
}
for id in &to_remove {
borders.remove(id);
}
continue 'monitors;
}
@@ -366,7 +361,10 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
WindowKind::Monocle
};
border.window_kind = new_focus_state;
focus_state.insert(border.hwnd, new_focus_state);
{
let mut focus_state = FOCUS_STATE.lock();
focus_state.insert(border.hwnd, new_focus_state);
}
let reference_hwnd =
monocle.focused_window().copied().unwrap_or_default().hwnd;
@@ -386,15 +384,20 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
);
let border_hwnd = border.hwnd;
// Remove all borders on this monitor except monocle
remove_borders(
&mut borders,
&mut windows_borders,
&mut focus_state,
&mut borders_monitors,
monitor_idx,
|_, b| border_hwnd != b.hwnd,
)?;
let mut to_remove = vec![];
for (id, b) in borders.iter() {
if borders_monitors.get(id).copied().unwrap_or_default()
== monitor_idx
&& border_hwnd != b.hwnd
{
b.destroy()?;
to_remove.push(id.clone());
}
}
for id in &to_remove {
borders.remove(id);
}
continue 'monitors;
}
@@ -406,20 +409,24 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
&& WindowsApi::is_zoomed(foreground_hwnd);
if is_maximized {
// Remove all borders on this monitor
remove_borders(
&mut borders,
&mut windows_borders,
&mut focus_state,
&mut borders_monitors,
monitor_idx,
|_, _| true,
)?;
let mut to_remove = vec![];
for (id, border) in borders.iter() {
if borders_monitors.get(id).copied().unwrap_or_default()
== monitor_idx
{
border.destroy()?;
to_remove.push(id.clone());
}
}
for id in &to_remove {
borders.remove(id);
}
continue 'monitors;
}
// Collect focused workspace container and floating windows ID's
// Destroy any borders not associated with the focused workspace
let mut container_and_floating_window_ids = ws
.containers()
.iter()
@@ -430,61 +437,30 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
container_and_floating_window_ids.push(w.hwnd.to_string());
}
// Remove any borders not associated with the focused workspace
remove_borders(
&mut borders,
&mut windows_borders,
&mut focus_state,
&mut borders_monitors,
monitor_idx,
|id, _| !container_and_floating_window_ids.contains(id),
)?;
let mut to_remove = vec![];
for (id, border) in borders.iter() {
if borders_monitors.get(id).copied().unwrap_or_default() == monitor_idx
&& !container_and_floating_window_ids.contains(id)
{
border.destroy()?;
to_remove.push(id.clone());
}
}
for id in &to_remove {
borders.remove(id);
}
'containers: for (idx, c) in ws.containers().iter().enumerate() {
// In case this container is a stack we need to check it's
// unfocused windows to remove any attached border
let is_stack = c.windows().len() > 1;
if is_stack {
let focused_window_idx = c.focused_window_idx();
let potential_stacked_border_handles = c
.windows()
.iter()
.enumerate()
.flat_map(|(i, w)| {
if i != focused_window_idx {
windows_borders.get(&w.hwnd).map(|b| b.hwnd)
} else {
None
}
})
.collect::<Vec<_>>();
if !potential_stacked_border_handles.is_empty() {
tracing::debug!(
"purging stacked borders: {:?}",
potential_stacked_border_handles
);
remove_borders(
&mut borders,
&mut windows_borders,
&mut focus_state,
&mut borders_monitors,
monitor_idx,
|_, b| potential_stacked_border_handles.contains(&b.hwnd),
)?;
}
}
let focused_window_hwnd =
c.focused_window().map(|w| w.hwnd).unwrap_or_default();
// Get the border entry for this container from the map or create one
let mut new_border = false;
let border = match borders.entry(c.id().clone()) {
Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => {
if let Ok(border) = Border::create(c.id(), focused_window_hwnd)
{
if let Ok(border) = Border::create(
c.id(),
c.focused_window().copied().unwrap_or_default().hwnd,
) {
new_border = true;
entry.insert(border)
} else {
@@ -498,7 +474,9 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
let new_focus_state = if idx != ws.focused_container_idx()
|| monitor_idx != focused_monitor_idx
|| focused_window_hwnd != foreground_window
|| c.focused_window()
.map(|w| w.hwnd != foreground_window)
.unwrap_or_default()
{
WindowKind::Unfocused
} else if c.windows().len() > 1 {
@@ -508,69 +486,34 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
};
border.window_kind = new_focus_state;
last_focus_state = focus_state.get(&border.hwnd).copied();
// If this container's border was previously tracking a different
// window, then we need to destroy that border and create a new one
// tracking the correct window.
if border.tracking_hwnd != focused_window_hwnd {
// Create new border
if let Ok(b) = Border::create(
c.id(),
c.focused_window().copied().unwrap_or_default().hwnd,
) {
// Destroy previously stacked border window and remove its hwnd
// and tracking_hwnd.
border.destroy()?;
focus_state.remove(&border.hwnd);
if let Some(previous) =
windows_borders.get(&border.tracking_hwnd)
{
// Only remove the border from `windows_borders` if it
// still is the same border, if it isn't then it means it
// was already updated by another border for that window
// and in that case we don't want to remove it.
if previous.hwnd == border.hwnd {
windows_borders.remove(&border.tracking_hwnd);
}
}
// Replace with new border
new_border = true;
*border = b;
} else {
continue 'monitors;
}
// Update the focused state for all containers on this workspace
{
let mut focus_state = FOCUS_STATE.lock();
last_focus_state = focus_state.insert(border.hwnd, new_focus_state);
}
let reference_hwnd =
c.focused_window().copied().unwrap_or_default().hwnd;
// avoid getting into a thread restart loop if we try to look up
// rect info for a window that has been destroyed by the time
// we get here
let rect = match WindowsApi::window_rect(focused_window_hwnd) {
let rect = match WindowsApi::window_rect(reference_hwnd) {
Ok(rect) => rect,
Err(_) => {
remove_border(
c.id(),
&mut borders,
&mut windows_borders,
&mut focus_state,
&mut borders_monitors,
)?;
let _ = border.destroy();
borders.remove(c.id());
continue 'containers;
}
};
let layer_changed = previous_layer != workspace_layer;
let should_invalidate = match last_focus_state {
None => true,
Some(last_focus_state) => {
(last_focus_state != new_focus_state) || layer_changed
}
Some(last_focus_state) => last_focus_state != new_focus_state,
};
if new_border || should_invalidate {
border.set_position(&rect, focused_window_hwnd)?;
border.set_position(&rect, reference_hwnd)?;
}
if should_invalidate {
@@ -582,7 +525,6 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
c.focused_window().cloned().unwrap_or_default().hwnd,
border.clone(),
);
focus_state.insert(border.hwnd, new_focus_state);
}
{
@@ -611,17 +553,17 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
}
border.window_kind = new_focus_state;
last_focus_state = focus_state.get(&border.hwnd).copied();
{
let mut focus_state = FOCUS_STATE.lock();
last_focus_state =
focus_state.insert(border.hwnd, new_focus_state);
}
let rect = WindowsApi::window_rect(window.hwnd)?;
let layer_changed = previous_layer != workspace_layer;
let should_invalidate = match last_focus_state {
None => true,
Some(last_focus_state) => {
last_focus_state != new_focus_state || layer_changed
}
Some(last_focus_state) => last_focus_state != new_focus_state,
};
if new_border {
@@ -634,7 +576,6 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
borders_monitors.insert(window.hwnd.to_string(), monitor_idx);
windows_borders.insert(window.hwnd, border.clone());
focus_state.insert(border.hwnd, new_focus_state);
}
}
}
@@ -646,58 +587,11 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
previous_pending_move_op = pending_move_op;
previous_is_paused = is_paused;
previous_notification = Some(notification);
previous_layer = workspace_layer;
}
Ok(())
}
/// Removes all borders from monitor with index `monitor_idx` filtered by
/// `condition`. This condition is a function that will take a reference to
/// the container id and the border and returns a bool, if true that border
/// will be removed.
fn remove_borders(
borders: &mut HashMap<String, Border>,
windows_borders: &mut HashMap<isize, Border>,
focus_state: &mut HashMap<isize, WindowKind>,
borders_monitors: &mut HashMap<String, usize>,
monitor_idx: usize,
condition: impl Fn(&String, &Border) -> bool,
) -> color_eyre::Result<()> {
let mut to_remove = vec![];
for (id, border) in borders.iter() {
if borders_monitors.get(id).copied().unwrap_or_default() == monitor_idx
&& condition(id, border)
{
to_remove.push(id.clone());
}
}
for id in &to_remove {
remove_border(id, borders, windows_borders, focus_state, borders_monitors)?;
}
Ok(())
}
/// Removes the border with `id` and all its related info from all maps
fn remove_border(
id: &str,
borders: &mut HashMap<String, Border>,
windows_borders: &mut HashMap<isize, Border>,
focus_state: &mut HashMap<isize, WindowKind>,
borders_monitors: &mut HashMap<String, usize>,
) -> color_eyre::Result<()> {
if let Some(removed_border) = borders.remove(id) {
removed_border.destroy()?;
windows_borders.remove(&removed_border.tracking_hwnd);
focus_state.remove(&removed_border.hwnd);
}
borders_monitors.remove(id);
Ok(())
}
#[derive(Debug, Copy, Clone, Display, Serialize, Deserialize, JsonSchema, PartialEq)]
pub enum ZOrder {
Top,

View File

@@ -244,10 +244,16 @@ fn main() -> Result<()> {
StaticConfig::postload(config, &wm)?;
}
listen_for_commands(wm.clone());
if !opts.await_configuration && !INITIAL_CONFIGURATION_LOADED.load(Ordering::SeqCst) {
INITIAL_CONFIGURATION_LOADED.store(true, Ordering::SeqCst);
};
if let Some(port) = opts.tcp_port {
listen_for_commands_tcp(wm.clone(), port);
}
if static_config.is_none() {
std::thread::spawn(|| load_configuration().expect("could not load configuration"));
@@ -274,27 +280,21 @@ fn main() -> Result<()> {
wm.lock().retile_all(false)?;
border_manager::listen_for_notifications(wm.clone());
stackbar_manager::listen_for_notifications(wm.clone());
transparency_manager::listen_for_notifications(wm.clone());
workspace_reconciliator::listen_for_notifications(wm.clone());
monitor_reconciliator::listen_for_notifications(wm.clone())?;
reaper::listen_for_notifications(wm.clone(), wm.lock().known_hwnds.clone());
focus_manager::listen_for_notifications(wm.clone());
theme_manager::listen_for_notifications();
listen_for_commands(wm.clone());
if let Some(port) = opts.tcp_port {
listen_for_commands_tcp(wm.clone(), port);
}
listen_for_events(wm.clone());
if CUSTOM_FFM.load(Ordering::SeqCst) {
listen_for_movements(wm.clone());
}
border_manager::listen_for_notifications(wm.clone());
stackbar_manager::listen_for_notifications(wm.clone());
transparency_manager::listen_for_notifications(wm.clone());
workspace_reconciliator::listen_for_notifications(wm.clone());
monitor_reconciliator::listen_for_notifications(wm.clone())?;
reaper::listen_for_notifications(wm.clone());
focus_manager::listen_for_notifications(wm.clone());
theme_manager::listen_for_notifications();
let (ctrlc_sender, ctrlc_receiver) = crossbeam_channel::bounded(1);
ctrlc::set_handler(move || {
ctrlc_sender

View File

@@ -1,6 +1,5 @@
use std::collections::HashMap;
use std::collections::VecDeque;
use std::sync::atomic::Ordering;
use color_eyre::eyre::anyhow;
use color_eyre::eyre::bail;
@@ -22,8 +21,6 @@ use crate::DefaultLayout;
use crate::Layout;
use crate::OperationDirection;
use crate::WindowsApi;
use crate::DEFAULT_CONTAINER_PADDING;
use crate::DEFAULT_WORKSPACE_PADDING;
#[derive(
Debug,
@@ -64,10 +61,6 @@ pub struct Monitor {
pub last_focused_workspace: Option<usize>,
#[getset(get_mut = "pub")]
pub workspace_names: HashMap<usize, String>,
#[getset(get_copy = "pub", set = "pub")]
pub container_padding: Option<i32>,
#[getset(get_copy = "pub", set = "pub")]
pub workspace_padding: Option<i32>,
}
impl_ring_elements!(Monitor, Workspace);
@@ -121,8 +114,6 @@ pub fn new(
workspaces,
last_focused_workspace: None,
workspace_names: HashMap::default(),
container_padding: None,
workspace_padding: None,
}
}
@@ -162,8 +153,6 @@ impl Monitor {
workspaces: Default::default(),
last_focused_workspace: None,
workspace_names: Default::default(),
container_padding: None,
workspace_padding: None,
}
}
@@ -186,52 +175,6 @@ impl Monitor {
Ok(())
}
/// Updates the `globals` field of all workspaces
pub fn update_workspaces_globals(&mut self, offset: Option<Rect>) {
let container_padding = self
.container_padding()
.or(Some(DEFAULT_CONTAINER_PADDING.load(Ordering::SeqCst)));
let workspace_padding = self
.workspace_padding()
.or(Some(DEFAULT_WORKSPACE_PADDING.load(Ordering::SeqCst)));
let work_area = *self.work_area_size();
let offset = self.work_area_offset.or(offset);
let window_based_work_area_offset = self.window_based_work_area_offset();
let limit = self.window_based_work_area_offset_limit();
for workspace in self.workspaces_mut() {
workspace.globals_mut().container_padding = container_padding;
workspace.globals_mut().workspace_padding = workspace_padding;
workspace.globals_mut().work_area = work_area;
workspace.globals_mut().work_area_offset = offset;
workspace.globals_mut().window_based_work_area_offset = window_based_work_area_offset;
workspace.globals_mut().window_based_work_area_offset_limit = limit;
}
}
/// Updates the `globals` field of workspace with index `workspace_idx`
pub fn update_workspace_globals(&mut self, workspace_idx: usize, offset: Option<Rect>) {
let container_padding = self
.container_padding()
.or(Some(DEFAULT_CONTAINER_PADDING.load(Ordering::SeqCst)));
let workspace_padding = self
.workspace_padding()
.or(Some(DEFAULT_WORKSPACE_PADDING.load(Ordering::SeqCst)));
let work_area = *self.work_area_size();
let offset = self.work_area_offset.or(offset);
let window_based_work_area_offset = self.window_based_work_area_offset();
let limit = self.window_based_work_area_offset_limit();
if let Some(workspace) = self.workspaces_mut().get_mut(workspace_idx) {
workspace.globals_mut().container_padding = container_padding;
workspace.globals_mut().workspace_padding = workspace_padding;
workspace.globals_mut().work_area = work_area;
workspace.globals_mut().work_area_offset = offset;
workspace.globals_mut().window_based_work_area_offset = window_based_work_area_offset;
workspace.globals_mut().window_based_work_area_offset_limit = limit;
}
}
pub fn add_container(
&mut self,
container: Container,
@@ -458,17 +401,21 @@ impl Monitor {
}
pub fn update_focused_workspace(&mut self, offset: Option<Rect>) -> Result<()> {
let work_area = *self.work_area_size();
let window_based_work_area_offset = (
self.window_based_work_area_offset_limit(),
self.window_based_work_area_offset(),
);
let offset = if self.work_area_offset().is_some() {
self.work_area_offset()
} else {
offset
};
let focused_workspace_idx = self.focused_workspace_idx();
self.update_workspace_globals(focused_workspace_idx, offset);
self.focused_workspace_mut()
.ok_or_else(|| anyhow!("there is no workspace"))?
.update()?;
.update(&work_area, offset, window_based_work_area_offset)?;
Ok(())
}

View File

@@ -264,7 +264,6 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
|| attached.device_id().eq(monitor.device_id())
{
monitor.set_id(attached.id());
monitor.set_device(attached.device().clone());
monitor.set_device_id(attached.device_id().clone());
monitor.set_serial_number_id(attached.serial_number_id().clone());
monitor.set_name(attached.name().clone());
@@ -463,31 +462,9 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
tracing::info!("found monitor and workspace configuration for {id} in the monitor cache, applying");
// If it does, update the cached monitor info with the new one and
// load the cached monitor removing any window that has since been
// closed or moved to another workspace
*m = Monitor {
// Data that should be the one just read from `win32-display-data`
id: m.id,
name: m.name.clone(),
device: m.device.clone(),
device_id: m.device_id.clone(),
serial_number_id: m.serial_number_id.clone(),
size: m.size,
work_area_size: m.work_area_size,
// The rest should come from the cached monitor
work_area_offset: cached.work_area_offset,
window_based_work_area_offset: cached
.window_based_work_area_offset,
window_based_work_area_offset_limit: cached
.window_based_work_area_offset_limit,
workspaces: cached.workspaces.clone(),
last_focused_workspace: cached.last_focused_workspace,
workspace_names: cached.workspace_names.clone(),
container_padding: cached.container_padding,
workspace_padding: cached.workspace_padding,
};
// If it does, load the monitor removing any window that has since
// been closed or moved to another workspace
*m = cached.clone();
let focused_workspace_idx = m.focused_workspace_idx();

View File

@@ -1049,45 +1049,24 @@ impl WindowManager {
let mouse_follows_focus = self.mouse_follows_focus;
let workspace = self.focused_workspace_mut()?;
let mut to_focus = None;
match workspace.layer() {
WorkspaceLayer::Tiling => {
workspace.set_layer(WorkspaceLayer::Floating);
for (i, window) in workspace.floating_windows().iter().enumerate() {
if i == 0 {
to_focus = Some(*window);
}
window.raise()?;
}
for container in workspace.containers() {
if let Some(window) = container.focused_window() {
window.lower()?;
}
if let Some(first) = workspace.floating_windows().first() {
first.focus(mouse_follows_focus)?;
}
}
WorkspaceLayer::Floating => {
workspace.set_layer(WorkspaceLayer::Tiling);
let focused_container_idx = workspace.focused_container_idx();
for (i, container) in workspace.containers_mut().iter_mut().enumerate() {
if let Some(container) = workspace.focused_container() {
if let Some(window) = container.focused_window() {
if i == focused_container_idx {
to_focus = Some(*window);
}
window.raise()?;
window.focus(mouse_follows_focus)?;
}
}
for window in workspace.floating_windows() {
window.lower()?;
}
}
};
if let Some(window) = to_focus {
window.focus(mouse_follows_focus)?;
}
}
SocketMessage::Stop => {
self.stop(false)?;

View File

@@ -26,7 +26,6 @@ use crate::window_manager::WindowManager;
use crate::window_manager_event::WindowManagerEvent;
use crate::windows_api::WindowsApi;
use crate::winevent::WinEvent;
use crate::workspace::WorkspaceLayer;
use crate::workspace_reconciliator;
use crate::workspace_reconciliator::ALT_TAB_HWND;
use crate::workspace_reconciliator::ALT_TAB_HWND_INSTANT;
@@ -281,12 +280,10 @@ impl WindowManager {
} else {
workspace.focus_container_by_window(window.hwnd)?;
}
workspace.set_layer(WorkspaceLayer::Tiling);
}
Some(idx) => {
if let Some(_window) = workspace.floating_windows().get(idx) {
workspace.set_layer(WorkspaceLayer::Floating);
if let Some(window) = workspace.floating_windows().get(idx) {
window.focus(false)?;
}
}
}
@@ -396,13 +393,11 @@ impl WindowManager {
if behaviour.float_override {
workspace.floating_windows_mut().push(window);
workspace.set_layer(WorkspaceLayer::Floating);
self.update_focused_workspace(false, false)?;
} else {
match behaviour.current_behaviour {
WindowContainerBehaviour::Create => {
workspace.new_container_for_window(window);
workspace.set_layer(WorkspaceLayer::Tiling);
self.update_focused_workspace(false, false)?;
}
WindowContainerBehaviour::Append => {
@@ -412,7 +407,6 @@ impl WindowManager {
anyhow!("there is no focused container")
})?
.add_window(window);
workspace.set_layer(WorkspaceLayer::Tiling);
self.update_focused_workspace(true, false)?;
stackbar_manager::send_notification();
}

View File

@@ -47,11 +47,8 @@ pub fn send_notification(hwnds: HashMap<isize, (usize, usize)>) {
}
}
pub fn listen_for_notifications(
wm: Arc<Mutex<WindowManager>>,
known_hwnds: HashMap<isize, (usize, usize)>,
) {
watch_for_orphans(known_hwnds);
pub fn listen_for_notifications(wm: Arc<Mutex<WindowManager>>) {
watch_for_orphans(wm.clone());
std::thread::spawn(move || loop {
match handle_notifications(wm.clone()) {
@@ -73,12 +70,24 @@ fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result<()>
for notification in receiver {
let orphan_hwnds = notification.0;
let mut wm = wm.lock();
let offset = wm.work_area_offset;
let mut update_borders = false;
for (hwnd, (m_idx, w_idx)) in orphan_hwnds.iter() {
if let Some(monitor) = wm.monitors_mut().get_mut(*m_idx) {
let focused_workspace_idx = monitor.focused_workspace_idx();
let work_area = *monitor.work_area_size();
let window_based_work_area_offset = (
monitor.window_based_work_area_offset_limit(),
monitor.window_based_work_area_offset(),
);
let offset = if monitor.work_area_offset().is_some() {
monitor.work_area_offset()
} else {
offset
};
if let Some(workspace) = monitor.workspaces_mut().get_mut(*w_idx) {
// Remove orphan window
@@ -96,7 +105,7 @@ fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result<()>
// If this is not a focused workspace there is no need to update the
// workspace or the borders. That will already be done when the user
// changes to this workspace.
workspace.update()?;
workspace.update(&work_area, offset, window_based_work_area_offset)?;
update_borders = true;
}
tracing::info!(
@@ -141,11 +150,11 @@ fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result<()>
Ok(())
}
fn watch_for_orphans(known_hwnds: HashMap<isize, (usize, usize)>) {
fn watch_for_orphans(wm: Arc<Mutex<WindowManager>>) {
// Cache current hwnds
{
let mut cache = HWNDS_CACHE.lock();
*cache = known_hwnds;
*cache = wm.lock().known_hwnds.clone();
}
std::thread::spawn(move || loop {

View File

@@ -140,7 +140,7 @@ pub struct WorkspaceConfig {
/// Container padding (default: global)
#[serde(skip_serializing_if = "Option::is_none")]
pub container_padding: Option<i32>,
/// Workspace padding (default: global)
/// Container padding (default: global)
#[serde(skip_serializing_if = "Option::is_none")]
pub workspace_padding: Option<i32>,
/// Initial workspace application rules
@@ -256,12 +256,6 @@ pub struct MonitorConfig {
/// Open window limit after which the window based work area offset will no longer be applied (default: 1)
#[serde(skip_serializing_if = "Option::is_none")]
pub window_based_work_area_offset_limit: Option<isize>,
/// Container padding (default: global)
#[serde(skip_serializing_if = "Option::is_none")]
pub container_padding: Option<i32>,
/// Workspace padding (default: global)
#[serde(skip_serializing_if = "Option::is_none")]
pub workspace_padding: Option<i32>,
}
impl From<&Monitor> for MonitorConfig {
@@ -271,32 +265,11 @@ impl From<&Monitor> for MonitorConfig {
workspaces.push(WorkspaceConfig::from(w));
}
let default_container_padding = DEFAULT_CONTAINER_PADDING.load(Ordering::SeqCst);
let default_workspace_padding = DEFAULT_WORKSPACE_PADDING.load(Ordering::SeqCst);
let container_padding = value.container_padding().and_then(|container_padding| {
if container_padding == default_container_padding {
None
} else {
Option::from(container_padding)
}
});
let workspace_padding = value.workspace_padding().and_then(|workspace_padding| {
if workspace_padding == default_workspace_padding {
None
} else {
Option::from(workspace_padding)
}
});
Self {
workspaces,
work_area_offset: value.work_area_offset(),
window_based_work_area_offset: value.window_based_work_area_offset(),
window_based_work_area_offset_limit: Some(value.window_based_work_area_offset_limit()),
container_padding,
workspace_padding,
}
}
}
@@ -1277,7 +1250,6 @@ impl StaticConfig {
workspace_matching_rules.clear();
drop(workspace_matching_rules);
let offset = wm.work_area_offset;
for (i, monitor) in wm.monitors_mut().iter_mut().enumerate() {
let preferred_config_idx = {
let display_index_preferences = DISPLAY_INDEX_PREFERENCES.lock();
@@ -1323,10 +1295,7 @@ impl StaticConfig {
.window_based_work_area_offset_limit
.unwrap_or(1),
);
monitor.set_container_padding(monitor_config.container_padding);
monitor.set_workspace_padding(monitor_config.workspace_padding);
monitor.update_workspaces_globals(offset);
for (j, ws) in monitor.workspaces_mut().iter_mut().enumerate() {
if let Some(workspace_config) = monitor_config.workspaces.get(j) {
ws.load_static_config(workspace_config)?;
@@ -1408,10 +1377,6 @@ impl StaticConfig {
.window_based_work_area_offset_limit
.unwrap_or(1),
);
m.set_container_padding(monitor_config.container_padding);
m.set_workspace_padding(monitor_config.workspace_padding);
m.update_workspaces_globals(offset);
for (j, ws) in m.workspaces_mut().iter_mut().enumerate() {
if let Some(workspace_config) = monitor_config.workspaces.get(j) {
@@ -1446,7 +1411,6 @@ impl StaticConfig {
workspace_matching_rules.clear();
drop(workspace_matching_rules);
let offset = wm.work_area_offset;
for (i, monitor) in wm.monitors_mut().iter_mut().enumerate() {
let preferred_config_idx = {
let display_index_preferences = DISPLAY_INDEX_PREFERENCES.lock();
@@ -1494,10 +1458,6 @@ impl StaticConfig {
.window_based_work_area_offset_limit
.unwrap_or(1),
);
monitor.set_container_padding(monitor_config.container_padding);
monitor.set_workspace_padding(monitor_config.workspace_padding);
monitor.update_workspaces_globals(offset);
for (j, ws) in monitor.workspaces_mut().iter_mut().enumerate() {
if let Some(workspace_config) = monitor_config.workspaces.get(j) {
@@ -1580,10 +1540,6 @@ impl StaticConfig {
.window_based_work_area_offset_limit
.unwrap_or(1),
);
m.set_container_padding(monitor_config.container_padding);
m.set_workspace_padding(monitor_config.workspace_padding);
m.update_workspaces_globals(offset);
for (j, ws) in m.workspaces_mut().iter_mut().enumerate() {
if let Some(workspace_config) = monitor_config.workspaces.get(j) {

View File

@@ -736,30 +736,6 @@ impl Window {
self.update_style(&style)
}
/// Raise the window to the top of the Z order, but do not activate or focus
/// it. Use raise_and_focus_window to activate and focus a window.
/// It also checks if there is a border attached to this window and if it is
/// it raises it as well.
pub fn raise(self) -> Result<()> {
WindowsApi::raise_window(self.hwnd)?;
if let Some(border) = crate::border_manager::window_border(self.hwnd) {
WindowsApi::raise_window(border.hwnd)?;
}
Ok(())
}
/// Lower the window to the bottom of the Z order, but do not activate or focus
/// it.
/// It also checks if there is a border attached to this window and if it is
/// it lowers it as well.
pub fn lower(self) -> Result<()> {
WindowsApi::lower_window(self.hwnd)?;
if let Some(border) = crate::border_manager::window_border(self.hwnd) {
WindowsApi::lower_window(border.hwnd)?;
}
Ok(())
}
#[tracing::instrument(fields(exe, title), skip(debug))]
pub fn should_manage(
self,

View File

@@ -337,7 +337,6 @@ impl From<&WindowManager> for State {
.clone(),
float_override: workspace.float_override,
layer: workspace.layer,
globals: workspace.globals,
workspace_config: None,
})
.collect::<VecDeque<_>>();
@@ -346,8 +345,6 @@ impl From<&WindowManager> for State {
},
last_focused_workspace: monitor.last_focused_workspace,
workspace_names: monitor.workspace_names.clone(),
container_padding: monitor.container_padding,
workspace_padding: monitor.workspace_padding,
})
.collect::<VecDeque<_>>();
stripped_monitors.focus(wm.monitors.focused_idx());
@@ -982,15 +979,18 @@ impl WindowManager {
let offset = self.work_area_offset;
for monitor in self.monitors_mut() {
let work_area = *monitor.work_area_size();
let window_based_work_area_offset = (
monitor.window_based_work_area_offset_limit(),
monitor.window_based_work_area_offset(),
);
let offset = if monitor.work_area_offset().is_some() {
monitor.work_area_offset()
} else {
offset
};
let focused_workspace_idx = monitor.focused_workspace_idx();
monitor.update_workspace_globals(focused_workspace_idx, offset);
let workspace = monitor
.focused_workspace_mut()
.ok_or_else(|| anyhow!("there is no workspace"))?;
@@ -1002,7 +1002,7 @@ impl WindowManager {
}
}
workspace.update()?;
workspace.update(&work_area, offset, window_based_work_area_offset)?;
}
Ok(())
@@ -1704,7 +1704,6 @@ impl WindowManager {
return Ok(());
}
let mouse_follows_focus = self.mouse_follows_focus;
let offset = self.work_area_offset;
let first_focused_workspace = {
let first_monitor = self
.monitors()
@@ -1749,13 +1748,11 @@ impl WindowManager {
// Set the focused workspaces for the first and second monitors
if let Some(first_monitor) = self.monitors_mut().get_mut(first_idx) {
first_monitor.update_workspaces_globals(offset);
first_monitor.focus_workspace(second_focused_workspace)?;
first_monitor.load_focused_workspace(mouse_follows_focus)?;
}
if let Some(second_monitor) = self.monitors_mut().get_mut(second_idx) {
second_monitor.update_workspaces_globals(offset);
second_monitor.focus_workspace(first_focused_workspace)?;
second_monitor.load_focused_workspace(mouse_follows_focus)?;
}
@@ -1923,22 +1920,13 @@ impl WindowManager {
pub fn remove_focused_workspace(&mut self) -> Option<Workspace> {
let focused_monitor: &mut Monitor = self.focused_monitor_mut()?;
let focused_workspace_idx = focused_monitor.focused_workspace_idx();
let workspace = focused_monitor.remove_workspace_by_idx(focused_workspace_idx);
if let Err(error) = focused_monitor.focus_workspace(focused_workspace_idx.saturating_sub(1))
{
tracing::error!(
"Error focusing previous workspace while removing the focused workspace: {}",
error
);
}
workspace
focused_monitor.remove_workspace_by_idx(focused_workspace_idx)
}
#[tracing::instrument(skip(self))]
pub fn move_workspace_to_monitor(&mut self, idx: usize) -> Result<()> {
tracing::info!("moving workspace");
let mouse_follows_focus = self.mouse_follows_focus;
let offset = self.work_area_offset;
let workspace = self
.remove_focused_workspace()
.ok_or_else(|| anyhow!("there is no workspace"))?;
@@ -1950,7 +1938,6 @@ impl WindowManager {
.ok_or_else(|| anyhow!("there is no monitor"))?;
target_monitor.workspaces_mut().push_back(workspace);
target_monitor.update_workspaces_globals(offset);
target_monitor.focus_workspace(target_monitor.workspaces().len().saturating_sub(1))?;
target_monitor.load_focused_workspace(mouse_follows_focus)?;
}
@@ -2683,16 +2670,12 @@ impl WindowManager {
anyhow!("this is not a valid direction from the current position")
})?;
let mut changed_focus = false;
let adjusted_new_index = if new_idx > current_container_idx
&& !matches!(
workspace.layout(),
Layout::Default(DefaultLayout::Grid)
| Layout::Default(DefaultLayout::UltrawideVerticalStack)
) {
workspace.focus_container(new_idx);
changed_focus = true;
new_idx.saturating_sub(1)
} else {
new_idx
@@ -2709,22 +2692,12 @@ impl WindowManager {
if let Some(current) = workspace.focused_container() {
if current.windows().len() > 1 && !target_container_is_stack {
workspace.focus_container(adjusted_new_index);
changed_focus = true;
workspace.move_window_to_container(current_container_idx)?;
} else {
workspace.move_window_to_container(adjusted_new_index)?;
}
}
if changed_focus {
if let Some(container) = workspace.focused_container_mut() {
container.load_focused_window();
if let Some(window) = container.focused_window() {
window.focus(self.mouse_follows_focus)?;
}
}
}
self.update_focused_workspace(self.mouse_follows_focus, false)?;
}
@@ -2808,10 +2781,8 @@ impl WindowManager {
}
if is_floating_window {
workspace.set_layer(WorkspaceLayer::Tiling);
self.unfloat_window()?;
} else {
workspace.set_layer(WorkspaceLayer::Floating);
self.float_window()?;
}
@@ -2872,10 +2843,6 @@ impl WindowManager {
container.hide(None);
}
for window in workspace.floating_windows_mut() {
window.hide();
}
Ok(())
}
@@ -2889,10 +2856,6 @@ impl WindowManager {
container.restore();
}
for window in workspace.floating_windows_mut() {
window.restore();
}
workspace.reintegrate_monocle_container()
}
@@ -3109,6 +3072,7 @@ impl WindowManager {
) -> Result<()> {
tracing::info!("setting workspace layout");
let offset = self.work_area_offset;
let focused_monitor_idx = self.focused_monitor_idx();
let monitor = self
@@ -3116,7 +3080,18 @@ impl WindowManager {
.get_mut(monitor_idx)
.ok_or_else(|| anyhow!("there is no monitor"))?;
let work_area = *monitor.work_area_size();
let window_based_work_area_offset = (
monitor.window_based_work_area_offset_limit(),
monitor.window_based_work_area_offset(),
);
let focused_workspace_idx = monitor.focused_workspace_idx();
let offset = if monitor.work_area_offset().is_some() {
monitor.work_area_offset()
} else {
offset
};
let workspace = monitor
.workspaces_mut()
@@ -3130,7 +3105,7 @@ impl WindowManager {
// If this is the focused workspace on a non-focused screen, let's update it
if focused_monitor_idx != monitor_idx && focused_workspace_idx == workspace_idx {
workspace.update()?;
workspace.update(&work_area, offset, window_based_work_area_offset)?;
Ok(())
} else {
Ok(self.update_focused_workspace(false, false)?)
@@ -3150,6 +3125,7 @@ impl WindowManager {
{
tracing::info!("setting workspace layout");
let offset = self.work_area_offset;
let focused_monitor_idx = self.focused_monitor_idx();
let monitor = self
@@ -3157,7 +3133,18 @@ impl WindowManager {
.get_mut(monitor_idx)
.ok_or_else(|| anyhow!("there is no monitor"))?;
let work_area = *monitor.work_area_size();
let window_based_work_area_offset = (
monitor.window_based_work_area_offset_limit(),
monitor.window_based_work_area_offset(),
);
let focused_workspace_idx = monitor.focused_workspace_idx();
let offset = if monitor.work_area_offset().is_some() {
monitor.work_area_offset()
} else {
offset
};
let workspace = monitor
.workspaces_mut()
@@ -3173,7 +3160,7 @@ impl WindowManager {
// If this is the focused workspace on a non-focused screen, let's update it
if focused_monitor_idx != monitor_idx && focused_workspace_idx == workspace_idx {
workspace.update()?;
workspace.update(&work_area, offset, window_based_work_area_offset)?;
Ok(())
} else {
Ok(self.update_focused_workspace(false, false)?)
@@ -3188,6 +3175,7 @@ impl WindowManager {
) -> Result<()> {
tracing::info!("setting workspace layout");
let offset = self.work_area_offset;
let focused_monitor_idx = self.focused_monitor_idx();
let monitor = self
@@ -3195,7 +3183,18 @@ impl WindowManager {
.get_mut(monitor_idx)
.ok_or_else(|| anyhow!("there is no monitor"))?;
let work_area = *monitor.work_area_size();
let window_based_work_area_offset = (
monitor.window_based_work_area_offset_limit(),
monitor.window_based_work_area_offset(),
);
let focused_workspace_idx = monitor.focused_workspace_idx();
let offset = if monitor.work_area_offset().is_some() {
monitor.work_area_offset()
} else {
offset
};
let workspace = monitor
.workspaces_mut()
@@ -3207,7 +3206,7 @@ impl WindowManager {
// If this is the focused workspace on a non-focused screen, let's update it
if focused_monitor_idx != monitor_idx && focused_workspace_idx == workspace_idx {
workspace.update()?;
workspace.update(&work_area, offset, window_based_work_area_offset)?;
Ok(())
} else {
Ok(self.update_focused_workspace(false, false)?)
@@ -3223,6 +3222,7 @@ impl WindowManager {
) -> Result<()> {
tracing::info!("setting workspace layout");
let offset = self.work_area_offset;
let focused_monitor_idx = self.focused_monitor_idx();
let monitor = self
@@ -3230,7 +3230,18 @@ impl WindowManager {
.get_mut(monitor_idx)
.ok_or_else(|| anyhow!("there is no monitor"))?;
let work_area = *monitor.work_area_size();
let window_based_work_area_offset = (
monitor.window_based_work_area_offset_limit(),
monitor.window_based_work_area_offset(),
);
let focused_workspace_idx = monitor.focused_workspace_idx();
let offset = if monitor.work_area_offset().is_some() {
monitor.work_area_offset()
} else {
offset
};
let workspace = monitor
.workspaces_mut()
@@ -3241,7 +3252,7 @@ impl WindowManager {
// If this is the focused workspace on a non-focused screen, let's update it
if focused_monitor_idx != monitor_idx && focused_workspace_idx == workspace_idx {
workspace.update()?;
workspace.update(&work_area, offset, window_based_work_area_offset)?;
Ok(())
} else {
Ok(self.update_focused_workspace(false, false)?)
@@ -3260,6 +3271,7 @@ impl WindowManager {
{
tracing::info!("setting workspace layout");
let layout = CustomLayout::from_path(path)?;
let offset = self.work_area_offset;
let focused_monitor_idx = self.focused_monitor_idx();
let monitor = self
@@ -3267,7 +3279,18 @@ impl WindowManager {
.get_mut(monitor_idx)
.ok_or_else(|| anyhow!("there is no monitor"))?;
let work_area = *monitor.work_area_size();
let window_based_work_area_offset = (
monitor.window_based_work_area_offset_limit(),
monitor.window_based_work_area_offset(),
);
let focused_workspace_idx = monitor.focused_workspace_idx();
let offset = if monitor.work_area_offset().is_some() {
monitor.work_area_offset()
} else {
offset
};
let workspace = monitor
.workspaces_mut()
@@ -3279,7 +3302,7 @@ impl WindowManager {
// If this is the focused workspace on a non-focused screen, let's update it
if focused_monitor_idx != monitor_idx && focused_workspace_idx == workspace_idx {
workspace.update()?;
workspace.update(&work_area, offset, window_based_work_area_offset)?;
Ok(())
} else {
Ok(self.update_focused_workspace(false, false)?)

View File

@@ -109,7 +109,6 @@ use windows::Win32::UI::WindowsAndMessaging::GWL_EXSTYLE;
use windows::Win32::UI::WindowsAndMessaging::GWL_STYLE;
use windows::Win32::UI::WindowsAndMessaging::GW_HWNDNEXT;
use windows::Win32::UI::WindowsAndMessaging::HDEVNOTIFY;
use windows::Win32::UI::WindowsAndMessaging::HWND_BOTTOM;
use windows::Win32::UI::WindowsAndMessaging::HWND_TOP;
use windows::Win32::UI::WindowsAndMessaging::LWA_ALPHA;
use windows::Win32::UI::WindowsAndMessaging::REGISTER_NOTIFICATION_FLAGS;
@@ -478,13 +477,10 @@ impl WindowsApi {
unsafe { BringWindowToTop(HWND(as_ptr!(hwnd))) }.process()
}
/// Raise the window to the top of the Z order, but do not activate or focus
/// it. Use raise_and_focus_window to activate and focus a window.
// Raise the window to the top of the Z order, but do not activate or focus
// it. Use raise_and_focus_window to activate and focus a window.
pub fn raise_window(hwnd: isize) -> Result<()> {
let flags = SetWindowPosition::NO_MOVE
| SetWindowPosition::NO_SIZE
| SetWindowPosition::NO_ACTIVATE
| SetWindowPosition::SHOW_WINDOW;
let flags = SetWindowPosition::NO_MOVE | SetWindowPosition::NO_ACTIVATE;
let position = HWND_TOP;
Self::set_window_pos(
@@ -495,23 +491,6 @@ impl WindowsApi {
)
}
/// Lower the window to the bottom of the Z order, but do not activate or focus
/// it.
pub fn lower_window(hwnd: isize) -> Result<()> {
let flags = SetWindowPosition::NO_MOVE
| SetWindowPosition::NO_SIZE
| SetWindowPosition::NO_ACTIVATE
| SetWindowPosition::SHOW_WINDOW;
let position = HWND_BOTTOM;
Self::set_window_pos(
HWND(as_ptr!(hwnd)),
&Rect::default(),
position,
flags.bits(),
)
}
pub fn set_border_pos(hwnd: isize, layout: &Rect, position: isize) -> Result<()> {
let flags = {
SetWindowPosition::NO_SEND_CHANGING

View File

@@ -95,8 +95,6 @@ pub struct Workspace {
#[getset(get = "pub", get_mut = "pub", set = "pub")]
pub float_override: Option<bool>,
#[getset(get = "pub", get_mut = "pub", set = "pub")]
pub globals: WorkspaceGlobals,
#[getset(get = "pub", get_mut = "pub", set = "pub")]
pub layer: WorkspaceLayer,
#[serde(skip_serializing_if = "Option::is_none")]
#[getset(get = "pub", set = "pub")]
@@ -143,9 +141,8 @@ impl Default for Workspace {
window_container_behaviour: None,
window_container_behaviour_rules: None,
float_override: None,
layer: Default::default(),
globals: Default::default(),
workspace_config: None,
layer: Default::default(),
}
}
}
@@ -158,37 +155,21 @@ pub enum WorkspaceWindowLocation {
Floating(usize), // idx in floating_windows
}
#[derive(
Debug,
Default,
Copy,
Clone,
Serialize,
Deserialize,
Getters,
CopyGetters,
MutGetters,
Setters,
JsonSchema,
PartialEq,
)]
/// Settings setup either by the parent monitor or by the `WindowManager`
pub struct WorkspaceGlobals {
pub container_padding: Option<i32>,
pub workspace_padding: Option<i32>,
pub work_area: Rect,
pub work_area_offset: Option<Rect>,
pub window_based_work_area_offset: Option<Rect>,
pub window_based_work_area_offset_limit: isize,
}
impl Workspace {
pub fn load_static_config(&mut self, config: &WorkspaceConfig) -> Result<()> {
self.name = Option::from(config.name.clone());
self.set_container_padding(config.container_padding);
if config.container_padding.is_some() {
self.set_container_padding(config.container_padding);
} else {
self.set_container_padding(Some(DEFAULT_CONTAINER_PADDING.load(Ordering::SeqCst)));
}
self.set_workspace_padding(config.workspace_padding);
if config.workspace_padding.is_some() {
self.set_workspace_padding(config.workspace_padding);
} else {
self.set_container_padding(Some(DEFAULT_WORKSPACE_PADDING.load(Ordering::SeqCst)));
}
if let Some(layout) = &config.layout {
self.layout = Layout::Default(*layout);
@@ -322,7 +303,7 @@ impl Workspace {
// Maximised windows and floating windows should always be drawn at the top of the Z order
// when switching to a workspace
if let Some(window) = to_focus {
if self.maximized_window().is_none() && matches!(self.layer, WorkspaceLayer::Tiling) {
if self.maximized_window().is_none() && self.floating_windows().is_empty() {
window.focus(mouse_follows_focus)?;
} else if let Some(maximized_window) = self.maximized_window() {
maximized_window.focus(mouse_follows_focus)?;
@@ -334,29 +315,24 @@ impl Workspace {
Ok(())
}
pub fn update(&mut self) -> Result<()> {
pub fn update(
&mut self,
work_area: &Rect,
work_area_offset: Option<Rect>,
window_based_work_area_offset: (isize, Option<Rect>),
) -> Result<()> {
if !INITIAL_CONFIGURATION_LOADED.load(Ordering::SeqCst) {
return Ok(());
}
let container_padding = self
.container_padding()
.or(self.globals().container_padding)
.unwrap_or_default();
let workspace_padding = self
.workspace_padding()
.or(self.globals().workspace_padding)
.unwrap_or_default();
let work_area = self.globals().work_area;
let work_area_offset = self.globals().work_area_offset;
let window_based_work_area_offset = self.globals().window_based_work_area_offset;
let window_based_work_area_offset_limit =
self.globals().window_based_work_area_offset_limit;
let (window_based_work_area_offset_limit, window_based_work_area_offset) =
window_based_work_area_offset;
let container_padding = self.container_padding();
let mut adjusted_work_area = work_area_offset.map_or_else(
|| work_area,
|| *work_area,
|offset| {
let mut with_offset = work_area;
let mut with_offset = *work_area;
with_offset.left += offset.left;
with_offset.top += offset.top;
with_offset.right -= offset.right;
@@ -384,7 +360,7 @@ impl Workspace {
);
}
adjusted_work_area.add_padding(workspace_padding);
adjusted_work_area.add_padding(self.workspace_padding().unwrap_or_default());
self.enforce_resize_constraints();
@@ -418,7 +394,7 @@ impl Workspace {
if *self.tile() {
if let Some(container) = self.monocle_container_mut() {
if let Some(window) = container.focused_window_mut() {
adjusted_work_area.add_padding(container_padding);
adjusted_work_area.add_padding(container_padding.unwrap_or_default());
{
let border_offset = BORDER_OFFSET.load(Ordering::SeqCst);
adjusted_work_area.add_padding(border_offset);
@@ -437,7 +413,7 @@ impl Workspace {
"there must be at least one container to calculate a workspace layout"
)
})?,
Some(container_padding),
self.container_padding(),
self.layout_flip(),
self.resize_dimensions(),
);
@@ -446,6 +422,7 @@ impl Workspace {
let no_titlebar = NO_TITLEBAR.lock().clone();
let regex_identifiers = REGEX_IDENTIFIERS.lock().clone();
let container_padding = self.container_padding().unwrap_or(0);
let containers = self.containers_mut();
for (i, container) in containers.iter_mut().enumerate() {

View File

@@ -529,73 +529,39 @@
"description": "Display format of the workspace",
"oneOf": [
{
"description": "Show all icons only",
"description": "Show only icon",
"type": "string",
"enum": [
"AllIcons"
"Icon"
]
},
{
"description": "Show both all icons and text",
"description": "Show only text",
"type": "string",
"enum": [
"AllIconsAndText"
"Text"
]
},
{
"description": "Show all icons and text for the selected element, and all icons on the rest",
"description": "Show an icon and text for the selected element, and text on the rest",
"type": "string",
"enum": [
"AllIconsAndTextOnSelected"
"TextAndIconOnSelected"
]
},
{
"type": "object",
"required": [
"Existing"
],
"properties": {
"Existing": {
"oneOf": [
{
"description": "Show only icon",
"type": "string",
"enum": [
"Icon"
]
},
{
"description": "Show only text",
"type": "string",
"enum": [
"Text"
]
},
{
"description": "Show an icon and text for the selected element, and text on the rest",
"type": "string",
"enum": [
"TextAndIconOnSelected"
]
},
{
"description": "Show both icon and text",
"type": "string",
"enum": [
"IconAndText"
]
},
{
"description": "Show an icon and text for the selected element, and icons on the rest",
"type": "string",
"enum": [
"IconAndTextOnSelected"
]
}
]
}
},
"additionalProperties": false
"description": "Show both icon and text",
"type": "string",
"enum": [
"IconAndText"
]
},
{
"description": "Show an icon and text for the selected element, and icons on the rest",
"type": "string",
"enum": [
"IconAndTextOnSelected"
]
}
]
},
@@ -1883,73 +1849,39 @@
"description": "Display format of the workspace",
"oneOf": [
{
"description": "Show all icons only",
"description": "Show only icon",
"type": "string",
"enum": [
"AllIcons"
"Icon"
]
},
{
"description": "Show both all icons and text",
"description": "Show only text",
"type": "string",
"enum": [
"AllIconsAndText"
"Text"
]
},
{
"description": "Show all icons and text for the selected element, and all icons on the rest",
"description": "Show an icon and text for the selected element, and text on the rest",
"type": "string",
"enum": [
"AllIconsAndTextOnSelected"
"TextAndIconOnSelected"
]
},
{
"type": "object",
"required": [
"Existing"
],
"properties": {
"Existing": {
"oneOf": [
{
"description": "Show only icon",
"type": "string",
"enum": [
"Icon"
]
},
{
"description": "Show only text",
"type": "string",
"enum": [
"Text"
]
},
{
"description": "Show an icon and text for the selected element, and text on the rest",
"type": "string",
"enum": [
"TextAndIconOnSelected"
]
},
{
"description": "Show both icon and text",
"type": "string",
"enum": [
"IconAndText"
]
},
{
"description": "Show an icon and text for the selected element, and icons on the rest",
"type": "string",
"enum": [
"IconAndTextOnSelected"
]
}
]
}
},
"additionalProperties": false
"description": "Show both icon and text",
"type": "string",
"enum": [
"IconAndText"
]
},
{
"description": "Show an icon and text for the selected element, and icons on the rest",
"type": "string",
"enum": [
"IconAndTextOnSelected"
]
}
]
},
@@ -3170,73 +3102,39 @@
"description": "Display format of the workspace",
"oneOf": [
{
"description": "Show all icons only",
"description": "Show only icon",
"type": "string",
"enum": [
"AllIcons"
"Icon"
]
},
{
"description": "Show both all icons and text",
"description": "Show only text",
"type": "string",
"enum": [
"AllIconsAndText"
"Text"
]
},
{
"description": "Show all icons and text for the selected element, and all icons on the rest",
"description": "Show an icon and text for the selected element, and text on the rest",
"type": "string",
"enum": [
"AllIconsAndTextOnSelected"
"TextAndIconOnSelected"
]
},
{
"type": "object",
"required": [
"Existing"
],
"properties": {
"Existing": {
"oneOf": [
{
"description": "Show only icon",
"type": "string",
"enum": [
"Icon"
]
},
{
"description": "Show only text",
"type": "string",
"enum": [
"Text"
]
},
{
"description": "Show an icon and text for the selected element, and text on the rest",
"type": "string",
"enum": [
"TextAndIconOnSelected"
]
},
{
"description": "Show both icon and text",
"type": "string",
"enum": [
"IconAndText"
]
},
{
"description": "Show an icon and text for the selected element, and icons on the rest",
"type": "string",
"enum": [
"IconAndTextOnSelected"
]
}
]
}
},
"additionalProperties": false
"description": "Show both icon and text",
"type": "string",
"enum": [
"IconAndText"
]
},
{
"description": "Show an icon and text for the selected element, and icons on the rest",
"type": "string",
"enum": [
"IconAndTextOnSelected"
]
}
]
},

View File

@@ -1075,11 +1075,6 @@
"workspaces"
],
"properties": {
"container_padding": {
"description": "Container padding (default: global)",
"type": "integer",
"format": "int32"
},
"window_based_work_area_offset": {
"description": "Window based work area offset (default: None)",
"type": "object",
@@ -1149,11 +1144,6 @@
}
}
},
"workspace_padding": {
"description": "Workspace padding (default: global)",
"type": "integer",
"format": "int32"
},
"workspaces": {
"description": "Workspace configurations",
"type": "array",
@@ -1356,7 +1346,7 @@
}
},
"workspace_padding": {
"description": "Workspace padding (default: global)",
"description": "Container padding (default: global)",
"type": "integer",
"format": "int32"
},