mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-02-11 15:57:40 +01:00
Compare commits
1 Commits
feature/ru
...
feature/wo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
557ef98ee5 |
356
Cargo.lock
generated
356
Cargo.lock
generated
@@ -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",
|
||||
|
||||
22
Cargo.toml
22
Cargo.toml
@@ -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
|
||||
14
justfile
14
justfile
@@ -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
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "komorebi-bar"
|
||||
version = "0.1.35"
|
||||
edition = "2024"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -1,16 +1,9 @@
|
||||
use crate::BAR_HEIGHT;
|
||||
use crate::DEFAULT_PADDING;
|
||||
use crate::KomorebiEvent;
|
||||
use crate::MAX_LABEL_WIDTH;
|
||||
use crate::MONITOR_LEFT;
|
||||
use crate::MONITOR_RIGHT;
|
||||
use crate::MONITOR_TOP;
|
||||
use crate::config::get_individual_spacing;
|
||||
use crate::config::KomobarConfig;
|
||||
use crate::config::KomobarTheme;
|
||||
use crate::config::MonitorConfigOrIndex;
|
||||
use crate::config::Position;
|
||||
use crate::config::PositionConfig;
|
||||
use crate::config::get_individual_spacing;
|
||||
use crate::komorebi::Komorebi;
|
||||
use crate::komorebi::KomorebiNotificationState;
|
||||
use crate::process_hwnd;
|
||||
@@ -20,6 +13,13 @@ use crate::render::RenderConfig;
|
||||
use crate::render::RenderExt;
|
||||
use crate::widget::BarWidget;
|
||||
use crate::widget::WidgetConfig;
|
||||
use crate::KomorebiEvent;
|
||||
use crate::BAR_HEIGHT;
|
||||
use crate::DEFAULT_PADDING;
|
||||
use crate::MAX_LABEL_WIDTH;
|
||||
use crate::MONITOR_LEFT;
|
||||
use crate::MONITOR_RIGHT;
|
||||
use crate::MONITOR_TOP;
|
||||
use crossbeam_channel::Receiver;
|
||||
use crossbeam_channel::TryRecvError;
|
||||
use eframe::egui::Align;
|
||||
@@ -47,16 +47,16 @@ use komorebi_client::KomorebiTheme;
|
||||
use komorebi_client::MonitorNotification;
|
||||
use komorebi_client::NotificationEvent;
|
||||
use komorebi_client::SocketMessage;
|
||||
use komorebi_themes::catppuccin_egui;
|
||||
use komorebi_themes::Base16Value;
|
||||
use komorebi_themes::Catppuccin;
|
||||
use komorebi_themes::CatppuccinValue;
|
||||
use komorebi_themes::catppuccin_egui;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct Komobar {
|
||||
pub hwnd: Option<isize>,
|
||||
@@ -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,22 +365,18 @@ 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}",);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if self.komorebi_notification_state.is_some() && !self.disabled {
|
||||
tracing::warn!(
|
||||
"couldn't find the monitor index of this bar! Disabling the bar until the monitor connects..."
|
||||
);
|
||||
tracing::warn!("couldn't find the monitor index of this bar! Disabling the bar until the monitor connects...");
|
||||
self.disabled = true;
|
||||
} else {
|
||||
tracing::warn!(
|
||||
"couldn't find the monitor index of this bar, if the bar is starting up this is normal until it receives the first state from komorebi."
|
||||
);
|
||||
tracing::warn!("couldn't find the monitor index of this bar, if the bar is starting up this is normal until it receives the first state from komorebi.");
|
||||
self.disabled = true;
|
||||
}
|
||||
|
||||
@@ -423,9 +419,7 @@ impl Komobar {
|
||||
end.x -= margin.left + margin.right;
|
||||
|
||||
if end.y == 0.0 {
|
||||
tracing::warn!(
|
||||
"position.end.y is set to 0.0 which will make your bar invisible on a config reload - this is usually set to 50.0 by default"
|
||||
)
|
||||
tracing::warn!("position.end.y is set to 0.0 which will make your bar invisible on a config reload - this is usually set to 50.0 by default")
|
||||
}
|
||||
|
||||
self.size_rect = komorebi_client::Rect {
|
||||
@@ -508,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();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -630,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())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -725,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;
|
||||
@@ -846,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())
|
||||
}
|
||||
@@ -878,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;
|
||||
@@ -904,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| {
|
||||
@@ -940,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| {
|
||||
@@ -984,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| {
|
||||
|
||||
@@ -2,18 +2,18 @@ use crate::config::LabelPrefix;
|
||||
use crate::render::RenderConfig;
|
||||
use crate::selected_frame::SelectableFrame;
|
||||
use crate::widget::BarWidget;
|
||||
use eframe::egui::text::LayoutJob;
|
||||
use eframe::egui::Align;
|
||||
use eframe::egui::Context;
|
||||
use eframe::egui::Label;
|
||||
use eframe::egui::TextFormat;
|
||||
use eframe::egui::Ui;
|
||||
use eframe::egui::text::LayoutJob;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use starship_battery::units::ratio::percent;
|
||||
use starship_battery::Manager;
|
||||
use starship_battery::State;
|
||||
use starship_battery::units::ratio::percent;
|
||||
use std::process::Command;
|
||||
use std::time::Duration;
|
||||
use std::time::Instant;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::DEFAULT_PADDING;
|
||||
use crate::render::Grouping;
|
||||
use crate::widget::WidgetConfig;
|
||||
use crate::DEFAULT_PADDING;
|
||||
use eframe::egui::Pos2;
|
||||
use eframe::egui::TextBuffer;
|
||||
use eframe::egui::Vec2;
|
||||
@@ -115,9 +115,7 @@ impl KomobarConfig {
|
||||
}
|
||||
|
||||
if display {
|
||||
println!(
|
||||
"\nYour bar configuration file contains some options that have been renamed or deprecated:\n"
|
||||
);
|
||||
println!("\nYour bar configuration file contains some options that have been renamed or deprecated:\n");
|
||||
for (canonical, aliases) in map {
|
||||
for alias in aliases {
|
||||
if raw.contains(alias) {
|
||||
@@ -127,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)]
|
||||
@@ -427,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())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,12 @@ use crate::config::LabelPrefix;
|
||||
use crate::render::RenderConfig;
|
||||
use crate::selected_frame::SelectableFrame;
|
||||
use crate::widget::BarWidget;
|
||||
use eframe::egui::text::LayoutJob;
|
||||
use eframe::egui::Align;
|
||||
use eframe::egui::Context;
|
||||
use eframe::egui::Label;
|
||||
use eframe::egui::TextFormat;
|
||||
use eframe::egui::Ui;
|
||||
use eframe::egui::text::LayoutJob;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
@@ -2,13 +2,13 @@ use crate::config::LabelPrefix;
|
||||
use crate::render::RenderConfig;
|
||||
use crate::selected_frame::SelectableFrame;
|
||||
use crate::widget::BarWidget;
|
||||
use eframe::egui::text::LayoutJob;
|
||||
use eframe::egui::Align;
|
||||
use eframe::egui::Context;
|
||||
use eframe::egui::Label;
|
||||
use eframe::egui::TextFormat;
|
||||
use eframe::egui::Ui;
|
||||
use eframe::egui::WidgetText;
|
||||
use eframe::egui::text::LayoutJob;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use crate::config::LabelPrefix;
|
||||
use crate::render::RenderConfig;
|
||||
use crate::widget::BarWidget;
|
||||
use eframe::egui::text::LayoutJob;
|
||||
use eframe::egui::Align;
|
||||
use eframe::egui::Context;
|
||||
use eframe::egui::Label;
|
||||
use eframe::egui::TextFormat;
|
||||
use eframe::egui::Ui;
|
||||
use eframe::egui::WidgetText;
|
||||
use eframe::egui::text::LayoutJob;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
@@ -1,33 +1,30 @@
|
||||
use crate::ICON_CACHE;
|
||||
use crate::MAX_LABEL_WIDTH;
|
||||
use crate::MONITOR_INDEX;
|
||||
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;
|
||||
use crate::selected_frame::SelectableFrame;
|
||||
use crate::ui::CustomUi;
|
||||
use crate::widget::BarWidget;
|
||||
use crate::ICON_CACHE;
|
||||
use crate::MAX_LABEL_WIDTH;
|
||||
use crate::MONITOR_INDEX;
|
||||
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;
|
||||
use eframe::egui::Vec2;
|
||||
use eframe::egui::vec2;
|
||||
use image::RgbaImage;
|
||||
use komorebi_client::Container;
|
||||
use komorebi_client::NotificationEvent;
|
||||
@@ -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(_) => {}
|
||||
@@ -599,13 +584,9 @@ impl KomorebiNotificationState {
|
||||
grouping,
|
||||
render_config,
|
||||
);
|
||||
tracing::info!(
|
||||
"removed theme from updated komorebi.json and applied default theme"
|
||||
);
|
||||
tracing::info!("removed theme from updated komorebi.json and applied default theme");
|
||||
} else {
|
||||
tracing::warn!(
|
||||
"theme was removed from updated komorebi.json but there was no default theme to apply"
|
||||
);
|
||||
tracing::warn!("theme was removed from updated komorebi.json but there was no default theme to apply");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -646,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()
|
||||
@@ -662,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(),
|
||||
));
|
||||
}
|
||||
|
||||
@@ -2,23 +2,22 @@ use crate::config::DisplayFormat;
|
||||
use crate::komorebi::KomorebiLayoutConfig;
|
||||
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 eframe::egui::vec2;
|
||||
use komorebi_client::SocketMessage;
|
||||
use schemars::JsonSchema;
|
||||
use serde::de::Error;
|
||||
use serde::Deserialize;
|
||||
use serde::Deserializer;
|
||||
use serde::Serialize;
|
||||
use serde::de::Error;
|
||||
use serde_json::from_str;
|
||||
use std::fmt::Display;
|
||||
use std::fmt::Formatter;
|
||||
@@ -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(),
|
||||
|
||||
@@ -30,24 +30,24 @@ use hotwatch::Hotwatch;
|
||||
use image::RgbaImage;
|
||||
use komorebi_client::SocketMessage;
|
||||
use komorebi_client::SubscribeOptions;
|
||||
use schemars::r#gen::SchemaSettings;
|
||||
use schemars::gen::SchemaSettings;
|
||||
use std::collections::HashMap;
|
||||
use std::io::BufReader;
|
||||
use std::io::Read;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::LazyLock;
|
||||
use std::sync::Mutex;
|
||||
use std::sync::atomic::AtomicI32;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::LazyLock;
|
||||
use std::sync::Mutex;
|
||||
use std::time::Duration;
|
||||
use tracing_subscriber::EnvFilter;
|
||||
use windows::Win32::Foundation::HWND;
|
||||
use windows::Win32::Foundation::LPARAM;
|
||||
use windows::Win32::System::Threading::GetCurrentProcessId;
|
||||
use windows::Win32::System::Threading::GetCurrentThreadId;
|
||||
use windows::Win32::UI::HiDpi::DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2;
|
||||
use windows::Win32::UI::HiDpi::SetProcessDpiAwarenessContext;
|
||||
use windows::Win32::UI::HiDpi::DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EnumThreadWindows;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GetWindowThreadProcessId;
|
||||
use windows_core::BOOL;
|
||||
@@ -132,8 +132,8 @@ fn main() -> color_eyre::Result<()> {
|
||||
s.inline_subschemas = true;
|
||||
});
|
||||
|
||||
let r#gen = settings.into_generator();
|
||||
let socket_message = r#gen.into_root_schema_for::<KomobarConfig>();
|
||||
let gen = settings.into_generator();
|
||||
let socket_message = gen.into_root_schema_for::<KomobarConfig>();
|
||||
let schema = serde_json::to_string_pretty(&socket_message)?;
|
||||
|
||||
println!("{schema}");
|
||||
@@ -149,15 +149,13 @@ fn main() -> color_eyre::Result<()> {
|
||||
}
|
||||
|
||||
if std::env::var("RUST_LIB_BACKTRACE").is_err() {
|
||||
// TODO: Audit that the environment access only happens in single-threaded code.
|
||||
unsafe { std::env::set_var("RUST_LIB_BACKTRACE", "1") };
|
||||
std::env::set_var("RUST_LIB_BACKTRACE", "1");
|
||||
}
|
||||
|
||||
color_eyre::install()?;
|
||||
|
||||
if std::env::var("RUST_LOG").is_err() {
|
||||
// TODO: Audit that the environment access only happens in single-threaded code.
|
||||
unsafe { std::env::set_var("RUST_LOG", "info") };
|
||||
std::env::set_var("RUST_LOG", "info");
|
||||
}
|
||||
|
||||
tracing::subscriber::set_global_default(
|
||||
@@ -351,7 +349,7 @@ fn main() -> color_eyre::Result<()> {
|
||||
|
||||
let ctx_komorebi = cc.egui_ctx.clone();
|
||||
std::thread::spawn(move || {
|
||||
let subscriber_name = format!("komorebi-bar-{}", random_word::r#gen(random_word::Lang::En));
|
||||
let subscriber_name = format!("komorebi-bar-{}", random_word::gen(random_word::Lang::En));
|
||||
|
||||
let listener = komorebi_client::subscribe_with_options(&subscriber_name, SubscribeOptions {
|
||||
filter_state_changes: true,
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
use crate::MAX_LABEL_WIDTH;
|
||||
use crate::render::RenderConfig;
|
||||
use crate::selected_frame::SelectableFrame;
|
||||
use crate::ui::CustomUi;
|
||||
use crate::widget::BarWidget;
|
||||
use crate::MAX_LABEL_WIDTH;
|
||||
use eframe::egui::text::LayoutJob;
|
||||
use eframe::egui::Align;
|
||||
use eframe::egui::Context;
|
||||
use eframe::egui::Label;
|
||||
use eframe::egui::TextFormat;
|
||||
use eframe::egui::Ui;
|
||||
use eframe::egui::Vec2;
|
||||
use eframe::egui::text::LayoutJob;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
@@ -2,12 +2,12 @@ use crate::config::LabelPrefix;
|
||||
use crate::render::RenderConfig;
|
||||
use crate::selected_frame::SelectableFrame;
|
||||
use crate::widget::BarWidget;
|
||||
use eframe::egui::text::LayoutJob;
|
||||
use eframe::egui::Align;
|
||||
use eframe::egui::Context;
|
||||
use eframe::egui::Label;
|
||||
use eframe::egui::TextFormat;
|
||||
use eframe::egui::Ui;
|
||||
use eframe::egui::text::LayoutJob;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
@@ -2,12 +2,12 @@ use crate::config::LabelPrefix;
|
||||
use crate::render::RenderConfig;
|
||||
use crate::selected_frame::SelectableFrame;
|
||||
use crate::widget::BarWidget;
|
||||
use eframe::egui::text::LayoutJob;
|
||||
use eframe::egui::Align;
|
||||
use eframe::egui::Context;
|
||||
use eframe::egui::Label;
|
||||
use eframe::egui::TextFormat;
|
||||
use eframe::egui::Ui;
|
||||
use eframe::egui::text::LayoutJob;
|
||||
use num_derive::FromPrimitive;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
|
||||
@@ -3,20 +3,21 @@ 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;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Arc;
|
||||
|
||||
static SHOW_KOMOREBI_LAYOUT_OPTIONS: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
@@ -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],
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -2,12 +2,12 @@ use crate::config::LabelPrefix;
|
||||
use crate::render::RenderConfig;
|
||||
use crate::selected_frame::SelectableFrame;
|
||||
use crate::widget::BarWidget;
|
||||
use eframe::egui::text::LayoutJob;
|
||||
use eframe::egui::Align;
|
||||
use eframe::egui::Context;
|
||||
use eframe::egui::Label;
|
||||
use eframe::egui::TextFormat;
|
||||
use eframe::egui::Ui;
|
||||
use eframe::egui::text::LayoutJob;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
@@ -3,17 +3,16 @@ use crate::config::LabelPrefix;
|
||||
use crate::render::RenderConfig;
|
||||
use crate::selected_frame::SelectableFrame;
|
||||
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::egui::text::LayoutJob;
|
||||
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;
|
||||
|
||||
@@ -2,12 +2,12 @@ use crate::config::LabelPrefix;
|
||||
use crate::render::RenderConfig;
|
||||
use crate::selected_frame::SelectableFrame;
|
||||
use crate::widget::BarWidget;
|
||||
use eframe::egui::text::LayoutJob;
|
||||
use eframe::egui::Align;
|
||||
use eframe::egui::Context;
|
||||
use eframe::egui::Label;
|
||||
use eframe::egui::TextFormat;
|
||||
use eframe::egui::Ui;
|
||||
use eframe::egui::text::LayoutJob;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "komorebi-client"
|
||||
version = "0.1.35"
|
||||
edition = "2024"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -1,27 +1,8 @@
|
||||
#![warn(clippy::all)]
|
||||
#![allow(clippy::missing_errors_doc)]
|
||||
|
||||
pub use komorebi::AnimationsConfig;
|
||||
pub use komorebi::AspectRatio;
|
||||
pub use komorebi::BorderColours;
|
||||
pub use komorebi::CrossBoundaryBehaviour;
|
||||
pub use komorebi::GlobalState;
|
||||
pub use komorebi::KomorebiTheme;
|
||||
pub use komorebi::MonitorConfig;
|
||||
pub use komorebi::Notification;
|
||||
pub use komorebi::NotificationEvent;
|
||||
pub use komorebi::PredefinedAspectRatio;
|
||||
pub use komorebi::RuleDebug;
|
||||
pub use komorebi::StackbarConfig;
|
||||
pub use komorebi::State;
|
||||
pub use komorebi::StaticConfig;
|
||||
pub use komorebi::SubscribeOptions;
|
||||
pub use komorebi::TabsConfig;
|
||||
pub use komorebi::WindowContainerBehaviour;
|
||||
pub use komorebi::WindowsApi;
|
||||
pub use komorebi::WorkspaceConfig;
|
||||
pub use komorebi::animation::PerAnimationPrefixConfig;
|
||||
pub use komorebi::animation::prefix::AnimationPrefix;
|
||||
pub use komorebi::animation::PerAnimationPrefixConfig;
|
||||
pub use komorebi::asc::ApplicationSpecificConfiguration;
|
||||
pub use komorebi::colour::Colour;
|
||||
pub use komorebi::colour::Rgb;
|
||||
@@ -31,6 +12,8 @@ pub use komorebi::config_generation::IdWithIdentifierAndComment;
|
||||
pub use komorebi::config_generation::MatchingRule;
|
||||
pub use komorebi::config_generation::MatchingStrategy;
|
||||
pub use komorebi::container::Container;
|
||||
pub use komorebi::core::config_generation::ApplicationConfigurationGenerator;
|
||||
pub use komorebi::core::resolve_home_path;
|
||||
pub use komorebi::core::AnimationStyle;
|
||||
pub use komorebi::core::ApplicationIdentifier;
|
||||
pub use komorebi::core::Arrangement;
|
||||
@@ -59,16 +42,32 @@ pub use komorebi::core::StackbarLabel;
|
||||
pub use komorebi::core::StackbarMode;
|
||||
pub use komorebi::core::StateQuery;
|
||||
pub use komorebi::core::WindowKind;
|
||||
pub use komorebi::core::config_generation::ApplicationConfigurationGenerator;
|
||||
pub use komorebi::core::resolve_home_path;
|
||||
pub use komorebi::monitor::Monitor;
|
||||
pub use komorebi::monitor_reconciliator::MonitorNotification;
|
||||
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;
|
||||
pub use komorebi::BorderColours;
|
||||
pub use komorebi::CrossBoundaryBehaviour;
|
||||
pub use komorebi::GlobalState;
|
||||
pub use komorebi::KomorebiTheme;
|
||||
pub use komorebi::MonitorConfig;
|
||||
pub use komorebi::Notification;
|
||||
pub use komorebi::NotificationEvent;
|
||||
pub use komorebi::PredefinedAspectRatio;
|
||||
pub use komorebi::RuleDebug;
|
||||
pub use komorebi::StackbarConfig;
|
||||
pub use komorebi::State;
|
||||
pub use komorebi::StaticConfig;
|
||||
pub use komorebi::SubscribeOptions;
|
||||
pub use komorebi::TabsConfig;
|
||||
pub use komorebi::WindowContainerBehaviour;
|
||||
pub use komorebi::WindowsApi;
|
||||
pub use komorebi::WorkspaceConfig;
|
||||
|
||||
use komorebi::DATA_DIR;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "komorebi-gui"
|
||||
version = "0.1.35"
|
||||
edition = "2024"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#![warn(clippy::all)]
|
||||
|
||||
use eframe::egui;
|
||||
use eframe::egui::color_picker::Alpha;
|
||||
use eframe::egui::Color32;
|
||||
use eframe::egui::ViewportBuilder;
|
||||
use eframe::egui::color_picker::Alpha;
|
||||
use komorebi_client::BorderStyle;
|
||||
use komorebi_client::Colour;
|
||||
use komorebi_client::DefaultLayout;
|
||||
@@ -101,7 +101,7 @@ impl From<&komorebi_client::Workspace> for WorkspaceConfig {
|
||||
let name = value
|
||||
.name()
|
||||
.to_owned()
|
||||
.unwrap_or_else(|| random_word::r#gen(random_word::Lang::En).to_string());
|
||||
.unwrap_or_else(|| random_word::gen(random_word::Lang::En).to_string());
|
||||
|
||||
Self {
|
||||
layout,
|
||||
@@ -248,11 +248,10 @@ impl eframe::App for KomorebiGui {
|
||||
ui.collapsing("Window Rules", |ui| {
|
||||
let window = Window::from(self.debug_hwnd);
|
||||
|
||||
let label = match (window.title(), window.exe()) {
|
||||
(Ok(title), Ok(exe)) => {
|
||||
format!("{title} ({exe})")
|
||||
}
|
||||
_ => String::from("Select a Window"),
|
||||
let label = if let (Ok(title), Ok(exe)) = (window.title(), window.exe()) {
|
||||
format!("{title} ({exe})")
|
||||
} else {
|
||||
String::from("Select a Window")
|
||||
};
|
||||
|
||||
if ui.button("Refresh Windows").clicked() {
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
[package]
|
||||
name = "komorebi-themes"
|
||||
version = "0.1.35"
|
||||
edition = "2024"
|
||||
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"
|
||||
|
||||
@@ -3,7 +3,7 @@ name = "komorebi"
|
||||
version = "0.1.35"
|
||||
description = "A tiling window manager for Windows"
|
||||
repository = "https://github.com/LGUG2Z/komorebi"
|
||||
edition = "2024"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use std::collections::HashMap;
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use super::prefix::AnimationPrefix;
|
||||
|
||||
|
||||
@@ -8,10 +8,10 @@ use std::sync::atomic::Ordering;
|
||||
use std::time::Duration;
|
||||
use std::time::Instant;
|
||||
|
||||
use super::RenderDispatcher;
|
||||
use super::ANIMATION_DURATION_GLOBAL;
|
||||
use super::ANIMATION_FPS;
|
||||
use super::ANIMATION_MANAGER;
|
||||
use super::RenderDispatcher;
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, Serialize, Deserialize, JsonSchema, PartialEq)]
|
||||
pub struct AnimationEngine;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::AnimationStyle;
|
||||
use crate::core::Rect;
|
||||
use crate::AnimationStyle;
|
||||
|
||||
use super::style::apply_ease_func;
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@ use crate::core::animation::AnimationStyle;
|
||||
use lazy_static::lazy_static;
|
||||
use prefix::AnimationPrefix;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::atomic::AtomicU64;
|
||||
use std::sync::Arc;
|
||||
|
||||
use parking_lot::Mutex;
|
||||
|
||||
|
||||
@@ -1,34 +1,37 @@
|
||||
use crate::WINDOWS_11;
|
||||
use crate::WindowsApi;
|
||||
use crate::border_manager::window_kind_colour;
|
||||
use crate::border_manager::RenderTarget;
|
||||
use crate::border_manager::WindowKind;
|
||||
use crate::border_manager::BORDER_OFFSET;
|
||||
use crate::border_manager::BORDER_WIDTH;
|
||||
use crate::border_manager::FOCUS_STATE;
|
||||
use crate::border_manager::RENDER_TARGETS;
|
||||
use crate::border_manager::RenderTarget;
|
||||
use crate::border_manager::STYLE;
|
||||
use crate::border_manager::WindowKind;
|
||||
use crate::border_manager::window_kind_colour;
|
||||
use crate::core::BorderStyle;
|
||||
use crate::core::Rect;
|
||||
use crate::windows_api;
|
||||
use crate::WindowsApi;
|
||||
use crate::WINDOWS_11;
|
||||
use color_eyre::eyre::anyhow;
|
||||
use std::collections::HashMap;
|
||||
use std::ops::Deref;
|
||||
use std::sync::LazyLock;
|
||||
use std::sync::OnceLock;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::mpsc;
|
||||
use std::sync::LazyLock;
|
||||
use std::sync::OnceLock;
|
||||
use windows::Win32::Foundation::FALSE;
|
||||
use windows::Win32::Foundation::HWND;
|
||||
use windows::Win32::Foundation::LPARAM;
|
||||
use windows::Win32::Foundation::LRESULT;
|
||||
use windows::Win32::Foundation::TRUE;
|
||||
use windows::Win32::Foundation::WPARAM;
|
||||
use windows::Win32::Graphics::Direct2D::Common::D2D_RECT_F;
|
||||
use windows::Win32::Graphics::Direct2D::Common::D2D_SIZE_U;
|
||||
use windows::Win32::Graphics::Direct2D::Common::D2D1_ALPHA_MODE_PREMULTIPLIED;
|
||||
use windows::Win32::Graphics::Direct2D::Common::D2D1_COLOR_F;
|
||||
use windows::Win32::Graphics::Direct2D::Common::D2D1_PIXEL_FORMAT;
|
||||
use windows::Win32::Graphics::Direct2D::Common::D2D_RECT_F;
|
||||
use windows::Win32::Graphics::Direct2D::Common::D2D_SIZE_U;
|
||||
use windows::Win32::Graphics::Direct2D::D2D1CreateFactory;
|
||||
use windows::Win32::Graphics::Direct2D::ID2D1Factory;
|
||||
use windows::Win32::Graphics::Direct2D::ID2D1SolidColorBrush;
|
||||
use windows::Win32::Graphics::Direct2D::D2D1_ANTIALIAS_MODE_PER_PRIMITIVE;
|
||||
use windows::Win32::Graphics::Direct2D::D2D1_BRUSH_PROPERTIES;
|
||||
use windows::Win32::Graphics::Direct2D::D2D1_FACTORY_TYPE_MULTI_THREADED;
|
||||
@@ -37,31 +40,28 @@ use windows::Win32::Graphics::Direct2D::D2D1_PRESENT_OPTIONS_IMMEDIATELY;
|
||||
use windows::Win32::Graphics::Direct2D::D2D1_RENDER_TARGET_PROPERTIES;
|
||||
use windows::Win32::Graphics::Direct2D::D2D1_RENDER_TARGET_TYPE_DEFAULT;
|
||||
use windows::Win32::Graphics::Direct2D::D2D1_ROUNDED_RECT;
|
||||
use windows::Win32::Graphics::Direct2D::D2D1CreateFactory;
|
||||
use windows::Win32::Graphics::Direct2D::ID2D1Factory;
|
||||
use windows::Win32::Graphics::Direct2D::ID2D1SolidColorBrush;
|
||||
use windows::Win32::Graphics::Dwm::DwmEnableBlurBehindWindow;
|
||||
use windows::Win32::Graphics::Dwm::DWM_BB_BLURREGION;
|
||||
use windows::Win32::Graphics::Dwm::DWM_BB_ENABLE;
|
||||
use windows::Win32::Graphics::Dwm::DWM_BLURBEHIND;
|
||||
use windows::Win32::Graphics::Dwm::DwmEnableBlurBehindWindow;
|
||||
use windows::Win32::Graphics::Dxgi::Common::DXGI_FORMAT_UNKNOWN;
|
||||
use windows::Win32::Graphics::Gdi::CreateRectRgn;
|
||||
use windows::Win32::Graphics::Gdi::InvalidateRect;
|
||||
use windows::Win32::Graphics::Gdi::ValidateRect;
|
||||
use windows::Win32::UI::WindowsAndMessaging::CREATESTRUCTW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::DefWindowProcW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::DispatchMessageW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_DESTROY;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_LOCATIONCHANGE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GWLP_USERDATA;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GetMessageW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GetSystemMetrics;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GetWindowLongPtrW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::MSG;
|
||||
use windows::Win32::UI::WindowsAndMessaging::PostQuitMessage;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SM_CXVIRTUALSCREEN;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SetWindowLongPtrW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::TranslateMessage;
|
||||
use windows::Win32::UI::WindowsAndMessaging::CREATESTRUCTW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_DESTROY;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_OBJECT_LOCATIONCHANGE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GWLP_USERDATA;
|
||||
use windows::Win32::UI::WindowsAndMessaging::MSG;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SM_CXVIRTUALSCREEN;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WM_CREATE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WM_DESTROY;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WM_PAINT;
|
||||
@@ -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();
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
#![deny(clippy::unwrap_used, clippy::expect_used)]
|
||||
|
||||
mod border;
|
||||
use crate::Colour;
|
||||
use crate::Rgb;
|
||||
use crate::WindowManager;
|
||||
use crate::WindowsApi;
|
||||
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;
|
||||
pub use border::Border;
|
||||
use crate::Colour;
|
||||
use crate::Rgb;
|
||||
use crate::WindowManager;
|
||||
use crate::WindowsApi;
|
||||
use border::border_hwnds;
|
||||
pub use border::Border;
|
||||
use crossbeam_channel::Receiver;
|
||||
use crossbeam_channel::Sender;
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
@@ -22,15 +21,15 @@ use parking_lot::Mutex;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::collections::HashMap;
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
use std::sync::OnceLock;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::atomic::AtomicI32;
|
||||
use std::sync::atomic::AtomicU32;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Arc;
|
||||
use std::sync::OnceLock;
|
||||
use strum::Display;
|
||||
use windows::Win32::Graphics::Direct2D::ID2D1HwndRenderTarget;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -146,15 +144,13 @@ fn window_kind_colour(focus_kind: WindowKind) -> u32 {
|
||||
}
|
||||
|
||||
pub fn listen_for_notifications(wm: Arc<Mutex<WindowManager>>) {
|
||||
std::thread::spawn(move || {
|
||||
loop {
|
||||
match handle_notifications(wm.clone()) {
|
||||
Ok(()) => {
|
||||
tracing::warn!("restarting finished thread");
|
||||
}
|
||||
Err(error) => {
|
||||
tracing::warn!("restarting failed thread: {}", error);
|
||||
}
|
||||
std::thread::spawn(move || loop {
|
||||
match handle_notifications(wm.clone()) {
|
||||
Ok(()) => {
|
||||
tracing::warn!("restarting finished thread");
|
||||
}
|
||||
Err(error) => {
|
||||
tracing::warn!("restarting failed thread: {}", error);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -170,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
|
||||
@@ -187,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);
|
||||
@@ -303,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()
|
||||
@@ -318,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;
|
||||
@@ -331,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;
|
||||
}
|
||||
@@ -350,17 +343,14 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
|
||||
let border = match borders.entry(monocle.id().clone()) {
|
||||
Entry::Occupied(entry) => entry.into_mut(),
|
||||
Entry::Vacant(entry) => {
|
||||
match Border::create(
|
||||
if let Ok(border) = Border::create(
|
||||
monocle.id(),
|
||||
monocle.focused_window().copied().unwrap_or_default().hwnd,
|
||||
) {
|
||||
Ok(border) => {
|
||||
new_border = true;
|
||||
entry.insert(border)
|
||||
}
|
||||
_ => {
|
||||
continue 'monitors;
|
||||
}
|
||||
new_border = true;
|
||||
entry.insert(border)
|
||||
} else {
|
||||
continue 'monitors;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -371,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;
|
||||
@@ -391,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;
|
||||
}
|
||||
@@ -411,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()
|
||||
@@ -435,67 +437,34 @@ 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) => {
|
||||
match Border::create(c.id(), focused_window_hwnd) {
|
||||
Ok(border) => {
|
||||
new_border = true;
|
||||
entry.insert(border)
|
||||
}
|
||||
_ => {
|
||||
continue 'monitors;
|
||||
}
|
||||
if let Ok(border) = Border::create(
|
||||
c.id(),
|
||||
c.focused_window().copied().unwrap_or_default().hwnd,
|
||||
) {
|
||||
new_border = true;
|
||||
entry.insert(border)
|
||||
} else {
|
||||
continue 'monitors;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -505,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 {
|
||||
@@ -515,72 +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
|
||||
match Border::create(
|
||||
c.id(),
|
||||
c.focused_window().copied().unwrap_or_default().hwnd,
|
||||
) {
|
||||
Ok(b) => {
|
||||
// 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;
|
||||
}
|
||||
_ => {
|
||||
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 {
|
||||
@@ -592,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);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -601,15 +533,13 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
|
||||
let border = match borders.entry(window.hwnd.to_string()) {
|
||||
Entry::Occupied(entry) => entry.into_mut(),
|
||||
Entry::Vacant(entry) => {
|
||||
match Border::create(&window.hwnd.to_string(), window.hwnd)
|
||||
if let Ok(border) =
|
||||
Border::create(&window.hwnd.to_string(), window.hwnd)
|
||||
{
|
||||
Ok(border) => {
|
||||
new_border = true;
|
||||
entry.insert(border)
|
||||
}
|
||||
_ => {
|
||||
continue 'monitors;
|
||||
}
|
||||
new_border = true;
|
||||
entry.insert(border)
|
||||
} else {
|
||||
continue 'monitors;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -623,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 {
|
||||
@@ -646,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -658,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,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use hex_color::HexColor;
|
||||
use komorebi_themes::Color32;
|
||||
use schemars::JsonSchema;
|
||||
use schemars::r#gen::SchemaGenerator;
|
||||
use schemars::gen::SchemaGenerator;
|
||||
use schemars::schema::InstanceType;
|
||||
use schemars::schema::Schema;
|
||||
use schemars::schema::SchemaObject;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
|
||||
@@ -6,17 +6,17 @@
|
||||
|
||||
use std::ffi::c_void;
|
||||
use std::ops::Deref;
|
||||
use windows::core::IUnknown;
|
||||
use windows::core::IUnknown_Vtbl;
|
||||
use windows::core::GUID;
|
||||
use windows::core::HRESULT;
|
||||
use windows::core::HSTRING;
|
||||
use windows::core::PCWSTR;
|
||||
use windows::core::PWSTR;
|
||||
use windows::Win32::Foundation::HWND;
|
||||
use windows::Win32::Foundation::RECT;
|
||||
use windows::Win32::Foundation::SIZE;
|
||||
use windows::Win32::UI::Shell::Common::IObjectArray;
|
||||
use windows::core::GUID;
|
||||
use windows::core::HRESULT;
|
||||
use windows::core::HSTRING;
|
||||
use windows::core::IUnknown;
|
||||
use windows::core::IUnknown_Vtbl;
|
||||
use windows::core::PCWSTR;
|
||||
use windows::core::PWSTR;
|
||||
use windows_core::BOOL;
|
||||
|
||||
type DesktopID = GUID;
|
||||
@@ -129,7 +129,7 @@ pub unsafe trait IApplicationView: IUnknown {
|
||||
pub unsafe fn get_app_user_model_id(&self, id: *mut PWSTR) -> HRESULT; // Proc17
|
||||
pub unsafe fn set_app_user_model_id(&self, id: PCWSTR) -> HRESULT;
|
||||
pub unsafe fn is_equal_by_app_user_model_id(&self, id: PCWSTR, out_result: *mut INT)
|
||||
-> HRESULT;
|
||||
-> HRESULT;
|
||||
|
||||
/*** IApplicationView methods ***/
|
||||
pub unsafe fn get_view_state(&self, out_state: *mut UINT) -> HRESULT; // Proc20
|
||||
|
||||
@@ -11,11 +11,11 @@ use interfaces::IServiceProvider;
|
||||
use std::ffi::c_void;
|
||||
|
||||
use windows::Win32::Foundation::HWND;
|
||||
use windows::Win32::System::Com::CLSCTX_ALL;
|
||||
use windows::Win32::System::Com::COINIT_MULTITHREADED;
|
||||
use windows::Win32::System::Com::CoCreateInstance;
|
||||
use windows::Win32::System::Com::CoInitializeEx;
|
||||
use windows::Win32::System::Com::CoUninitialize;
|
||||
use windows::Win32::System::Com::CLSCTX_ALL;
|
||||
use windows::Win32::System::Com::COINIT_MULTITHREADED;
|
||||
use windows_core::Interface;
|
||||
|
||||
struct ComInit();
|
||||
@@ -64,7 +64,7 @@ fn get_iapplication_view_collection(provider: &IServiceProvider) -> IApplication
|
||||
})
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn SetCloak(hwnd: HWND, cloak_type: u32, flags: i32) {
|
||||
COM_INIT.with(|_| {
|
||||
let provider = get_iservice_provider();
|
||||
|
||||
@@ -7,12 +7,12 @@ use serde::Serialize;
|
||||
use strum::Display;
|
||||
use strum::EnumString;
|
||||
|
||||
use super::CustomLayout;
|
||||
use super::DefaultLayout;
|
||||
use super::Rect;
|
||||
use super::custom_layout::Column;
|
||||
use super::custom_layout::ColumnSplit;
|
||||
use super::custom_layout::ColumnSplitWithCapacity;
|
||||
use super::CustomLayout;
|
||||
use super::DefaultLayout;
|
||||
use super::Rect;
|
||||
|
||||
pub trait Arrangement {
|
||||
fn calculate(
|
||||
|
||||
@@ -5,9 +5,9 @@ use std::ops::Deref;
|
||||
use std::ops::DerefMut;
|
||||
use std::path::Path;
|
||||
|
||||
use color_eyre::Result;
|
||||
use color_eyre::eyre::anyhow;
|
||||
use color_eyre::eyre::bail;
|
||||
use color_eyre::Result;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use super::DefaultLayout;
|
||||
use super::OperationDirection;
|
||||
use super::custom_layout::Column;
|
||||
use super::custom_layout::ColumnSplit;
|
||||
use super::custom_layout::ColumnSplitWithCapacity;
|
||||
use super::custom_layout::CustomLayout;
|
||||
use super::DefaultLayout;
|
||||
use super::OperationDirection;
|
||||
|
||||
pub trait Direction {
|
||||
fn index_in_direction(
|
||||
|
||||
@@ -6,16 +6,16 @@ use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
|
||||
use clap::ValueEnum;
|
||||
use color_eyre::Result;
|
||||
use color_eyre::eyre::anyhow;
|
||||
use color_eyre::Result;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use strum::Display;
|
||||
use strum::EnumString;
|
||||
|
||||
use crate::KomorebiTheme;
|
||||
use crate::animation::prefix::AnimationPrefix;
|
||||
use crate::KomorebiTheme;
|
||||
pub use animation::AnimationStyle;
|
||||
pub use arrangement::Arrangement;
|
||||
pub use arrangement::Axis;
|
||||
|
||||
@@ -7,8 +7,8 @@ use serde::Serialize;
|
||||
use strum::Display;
|
||||
use strum::EnumString;
|
||||
|
||||
use super::Axis;
|
||||
use super::direction::Direction;
|
||||
use super::Axis;
|
||||
|
||||
#[derive(
|
||||
Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ValueEnum, JsonSchema,
|
||||
|
||||
@@ -44,15 +44,13 @@ pub fn send_notification(hwnd: isize) {
|
||||
}
|
||||
|
||||
pub fn listen_for_notifications(wm: Arc<Mutex<WindowManager>>) {
|
||||
std::thread::spawn(move || {
|
||||
loop {
|
||||
match handle_notifications(wm.clone()) {
|
||||
Ok(()) => {
|
||||
tracing::warn!("restarting finished thread");
|
||||
}
|
||||
Err(error) => {
|
||||
tracing::warn!("restarting failed thread: {}", error);
|
||||
}
|
||||
std::thread::spawn(move || loop {
|
||||
match handle_notifications(wm.clone()) {
|
||||
Ok(()) => {
|
||||
tracing::warn!("restarting finished thread");
|
||||
}
|
||||
Err(error) => {
|
||||
tracing::warn!("restarting failed thread: {}", error);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -40,12 +40,12 @@ use std::io::Write;
|
||||
use std::net::TcpStream;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::atomic::AtomicI32;
|
||||
use std::sync::atomic::AtomicU32;
|
||||
use std::sync::atomic::AtomicU64;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub use colour::*;
|
||||
pub use core::*;
|
||||
@@ -71,8 +71,8 @@ use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use uds_windows::UnixStream;
|
||||
use which::which;
|
||||
use winreg::RegKey;
|
||||
use winreg::enums::HKEY_CURRENT_USER;
|
||||
use winreg::RegKey;
|
||||
|
||||
lazy_static! {
|
||||
static ref HIDDEN_HWNDS: Arc<Mutex<Vec<isize>>> = Arc::new(Mutex::new(vec![]));
|
||||
|
||||
@@ -10,32 +10,27 @@
|
||||
use std::env::temp_dir;
|
||||
use std::net::Shutdown;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Arc;
|
||||
#[cfg(feature = "deadlock_detection")]
|
||||
use std::time::Duration;
|
||||
|
||||
use clap::Parser;
|
||||
use color_eyre::Result;
|
||||
use crossbeam_utils::Backoff;
|
||||
use komorebi::animation::AnimationEngine;
|
||||
use komorebi::animation::ANIMATION_ENABLED_GLOBAL;
|
||||
use komorebi::animation::ANIMATION_ENABLED_PER_ANIMATION;
|
||||
use komorebi::animation::AnimationEngine;
|
||||
use parking_lot::Mutex;
|
||||
#[cfg(feature = "deadlock_detection")]
|
||||
use parking_lot::deadlock;
|
||||
use parking_lot::Mutex;
|
||||
use sysinfo::Process;
|
||||
use sysinfo::ProcessesToUpdate;
|
||||
use tracing_appender::non_blocking::WorkerGuard;
|
||||
use tracing_subscriber::EnvFilter;
|
||||
use tracing_subscriber::layer::SubscriberExt;
|
||||
use tracing_subscriber::EnvFilter;
|
||||
use uds_windows::UnixStream;
|
||||
|
||||
use komorebi::CUSTOM_FFM;
|
||||
use komorebi::DATA_DIR;
|
||||
use komorebi::HOME_DIR;
|
||||
use komorebi::INITIAL_CONFIGURATION_LOADED;
|
||||
use komorebi::SESSION_ID;
|
||||
use komorebi::border_manager;
|
||||
use komorebi::focus_manager;
|
||||
use komorebi::load_configuration;
|
||||
@@ -54,20 +49,23 @@ use komorebi::window_manager::WindowManager;
|
||||
use komorebi::windows_api::WindowsApi;
|
||||
use komorebi::winevent_listener;
|
||||
use komorebi::workspace_reconciliator;
|
||||
use komorebi::CUSTOM_FFM;
|
||||
use komorebi::DATA_DIR;
|
||||
use komorebi::HOME_DIR;
|
||||
use komorebi::INITIAL_CONFIGURATION_LOADED;
|
||||
use komorebi::SESSION_ID;
|
||||
|
||||
shadow_rs::shadow!(build);
|
||||
|
||||
fn setup() -> Result<(WorkerGuard, WorkerGuard)> {
|
||||
if std::env::var("RUST_LIB_BACKTRACE").is_err() {
|
||||
// TODO: Audit that the environment access only happens in single-threaded code.
|
||||
unsafe { std::env::set_var("RUST_LIB_BACKTRACE", "1") };
|
||||
std::env::set_var("RUST_LIB_BACKTRACE", "1");
|
||||
}
|
||||
|
||||
color_eyre::install()?;
|
||||
|
||||
if std::env::var("RUST_LOG").is_err() {
|
||||
// TODO: Audit that the environment access only happens in single-threaded code.
|
||||
unsafe { std::env::set_var("RUST_LOG", "info") };
|
||||
std::env::set_var("RUST_LOG", "info");
|
||||
}
|
||||
|
||||
let appender = tracing_appender::rolling::daily(std::env::temp_dir(), "komorebi_plaintext.log");
|
||||
@@ -126,22 +124,20 @@ fn setup() -> Result<(WorkerGuard, WorkerGuard)> {
|
||||
#[tracing::instrument]
|
||||
fn detect_deadlocks() {
|
||||
// Create a background thread which checks for deadlocks every 10s
|
||||
std::thread::spawn(move || {
|
||||
loop {
|
||||
tracing::info!("running deadlock detector");
|
||||
std::thread::sleep(Duration::from_secs(5));
|
||||
let deadlocks = deadlock::check_deadlock();
|
||||
if deadlocks.is_empty() {
|
||||
continue;
|
||||
}
|
||||
std::thread::spawn(move || loop {
|
||||
tracing::info!("running deadlock detector");
|
||||
std::thread::sleep(Duration::from_secs(5));
|
||||
let deadlocks = deadlock::check_deadlock();
|
||||
if deadlocks.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
tracing::error!("{} deadlocks detected", deadlocks.len());
|
||||
for (i, threads) in deadlocks.iter().enumerate() {
|
||||
tracing::error!("deadlock #{}", i);
|
||||
for t in threads {
|
||||
tracing::error!("thread id: {:#?}", t.thread_id());
|
||||
tracing::error!("{:#?}", t.backtrace());
|
||||
}
|
||||
tracing::error!("{} deadlocks detected", deadlocks.len());
|
||||
for (i, threads) in deadlocks.iter().enumerate() {
|
||||
tracing::error!("deadlock #{}", i);
|
||||
for t in threads {
|
||||
tracing::error!("thread id: {:#?}", t.thread_id());
|
||||
tracing::error!("{:#?}", t.backtrace());
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -196,9 +192,7 @@ fn main() -> Result<()> {
|
||||
}
|
||||
|
||||
if len > 1 {
|
||||
tracing::error!(
|
||||
"komorebi.exe is already running, please exit the existing process before starting a new one"
|
||||
);
|
||||
tracing::error!("komorebi.exe is already running, please exit the existing process before starting a new one");
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
@@ -250,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"));
|
||||
|
||||
@@ -280,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
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
use std::collections::HashMap;
|
||||
use std::collections::VecDeque;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use color_eyre::Result;
|
||||
use color_eyre::eyre::anyhow;
|
||||
use color_eyre::eyre::bail;
|
||||
use color_eyre::Result;
|
||||
use getset::CopyGetters;
|
||||
use getset::Getters;
|
||||
use getset::MutGetters;
|
||||
@@ -15,15 +14,13 @@ use serde::Serialize;
|
||||
|
||||
use crate::core::Rect;
|
||||
|
||||
use crate::DEFAULT_CONTAINER_PADDING;
|
||||
use crate::DEFAULT_WORKSPACE_PADDING;
|
||||
use crate::container::Container;
|
||||
use crate::ring::Ring;
|
||||
use crate::workspace::Workspace;
|
||||
use crate::DefaultLayout;
|
||||
use crate::Layout;
|
||||
use crate::OperationDirection;
|
||||
use crate::WindowsApi;
|
||||
use crate::container::Container;
|
||||
use crate::ring::Ring;
|
||||
use crate::workspace::Workspace;
|
||||
|
||||
#[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(())
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use std::sync::mpsc;
|
||||
use std::time::Duration;
|
||||
|
||||
use windows::core::PCWSTR;
|
||||
use windows::Win32::Devices::Display::GUID_DEVINTERFACE_DISPLAY_ADAPTER;
|
||||
use windows::Win32::Devices::Display::GUID_DEVINTERFACE_MONITOR;
|
||||
use windows::Win32::Devices::Display::GUID_DEVINTERFACE_VIDEO_OUTPUT_ARRIVAL;
|
||||
@@ -10,6 +11,10 @@ use windows::Win32::Foundation::LRESULT;
|
||||
use windows::Win32::Foundation::WPARAM;
|
||||
use windows::Win32::System::Power::POWERBROADCAST_SETTING;
|
||||
use windows::Win32::System::SystemServices::GUID_LIDSWITCH_STATE_CHANGE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::DefWindowProcW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::DispatchMessageW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GetMessageW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::TranslateMessage;
|
||||
use windows::Win32::UI::WindowsAndMessaging::CS_HREDRAW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::CS_VREDRAW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::DBT_CONFIGCHANGED;
|
||||
@@ -18,9 +23,6 @@ use windows::Win32::UI::WindowsAndMessaging::DBT_DEVICEREMOVECOMPLETE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::DBT_DEVNODES_CHANGED;
|
||||
use windows::Win32::UI::WindowsAndMessaging::DBT_DEVTYP_DEVICEINTERFACE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::DEV_BROADCAST_DEVICEINTERFACE_W;
|
||||
use windows::Win32::UI::WindowsAndMessaging::DefWindowProcW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::DispatchMessageW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GetMessageW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::MSG;
|
||||
use windows::Win32::UI::WindowsAndMessaging::PBT_APMRESUMEAUTOMATIC;
|
||||
use windows::Win32::UI::WindowsAndMessaging::PBT_APMRESUMESUSPEND;
|
||||
@@ -28,7 +30,6 @@ use windows::Win32::UI::WindowsAndMessaging::PBT_APMSUSPEND;
|
||||
use windows::Win32::UI::WindowsAndMessaging::PBT_POWERSETTINGCHANGE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::REGISTER_NOTIFICATION_FLAGS;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SPI_SETWORKAREA;
|
||||
use windows::Win32::UI::WindowsAndMessaging::TranslateMessage;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WM_DEVICECHANGE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WM_DISPLAYCHANGE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WM_POWERBROADCAST;
|
||||
@@ -37,11 +38,10 @@ use windows::Win32::UI::WindowsAndMessaging::WM_WTSSESSION_CHANGE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WNDCLASSW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WTS_SESSION_LOCK;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WTS_SESSION_UNLOCK;
|
||||
use windows::core::PCWSTR;
|
||||
|
||||
use crate::WindowsApi;
|
||||
use crate::monitor_reconciliator;
|
||||
use crate::windows_api;
|
||||
use crate::WindowsApi;
|
||||
|
||||
// This is a hidden window specifically spawned to listen to system-wide events related to monitors
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
@@ -224,18 +224,14 @@ impl Hidden {
|
||||
WM_WTSSESSION_CHANGE => {
|
||||
match wparam.0 as u32 {
|
||||
WTS_SESSION_LOCK => {
|
||||
tracing::debug!(
|
||||
"WM_WTSSESSION_CHANGE event received with WTS_SESSION_LOCK - screen locked"
|
||||
);
|
||||
tracing::debug!("WM_WTSSESSION_CHANGE event received with WTS_SESSION_LOCK - screen locked");
|
||||
|
||||
monitor_reconciliator::send_notification(
|
||||
monitor_reconciliator::MonitorNotification::SessionLocked,
|
||||
);
|
||||
}
|
||||
WTS_SESSION_UNLOCK => {
|
||||
tracing::debug!(
|
||||
"WM_WTSSESSION_CHANGE event received with WTS_SESSION_UNLOCK - screen unlocked"
|
||||
);
|
||||
tracing::debug!("WM_WTSSESSION_CHANGE event received with WTS_SESSION_UNLOCK - screen unlocked");
|
||||
|
||||
monitor_reconciliator::send_notification(
|
||||
monitor_reconciliator::MonitorNotification::SessionUnlocked,
|
||||
@@ -255,8 +251,7 @@ impl Hidden {
|
||||
// and resolution changes here
|
||||
WM_DISPLAYCHANGE => {
|
||||
tracing::debug!(
|
||||
"WM_DISPLAYCHANGE event received with wparam: {}- work area or display resolution changed",
|
||||
wparam.0
|
||||
"WM_DISPLAYCHANGE event received with wparam: {}- work area or display resolution changed", wparam.0
|
||||
);
|
||||
|
||||
monitor_reconciliator::send_notification(
|
||||
@@ -270,8 +265,8 @@ impl Hidden {
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
if wparam.0 as u32 == SPI_SETWORKAREA.0 {
|
||||
tracing::debug!(
|
||||
"WM_SETTINGCHANGE event received with SPI_SETWORKAREA - work area changed (probably butterytaskbar or something similar)"
|
||||
);
|
||||
"WM_SETTINGCHANGE event received with SPI_SETWORKAREA - work area changed (probably butterytaskbar or something similar)"
|
||||
);
|
||||
|
||||
monitor_reconciliator::send_notification(
|
||||
monitor_reconciliator::MonitorNotification::WorkAreaChanged,
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
#![deny(clippy::unwrap_used, clippy::expect_used)]
|
||||
|
||||
use crate::Notification;
|
||||
use crate::NotificationEvent;
|
||||
use crate::State;
|
||||
use crate::WORKSPACE_MATCHING_RULES;
|
||||
use crate::WindowManager;
|
||||
use crate::WindowsApi;
|
||||
use crate::border_manager;
|
||||
use crate::config_generation::WorkspaceMatchingRule;
|
||||
use crate::core::Rect;
|
||||
@@ -13,6 +7,12 @@ use crate::monitor;
|
||||
use crate::monitor::Monitor;
|
||||
use crate::monitor_reconciliator::hidden::Hidden;
|
||||
use crate::notify_subscribers;
|
||||
use crate::Notification;
|
||||
use crate::NotificationEvent;
|
||||
use crate::State;
|
||||
use crate::WindowManager;
|
||||
use crate::WindowsApi;
|
||||
use crate::WORKSPACE_MATCHING_RULES;
|
||||
use crossbeam_channel::Receiver;
|
||||
use crossbeam_channel::Sender;
|
||||
use crossbeam_utils::atomic::AtomicConsume;
|
||||
@@ -21,10 +21,10 @@ use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use std::sync::OnceLock;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Arc;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
pub mod hidden;
|
||||
|
||||
@@ -112,18 +112,16 @@ pub fn listen_for_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Re
|
||||
|
||||
tracing::info!("created hidden window to listen for monitor-related events");
|
||||
|
||||
std::thread::spawn(move || {
|
||||
loop {
|
||||
match handle_notifications(wm.clone()) {
|
||||
Ok(()) => {
|
||||
tracing::warn!("restarting finished thread");
|
||||
}
|
||||
Err(error) => {
|
||||
if cfg!(debug_assertions) {
|
||||
tracing::error!("restarting failed thread: {:?}", error)
|
||||
} else {
|
||||
tracing::error!("restarting failed thread: {}", error)
|
||||
}
|
||||
std::thread::spawn(move || loop {
|
||||
match handle_notifications(wm.clone()) {
|
||||
Ok(()) => {
|
||||
tracing::warn!("restarting finished thread");
|
||||
}
|
||||
Err(error) => {
|
||||
if cfg!(debug_assertions) {
|
||||
tracing::error!("restarting failed thread: {:?}", error)
|
||||
} else {
|
||||
tracing::error!("restarting failed thread: {}", error)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -266,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,35 +460,11 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
|
||||
cache_hit = true;
|
||||
cached_id = id.clone();
|
||||
|
||||
tracing::info!(
|
||||
"found monitor and workspace configuration for {id} in the monitor cache, applying"
|
||||
);
|
||||
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();
|
||||
|
||||
|
||||
@@ -8,22 +8,26 @@ use std::net::TcpListener;
|
||||
use std::net::TcpStream;
|
||||
use std::num::NonZeroUsize;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use color_eyre::Result;
|
||||
use color_eyre::eyre::anyhow;
|
||||
use color_eyre::Result;
|
||||
use miow::pipe::connect;
|
||||
use net2::TcpStreamExt;
|
||||
use parking_lot::Mutex;
|
||||
use schemars::r#gen::SchemaSettings;
|
||||
use schemars::gen::SchemaSettings;
|
||||
use schemars::schema_for;
|
||||
use uds_windows::UnixStream;
|
||||
|
||||
use crate::animation::ANIMATION_DURATION_PER_ANIMATION;
|
||||
use crate::animation::ANIMATION_ENABLED_PER_ANIMATION;
|
||||
use crate::animation::ANIMATION_STYLE_PER_ANIMATION;
|
||||
use crate::core::config_generation::ApplicationConfiguration;
|
||||
use crate::core::config_generation::IdWithIdentifier;
|
||||
use crate::core::config_generation::MatchingRule;
|
||||
use crate::core::config_generation::MatchingStrategy;
|
||||
use crate::core::ApplicationIdentifier;
|
||||
use crate::core::Axis;
|
||||
use crate::core::BorderImplementation;
|
||||
@@ -37,34 +41,7 @@ use crate::core::SocketMessage;
|
||||
use crate::core::StateQuery;
|
||||
use crate::core::WindowContainerBehaviour;
|
||||
use crate::core::WindowKind;
|
||||
use crate::core::config_generation::ApplicationConfiguration;
|
||||
use crate::core::config_generation::IdWithIdentifier;
|
||||
use crate::core::config_generation::MatchingRule;
|
||||
use crate::core::config_generation::MatchingStrategy;
|
||||
|
||||
use crate::CUSTOM_FFM;
|
||||
use crate::DATA_DIR;
|
||||
use crate::DISPLAY_INDEX_PREFERENCES;
|
||||
use crate::GlobalState;
|
||||
use crate::HIDING_BEHAVIOUR;
|
||||
use crate::IGNORE_IDENTIFIERS;
|
||||
use crate::INITIAL_CONFIGURATION_LOADED;
|
||||
use crate::LAYERED_WHITELIST;
|
||||
use crate::MANAGE_IDENTIFIERS;
|
||||
use crate::MONITOR_INDEX_PREFERENCES;
|
||||
use crate::NO_TITLEBAR;
|
||||
use crate::Notification;
|
||||
use crate::NotificationEvent;
|
||||
use crate::OBJECT_NAME_CHANGE_ON_LAUNCH;
|
||||
use crate::REMOVE_TITLEBARS;
|
||||
use crate::SUBSCRIPTION_PIPES;
|
||||
use crate::SUBSCRIPTION_SOCKET_OPTIONS;
|
||||
use crate::SUBSCRIPTION_SOCKETS;
|
||||
use crate::State;
|
||||
use crate::TCP_CONNECTIONS;
|
||||
use crate::TRAY_AND_MULTI_WINDOW_IDENTIFIERS;
|
||||
use crate::WINDOWS_11;
|
||||
use crate::WORKSPACE_MATCHING_RULES;
|
||||
use crate::animation::ANIMATION_DURATION_GLOBAL;
|
||||
use crate::animation::ANIMATION_ENABLED_GLOBAL;
|
||||
use crate::animation::ANIMATION_FPS;
|
||||
@@ -91,6 +68,29 @@ use crate::windows_api::WindowsApi;
|
||||
use crate::winevent_listener;
|
||||
use crate::workspace::WorkspaceLayer;
|
||||
use crate::workspace::WorkspaceWindowLocation;
|
||||
use crate::GlobalState;
|
||||
use crate::Notification;
|
||||
use crate::NotificationEvent;
|
||||
use crate::State;
|
||||
use crate::CUSTOM_FFM;
|
||||
use crate::DATA_DIR;
|
||||
use crate::DISPLAY_INDEX_PREFERENCES;
|
||||
use crate::HIDING_BEHAVIOUR;
|
||||
use crate::IGNORE_IDENTIFIERS;
|
||||
use crate::INITIAL_CONFIGURATION_LOADED;
|
||||
use crate::LAYERED_WHITELIST;
|
||||
use crate::MANAGE_IDENTIFIERS;
|
||||
use crate::MONITOR_INDEX_PREFERENCES;
|
||||
use crate::NO_TITLEBAR;
|
||||
use crate::OBJECT_NAME_CHANGE_ON_LAUNCH;
|
||||
use crate::REMOVE_TITLEBARS;
|
||||
use crate::SUBSCRIPTION_PIPES;
|
||||
use crate::SUBSCRIPTION_SOCKETS;
|
||||
use crate::SUBSCRIPTION_SOCKET_OPTIONS;
|
||||
use crate::TCP_CONNECTIONS;
|
||||
use crate::TRAY_AND_MULTI_WINDOW_IDENTIFIERS;
|
||||
use crate::WINDOWS_11;
|
||||
use crate::WORKSPACE_MATCHING_RULES;
|
||||
use stackbar_manager::STACKBAR_FOCUSED_TEXT_COLOUR;
|
||||
use stackbar_manager::STACKBAR_LABEL;
|
||||
use stackbar_manager::STACKBAR_MODE;
|
||||
@@ -101,44 +101,42 @@ use stackbar_manager::STACKBAR_UNFOCUSED_TEXT_COLOUR;
|
||||
|
||||
#[tracing::instrument]
|
||||
pub fn listen_for_commands(wm: Arc<Mutex<WindowManager>>) {
|
||||
std::thread::spawn(move || {
|
||||
loop {
|
||||
let wm = wm.clone();
|
||||
std::thread::spawn(move || loop {
|
||||
let wm = wm.clone();
|
||||
|
||||
let _ = std::thread::spawn(move || {
|
||||
let listener = wm
|
||||
.lock()
|
||||
.command_listener
|
||||
.try_clone()
|
||||
.expect("could not clone unix listener");
|
||||
let _ = std::thread::spawn(move || {
|
||||
let listener = wm
|
||||
.lock()
|
||||
.command_listener
|
||||
.try_clone()
|
||||
.expect("could not clone unix listener");
|
||||
|
||||
tracing::info!("listening on komorebi.sock");
|
||||
for client in listener.incoming() {
|
||||
match client {
|
||||
Ok(stream) => {
|
||||
let wm_clone = wm.clone();
|
||||
std::thread::spawn(move || {
|
||||
match stream.set_read_timeout(Some(Duration::from_secs(1))) {
|
||||
Ok(()) => {}
|
||||
Err(error) => tracing::error!("{}", error),
|
||||
}
|
||||
match read_commands_uds(&wm_clone, stream) {
|
||||
Ok(()) => {}
|
||||
Err(error) => tracing::error!("{}", error),
|
||||
}
|
||||
});
|
||||
}
|
||||
Err(error) => {
|
||||
tracing::error!("{}", error);
|
||||
break;
|
||||
}
|
||||
tracing::info!("listening on komorebi.sock");
|
||||
for client in listener.incoming() {
|
||||
match client {
|
||||
Ok(stream) => {
|
||||
let wm_clone = wm.clone();
|
||||
std::thread::spawn(move || {
|
||||
match stream.set_read_timeout(Some(Duration::from_secs(1))) {
|
||||
Ok(()) => {}
|
||||
Err(error) => tracing::error!("{}", error),
|
||||
}
|
||||
match read_commands_uds(&wm_clone, stream) {
|
||||
Ok(()) => {}
|
||||
Err(error) => tracing::error!("{}", error),
|
||||
}
|
||||
});
|
||||
}
|
||||
Err(error) => {
|
||||
tracing::error!("{}", error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
})
|
||||
.join();
|
||||
}
|
||||
})
|
||||
.join();
|
||||
|
||||
tracing::error!("restarting failed thread");
|
||||
}
|
||||
tracing::error!("restarting failed thread");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1051,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)?;
|
||||
@@ -1216,7 +1193,7 @@ impl WindowManager {
|
||||
let container_len = workspace.containers().len();
|
||||
let no_layout_rules = workspace.layout_rules().is_empty();
|
||||
|
||||
if let Layout::Custom(custom) = workspace.layout_mut() {
|
||||
if let Layout::Custom(ref mut custom) = workspace.layout_mut() {
|
||||
if matches!(axis, Axis::Horizontal) {
|
||||
#[allow(clippy::cast_precision_loss)]
|
||||
let percentage = custom
|
||||
@@ -1378,9 +1355,7 @@ impl WindowManager {
|
||||
self.focus_follows_mouse = None;
|
||||
}
|
||||
Some(FocusFollowsMouseImplementation::Windows) => {
|
||||
tracing::warn!(
|
||||
"ignoring command that could mix different focus follows mouse implementations"
|
||||
);
|
||||
tracing::warn!("ignoring command that could mix different focus follows mouse implementations");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1404,9 +1379,7 @@ impl WindowManager {
|
||||
self.focus_follows_mouse = None;
|
||||
}
|
||||
Some(FocusFollowsMouseImplementation::Komorebi) => {
|
||||
tracing::warn!(
|
||||
"ignoring command that could mix different focus follows mouse implementations"
|
||||
);
|
||||
tracing::warn!("ignoring command that could mix different focus follows mouse implementations");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1648,41 +1621,33 @@ impl WindowManager {
|
||||
}
|
||||
SocketMessage::ToggleWorkspaceWindowContainerBehaviour => {
|
||||
let current_global_behaviour = self.window_management_behaviour.current_behaviour;
|
||||
match self
|
||||
if let Some(behaviour) = self
|
||||
.focused_workspace_mut()?
|
||||
.window_container_behaviour_mut()
|
||||
{
|
||||
Some(behaviour) => match behaviour {
|
||||
match behaviour {
|
||||
WindowContainerBehaviour::Create => {
|
||||
*behaviour = WindowContainerBehaviour::Append
|
||||
}
|
||||
WindowContainerBehaviour::Append => {
|
||||
*behaviour = WindowContainerBehaviour::Create
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
self.focused_workspace_mut()?
|
||||
.set_window_container_behaviour(Some(match current_global_behaviour {
|
||||
WindowContainerBehaviour::Create => {
|
||||
WindowContainerBehaviour::Append
|
||||
}
|
||||
WindowContainerBehaviour::Append => {
|
||||
WindowContainerBehaviour::Create
|
||||
}
|
||||
}));
|
||||
}
|
||||
} else {
|
||||
self.focused_workspace_mut()?
|
||||
.set_window_container_behaviour(Some(match current_global_behaviour {
|
||||
WindowContainerBehaviour::Create => WindowContainerBehaviour::Append,
|
||||
WindowContainerBehaviour::Append => WindowContainerBehaviour::Create,
|
||||
}));
|
||||
};
|
||||
}
|
||||
SocketMessage::ToggleWorkspaceFloatOverride => {
|
||||
let current_global_override = self.window_management_behaviour.float_override;
|
||||
match self.focused_workspace_mut()?.float_override_mut() {
|
||||
Some(float_override) => {
|
||||
*float_override = !*float_override;
|
||||
}
|
||||
_ => {
|
||||
self.focused_workspace_mut()?
|
||||
.set_float_override(Some(!current_global_override));
|
||||
}
|
||||
if let Some(float_override) = self.focused_workspace_mut()?.float_override_mut() {
|
||||
*float_override = !*float_override;
|
||||
} else {
|
||||
self.focused_workspace_mut()?
|
||||
.set_float_override(Some(!current_global_override));
|
||||
};
|
||||
}
|
||||
SocketMessage::WindowHidingBehaviour(behaviour) => {
|
||||
@@ -1866,8 +1831,8 @@ impl WindowManager {
|
||||
s.inline_subschemas = true;
|
||||
});
|
||||
|
||||
let r#gen = settings.into_generator();
|
||||
let socket_message = r#gen.into_root_schema_for::<StaticConfig>();
|
||||
let gen = settings.into_generator();
|
||||
let socket_message = gen.into_root_schema_for::<StaticConfig>();
|
||||
let schema = serde_json::to_string_pretty(&socket_message)?;
|
||||
|
||||
reply.write_all(schema.as_bytes())?;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use std::time::Instant;
|
||||
|
||||
use color_eyre::Result;
|
||||
use color_eyre::eyre::anyhow;
|
||||
use color_eyre::Result;
|
||||
use crossbeam_utils::atomic::AtomicConsume;
|
||||
use parking_lot::Mutex;
|
||||
|
||||
@@ -13,13 +13,6 @@ use crate::core::Rect;
|
||||
use crate::core::Sizing;
|
||||
use crate::core::WindowContainerBehaviour;
|
||||
|
||||
use crate::FLOATING_APPLICATIONS;
|
||||
use crate::HIDDEN_HWNDS;
|
||||
use crate::Notification;
|
||||
use crate::NotificationEvent;
|
||||
use crate::REGEX_IDENTIFIERS;
|
||||
use crate::State;
|
||||
use crate::TRAY_AND_MULTI_WINDOW_IDENTIFIERS;
|
||||
use crate::border_manager;
|
||||
use crate::border_manager::BORDER_OFFSET;
|
||||
use crate::border_manager::BORDER_WIDTH;
|
||||
@@ -27,16 +20,22 @@ use crate::current_virtual_desktop;
|
||||
use crate::notify_subscribers;
|
||||
use crate::stackbar_manager;
|
||||
use crate::transparency_manager;
|
||||
use crate::window::RuleDebug;
|
||||
use crate::window::should_act;
|
||||
use crate::window::RuleDebug;
|
||||
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;
|
||||
use crate::Notification;
|
||||
use crate::NotificationEvent;
|
||||
use crate::State;
|
||||
use crate::FLOATING_APPLICATIONS;
|
||||
use crate::HIDDEN_HWNDS;
|
||||
use crate::REGEX_IDENTIFIERS;
|
||||
use crate::TRAY_AND_MULTI_WINDOW_IDENTIFIERS;
|
||||
|
||||
#[tracing::instrument]
|
||||
pub fn listen_for_events(wm: Arc<Mutex<WindowManager>>) {
|
||||
@@ -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();
|
||||
}
|
||||
@@ -661,7 +655,7 @@ impl WindowManager {
|
||||
let mut ops = vec![];
|
||||
|
||||
macro_rules! resize_op {
|
||||
($coordinate:expr_2021, $comparator:tt, $direction:expr_2021) => {{
|
||||
($coordinate:expr, $comparator:tt, $direction:expr) => {{
|
||||
let adjusted = $coordinate * 2;
|
||||
let sizing = if adjusted $comparator 0 {
|
||||
Sizing::Decrease
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use parking_lot::Mutex;
|
||||
use winput::Action;
|
||||
use winput::message_loop;
|
||||
use winput::message_loop::Event;
|
||||
use winput::Action;
|
||||
|
||||
use crate::core::FocusFollowsMouseImplementation;
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#![deny(clippy::unwrap_used, clippy::expect_used)]
|
||||
|
||||
use crate::DATA_DIR;
|
||||
use crate::border_manager;
|
||||
use crate::notify_subscribers;
|
||||
use crate::winevent::WinEvent;
|
||||
use crate::NotificationEvent;
|
||||
use crate::Window;
|
||||
use crate::WindowManager;
|
||||
use crate::WindowManagerEvent;
|
||||
use crate::border_manager;
|
||||
use crate::notify_subscribers;
|
||||
use crate::winevent::WinEvent;
|
||||
use crate::DATA_DIR;
|
||||
|
||||
use crossbeam_channel::Receiver;
|
||||
use crossbeam_channel::Sender;
|
||||
@@ -47,21 +47,16 @@ 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()) {
|
||||
Ok(()) => {
|
||||
tracing::warn!("restarting finished thread");
|
||||
}
|
||||
Err(error) => {
|
||||
tracing::warn!("restarting failed thread: {}", error);
|
||||
}
|
||||
std::thread::spawn(move || loop {
|
||||
match handle_notifications(wm.clone()) {
|
||||
Ok(()) => {
|
||||
tracing::warn!("restarting finished thread");
|
||||
}
|
||||
Err(error) => {
|
||||
tracing::warn!("restarting failed thread: {}", error);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -75,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
|
||||
@@ -98,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!(
|
||||
@@ -143,25 +150,23 @@ 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 {
|
||||
match find_orphans() {
|
||||
Ok(()) => {
|
||||
tracing::warn!("restarting finished thread");
|
||||
}
|
||||
Err(error) => {
|
||||
if cfg!(debug_assertions) {
|
||||
tracing::error!("restarting failed thread: {:?}", error)
|
||||
} else {
|
||||
tracing::error!("restarting failed thread: {}", error)
|
||||
}
|
||||
std::thread::spawn(move || loop {
|
||||
match find_orphans() {
|
||||
Ok(()) => {
|
||||
tracing::warn!("restarting finished thread");
|
||||
}
|
||||
Err(error) => {
|
||||
if cfg!(debug_assertions) {
|
||||
tracing::error!("restarting failed thread: {:?}", error)
|
||||
} else {
|
||||
tracing::error!("restarting failed thread: {}", error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
mod stackbar;
|
||||
|
||||
use crate::DEFAULT_CONTAINER_PADDING;
|
||||
use crate::WindowManager;
|
||||
use crate::WindowsApi;
|
||||
use crate::container::Container;
|
||||
use crate::core::StackbarLabel;
|
||||
use crate::core::StackbarMode;
|
||||
use crate::stackbar_manager::stackbar::Stackbar;
|
||||
use crate::WindowManager;
|
||||
use crate::WindowsApi;
|
||||
use crate::DEFAULT_CONTAINER_PADDING;
|
||||
use crossbeam_channel::Receiver;
|
||||
use crossbeam_channel::Sender;
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
use crossbeam_utils::atomic::AtomicConsume;
|
||||
use lazy_static::lazy_static;
|
||||
use parking_lot::Mutex;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::sync::Arc;
|
||||
use std::sync::OnceLock;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::atomic::AtomicI32;
|
||||
use std::sync::atomic::AtomicU32;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Arc;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
pub static STACKBAR_FONT_SIZE: AtomicI32 = AtomicI32::new(0); // 0 will produce the system default
|
||||
pub static STACKBAR_FOCUSED_TEXT_COLOUR: AtomicU32 = AtomicU32::new(16777215); // white
|
||||
@@ -71,15 +71,13 @@ pub fn should_have_stackbar(window_count: usize) -> bool {
|
||||
}
|
||||
|
||||
pub fn listen_for_notifications(wm: Arc<Mutex<WindowManager>>) {
|
||||
std::thread::spawn(move || {
|
||||
loop {
|
||||
match handle_notifications(wm.clone()) {
|
||||
Ok(()) => {
|
||||
tracing::warn!("restarting finished thread");
|
||||
}
|
||||
Err(error) => {
|
||||
tracing::warn!("restarting failed thread: {}", error);
|
||||
}
|
||||
std::thread::spawn(move || loop {
|
||||
match handle_notifications(wm.clone()) {
|
||||
Ok(()) => {
|
||||
tracing::warn!("restarting finished thread");
|
||||
}
|
||||
Err(error) => {
|
||||
tracing::warn!("restarting failed thread: {}", error);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -195,12 +193,13 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
|
||||
// Get the stackbar entry for this container from the map or create one
|
||||
let stackbar = match stackbars.entry(container.id().clone()) {
|
||||
Entry::Occupied(entry) => entry.into_mut(),
|
||||
Entry::Vacant(entry) => match Stackbar::create(container.id()) {
|
||||
Ok(stackbar) => entry.insert(stackbar),
|
||||
_ => {
|
||||
Entry::Vacant(entry) => {
|
||||
if let Ok(stackbar) = Stackbar::create(container.id()) {
|
||||
entry.insert(stackbar)
|
||||
} else {
|
||||
continue 'receiver;
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
stackbars_monitors.insert(container.id().clone(), monitor_idx);
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
use crate::DEFAULT_CONTAINER_PADDING;
|
||||
use crate::WINDOWS_11;
|
||||
use crate::WindowsApi;
|
||||
use crate::border_manager::BORDER_OFFSET;
|
||||
use crate::border_manager::BORDER_WIDTH;
|
||||
use crate::border_manager::STYLE;
|
||||
@@ -8,6 +5,7 @@ use crate::container::Container;
|
||||
use crate::core::BorderStyle;
|
||||
use crate::core::Rect;
|
||||
use crate::core::StackbarLabel;
|
||||
use crate::stackbar_manager::STACKBARS_CONTAINERS;
|
||||
use crate::stackbar_manager::STACKBAR_FOCUSED_TEXT_COLOUR;
|
||||
use crate::stackbar_manager::STACKBAR_FONT_FAMILY;
|
||||
use crate::stackbar_manager::STACKBAR_FONT_SIZE;
|
||||
@@ -16,13 +14,16 @@ use crate::stackbar_manager::STACKBAR_TAB_BACKGROUND_COLOUR;
|
||||
use crate::stackbar_manager::STACKBAR_TAB_HEIGHT;
|
||||
use crate::stackbar_manager::STACKBAR_TAB_WIDTH;
|
||||
use crate::stackbar_manager::STACKBAR_UNFOCUSED_TEXT_COLOUR;
|
||||
use crate::stackbar_manager::STACKBARS_CONTAINERS;
|
||||
use crate::windows_api;
|
||||
use crate::WindowsApi;
|
||||
use crate::DEFAULT_CONTAINER_PADDING;
|
||||
use crate::WINDOWS_11;
|
||||
use crossbeam_utils::atomic::AtomicConsume;
|
||||
use std::os::windows::ffi::OsStrExt;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::mpsc;
|
||||
use std::time::Duration;
|
||||
use windows::core::PCWSTR;
|
||||
use windows::Win32::Foundation::COLORREF;
|
||||
use windows::Win32::Foundation::HINSTANCE;
|
||||
use windows::Win32::Foundation::HWND;
|
||||
@@ -32,38 +33,38 @@ use windows::Win32::Foundation::WPARAM;
|
||||
use windows::Win32::Graphics::Gdi::CreateFontIndirectW;
|
||||
use windows::Win32::Graphics::Gdi::CreatePen;
|
||||
use windows::Win32::Graphics::Gdi::CreateSolidBrush;
|
||||
use windows::Win32::Graphics::Gdi::DT_CENTER;
|
||||
use windows::Win32::Graphics::Gdi::DT_END_ELLIPSIS;
|
||||
use windows::Win32::Graphics::Gdi::DT_SINGLELINE;
|
||||
use windows::Win32::Graphics::Gdi::DT_VCENTER;
|
||||
use windows::Win32::Graphics::Gdi::DeleteObject;
|
||||
use windows::Win32::Graphics::Gdi::DrawTextW;
|
||||
use windows::Win32::Graphics::Gdi::FONT_QUALITY;
|
||||
use windows::Win32::Graphics::Gdi::FW_BOLD;
|
||||
use windows::Win32::Graphics::Gdi::GetDC;
|
||||
use windows::Win32::Graphics::Gdi::GetDeviceCaps;
|
||||
use windows::Win32::Graphics::Gdi::LOGFONTW;
|
||||
use windows::Win32::Graphics::Gdi::LOGPIXELSY;
|
||||
use windows::Win32::Graphics::Gdi::PROOF_QUALITY;
|
||||
use windows::Win32::Graphics::Gdi::PS_SOLID;
|
||||
use windows::Win32::Graphics::Gdi::Rectangle;
|
||||
use windows::Win32::Graphics::Gdi::ReleaseDC;
|
||||
use windows::Win32::Graphics::Gdi::RoundRect;
|
||||
use windows::Win32::Graphics::Gdi::SelectObject;
|
||||
use windows::Win32::Graphics::Gdi::SetBkColor;
|
||||
use windows::Win32::Graphics::Gdi::SetTextColor;
|
||||
use windows::Win32::Graphics::Gdi::DT_CENTER;
|
||||
use windows::Win32::Graphics::Gdi::DT_END_ELLIPSIS;
|
||||
use windows::Win32::Graphics::Gdi::DT_SINGLELINE;
|
||||
use windows::Win32::Graphics::Gdi::DT_VCENTER;
|
||||
use windows::Win32::Graphics::Gdi::FONT_QUALITY;
|
||||
use windows::Win32::Graphics::Gdi::FW_BOLD;
|
||||
use windows::Win32::Graphics::Gdi::LOGFONTW;
|
||||
use windows::Win32::Graphics::Gdi::LOGPIXELSY;
|
||||
use windows::Win32::Graphics::Gdi::PROOF_QUALITY;
|
||||
use windows::Win32::Graphics::Gdi::PS_SOLID;
|
||||
use windows::Win32::System::WindowsProgramming::MulDiv;
|
||||
use windows::Win32::UI::WindowsAndMessaging::CS_HREDRAW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::CS_VREDRAW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::CreateWindowExW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::DefWindowProcW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::DispatchMessageW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GetMessageW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::LWA_COLORKEY;
|
||||
use windows::Win32::UI::WindowsAndMessaging::MSG;
|
||||
use windows::Win32::UI::WindowsAndMessaging::PostQuitMessage;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SetLayeredWindowAttributes;
|
||||
use windows::Win32::UI::WindowsAndMessaging::TranslateMessage;
|
||||
use windows::Win32::UI::WindowsAndMessaging::CS_HREDRAW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::CS_VREDRAW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::LWA_COLORKEY;
|
||||
use windows::Win32::UI::WindowsAndMessaging::MSG;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WM_DESTROY;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WM_LBUTTONDOWN;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WNDCLASSW;
|
||||
@@ -71,7 +72,6 @@ use windows::Win32::UI::WindowsAndMessaging::WS_EX_LAYERED;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_TOOLWINDOW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_POPUP;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_VISIBLE;
|
||||
use windows::core::PCWSTR;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Stackbar {
|
||||
@@ -342,10 +342,10 @@ impl Stackbar {
|
||||
window.set_position(&focused_window_rect, false)
|
||||
{
|
||||
tracing::error!(
|
||||
"stackbar WM_LBUTTONDOWN repositioning error: hwnd {} ({})",
|
||||
*window,
|
||||
err
|
||||
);
|
||||
"stackbar WM_LBUTTONDOWN repositioning error: hwnd {} ({})",
|
||||
*window,
|
||||
err
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,28 +1,4 @@
|
||||
use crate::AspectRatio;
|
||||
use crate::Axis;
|
||||
use crate::CrossBoundaryBehaviour;
|
||||
use crate::DATA_DIR;
|
||||
use crate::DEFAULT_CONTAINER_PADDING;
|
||||
use crate::DEFAULT_WORKSPACE_PADDING;
|
||||
use crate::DISPLAY_INDEX_PREFERENCES;
|
||||
use crate::FLOATING_APPLICATIONS;
|
||||
use crate::FLOATING_WINDOW_TOGGLE_ASPECT_RATIO;
|
||||
use crate::HIDING_BEHAVIOUR;
|
||||
use crate::IGNORE_IDENTIFIERS;
|
||||
use crate::LAYERED_WHITELIST;
|
||||
use crate::MANAGE_IDENTIFIERS;
|
||||
use crate::MONITOR_INDEX_PREFERENCES;
|
||||
use crate::NO_TITLEBAR;
|
||||
use crate::OBJECT_NAME_CHANGE_ON_LAUNCH;
|
||||
use crate::OBJECT_NAME_CHANGE_TITLE_IGNORE_LIST;
|
||||
use crate::PredefinedAspectRatio;
|
||||
use crate::REGEX_IDENTIFIERS;
|
||||
use crate::SLOW_APPLICATION_COMPENSATION_TIME;
|
||||
use crate::SLOW_APPLICATION_IDENTIFIERS;
|
||||
use crate::TRANSPARENCY_BLACKLIST;
|
||||
use crate::TRAY_AND_MULTI_WINDOW_IDENTIFIERS;
|
||||
use crate::WINDOWS_11;
|
||||
use crate::WORKSPACE_MATCHING_RULES;
|
||||
use crate::animation::PerAnimationPrefixConfig;
|
||||
use crate::animation::ANIMATION_DURATION_GLOBAL;
|
||||
use crate::animation::ANIMATION_DURATION_PER_ANIMATION;
|
||||
use crate::animation::ANIMATION_ENABLED_GLOBAL;
|
||||
@@ -31,11 +7,10 @@ use crate::animation::ANIMATION_FPS;
|
||||
use crate::animation::ANIMATION_STYLE_GLOBAL;
|
||||
use crate::animation::ANIMATION_STYLE_PER_ANIMATION;
|
||||
use crate::animation::DEFAULT_ANIMATION_FPS;
|
||||
use crate::animation::PerAnimationPrefixConfig;
|
||||
use crate::border_manager;
|
||||
use crate::border_manager::ZOrder;
|
||||
use crate::border_manager::IMPLEMENTATION;
|
||||
use crate::border_manager::STYLE;
|
||||
use crate::border_manager::ZOrder;
|
||||
use crate::colour::Colour;
|
||||
use crate::core::BorderImplementation;
|
||||
use crate::core::StackbarLabel;
|
||||
@@ -61,10 +36,41 @@ use crate::window_manager::WindowManager;
|
||||
use crate::window_manager_event::WindowManagerEvent;
|
||||
use crate::windows_api::WindowsApi;
|
||||
use crate::workspace::Workspace;
|
||||
use crate::AspectRatio;
|
||||
use crate::Axis;
|
||||
use crate::CrossBoundaryBehaviour;
|
||||
use crate::PredefinedAspectRatio;
|
||||
use crate::DATA_DIR;
|
||||
use crate::DEFAULT_CONTAINER_PADDING;
|
||||
use crate::DEFAULT_WORKSPACE_PADDING;
|
||||
use crate::DISPLAY_INDEX_PREFERENCES;
|
||||
use crate::FLOATING_APPLICATIONS;
|
||||
use crate::FLOATING_WINDOW_TOGGLE_ASPECT_RATIO;
|
||||
use crate::HIDING_BEHAVIOUR;
|
||||
use crate::IGNORE_IDENTIFIERS;
|
||||
use crate::LAYERED_WHITELIST;
|
||||
use crate::MANAGE_IDENTIFIERS;
|
||||
use crate::MONITOR_INDEX_PREFERENCES;
|
||||
use crate::NO_TITLEBAR;
|
||||
use crate::OBJECT_NAME_CHANGE_ON_LAUNCH;
|
||||
use crate::OBJECT_NAME_CHANGE_TITLE_IGNORE_LIST;
|
||||
use crate::REGEX_IDENTIFIERS;
|
||||
use crate::SLOW_APPLICATION_COMPENSATION_TIME;
|
||||
use crate::SLOW_APPLICATION_IDENTIFIERS;
|
||||
use crate::TRANSPARENCY_BLACKLIST;
|
||||
use crate::TRAY_AND_MULTI_WINDOW_IDENTIFIERS;
|
||||
use crate::WINDOWS_11;
|
||||
use crate::WORKSPACE_MATCHING_RULES;
|
||||
|
||||
use crate::asc::ApplicationSpecificConfiguration;
|
||||
use crate::asc::AscApplicationRulesOrSchema;
|
||||
use crate::config_generation::WorkspaceMatchingRule;
|
||||
use crate::core::config_generation::ApplicationConfiguration;
|
||||
use crate::core::config_generation::ApplicationConfigurationGenerator;
|
||||
use crate::core::config_generation::ApplicationOptions;
|
||||
use crate::core::config_generation::MatchingRule;
|
||||
use crate::core::config_generation::MatchingStrategy;
|
||||
use crate::core::resolve_home_path;
|
||||
use crate::core::AnimationStyle;
|
||||
use crate::core::BorderStyle;
|
||||
use crate::core::DefaultLayout;
|
||||
@@ -77,12 +83,6 @@ use crate::core::Rect;
|
||||
use crate::core::SocketMessage;
|
||||
use crate::core::WindowContainerBehaviour;
|
||||
use crate::core::WindowManagementBehaviour;
|
||||
use crate::core::config_generation::ApplicationConfiguration;
|
||||
use crate::core::config_generation::ApplicationConfigurationGenerator;
|
||||
use crate::core::config_generation::ApplicationOptions;
|
||||
use crate::core::config_generation::MatchingRule;
|
||||
use crate::core::config_generation::MatchingStrategy;
|
||||
use crate::core::resolve_home_path;
|
||||
use color_eyre::Result;
|
||||
use crossbeam_channel::Receiver;
|
||||
use hotwatch::EventKind;
|
||||
@@ -97,8 +97,8 @@ use std::collections::HashSet;
|
||||
use std::io::ErrorKind;
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Arc;
|
||||
use uds_windows::UnixListener;
|
||||
use uds_windows::UnixStream;
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -555,9 +528,7 @@ impl StaticConfig {
|
||||
}
|
||||
|
||||
if display {
|
||||
println!(
|
||||
"\nEnd-of-life features will not receive any further bug fixes or updates; they should not be used\n"
|
||||
)
|
||||
println!("\nEnd-of-life features will not receive any further bug fixes or updates; they should not be used\n")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -582,9 +553,7 @@ impl StaticConfig {
|
||||
}
|
||||
|
||||
if display {
|
||||
println!(
|
||||
"\nYour configuration file contains some options that have been renamed or deprecated:\n"
|
||||
);
|
||||
println!("\nYour configuration file contains some options that have been renamed or deprecated:\n");
|
||||
for (canonical, aliases) in map {
|
||||
for alias in aliases {
|
||||
if raw.contains(alias) {
|
||||
@@ -1281,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();
|
||||
@@ -1327,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)?;
|
||||
@@ -1412,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) {
|
||||
@@ -1450,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();
|
||||
@@ -1498,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) {
|
||||
@@ -1584,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) {
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
#![deny(clippy::unwrap_used, clippy::expect_used)]
|
||||
|
||||
use crate::Colour;
|
||||
use crate::KomorebiTheme;
|
||||
use crate::border_manager;
|
||||
use crate::stackbar_manager;
|
||||
use crate::stackbar_manager::STACKBAR_FOCUSED_TEXT_COLOUR;
|
||||
use crate::stackbar_manager::STACKBAR_TAB_BACKGROUND_COLOUR;
|
||||
use crate::stackbar_manager::STACKBAR_UNFOCUSED_TEXT_COLOUR;
|
||||
use crate::Colour;
|
||||
use crate::KomorebiTheme;
|
||||
use crossbeam_channel::Receiver;
|
||||
use crossbeam_channel::Sender;
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
use std::ops::Deref;
|
||||
use std::sync::OnceLock;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
pub struct Notification(KomorebiTheme);
|
||||
|
||||
@@ -50,15 +50,13 @@ pub fn send_notification(theme: KomorebiTheme) {
|
||||
}
|
||||
|
||||
pub fn listen_for_notifications() {
|
||||
std::thread::spawn(move || {
|
||||
loop {
|
||||
match handle_notifications() {
|
||||
Ok(()) => {
|
||||
tracing::warn!("restarting finished thread");
|
||||
}
|
||||
Err(error) => {
|
||||
tracing::warn!("restarting failed thread: {}", error);
|
||||
}
|
||||
std::thread::spawn(move || loop {
|
||||
match handle_notifications() {
|
||||
Ok(()) => {
|
||||
tracing::warn!("restarting finished thread");
|
||||
}
|
||||
Err(error) => {
|
||||
tracing::warn!("restarting failed thread: {}", error);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -4,17 +4,17 @@ use crossbeam_channel::Receiver;
|
||||
use crossbeam_channel::Sender;
|
||||
use crossbeam_utils::atomic::AtomicConsume;
|
||||
use parking_lot::Mutex;
|
||||
use std::sync::Arc;
|
||||
use std::sync::OnceLock;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::atomic::AtomicU8;
|
||||
use std::sync::Arc;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
use crate::REGEX_IDENTIFIERS;
|
||||
use crate::TRANSPARENCY_BLACKLIST;
|
||||
use crate::should_act;
|
||||
use crate::Window;
|
||||
use crate::WindowManager;
|
||||
use crate::WindowsApi;
|
||||
use crate::should_act;
|
||||
use crate::REGEX_IDENTIFIERS;
|
||||
use crate::TRANSPARENCY_BLACKLIST;
|
||||
|
||||
pub static TRANSPARENCY_ENABLED: AtomicBool = AtomicBool::new(false);
|
||||
pub static TRANSPARENCY_ALPHA: AtomicU8 = AtomicU8::new(200);
|
||||
@@ -49,15 +49,13 @@ pub fn send_notification() {
|
||||
}
|
||||
|
||||
pub fn listen_for_notifications(wm: Arc<Mutex<WindowManager>>) {
|
||||
std::thread::spawn(move || {
|
||||
loop {
|
||||
match handle_notifications(wm.clone()) {
|
||||
Ok(()) => {
|
||||
tracing::warn!("restarting finished thread");
|
||||
}
|
||||
Err(error) => {
|
||||
tracing::warn!("restarting failed thread: {}", error);
|
||||
}
|
||||
std::thread::spawn(move || loop {
|
||||
match handle_notifications(wm.clone()) {
|
||||
Ok(()) => {
|
||||
tracing::warn!("restarting finished thread");
|
||||
}
|
||||
Err(error) => {
|
||||
tracing::warn!("restarting failed thread: {}", error);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -177,9 +175,7 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
|
||||
match window.transparent() {
|
||||
Err(error) => {
|
||||
let hwnd = foreground_hwnd;
|
||||
tracing::error!(
|
||||
"failed to make unfocused window {hwnd} transparent: {error}"
|
||||
)
|
||||
tracing::error!("failed to make unfocused window {hwnd} transparent: {error}" )
|
||||
}
|
||||
Ok(..) => {
|
||||
known_hwnds.lock().push(window.hwnd);
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use crate::AnimationStyle;
|
||||
use crate::FLOATING_WINDOW_TOGGLE_ASPECT_RATIO;
|
||||
use crate::SLOW_APPLICATION_COMPENSATION_TIME;
|
||||
use crate::SLOW_APPLICATION_IDENTIFIERS;
|
||||
use crate::animation::lerp::Lerp;
|
||||
use crate::animation::prefix::new_animation_key;
|
||||
use crate::animation::prefix::AnimationPrefix;
|
||||
use crate::animation::AnimationEngine;
|
||||
use crate::animation::RenderDispatcher;
|
||||
use crate::animation::ANIMATION_DURATION_GLOBAL;
|
||||
use crate::animation::ANIMATION_DURATION_PER_ANIMATION;
|
||||
use crate::animation::ANIMATION_ENABLED_GLOBAL;
|
||||
@@ -9,15 +10,14 @@ use crate::animation::ANIMATION_ENABLED_PER_ANIMATION;
|
||||
use crate::animation::ANIMATION_MANAGER;
|
||||
use crate::animation::ANIMATION_STYLE_GLOBAL;
|
||||
use crate::animation::ANIMATION_STYLE_PER_ANIMATION;
|
||||
use crate::animation::AnimationEngine;
|
||||
use crate::animation::RenderDispatcher;
|
||||
use crate::animation::lerp::Lerp;
|
||||
use crate::animation::prefix::AnimationPrefix;
|
||||
use crate::animation::prefix::new_animation_key;
|
||||
use crate::com::SetCloak;
|
||||
use crate::focus_manager;
|
||||
use crate::stackbar_manager;
|
||||
use crate::windows_api;
|
||||
use crate::AnimationStyle;
|
||||
use crate::FLOATING_WINDOW_TOGGLE_ASPECT_RATIO;
|
||||
use crate::SLOW_APPLICATION_COMPENSATION_TIME;
|
||||
use crate::SLOW_APPLICATION_IDENTIFIERS;
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryFrom;
|
||||
use std::fmt::Display;
|
||||
@@ -31,15 +31,15 @@ use std::time::Duration;
|
||||
use crate::core::config_generation::IdWithIdentifier;
|
||||
use crate::core::config_generation::MatchingRule;
|
||||
use crate::core::config_generation::MatchingStrategy;
|
||||
use color_eyre::Result;
|
||||
use color_eyre::eyre;
|
||||
use color_eyre::Result;
|
||||
use crossbeam_utils::atomic::AtomicConsume;
|
||||
use regex::Regex;
|
||||
use schemars::JsonSchema;
|
||||
use serde::ser::SerializeStruct;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use serde::Serializer;
|
||||
use serde::ser::SerializeStruct;
|
||||
use strum::Display;
|
||||
use strum::EnumString;
|
||||
use windows::Win32::Foundation::HWND;
|
||||
@@ -48,6 +48,11 @@ use crate::core::ApplicationIdentifier;
|
||||
use crate::core::HidingBehaviour;
|
||||
use crate::core::Rect;
|
||||
|
||||
use crate::styles::ExtendedWindowStyle;
|
||||
use crate::styles::WindowStyle;
|
||||
use crate::transparency_manager;
|
||||
use crate::window_manager_event::WindowManagerEvent;
|
||||
use crate::windows_api::WindowsApi;
|
||||
use crate::FLOATING_APPLICATIONS;
|
||||
use crate::HIDDEN_HWNDS;
|
||||
use crate::HIDING_BEHAVIOUR;
|
||||
@@ -58,11 +63,6 @@ use crate::NO_TITLEBAR;
|
||||
use crate::PERMAIGNORE_CLASSES;
|
||||
use crate::REGEX_IDENTIFIERS;
|
||||
use crate::WSL2_UI_PROCESSES;
|
||||
use crate::styles::ExtendedWindowStyle;
|
||||
use crate::styles::WindowStyle;
|
||||
use crate::transparency_manager;
|
||||
use crate::window_manager_event::WindowManagerEvent;
|
||||
use crate::windows_api::WindowsApi;
|
||||
|
||||
pub static MINIMUM_WIDTH: AtomicI32 = AtomicI32::new(0);
|
||||
pub static MINIMUM_HEIGHT: AtomicI32 = AtomicI32::new(0);
|
||||
@@ -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,
|
||||
@@ -886,7 +862,7 @@ fn window_is_eligible(
|
||||
let regex_identifiers = REGEX_IDENTIFIERS.lock();
|
||||
|
||||
let ignore_identifiers = IGNORE_IDENTIFIERS.lock();
|
||||
let should_ignore = match should_act(
|
||||
let should_ignore = if let Some(rule) = should_act(
|
||||
title,
|
||||
exe_name,
|
||||
class,
|
||||
@@ -894,15 +870,14 @@ fn window_is_eligible(
|
||||
&ignore_identifiers,
|
||||
®ex_identifiers,
|
||||
) {
|
||||
Some(rule) => {
|
||||
debug.matches_ignore_identifier = Some(rule);
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
debug.matches_ignore_identifier = Some(rule);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
let manage_identifiers = MANAGE_IDENTIFIERS.lock();
|
||||
let managed_override = match should_act(
|
||||
let managed_override = if let Some(rule) = should_act(
|
||||
title,
|
||||
exe_name,
|
||||
class,
|
||||
@@ -910,11 +885,10 @@ fn window_is_eligible(
|
||||
&manage_identifiers,
|
||||
®ex_identifiers,
|
||||
) {
|
||||
Some(rule) => {
|
||||
debug.matches_managed_override = Some(rule);
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
debug.matches_managed_override = Some(rule);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
let floating_identifiers = FLOATING_APPLICATIONS.lock();
|
||||
@@ -934,7 +908,7 @@ fn window_is_eligible(
|
||||
}
|
||||
|
||||
let layered_whitelist = LAYERED_WHITELIST.lock();
|
||||
let mut allow_layered = match should_act(
|
||||
let mut allow_layered = if let Some(rule) = should_act(
|
||||
title,
|
||||
exe_name,
|
||||
class,
|
||||
@@ -942,11 +916,10 @@ fn window_is_eligible(
|
||||
&layered_whitelist,
|
||||
®ex_identifiers,
|
||||
) {
|
||||
Some(rule) => {
|
||||
debug.matches_layered_whitelist = Some(rule);
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
debug.matches_layered_whitelist = Some(rule);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
let known_layered_hwnds = transparency_manager::known_hwnds();
|
||||
@@ -973,7 +946,7 @@ fn window_is_eligible(
|
||||
};
|
||||
|
||||
let titlebars_removed = NO_TITLEBAR.lock();
|
||||
let allow_titlebar_removed = match should_act(
|
||||
let allow_titlebar_removed = if let Some(rule) = should_act(
|
||||
title,
|
||||
exe_name,
|
||||
class,
|
||||
@@ -981,11 +954,10 @@ fn window_is_eligible(
|
||||
&titlebars_removed,
|
||||
®ex_identifiers,
|
||||
) {
|
||||
Some(rule) => {
|
||||
debug.matches_no_titlebar = Some(rule);
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
debug.matches_no_titlebar = Some(rule);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
{
|
||||
|
||||
@@ -8,16 +8,16 @@ use std::net::Shutdown;
|
||||
use std::num::NonZeroUsize;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Arc;
|
||||
|
||||
use color_eyre::Result;
|
||||
use color_eyre::eyre::anyhow;
|
||||
use color_eyre::eyre::bail;
|
||||
use color_eyre::Result;
|
||||
use crossbeam_channel::Receiver;
|
||||
use hotwatch::notify::ErrorKind as NotifyErrorKind;
|
||||
use hotwatch::EventKind;
|
||||
use hotwatch::Hotwatch;
|
||||
use hotwatch::notify::ErrorKind as NotifyErrorKind;
|
||||
use parking_lot::Mutex;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
@@ -25,9 +25,11 @@ use serde::Serialize;
|
||||
use uds_windows::UnixListener;
|
||||
use uds_windows::UnixStream;
|
||||
|
||||
use crate::animation::AnimationEngine;
|
||||
use crate::animation::ANIMATION_ENABLED_GLOBAL;
|
||||
use crate::animation::ANIMATION_ENABLED_PER_ANIMATION;
|
||||
use crate::animation::AnimationEngine;
|
||||
use crate::core::config_generation::MatchingRule;
|
||||
use crate::core::custom_layout::CustomLayout;
|
||||
use crate::core::Arrangement;
|
||||
use crate::core::Axis;
|
||||
use crate::core::BorderImplementation;
|
||||
@@ -45,30 +47,7 @@ use crate::core::Sizing;
|
||||
use crate::core::StackbarLabel;
|
||||
use crate::core::WindowContainerBehaviour;
|
||||
use crate::core::WindowManagementBehaviour;
|
||||
use crate::core::config_generation::MatchingRule;
|
||||
use crate::core::custom_layout::CustomLayout;
|
||||
|
||||
use crate::BorderColours;
|
||||
use crate::CUSTOM_FFM;
|
||||
use crate::Colour;
|
||||
use crate::CrossBoundaryBehaviour;
|
||||
use crate::DATA_DIR;
|
||||
use crate::DISPLAY_INDEX_PREFERENCES;
|
||||
use crate::HIDING_BEHAVIOUR;
|
||||
use crate::HOME_DIR;
|
||||
use crate::IGNORE_IDENTIFIERS;
|
||||
use crate::LAYERED_WHITELIST;
|
||||
use crate::MANAGE_IDENTIFIERS;
|
||||
use crate::MONITOR_INDEX_PREFERENCES;
|
||||
use crate::NO_TITLEBAR;
|
||||
use crate::OBJECT_NAME_CHANGE_ON_LAUNCH;
|
||||
use crate::REGEX_IDENTIFIERS;
|
||||
use crate::REMOVE_TITLEBARS;
|
||||
use crate::Rgb;
|
||||
use crate::SUBSCRIPTION_SOCKETS;
|
||||
use crate::TRANSPARENCY_BLACKLIST;
|
||||
use crate::TRAY_AND_MULTI_WINDOW_IDENTIFIERS;
|
||||
use crate::WORKSPACE_MATCHING_RULES;
|
||||
use crate::border_manager;
|
||||
use crate::border_manager::BORDER_OFFSET;
|
||||
use crate::border_manager::BORDER_WIDTH;
|
||||
@@ -99,6 +78,27 @@ use crate::windows_api::WindowsApi;
|
||||
use crate::winevent_listener;
|
||||
use crate::workspace::Workspace;
|
||||
use crate::workspace::WorkspaceLayer;
|
||||
use crate::BorderColours;
|
||||
use crate::Colour;
|
||||
use crate::CrossBoundaryBehaviour;
|
||||
use crate::Rgb;
|
||||
use crate::CUSTOM_FFM;
|
||||
use crate::DATA_DIR;
|
||||
use crate::DISPLAY_INDEX_PREFERENCES;
|
||||
use crate::HIDING_BEHAVIOUR;
|
||||
use crate::HOME_DIR;
|
||||
use crate::IGNORE_IDENTIFIERS;
|
||||
use crate::LAYERED_WHITELIST;
|
||||
use crate::MANAGE_IDENTIFIERS;
|
||||
use crate::MONITOR_INDEX_PREFERENCES;
|
||||
use crate::NO_TITLEBAR;
|
||||
use crate::OBJECT_NAME_CHANGE_ON_LAUNCH;
|
||||
use crate::REGEX_IDENTIFIERS;
|
||||
use crate::REMOVE_TITLEBARS;
|
||||
use crate::SUBSCRIPTION_SOCKETS;
|
||||
use crate::TRANSPARENCY_BLACKLIST;
|
||||
use crate::TRAY_AND_MULTI_WINDOW_IDENTIFIERS;
|
||||
use crate::WORKSPACE_MATCHING_RULES;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct WindowManager {
|
||||
@@ -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(())
|
||||
@@ -1317,41 +1317,32 @@ impl WindowManager {
|
||||
.update_focused_workspace(offset)?;
|
||||
|
||||
if follow_focus {
|
||||
match self.focused_workspace()?.maximized_window() {
|
||||
Some(window) => {
|
||||
if let Some(window) = self.focused_workspace()?.maximized_window() {
|
||||
if trigger_focus {
|
||||
window.focus(self.mouse_follows_focus)?;
|
||||
}
|
||||
} else if let Some(container) = self.focused_workspace()?.monocle_container() {
|
||||
if let Some(window) = container.focused_window() {
|
||||
if trigger_focus {
|
||||
window.focus(self.mouse_follows_focus)?;
|
||||
}
|
||||
}
|
||||
_ => match self.focused_workspace()?.monocle_container() {
|
||||
Some(container) => {
|
||||
if let Some(window) = container.focused_window() {
|
||||
if trigger_focus {
|
||||
window.focus(self.mouse_follows_focus)?;
|
||||
}
|
||||
}
|
||||
} else if let Ok(window) = self.focused_window_mut() {
|
||||
if trigger_focus {
|
||||
window.focus(self.mouse_follows_focus)?;
|
||||
}
|
||||
} else {
|
||||
let desktop_window = Window::from(WindowsApi::desktop_window()?);
|
||||
|
||||
let rect = self.focused_monitor_size()?;
|
||||
WindowsApi::center_cursor_in_rect(&rect)?;
|
||||
|
||||
match WindowsApi::raise_and_focus_window(desktop_window.hwnd) {
|
||||
Ok(()) => {}
|
||||
Err(error) => {
|
||||
tracing::warn!("{} {}:{}", error, file!(), line!());
|
||||
}
|
||||
_ => match self.focused_window_mut() {
|
||||
Ok(window) => {
|
||||
if trigger_focus {
|
||||
window.focus(self.mouse_follows_focus)?;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let desktop_window = Window::from(WindowsApi::desktop_window()?);
|
||||
|
||||
let rect = self.focused_monitor_size()?;
|
||||
WindowsApi::center_cursor_in_rect(&rect)?;
|
||||
|
||||
match WindowsApi::raise_and_focus_window(desktop_window.hwnd) {
|
||||
Ok(()) => {}
|
||||
Err(error) => {
|
||||
tracing::warn!("{} {}:{}", error, file!(), line!());
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if self.focused_workspace()?.is_empty() {
|
||||
@@ -1713,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()
|
||||
@@ -1758,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)?;
|
||||
}
|
||||
@@ -1932,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"))?;
|
||||
@@ -1959,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)?;
|
||||
}
|
||||
@@ -2520,10 +2498,12 @@ impl WindowManager {
|
||||
|
||||
tracing::info!("cycling container windows");
|
||||
|
||||
let container = match self.focused_workspace_mut()?.monocle_container_mut() {
|
||||
Some(container) => container,
|
||||
_ => self.focused_container_mut()?,
|
||||
};
|
||||
let container =
|
||||
if let Some(container) = self.focused_workspace_mut()?.monocle_container_mut() {
|
||||
container
|
||||
} else {
|
||||
self.focused_container_mut()?
|
||||
};
|
||||
|
||||
let len = NonZeroUsize::new(container.windows().len())
|
||||
.ok_or_else(|| anyhow!("there must be at least one window in a container"))?;
|
||||
@@ -2550,10 +2530,12 @@ impl WindowManager {
|
||||
|
||||
tracing::info!("cycling container window index");
|
||||
|
||||
let container = match self.focused_workspace_mut()?.monocle_container_mut() {
|
||||
Some(container) => container,
|
||||
_ => self.focused_container_mut()?,
|
||||
};
|
||||
let container =
|
||||
if let Some(container) = self.focused_workspace_mut()?.monocle_container_mut() {
|
||||
container
|
||||
} else {
|
||||
self.focused_container_mut()?
|
||||
};
|
||||
|
||||
let len = NonZeroUsize::new(container.windows().len())
|
||||
.ok_or_else(|| anyhow!("there must be at least one window in a container"))?;
|
||||
@@ -2578,10 +2560,12 @@ impl WindowManager {
|
||||
|
||||
tracing::info!("focusing container window at index {idx}");
|
||||
|
||||
let container = match self.focused_workspace_mut()?.monocle_container_mut() {
|
||||
Some(container) => container,
|
||||
_ => self.focused_container_mut()?,
|
||||
};
|
||||
let container =
|
||||
if let Some(container) = self.focused_workspace_mut()?.monocle_container_mut() {
|
||||
container
|
||||
} else {
|
||||
self.focused_container_mut()?
|
||||
};
|
||||
|
||||
let len = NonZeroUsize::new(container.windows().len())
|
||||
.ok_or_else(|| anyhow!("there must be at least one window in a container"))?;
|
||||
@@ -2686,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
|
||||
@@ -2712,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)?;
|
||||
}
|
||||
|
||||
@@ -2811,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()?;
|
||||
}
|
||||
|
||||
@@ -2875,10 +2843,6 @@ impl WindowManager {
|
||||
container.hide(None);
|
||||
}
|
||||
|
||||
for window in workspace.floating_windows_mut() {
|
||||
window.hide();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -2892,10 +2856,6 @@ impl WindowManager {
|
||||
container.restore();
|
||||
}
|
||||
|
||||
for window in workspace.floating_windows_mut() {
|
||||
window.restore();
|
||||
}
|
||||
|
||||
workspace.reintegrate_monocle_container()
|
||||
}
|
||||
|
||||
@@ -3112,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
|
||||
@@ -3119,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()
|
||||
@@ -3133,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)?)
|
||||
@@ -3153,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
|
||||
@@ -3160,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()
|
||||
@@ -3176,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)?)
|
||||
@@ -3191,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
|
||||
@@ -3198,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()
|
||||
@@ -3210,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)?)
|
||||
@@ -3226,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
|
||||
@@ -3233,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()
|
||||
@@ -3244,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)?)
|
||||
@@ -3263,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
|
||||
@@ -3270,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()
|
||||
@@ -3282,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)?)
|
||||
|
||||
@@ -5,12 +5,12 @@ use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::window::should_act;
|
||||
use crate::window::Window;
|
||||
use crate::winevent::WinEvent;
|
||||
use crate::OBJECT_NAME_CHANGE_ON_LAUNCH;
|
||||
use crate::OBJECT_NAME_CHANGE_TITLE_IGNORE_LIST;
|
||||
use crate::REGEX_IDENTIFIERS;
|
||||
use crate::window::Window;
|
||||
use crate::window::should_act;
|
||||
use crate::winevent::WinEvent;
|
||||
|
||||
#[derive(Debug, Copy, Clone, Serialize, Deserialize, JsonSchema)]
|
||||
#[serde(tag = "type", content = "content")]
|
||||
|
||||
@@ -4,12 +4,15 @@ use std::collections::VecDeque;
|
||||
use std::convert::TryFrom;
|
||||
use std::mem::size_of;
|
||||
|
||||
use color_eyre::Result;
|
||||
use color_eyre::eyre::Error;
|
||||
use color_eyre::eyre::anyhow;
|
||||
use color_eyre::eyre::bail;
|
||||
use windows::Win32::Foundation::COLORREF;
|
||||
use color_eyre::eyre::Error;
|
||||
use color_eyre::Result;
|
||||
use windows::core::Result as WindowsCrateResult;
|
||||
use windows::core::PCWSTR;
|
||||
use windows::core::PWSTR;
|
||||
use windows::Win32::Foundation::CloseHandle;
|
||||
use windows::Win32::Foundation::COLORREF;
|
||||
use windows::Win32::Foundation::HANDLE;
|
||||
use windows::Win32::Foundation::HINSTANCE;
|
||||
use windows::Win32::Foundation::HMODULE;
|
||||
@@ -18,9 +21,8 @@ use windows::Win32::Foundation::LPARAM;
|
||||
use windows::Win32::Foundation::POINT;
|
||||
use windows::Win32::Foundation::RECT;
|
||||
use windows::Win32::Foundation::WPARAM;
|
||||
use windows::Win32::Graphics::Dwm::DWM_CLOAKED_APP;
|
||||
use windows::Win32::Graphics::Dwm::DWM_CLOAKED_INHERITED;
|
||||
use windows::Win32::Graphics::Dwm::DWM_CLOAKED_SHELL;
|
||||
use windows::Win32::Graphics::Dwm::DwmGetWindowAttribute;
|
||||
use windows::Win32::Graphics::Dwm::DwmSetWindowAttribute;
|
||||
use windows::Win32::Graphics::Dwm::DWMWA_BORDER_COLOR;
|
||||
use windows::Win32::Graphics::Dwm::DWMWA_CLOAKED;
|
||||
use windows::Win32::Graphics::Dwm::DWMWA_COLOR_NONE;
|
||||
@@ -28,56 +30,52 @@ use windows::Win32::Graphics::Dwm::DWMWA_EXTENDED_FRAME_BOUNDS;
|
||||
use windows::Win32::Graphics::Dwm::DWMWA_WINDOW_CORNER_PREFERENCE;
|
||||
use windows::Win32::Graphics::Dwm::DWMWCP_ROUND;
|
||||
use windows::Win32::Graphics::Dwm::DWMWINDOWATTRIBUTE;
|
||||
use windows::Win32::Graphics::Dwm::DwmGetWindowAttribute;
|
||||
use windows::Win32::Graphics::Dwm::DwmSetWindowAttribute;
|
||||
use windows::Win32::Graphics::Dwm::DWM_CLOAKED_APP;
|
||||
use windows::Win32::Graphics::Dwm::DWM_CLOAKED_INHERITED;
|
||||
use windows::Win32::Graphics::Dwm::DWM_CLOAKED_SHELL;
|
||||
use windows::Win32::Graphics::Gdi::CreateSolidBrush;
|
||||
use windows::Win32::Graphics::Gdi::EnumDisplayMonitors;
|
||||
use windows::Win32::Graphics::Gdi::GetMonitorInfoW;
|
||||
use windows::Win32::Graphics::Gdi::HBRUSH;
|
||||
use windows::Win32::Graphics::Gdi::HDC;
|
||||
use windows::Win32::Graphics::Gdi::HMONITOR;
|
||||
use windows::Win32::Graphics::Gdi::InvalidateRect;
|
||||
use windows::Win32::Graphics::Gdi::MONITOR_DEFAULTTONEAREST;
|
||||
use windows::Win32::Graphics::Gdi::MONITORENUMPROC;
|
||||
use windows::Win32::Graphics::Gdi::MONITORINFOEXW;
|
||||
use windows::Win32::Graphics::Gdi::MonitorFromPoint;
|
||||
use windows::Win32::Graphics::Gdi::MonitorFromWindow;
|
||||
use windows::Win32::Graphics::Gdi::Rectangle;
|
||||
use windows::Win32::Graphics::Gdi::RoundRect;
|
||||
use windows::Win32::Graphics::Gdi::HBRUSH;
|
||||
use windows::Win32::Graphics::Gdi::HDC;
|
||||
use windows::Win32::Graphics::Gdi::HMONITOR;
|
||||
use windows::Win32::Graphics::Gdi::MONITORENUMPROC;
|
||||
use windows::Win32::Graphics::Gdi::MONITORINFOEXW;
|
||||
use windows::Win32::Graphics::Gdi::MONITOR_DEFAULTTONEAREST;
|
||||
use windows::Win32::System::LibraryLoader::GetModuleHandleW;
|
||||
use windows::Win32::System::Power::HPOWERNOTIFY;
|
||||
use windows::Win32::System::Power::RegisterPowerSettingNotification;
|
||||
use windows::Win32::System::Power::HPOWERNOTIFY;
|
||||
use windows::Win32::System::RemoteDesktop::ProcessIdToSessionId;
|
||||
use windows::Win32::System::RemoteDesktop::WTSRegisterSessionNotification;
|
||||
use windows::Win32::System::Threading::GetCurrentProcessId;
|
||||
use windows::Win32::System::Threading::OpenProcess;
|
||||
use windows::Win32::System::Threading::QueryFullProcessImageNameW;
|
||||
use windows::Win32::System::Threading::PROCESS_ACCESS_RIGHTS;
|
||||
use windows::Win32::System::Threading::PROCESS_NAME_WIN32;
|
||||
use windows::Win32::System::Threading::PROCESS_QUERY_INFORMATION;
|
||||
use windows::Win32::System::Threading::QueryFullProcessImageNameW;
|
||||
use windows::Win32::UI::HiDpi::DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2;
|
||||
use windows::Win32::UI::HiDpi::GetDpiForMonitor;
|
||||
use windows::Win32::UI::HiDpi::MDT_EFFECTIVE_DPI;
|
||||
use windows::Win32::UI::HiDpi::SetProcessDpiAwarenessContext;
|
||||
use windows::Win32::UI::HiDpi::DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2;
|
||||
use windows::Win32::UI::HiDpi::MDT_EFFECTIVE_DPI;
|
||||
use windows::Win32::UI::Input::KeyboardAndMouse::GetKeyState;
|
||||
use windows::Win32::UI::Input::KeyboardAndMouse::SendInput;
|
||||
use windows::Win32::UI::Input::KeyboardAndMouse::INPUT;
|
||||
use windows::Win32::UI::Input::KeyboardAndMouse::INPUT_0;
|
||||
use windows::Win32::UI::Input::KeyboardAndMouse::INPUT_MOUSE;
|
||||
use windows::Win32::UI::Input::KeyboardAndMouse::MOUSEEVENTF_LEFTDOWN;
|
||||
use windows::Win32::UI::Input::KeyboardAndMouse::MOUSEEVENTF_LEFTUP;
|
||||
use windows::Win32::UI::Input::KeyboardAndMouse::MOUSEINPUT;
|
||||
use windows::Win32::UI::Input::KeyboardAndMouse::SendInput;
|
||||
use windows::Win32::UI::Input::KeyboardAndMouse::VK_LBUTTON;
|
||||
use windows::Win32::UI::Input::KeyboardAndMouse::VK_MENU;
|
||||
use windows::Win32::UI::WindowsAndMessaging::AllowSetForegroundWindow;
|
||||
use windows::Win32::UI::WindowsAndMessaging::BringWindowToTop;
|
||||
use windows::Win32::UI::WindowsAndMessaging::CW_USEDEFAULT;
|
||||
use windows::Win32::UI::WindowsAndMessaging::CreateWindowExW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::DEV_BROADCAST_DEVICEINTERFACE_W;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EnumWindows;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GW_HWNDNEXT;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GWL_EXSTYLE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GWL_STYLE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GetCursorPos;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GetDesktopWindow;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GetForegroundWindow;
|
||||
@@ -88,37 +86,15 @@ use windows::Win32::UI::WindowsAndMessaging::GetWindowLongPtrW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GetWindowRect;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GetWindowTextW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GetWindowThreadProcessId;
|
||||
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::IsIconic;
|
||||
use windows::Win32::UI::WindowsAndMessaging::IsWindow;
|
||||
use windows::Win32::UI::WindowsAndMessaging::IsWindowVisible;
|
||||
use windows::Win32::UI::WindowsAndMessaging::IsZoomed;
|
||||
use windows::Win32::UI::WindowsAndMessaging::LWA_ALPHA;
|
||||
use windows::Win32::UI::WindowsAndMessaging::MoveWindow;
|
||||
use windows::Win32::UI::WindowsAndMessaging::PostMessageW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::REGISTER_NOTIFICATION_FLAGS;
|
||||
use windows::Win32::UI::WindowsAndMessaging::RealGetWindowClassW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::RegisterClassW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::RegisterDeviceNotificationW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SET_WINDOW_POS_FLAGS;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SHOW_WINDOW_CMD;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SPI_GETACTIVEWINDOWTRACKING;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SPI_GETFOREGROUNDLOCKTIMEOUT;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SPI_SETACTIVEWINDOWTRACKING;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SPI_SETFOREGROUNDLOCKTIMEOUT;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SPIF_SENDCHANGE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SW_HIDE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SW_MAXIMIZE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SW_MINIMIZE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SW_NORMAL;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SW_SHOWNOACTIVATE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SWP_NOMOVE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SWP_NOSIZE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SWP_SHOWWINDOW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SYSTEM_PARAMETERS_INFO_ACTION;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SetCursorPos;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SetForegroundWindow;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SetLayeredWindowAttributes;
|
||||
@@ -126,6 +102,33 @@ use windows::Win32::UI::WindowsAndMessaging::SetWindowLongPtrW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SetWindowPos;
|
||||
use windows::Win32::UI::WindowsAndMessaging::ShowWindow;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SystemParametersInfoW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WindowFromPoint;
|
||||
use windows::Win32::UI::WindowsAndMessaging::CW_USEDEFAULT;
|
||||
use windows::Win32::UI::WindowsAndMessaging::DEV_BROADCAST_DEVICEINTERFACE_W;
|
||||
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_TOP;
|
||||
use windows::Win32::UI::WindowsAndMessaging::LWA_ALPHA;
|
||||
use windows::Win32::UI::WindowsAndMessaging::REGISTER_NOTIFICATION_FLAGS;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SET_WINDOW_POS_FLAGS;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SHOW_WINDOW_CMD;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SPIF_SENDCHANGE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SPI_GETACTIVEWINDOWTRACKING;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SPI_GETFOREGROUNDLOCKTIMEOUT;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SPI_SETACTIVEWINDOWTRACKING;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SPI_SETFOREGROUNDLOCKTIMEOUT;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SWP_NOMOVE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SWP_NOSIZE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SWP_SHOWWINDOW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SW_HIDE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SW_MAXIMIZE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SW_MINIMIZE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SW_NORMAL;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SW_SHOWNOACTIVATE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SYSTEM_PARAMETERS_INFO_ACTION;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WINDOW_LONG_PTR_INDEX;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WM_CLOSE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WNDCLASSW;
|
||||
@@ -136,27 +139,23 @@ use windows::Win32::UI::WindowsAndMessaging::WS_EX_TOOLWINDOW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_TOPMOST;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_POPUP;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_SYSMENU;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WindowFromPoint;
|
||||
use windows::core::PCWSTR;
|
||||
use windows::core::PWSTR;
|
||||
use windows::core::Result as WindowsCrateResult;
|
||||
use windows_core::BOOL;
|
||||
|
||||
use crate::core::Rect;
|
||||
|
||||
use crate::DISPLAY_INDEX_PREFERENCES;
|
||||
use crate::MONITOR_INDEX_PREFERENCES;
|
||||
use crate::Window;
|
||||
use crate::WindowManager;
|
||||
use crate::container::Container;
|
||||
use crate::monitor;
|
||||
use crate::monitor::Monitor;
|
||||
use crate::ring::Ring;
|
||||
use crate::set_window_position::SetWindowPosition;
|
||||
use crate::windows_callbacks;
|
||||
use crate::Window;
|
||||
use crate::WindowManager;
|
||||
use crate::DISPLAY_INDEX_PREFERENCES;
|
||||
use crate::MONITOR_INDEX_PREFERENCES;
|
||||
|
||||
macro_rules! as_ptr {
|
||||
($value:expr_2021) => {
|
||||
($value:expr) => {
|
||||
$value as *mut core::ffi::c_void
|
||||
};
|
||||
}
|
||||
@@ -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
|
||||
@@ -1037,9 +1016,7 @@ impl WindowsApi {
|
||||
tracing::info!("current value of ForegroundLockTimeout is {value}");
|
||||
|
||||
if value != 0 {
|
||||
tracing::info!(
|
||||
"updating value of ForegroundLockTimeout to {value} in order to enable keyboard-driven focus updating"
|
||||
);
|
||||
tracing::info!("updating value of ForegroundLockTimeout to {value} in order to enable keyboard-driven focus updating");
|
||||
|
||||
Self::system_parameters_info_w(
|
||||
SPI_SETFOREGROUNDLOCKTIMEOUT,
|
||||
|
||||
@@ -12,11 +12,11 @@ use windows::Win32::Foundation::HWND;
|
||||
use windows::Win32::Foundation::LPARAM;
|
||||
use windows::Win32::Foundation::WPARAM;
|
||||
use windows::Win32::UI::Accessibility::HWINEVENTHOOK;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GetWindowLongW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SendNotifyMessageW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GWL_EXSTYLE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GWL_STYLE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GetWindowLongW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::OBJID_WINDOW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SendNotifyMessageW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_CHILD;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_NOACTIVATE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WS_EX_TOOLWINDOW;
|
||||
|
||||
@@ -5,11 +5,11 @@ use crossbeam_channel::Receiver;
|
||||
use crossbeam_channel::Sender;
|
||||
use windows::Win32::UI::Accessibility::SetWinEventHook;
|
||||
use windows::Win32::UI::WindowsAndMessaging::DispatchMessageW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GetMessageW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::TranslateMessage;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_MAX;
|
||||
use windows::Win32::UI::WindowsAndMessaging::EVENT_MIN;
|
||||
use windows::Win32::UI::WindowsAndMessaging::GetMessageW;
|
||||
use windows::Win32::UI::WindowsAndMessaging::MSG;
|
||||
use windows::Win32::UI::WindowsAndMessaging::TranslateMessage;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WINEVENT_OUTOFCONTEXT;
|
||||
use windows::Win32::UI::WindowsAndMessaging::WINEVENT_SKIPOWNPROCESS;
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ use std::fmt::Formatter;
|
||||
use std::num::NonZeroUsize;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use color_eyre::Result;
|
||||
use color_eyre::eyre::anyhow;
|
||||
use color_eyre::Result;
|
||||
use getset::CopyGetters;
|
||||
use getset::Getters;
|
||||
use getset::MutGetters;
|
||||
@@ -22,13 +22,6 @@ use crate::core::Layout;
|
||||
use crate::core::OperationDirection;
|
||||
use crate::core::Rect;
|
||||
|
||||
use crate::DEFAULT_CONTAINER_PADDING;
|
||||
use crate::DEFAULT_WORKSPACE_PADDING;
|
||||
use crate::INITIAL_CONFIGURATION_LOADED;
|
||||
use crate::NO_TITLEBAR;
|
||||
use crate::REGEX_IDENTIFIERS;
|
||||
use crate::REMOVE_TITLEBARS;
|
||||
use crate::WindowContainerBehaviour;
|
||||
use crate::border_manager::BORDER_OFFSET;
|
||||
use crate::border_manager::BORDER_WIDTH;
|
||||
use crate::container::Container;
|
||||
@@ -40,6 +33,13 @@ use crate::static_config::WorkspaceConfig;
|
||||
use crate::window::Window;
|
||||
use crate::window::WindowDetails;
|
||||
use crate::windows_api::WindowsApi;
|
||||
use crate::WindowContainerBehaviour;
|
||||
use crate::DEFAULT_CONTAINER_PADDING;
|
||||
use crate::DEFAULT_WORKSPACE_PADDING;
|
||||
use crate::INITIAL_CONFIGURATION_LOADED;
|
||||
use crate::NO_TITLEBAR;
|
||||
use crate::REGEX_IDENTIFIERS;
|
||||
use crate::REMOVE_TITLEBARS;
|
||||
|
||||
#[allow(clippy::struct_field_names)]
|
||||
#[derive(
|
||||
@@ -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() {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#![deny(clippy::unwrap_used, clippy::expect_used)]
|
||||
|
||||
use crate::WindowManager;
|
||||
use crate::border_manager;
|
||||
use crate::WindowManager;
|
||||
use crossbeam_channel::Receiver;
|
||||
use crossbeam_channel::Sender;
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
@@ -51,18 +51,16 @@ pub fn send_notification(monitor_idx: usize, workspace_idx: usize) {
|
||||
}
|
||||
|
||||
pub fn listen_for_notifications(wm: Arc<Mutex<WindowManager>>) {
|
||||
std::thread::spawn(move || {
|
||||
loop {
|
||||
match handle_notifications(wm.clone()) {
|
||||
Ok(()) => {
|
||||
tracing::warn!("restarting finished thread");
|
||||
}
|
||||
Err(error) => {
|
||||
if cfg!(debug_assertions) {
|
||||
tracing::error!("restarting failed thread: {:?}", error)
|
||||
} else {
|
||||
tracing::error!("restarting failed thread: {}", error)
|
||||
}
|
||||
std::thread::spawn(move || loop {
|
||||
match handle_notifications(wm.clone()) {
|
||||
Ok(()) => {
|
||||
tracing::warn!("restarting finished thread");
|
||||
}
|
||||
Err(error) => {
|
||||
if cfg!(debug_assertions) {
|
||||
tracing::error!("restarting failed thread: {:?}", error)
|
||||
} else {
|
||||
tracing::error!("restarting failed thread: {}", error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ name = "komorebic-no-console"
|
||||
version = "0.1.35"
|
||||
description = "The command-line interface (without a console) for Komorebi, a tiling window manager for Windows"
|
||||
repository = "https://github.com/LGUG2Z/komorebi"
|
||||
edition = "2024"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ name = "komorebic"
|
||||
version = "0.1.35"
|
||||
description = "The command-line interface for Komorebi, a tiling window manager for Windows"
|
||||
repository = "https://github.com/LGUG2Z/komorebi"
|
||||
edition = "2024"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
||||
@@ -17,31 +17,31 @@ use std::time::Duration;
|
||||
use clap::CommandFactory;
|
||||
use clap::Parser;
|
||||
use clap::ValueEnum;
|
||||
use color_eyre::Result;
|
||||
use color_eyre::eyre::anyhow;
|
||||
use color_eyre::eyre::bail;
|
||||
use color_eyre::Result;
|
||||
use dirs::data_local_dir;
|
||||
use fs_tail::TailedFile;
|
||||
use komorebi_client::ApplicationSpecificConfiguration;
|
||||
use komorebi_client::Notification;
|
||||
use komorebi_client::resolve_home_path;
|
||||
use komorebi_client::send_message;
|
||||
use komorebi_client::send_query;
|
||||
use komorebi_client::ApplicationSpecificConfiguration;
|
||||
use komorebi_client::Notification;
|
||||
use lazy_static::lazy_static;
|
||||
use miette::NamedSource;
|
||||
use miette::Report;
|
||||
use miette::SourceOffset;
|
||||
use miette::SourceSpan;
|
||||
use paste::paste;
|
||||
use schemars::r#gen::SchemaSettings;
|
||||
use schemars::gen::SchemaSettings;
|
||||
use schemars::schema_for;
|
||||
use serde::Deserialize;
|
||||
use sysinfo::ProcessesToUpdate;
|
||||
use which::which;
|
||||
use windows::Win32::Foundation::HWND;
|
||||
use windows::Win32::UI::WindowsAndMessaging::ShowWindow;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SHOW_WINDOW_CMD;
|
||||
use windows::Win32::UI::WindowsAndMessaging::SW_RESTORE;
|
||||
use windows::Win32::UI::WindowsAndMessaging::ShowWindow;
|
||||
|
||||
use komorebi_client::ApplicationConfigurationGenerator;
|
||||
use komorebi_client::ApplicationIdentifier;
|
||||
@@ -1541,9 +1541,7 @@ fn main() -> Result<()> {
|
||||
let whkdrc = include_str!("../../docs/whkdrc.sample");
|
||||
std::fs::write(WHKD_CONFIG_DIR.join("whkdrc"), whkdrc)?;
|
||||
|
||||
println!(
|
||||
"Example komorebi.json, komorebi.bar.json, whkdrc and latest applications.json files created"
|
||||
);
|
||||
println!("Example komorebi.json, komorebi.bar.json, whkdrc and latest applications.json files created");
|
||||
println!("You can now run komorebic start --whkd --bar");
|
||||
}
|
||||
SubCommand::EnableAutostart(args) => {
|
||||
@@ -1589,12 +1587,8 @@ fn main() -> Result<()> {
|
||||
.env("TARGET_ARGS", arguments)
|
||||
.output()?;
|
||||
|
||||
println!(
|
||||
"NOTE: If your komorebi.json file contains a reference to $Env:KOMOREBI_CONFIG_HOME,"
|
||||
);
|
||||
println!(
|
||||
"you need to add this to System Properties > Environment Variables > User Variables"
|
||||
);
|
||||
println!("NOTE: If your komorebi.json file contains a reference to $Env:KOMOREBI_CONFIG_HOME,");
|
||||
println!("you need to add this to System Properties > Environment Variables > User Variables");
|
||||
println!("in order for the autostart command to work properly");
|
||||
}
|
||||
SubCommand::DisableAutostart => {
|
||||
@@ -1658,23 +1652,16 @@ fn main() -> Result<()> {
|
||||
println!("{:?}", Report::new(diagnostic));
|
||||
}
|
||||
|
||||
println!(
|
||||
"Found komorebi.json; this file can be passed to the start command with the --config flag\n"
|
||||
);
|
||||
println!("Found komorebi.json; this file can be passed to the start command with the --config flag\n");
|
||||
|
||||
if let Ok(config) = StaticConfig::read(&static_config) {
|
||||
match config.app_specific_configuration_path {
|
||||
None => {
|
||||
println!(
|
||||
"Application specific configuration file path has not been set. Try running 'komorebic fetch-asc'\n"
|
||||
);
|
||||
println!("Application specific configuration file path has not been set. Try running 'komorebic fetch-asc'\n");
|
||||
}
|
||||
Some(path) => {
|
||||
if !Path::exists(Path::new(&path)) {
|
||||
println!(
|
||||
"Application specific configuration file path '{}' does not exist. Try running 'komorebic fetch-asc'\n",
|
||||
path.display()
|
||||
);
|
||||
println!("Application specific configuration file path '{}' does not exist. Try running 'komorebic fetch-asc'\n", path.display());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1692,14 +1679,9 @@ fn main() -> Result<()> {
|
||||
StaticConfig::end_of_life(&raw);
|
||||
|
||||
if config_whkd.exists() {
|
||||
println!(
|
||||
"Found {}; key bindings will be loaded from here when whkd is started, and you can start it automatically using the --whkd flag\n",
|
||||
config_whkd.to_string_lossy()
|
||||
);
|
||||
println!("Found {}; key bindings will be loaded from here when whkd is started, and you can start it automatically using the --whkd flag\n", config_whkd.to_string_lossy());
|
||||
} else {
|
||||
println!(
|
||||
"No ~/.config/whkdrc found; you may not be able to control komorebi with your keyboard\n"
|
||||
);
|
||||
println!("No ~/.config/whkdrc found; you may not be able to control komorebi with your keyboard\n");
|
||||
}
|
||||
} else if config_pwsh.exists() {
|
||||
println!("Found komorebi.ps1; this file will be autoloaded by komorebi\n");
|
||||
@@ -1709,17 +1691,13 @@ fn main() -> Result<()> {
|
||||
config_whkd.to_string_lossy()
|
||||
);
|
||||
} else {
|
||||
println!(
|
||||
"No ~/.config/whkdrc found; you may not be able to control komorebi with your keyboard\n"
|
||||
);
|
||||
println!("No ~/.config/whkdrc found; you may not be able to control komorebi with your keyboard\n");
|
||||
}
|
||||
} else if config_ahk.exists() {
|
||||
println!("Found komorebi.ahk; this file will be autoloaded by komorebi\n");
|
||||
} else {
|
||||
println!("No komorebi configuration found in {home_display}\n");
|
||||
println!(
|
||||
"If running 'komorebic start --await-configuration', you will manually have to call the following command to begin tiling: komorebic complete-configuration\n"
|
||||
);
|
||||
println!("If running 'komorebic start --await-configuration', you will manually have to call the following command to begin tiling: komorebic complete-configuration\n");
|
||||
}
|
||||
|
||||
let client = reqwest::blocking::Client::new();
|
||||
@@ -1741,9 +1719,7 @@ fn main() -> Result<()> {
|
||||
{
|
||||
let trimmed = release.tag_name.trim_start_matches("v");
|
||||
if trimmed > version {
|
||||
println!(
|
||||
"An updated version of komorebi is available! https://github.com/LGUG2Z/komorebi/releases/v{trimmed}"
|
||||
);
|
||||
println!("An updated version of komorebi is available! https://github.com/LGUG2Z/komorebi/releases/v{trimmed}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2058,45 +2034,38 @@ fn main() -> Result<()> {
|
||||
}
|
||||
|
||||
if arg.whkd && which("whkd").is_err() {
|
||||
bail!(
|
||||
"could not find whkd, please make sure it is installed before using the --whkd flag"
|
||||
);
|
||||
bail!("could not find whkd, please make sure it is installed before using the --whkd flag");
|
||||
}
|
||||
|
||||
if arg.masir && which("masir").is_err() {
|
||||
bail!(
|
||||
"could not find masir, please make sure it is installed before using the --masir flag"
|
||||
);
|
||||
bail!("could not find masir, please make sure it is installed before using the --masir flag");
|
||||
}
|
||||
|
||||
if arg.ahk && which(&ahk).is_err() {
|
||||
bail!(
|
||||
"could not find autohotkey, please make sure it is installed before using the --ahk flag"
|
||||
);
|
||||
bail!("could not find autohotkey, please make sure it is installed before using the --ahk flag");
|
||||
}
|
||||
|
||||
let mut buf: PathBuf;
|
||||
|
||||
// The komorebi.ps1 shim will only exist in the Path if installed by Scoop
|
||||
let exec = match Command::new("where.exe").arg("komorebi.ps1").output() {
|
||||
Ok(output) => {
|
||||
let stdout = String::from_utf8(output.stdout)?;
|
||||
match stdout.trim() {
|
||||
"" => None,
|
||||
// It's possible that a komorebi.ps1 config will be in %USERPROFILE% - ignore this
|
||||
stdout if !stdout.contains("scoop") => None,
|
||||
stdout => {
|
||||
buf = PathBuf::from(stdout);
|
||||
buf.pop(); // %USERPROFILE%\scoop\shims
|
||||
buf.pop(); // %USERPROFILE%\scoop
|
||||
buf.push("apps\\komorebi\\current\\komorebi.exe"); //%USERPROFILE%\scoop\komorebi\current\komorebi.exe
|
||||
Some(buf.to_str().ok_or_else(|| {
|
||||
anyhow!("cannot create a string from the scoop komorebi path")
|
||||
})?)
|
||||
}
|
||||
let exec = if let Ok(output) = Command::new("where.exe").arg("komorebi.ps1").output() {
|
||||
let stdout = String::from_utf8(output.stdout)?;
|
||||
match stdout.trim() {
|
||||
"" => None,
|
||||
// It's possible that a komorebi.ps1 config will be in %USERPROFILE% - ignore this
|
||||
stdout if !stdout.contains("scoop") => None,
|
||||
stdout => {
|
||||
buf = PathBuf::from(stdout);
|
||||
buf.pop(); // %USERPROFILE%\scoop\shims
|
||||
buf.pop(); // %USERPROFILE%\scoop
|
||||
buf.push("apps\\komorebi\\current\\komorebi.exe"); //%USERPROFILE%\scoop\komorebi\current\komorebi.exe
|
||||
Some(buf.to_str().ok_or_else(|| {
|
||||
anyhow!("cannot create a string from the scoop komorebi path")
|
||||
})?)
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let mut flags = vec![];
|
||||
@@ -2298,28 +2267,18 @@ if (!(Get-Process masir -ErrorAction SilentlyContinue))
|
||||
|
||||
println!("\nThank you for using komorebi!\n");
|
||||
println!("# Commercial Use License");
|
||||
println!(
|
||||
"* View licensing options https://lgug2z.com/software/komorebi - A commercial use license is required to use komorebi at work"
|
||||
);
|
||||
println!("* View licensing options https://lgug2z.com/software/komorebi - A commercial use license is required to use komorebi at work");
|
||||
println!("\n# Personal Use Sponsorship");
|
||||
println!(
|
||||
"* Become a sponsor https://github.com/sponsors/LGUG2Z - $5/month makes a big difference"
|
||||
);
|
||||
println!("* Become a sponsor https://github.com/sponsors/LGUG2Z - $5/month makes a big difference");
|
||||
println!("* Leave a tip https://ko-fi.com/lgug2z - An alternative to GitHub Sponsors");
|
||||
println!("\n# Community");
|
||||
println!(
|
||||
"* Join the Discord https://discord.gg/mGkn66PHkx - Chat, ask questions, share your desktops"
|
||||
);
|
||||
println!("* Join the Discord https://discord.gg/mGkn66PHkx - Chat, ask questions, share your desktops");
|
||||
println!(
|
||||
"* Subscribe to https://youtube.com/@LGUG2Z - Development videos, feature previews and release overviews"
|
||||
);
|
||||
println!(
|
||||
"* Explore the Awesome Komorebi list https://github.com/LGUG2Z/awesome-komorebi - Projects in the komorebi ecosystem"
|
||||
);
|
||||
println!("* Explore the Awesome Komorebi list https://github.com/LGUG2Z/awesome-komorebi - Projects in the komorebi ecosystem");
|
||||
println!("\n# Documentation");
|
||||
println!(
|
||||
"* Read the docs https://lgug2z.github.io/komorebi - Quickly search through all komorebic commands"
|
||||
);
|
||||
println!("* Read the docs https://lgug2z.github.io/komorebi - Quickly search through all komorebic commands");
|
||||
|
||||
let bar_config = arg.config.map_or_else(
|
||||
|| {
|
||||
@@ -2366,9 +2325,7 @@ if (!(Get-Process masir -ErrorAction SilentlyContinue))
|
||||
{
|
||||
let trimmed = release.tag_name.trim_start_matches("v");
|
||||
if trimmed > version {
|
||||
println!(
|
||||
"An updated version of komorebi is available! https://github.com/LGUG2Z/komorebi/releases/v{trimmed}"
|
||||
);
|
||||
println!("An updated version of komorebi is available! https://github.com/LGUG2Z/komorebi/releases/v{trimmed}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2993,9 +2950,7 @@ if (Get-Command Get-CimInstance -ErrorAction SilentlyContinue) {
|
||||
|
||||
file.write_all(formatted_content.as_bytes())?;
|
||||
|
||||
println!(
|
||||
"File successfully formatted for PRs to https://github.com/LGUG2Z/komorebi-application-specific-configuration"
|
||||
);
|
||||
println!("File successfully formatted for PRs to https://github.com/LGUG2Z/komorebi-application-specific-configuration");
|
||||
}
|
||||
SubCommand::FetchAppSpecificConfiguration => {
|
||||
let content = reqwest::blocking::get("https://raw.githubusercontent.com/LGUG2Z/komorebi-application-specific-configuration/master/applications.json")?
|
||||
@@ -3011,12 +2966,10 @@ if (Get-Command Get-CimInstance -ErrorAction SilentlyContinue) {
|
||||
|
||||
file.write_all(content.as_bytes())?;
|
||||
|
||||
println!("Latest version of applications.json from https://github.com/LGUG2Z/komorebi-application-specific-configuration downloaded\n");
|
||||
println!(
|
||||
"Latest version of applications.json from https://github.com/LGUG2Z/komorebi-application-specific-configuration downloaded\n"
|
||||
);
|
||||
println!(
|
||||
"You can add this to your komorebi.json static configuration file like this: \n\n\"app_specific_configuration_path\": \"{}\"",
|
||||
output_file.display().to_string().replace("\\", "/")
|
||||
"You can add this to your komorebi.json static configuration file like this: \n\n\"app_specific_configuration_path\": \"{}\"",
|
||||
output_file.display().to_string().replace("\\", "/")
|
||||
);
|
||||
}
|
||||
SubCommand::ApplicationSpecificConfigurationSchema => {
|
||||
@@ -3041,8 +2994,8 @@ if (Get-Command Get-CimInstance -ErrorAction SilentlyContinue) {
|
||||
s.inline_subschemas = true;
|
||||
});
|
||||
|
||||
let r#gen = settings.into_generator();
|
||||
let socket_message = r#gen.into_root_schema_for::<StaticConfig>();
|
||||
let gen = settings.into_generator();
|
||||
let socket_message = gen.into_root_schema_for::<StaticConfig>();
|
||||
let schema = serde_json::to_string_pretty(&socket_message)?;
|
||||
println!("{schema}");
|
||||
}
|
||||
|
||||
210
schema.bar.json
210
schema.bar.json
@@ -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"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
12
schema.json
12
schema.json
@@ -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"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user