Compare commits
62 Commits
v0.13.0
...
feat/works
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3fad8c6a16 | ||
|
|
0c0163cfa1 | ||
|
|
e1b1d6f465 | ||
|
|
1f824edd70 | ||
|
|
088ac971c1 | ||
|
|
59f66df079 | ||
|
|
2d5d1b450c | ||
|
|
7a2edcdffc | ||
|
|
8f4ad02c75 | ||
|
|
c5a1694b10 | ||
|
|
f8cc634cc9 | ||
|
|
ccc6ff2d94 | ||
|
|
71ea185a65 | ||
|
|
c793cd3c1a | ||
|
|
1f4b349423 | ||
|
|
4755e2c827 | ||
|
|
b548e3ec01 | ||
|
|
7033d29c6a | ||
|
|
0335aa4470 | ||
|
|
dce245ef5f | ||
|
|
bd002e278b | ||
|
|
ae1bc2ef84 | ||
|
|
4e67b73a83 | ||
|
|
60bb69feec | ||
|
|
5bc7b7f317 | ||
|
|
f88bec93ff | ||
|
|
0d0447bbd2 | ||
|
|
49a79bb011 | ||
|
|
1dcda6c90e | ||
|
|
4e9c05761e | ||
|
|
af674bb769 | ||
|
|
a31a07e451 | ||
|
|
0df3d4c725 | ||
|
|
50ab2e4742 | ||
|
|
abd1f80548 | ||
|
|
3ddf799739 | ||
|
|
6fbe0d5e71 | ||
|
|
bc553b4918 | ||
|
|
4ee2ce4d67 | ||
|
|
cf3dc17ad3 | ||
|
|
8b8ccf7be7 | ||
|
|
1035ce670f | ||
|
|
43b446d266 | ||
|
|
93eb4c6472 | ||
|
|
40432c8704 | ||
|
|
9ced8597e4 | ||
|
|
10f8bbae3f | ||
|
|
af1f9e39b0 | ||
|
|
25c490b8b4 | ||
|
|
6c38ff29c4 | ||
|
|
fea1f18524 | ||
|
|
b9c41af0f7 | ||
|
|
2a8a62eea6 | ||
|
|
d010fd6398 | ||
|
|
57cca121bf | ||
|
|
7f6ba90bfd | ||
|
|
9431d09de7 | ||
|
|
69bd650810 | ||
|
|
5f9ac64892 | ||
|
|
3f7904fefb | ||
|
|
84e0065c0c | ||
|
|
e5281e9619 |
55
CHANGELOG.md
55
CHANGELOG.md
@@ -4,6 +4,58 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [v0.13.0] - 2023-08-16
|
||||||
|
### :sparkles: New Features
|
||||||
|
- [`c3e9654`](https://github.com/JakeStanger/ironbar/commit/c3e9654cd3dfcea4276f5b114112b7541dd847fd) - **upower**: icon size option *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`f5bdc5a`](https://github.com/JakeStanger/ironbar/commit/f5bdc5a0272fefca4c91336699ea63913cdf3c08) - ipc server and cli *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`ded50cc`](https://github.com/JakeStanger/ironbar/commit/ded50cca6f01f08a8e44257394fdde634d421e8e) - support for 'ironvar' dynamic variables *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`c6319b7`](https://github.com/JakeStanger/ironbar/commit/c6319b78fd3992ad43327e90b6326ab653238f2e) - **ipc**: support for injecting additional stylesheets *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`27f920d`](https://github.com/JakeStanger/ironbar/commit/27f920d01217bedba279003291ad48c1aaa56bb0) - **launcher**: slightly improve focus logic when clicking item with multiple windows *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`bd90167`](https://github.com/JakeStanger/ironbar/commit/bd90167f4ea90cb97984b9f3b5e6f65b375d0c4a) - **clock**: format option for popup header *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`12053f1`](https://github.com/JakeStanger/ironbar/commit/12053f111a6f05a59e33396b9042821b98b9bc5c) - **music**: progress/seek bar in popup *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`7d3bb02`](https://github.com/JakeStanger/ironbar/commit/7d3bb02b4612f278bcc8a268a48c61b239c63e82) - **ipc**: reload config command *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`b310ea7`](https://github.com/JakeStanger/ironbar/commit/b310ea76362bcdf10e187d6b00cd2b8ed2870c41) - **clock**: localization support *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`738b9e3`](https://github.com/JakeStanger/ironbar/commit/738b9e3da714c9b998030e9f60b9b6f50c62ec76) - **config**: use default fallback with config instructions *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`2ccb263`](https://github.com/JakeStanger/ironbar/commit/2ccb2633c6c4d7f6eb264a6c49951853b728c9f3) - IPC for get_visible, set_visible, new bar `name` config option *(commit by [@A-Cloud-Ninja](https://github.com/A-Cloud-Ninja))*
|
||||||
|
- [`b7ee794`](https://github.com/JakeStanger/ironbar/commit/b7ee794bfc86730e7921c8a930cf8d8bb44474ad) - **ipc**: commands for opening/closing popups *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`ef443e6`](https://github.com/JakeStanger/ironbar/commit/ef443e6978949479388129760dabc3f8930c0b0f) - **image resolver**: add fallback image *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`9f65cf2`](https://github.com/JakeStanger/ironbar/commit/9f65cf293d9527a2c536847f0005957421a9be33) - **workspaces**: add `favorites` and `hidden` options *(commit by [@yavko](https://github.com/yavko))*
|
||||||
|
- [`19c684e`](https://github.com/JakeStanger/ironbar/commit/19c684e49facb57e3e2acf9cafecf177c2e1bfbf) - **nix**: automatic development environment with direnv *(commit by [@yavko](https://github.com/yavko))*
|
||||||
|
|
||||||
|
### :bug: Bug Fixes
|
||||||
|
- [`6db7742`](https://github.com/JakeStanger/ironbar/commit/6db7742e068dc03d67dbf35e0d9db27f900392fe) - crash on startup introduced by recent refactors *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`f78c7f9`](https://github.com/JakeStanger/ironbar/commit/f78c7f9b981c98676e855ff6a63e33a51927c709) - not resolving flatpak application icons *(commit by [@body20002](https://github.com/body20002))*
|
||||||
|
- [`1759945`](https://github.com/JakeStanger/ironbar/commit/1759945912e376581e5fcd5ed2916f89e2090f2b) - **music**: correctly show/hide popup elements based on player capabilities *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`a9ac29d`](https://github.com/JakeStanger/ironbar/commit/a9ac29d8857256d13e14104db235117e3c752972) - clipboard partially behind wrong feature flag *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`c711dd8`](https://github.com/JakeStanger/ironbar/commit/c711dd858554140bcfb6df515a43b40ee2baee67) - failing to resolve icons with home_manager *(commit by [@christoph00](https://github.com/christoph00))*
|
||||||
|
- [`1a272e0`](https://github.com/JakeStanger/ironbar/commit/1a272e00fbeca4b5e39b527ffed439bc51fd4080) - **label**: not using markup *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`4ca17d1`](https://github.com/JakeStanger/ironbar/commit/4ca17d1337acfbbc21c04058d97f689a1cce60a6) - **launcher**: incorrectly resolving some applications *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`eee2182`](https://github.com/JakeStanger/ironbar/commit/eee2182ab90fdc22cd05da9417cbee17e4c67088) - **ipc**: command/response casing *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`c582bc3`](https://github.com/JakeStanger/ironbar/commit/c582bc33905702a9ebe323e6dfa9413485f48fb7) - **cli**: `set-visible` command causing panic *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`87dd764`](https://github.com/JakeStanger/ironbar/commit/87dd7646fc9223ac7e67842934f3bd104b4eea80) - **launcher**: not clearing focused state when closing window *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`6f57ad4`](https://github.com/JakeStanger/ironbar/commit/6f57ad47ac30348c0ae2b7dba35d5ffdbf96f72d) - **launcher**: not setting focus state when opening favourite *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`2367faa`](https://github.com/JakeStanger/ironbar/commit/2367faab0440327620052de845c6a0d3032f2f05) - **image**: using fallback in places it shouldn't *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`7f6fef6`](https://github.com/JakeStanger/ironbar/commit/7f6fef6338d7a8c909f3224b32426dfc2aacc295) - **image**: matching desktop file names too eagerly *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`89ec06f`](https://github.com/JakeStanger/ironbar/commit/89ec06fc7b252052f96e45f5d0f6d6504878a13a) - **music**: hide album art widget when no image *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`2902331`](https://github.com/JakeStanger/ironbar/commit/2902331af00f2e52fdea06964fbd89d72fe2ebbb) - **dynamic string**: incorrectly handling strings containing multipoint utf-8 chars *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`901a86c`](https://github.com/JakeStanger/ironbar/commit/901a86caa491648268f0618e17a25b978552db0c) - **custom**: crash when clicking non-popup button *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`54f0f23`](https://github.com/JakeStanger/ironbar/commit/54f0f232f208602699e5021942c3d0f3947ca6de) - **launcher**: popup not closing when hover leaves widget *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
|
||||||
|
### :recycle: Refactors
|
||||||
|
- [`d121dc3`](https://github.com/JakeStanger/ironbar/commit/d121dc3d1e9468a67deb528c35fc3897c3840f77) - fix unused var warning *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`cc181a8`](https://github.com/JakeStanger/ironbar/commit/cc181a8b6d0ac1cccd4ed2f9f420c138ed5383d2) - fix new clippy warnings *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`7016f7f`](https://github.com/JakeStanger/ironbar/commit/7016f7f79e7e29a3318b535ba224aa78bd91688a) - use new smart pointer macros throughout codebase *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`06251e2`](https://github.com/JakeStanger/ironbar/commit/06251e293e8f56e1897fed80335f114fdea57183) - fix new pedantic clippy warnings *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`36f3db7`](https://github.com/JakeStanger/ironbar/commit/36f3db741178b959070ee90bcd6448e1b2a6ef26) - **image**: do not try to read desktop files where definitely not necessary *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
|
||||||
|
### :memo: Documentation Changes
|
||||||
|
- [`aea8de2`](https://github.com/JakeStanger/ironbar/commit/aea8de25522e5f5e7f92f46a6248eb2e79cb457e) - update CHANGELOG.md for v0.12.1 [skip ci] *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`607c728`](https://github.com/JakeStanger/ironbar/commit/607c7285d7e01265a8c8417e2941b2099e61aa42) - update for ipc/cli, tidy a bit *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`4b88079`](https://github.com/JakeStanger/ironbar/commit/4b88079561e5c9fec63480afe56a1f89c76dc094) - fix header *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`4620f29`](https://github.com/JakeStanger/ironbar/commit/4620f29d381394aef8b241b03009ef8c3b8d0145) - **examples**: update stylesheet *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
- [`3d94987`](https://github.com/JakeStanger/ironbar/commit/3d949874de90b0e5c06cb62726629133d0ea76e3) - **ipc**: add link to luajit library *(commit by [@JakeStanger](https://github.com/JakeStanger))*
|
||||||
|
|
||||||
|
|
||||||
## [v0.12.1] - 2023-06-18
|
## [v0.12.1] - 2023-06-18
|
||||||
### :boom: BREAKING CHANGES
|
### :boom: BREAKING CHANGES
|
||||||
- due to [`e11177f`](https://github.com/JakeStanger/ironbar/commit/e11177fea3095560057278d71cebca01bed295d6) - add sensible class names for icon labels *(commit by [@JakeStanger](https://github.com/JakeStanger))*:
|
- due to [`e11177f`](https://github.com/JakeStanger/ironbar/commit/e11177fea3095560057278d71cebca01bed295d6) - add sensible class names for icon labels *(commit by [@JakeStanger](https://github.com/JakeStanger))*:
|
||||||
@@ -372,4 +424,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
[v0.10.0]: https://github.com/JakeStanger/ironbar/compare/v0.9.0...v0.10.0
|
[v0.10.0]: https://github.com/JakeStanger/ironbar/compare/v0.9.0...v0.10.0
|
||||||
[v0.11.0]: https://github.com/JakeStanger/ironbar/compare/v0.10.0...v0.11.0
|
[v0.11.0]: https://github.com/JakeStanger/ironbar/compare/v0.10.0...v0.11.0
|
||||||
[v0.12.0]: https://github.com/JakeStanger/ironbar/compare/v0.11.0...v0.12.0
|
[v0.12.0]: https://github.com/JakeStanger/ironbar/compare/v0.11.0...v0.12.0
|
||||||
[v0.12.1]: https://github.com/JakeStanger/ironbar/compare/v0.12.0...v0.12.1
|
[v0.12.1]: https://github.com/JakeStanger/ironbar/compare/v0.12.0...v0.12.1
|
||||||
|
[v0.13.0]: https://github.com/JakeStanger/ironbar/compare/v0.12.1...v0.13.0
|
||||||
227
Cargo.lock
generated
227
Cargo.lock
generated
@@ -55,16 +55,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstream"
|
name = "anstream"
|
||||||
version = "0.3.2"
|
version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163"
|
checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstyle",
|
"anstyle",
|
||||||
"anstyle-parse",
|
"anstyle-parse",
|
||||||
"anstyle-query",
|
"anstyle-query",
|
||||||
"anstyle-wincon",
|
"anstyle-wincon",
|
||||||
"colorchoice",
|
"colorchoice",
|
||||||
"is-terminal",
|
|
||||||
"utf8parse",
|
"utf8parse",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -94,9 +93,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstyle-wincon"
|
name = "anstyle-wincon"
|
||||||
version = "1.0.2"
|
version = "2.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c677ab05e09154296dd37acecd46420c17b9713e8366facafa8fc0885167cf4c"
|
checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstyle",
|
"anstyle",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
@@ -169,7 +168,7 @@ dependencies = [
|
|||||||
"log",
|
"log",
|
||||||
"parking",
|
"parking",
|
||||||
"polling",
|
"polling",
|
||||||
"rustix 0.37.11",
|
"rustix",
|
||||||
"slab",
|
"slab",
|
||||||
"socket2 0.4.9",
|
"socket2 0.4.9",
|
||||||
"waker-fn",
|
"waker-fn",
|
||||||
@@ -207,7 +206,7 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
"event-listener",
|
"event-listener",
|
||||||
"futures-lite",
|
"futures-lite",
|
||||||
"rustix 0.37.11",
|
"rustix",
|
||||||
"signal-hook",
|
"signal-hook",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
@@ -424,36 +423,34 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chrono"
|
name = "chrono"
|
||||||
version = "0.4.26"
|
version = "0.4.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5"
|
checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"android-tzdata",
|
"android-tzdata",
|
||||||
"iana-time-zone",
|
"iana-time-zone",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"pure-rust-locales",
|
"pure-rust-locales",
|
||||||
"time 0.1.45",
|
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"winapi",
|
"windows-targets 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.3.21"
|
version = "4.4.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c27cdf28c0f604ba3f512b0c9a409f8de8513e4816705deb0498b627e7c3a3fd"
|
checksum = "b1d7b8d5ec32af0fadc644bf1fd509a688c2103b185644bb1e29d164e0703136"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap_builder",
|
"clap_builder",
|
||||||
"clap_derive",
|
"clap_derive",
|
||||||
"once_cell",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_builder"
|
name = "clap_builder"
|
||||||
version = "4.3.21"
|
version = "4.4.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "08a9f1ab5e9f01a9b81f202e8562eb9a10de70abf9eaeac1be465c28b75aa4aa"
|
checksum = "5179bb514e4d7c2051749d8fcefa2ed6d06a9f4e6d69faf3805f5d80b8cf8d56"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstream",
|
"anstream",
|
||||||
"anstyle",
|
"anstyle",
|
||||||
@@ -463,9 +460,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_derive"
|
name = "clap_derive"
|
||||||
version = "4.3.12"
|
version = "4.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050"
|
checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck 0.4.1",
|
"heck 0.4.1",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@@ -617,11 +614,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ctrlc"
|
name = "ctrlc"
|
||||||
version = "3.4.0"
|
version = "3.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2a011bbe2c35ce9c1f143b7af6f94f29a167beb4cd1d29e6740ce836f723120e"
|
checksum = "82e95fbd621905b854affdc67943b043a0fbb6ed7385fd5a25650d19a8a6cfdf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"nix 0.26.2",
|
"nix 0.27.1",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -913,13 +910,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "filetime"
|
name = "filetime"
|
||||||
version = "0.2.21"
|
version = "0.2.22"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153"
|
checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"redox_syscall 0.2.16",
|
"redox_syscall 0.3.5",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1156,7 +1153,7 @@ checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
"wasi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1480,9 +1477,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyprland"
|
name = "hyprland"
|
||||||
version = "0.3.8"
|
version = "0.3.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a84219159a2b7df96e2e6a8b8806d97c94d7ba2f661a0d4dd843d66b59f0ca28"
|
checksum = "dfa94ae7899f3f1bdcad21dcd50366a60f323375a25610889246f276d7f9fb06"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"derive_more",
|
"derive_more",
|
||||||
@@ -1625,7 +1622,7 @@ checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ironbar"
|
name = "ironbar"
|
||||||
version = "0.13.0"
|
version = "0.14.0-pre"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async_once",
|
"async_once",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
@@ -1644,7 +1641,7 @@ dependencies = [
|
|||||||
"lazy_static",
|
"lazy_static",
|
||||||
"mpd_client",
|
"mpd_client",
|
||||||
"mpris",
|
"mpris",
|
||||||
"nix 0.26.2",
|
"nix 0.27.1",
|
||||||
"notify",
|
"notify",
|
||||||
"regex",
|
"regex",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
@@ -1669,17 +1666,6 @@ dependencies = [
|
|||||||
"zbus",
|
"zbus",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "is-terminal"
|
|
||||||
version = "0.4.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
|
|
||||||
dependencies = [
|
|
||||||
"hermit-abi 0.3.1",
|
|
||||||
"rustix 0.38.8",
|
|
||||||
"windows-sys 0.48.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.6"
|
version = "1.0.6"
|
||||||
@@ -1729,9 +1715,9 @@ checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libcorn"
|
name = "libcorn"
|
||||||
version = "0.8.0"
|
version = "0.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a60c31be9f9db3b90d3d8da252357c5acb20af985843db75ed6223b5bf1bec60"
|
checksum = "07283e36c1e48784b5e24e27fd4f6deabd83ebfa05648316dcead505ecbab40f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"pest",
|
"pest",
|
||||||
@@ -1774,12 +1760,6 @@ version = "0.3.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f"
|
checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "linux-raw-sys"
|
|
||||||
version = "0.4.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
version = "0.4.9"
|
version = "0.4.9"
|
||||||
@@ -1810,9 +1790,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.5.0"
|
version = "2.6.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memmap2"
|
name = "memmap2"
|
||||||
@@ -1879,7 +1859,7 @@ checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
"wasi",
|
||||||
"windows-sys 0.45.0",
|
"windows-sys 0.45.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1954,16 +1934,25 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nix"
|
name = "nix"
|
||||||
version = "0.26.2"
|
version = "0.26.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a"
|
checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"memoffset 0.7.1",
|
"memoffset 0.7.1",
|
||||||
"pin-utils",
|
]
|
||||||
"static_assertions",
|
|
||||||
|
[[package]]
|
||||||
|
name = "nix"
|
||||||
|
version = "0.27.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.4.0",
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1978,18 +1967,19 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "notify"
|
name = "notify"
|
||||||
version = "6.0.1"
|
version = "6.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5738a2795d57ea20abec2d6d76c6081186709c0024187cd5977265eda6598b51"
|
checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 2.4.0",
|
||||||
"filetime",
|
"filetime",
|
||||||
"inotify",
|
"inotify",
|
||||||
"kqueue",
|
"kqueue",
|
||||||
"libc",
|
"libc",
|
||||||
|
"log",
|
||||||
"mio",
|
"mio",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
"windows-sys 0.45.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2313,9 +2303,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pure-rust-locales"
|
name = "pure-rust-locales"
|
||||||
version = "0.5.6"
|
version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b45c49fc4f91f35bae654f85ebb3a44d60ac64f11b3166ffa609def390c732d8"
|
checksum = "ed02a829e62dc2715ceb8afb4f80e298148e1345749ceb369540fe0eb3368432"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quick-xml"
|
name = "quick-xml"
|
||||||
@@ -2424,14 +2414,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.9.3"
|
version = "1.9.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a"
|
checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
"regex-automata 0.3.6",
|
"regex-automata 0.3.8",
|
||||||
"regex-syntax 0.7.4",
|
"regex-syntax 0.7.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2445,13 +2435,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-automata"
|
name = "regex-automata"
|
||||||
version = "0.3.6"
|
version = "0.3.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69"
|
checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
"regex-syntax 0.7.4",
|
"regex-syntax 0.7.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2462,15 +2452,15 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-syntax"
|
name = "regex-syntax"
|
||||||
version = "0.7.4"
|
version = "0.7.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2"
|
checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "reqwest"
|
name = "reqwest"
|
||||||
version = "0.11.18"
|
version = "0.11.20"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55"
|
checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.21.0",
|
"base64 0.21.0",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -2539,20 +2529,7 @@ dependencies = [
|
|||||||
"errno",
|
"errno",
|
||||||
"io-lifetimes",
|
"io-lifetimes",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-raw-sys 0.3.1",
|
"linux-raw-sys",
|
||||||
"windows-sys 0.48.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustix"
|
|
||||||
version = "0.38.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags 2.4.0",
|
|
||||||
"errno",
|
|
||||||
"libc",
|
|
||||||
"linux-raw-sys 0.4.5",
|
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -2635,18 +2612,18 @@ checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.183"
|
version = "1.0.188"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c"
|
checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.183"
|
version = "1.0.188"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816"
|
checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.32",
|
"quote 1.0.32",
|
||||||
@@ -2655,9 +2632,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.104"
|
version = "1.0.107"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c"
|
checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"ryu",
|
"ryu",
|
||||||
@@ -2795,7 +2772,7 @@ dependencies = [
|
|||||||
"lazy_static",
|
"lazy_static",
|
||||||
"log",
|
"log",
|
||||||
"memmap2",
|
"memmap2",
|
||||||
"nix 0.26.2",
|
"nix 0.26.4",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"wayland-backend",
|
"wayland-backend",
|
||||||
"wayland-client",
|
"wayland-client",
|
||||||
@@ -2848,24 +2825,24 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strum"
|
name = "strum"
|
||||||
version = "0.24.1"
|
version = "0.25.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
|
checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"strum_macros",
|
"strum_macros",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strum_macros"
|
name = "strum_macros"
|
||||||
version = "0.24.3"
|
version = "0.25.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59"
|
checksum = "ad8d03b598d3d0fff69bf533ee3ef19b8eeb342729596df84bcc7e1f96ec4059"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck 0.4.1",
|
"heck 0.4.1",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.32",
|
"quote 1.0.32",
|
||||||
"rustversion",
|
"rustversion",
|
||||||
"syn 1.0.109",
|
"syn 2.0.28",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2937,9 +2914,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sysinfo"
|
name = "sysinfo"
|
||||||
version = "0.29.8"
|
version = "0.29.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d10ed79c22663a35a255d289a7fdcb43559fc77ff15df5ce6c341809e7867528"
|
checksum = "0a18d114d420ada3a891e6bc8e96a2023402203296a47cdd65083377dad18ba5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"core-foundation-sys",
|
"core-foundation-sys",
|
||||||
@@ -2990,7 +2967,7 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
"fastrand",
|
"fastrand",
|
||||||
"redox_syscall 0.3.5",
|
"redox_syscall 0.3.5",
|
||||||
"rustix 0.37.11",
|
"rustix",
|
||||||
"windows-sys 0.45.0",
|
"windows-sys 0.45.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -3033,17 +3010,6 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "time"
|
|
||||||
version = "0.1.45"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"wasi 0.10.0+wasi-snapshot-preview1",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.3.20"
|
version = "0.3.20"
|
||||||
@@ -3088,9 +3054,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.31.0"
|
version = "1.32.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "40de3a2ba249dcb097e01be5e67a5ff53cf250397715a071a81543e8a832a920"
|
checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -3211,7 +3177,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "09d48f71a791638519505cefafe162606f706c25592e4bde4d97600c0195312e"
|
checksum = "09d48f71a791638519505cefafe162606f706c25592e4bde4d97600c0195312e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-channel",
|
"crossbeam-channel",
|
||||||
"time 0.3.20",
|
"time",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -3344,9 +3310,9 @@ checksum = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "universal-config"
|
name = "universal-config"
|
||||||
version = "0.4.2"
|
version = "0.4.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bfede7e084d97dec87efe3cee5712ec22d97edc5bc73e61337e8914e33fd425e"
|
checksum = "4e41ae277cedae5c3a4d6dbe5d7ad5068cdbcd9e7005de28996cada89c28c776"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dirs",
|
"dirs",
|
||||||
"libcorn",
|
"libcorn",
|
||||||
@@ -3451,9 +3417,9 @@ checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "walkdir"
|
name = "walkdir"
|
||||||
version = "2.3.3"
|
version = "2.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698"
|
checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"same-file",
|
"same-file",
|
||||||
"winapi-util",
|
"winapi-util",
|
||||||
@@ -3469,12 +3435,6 @@ dependencies = [
|
|||||||
"try-lock",
|
"try-lock",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasi"
|
|
||||||
version = "0.10.0+wasi-snapshot-preview1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.11.0+wasi-snapshot-preview1"
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
@@ -3556,7 +3516,7 @@ dependencies = [
|
|||||||
"cc",
|
"cc",
|
||||||
"downcast-rs",
|
"downcast-rs",
|
||||||
"io-lifetimes",
|
"io-lifetimes",
|
||||||
"nix 0.26.2",
|
"nix 0.26.4",
|
||||||
"scoped-tls",
|
"scoped-tls",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"wayland-sys",
|
"wayland-sys",
|
||||||
@@ -3570,7 +3530,7 @@ checksum = "489c9654770f674fc7e266b3c579f4053d7551df0ceb392f153adb1f9ed06ac8"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"calloop",
|
"calloop",
|
||||||
"nix 0.26.2",
|
"nix 0.26.4",
|
||||||
"wayland-backend",
|
"wayland-backend",
|
||||||
"wayland-scanner",
|
"wayland-scanner",
|
||||||
]
|
]
|
||||||
@@ -3581,7 +3541,7 @@ version = "0.30.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2d0c3a0d5b4b688b07b0442362d3ed6bf04724fcc16cd69ab6285b90dbc487aa"
|
checksum = "2d0c3a0d5b4b688b07b0442362d3ed6bf04724fcc16cd69ab6285b90dbc487aa"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"nix 0.26.2",
|
"nix 0.26.4",
|
||||||
"wayland-client",
|
"wayland-client",
|
||||||
"xcursor",
|
"xcursor",
|
||||||
]
|
]
|
||||||
@@ -3841,11 +3801,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winreg"
|
name = "winreg"
|
||||||
version = "0.10.1"
|
version = "0.50.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d"
|
checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"winapi",
|
"cfg-if",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3863,7 +3824,7 @@ version = "1.0.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2769203cd13a0c6015d515be729c526d041e9cf2c0cc478d57faee85f40c6dcd"
|
checksum = "2769203cd13a0c6015d515be729c526d041e9cf2c0cc478d57faee85f40c6dcd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"nix 0.26.2",
|
"nix 0.26.4",
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -3891,7 +3852,7 @@ dependencies = [
|
|||||||
"futures-sink",
|
"futures-sink",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"hex",
|
"hex",
|
||||||
"nix 0.26.2",
|
"nix 0.26.4",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"ordered-stream",
|
"ordered-stream",
|
||||||
"rand",
|
"rand",
|
||||||
|
|||||||
30
Cargo.toml
30
Cargo.toml
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ironbar"
|
name = "ironbar"
|
||||||
version = "0.13.0"
|
version = "0.14.0-pre"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
description = "Customisable GTK Layer Shell wlroots/sway bar"
|
description = "Customisable GTK Layer Shell wlroots/sway bar"
|
||||||
@@ -66,7 +66,7 @@ workspaces = ["futures-util"]
|
|||||||
gtk = "0.17.0"
|
gtk = "0.17.0"
|
||||||
gtk-layer-shell = "0.6.0"
|
gtk-layer-shell = "0.6.0"
|
||||||
glib = "0.17.10"
|
glib = "0.17.10"
|
||||||
tokio = { version = "1.31.0", features = [
|
tokio = { version = "1.32.0", features = [
|
||||||
"macros",
|
"macros",
|
||||||
"rt-multi-thread",
|
"rt-multi-thread",
|
||||||
"time",
|
"time",
|
||||||
@@ -81,45 +81,45 @@ tracing-error = "0.2.0"
|
|||||||
tracing-appender = "0.2.2"
|
tracing-appender = "0.2.2"
|
||||||
strip-ansi-escapes = "0.2.0"
|
strip-ansi-escapes = "0.2.0"
|
||||||
color-eyre = "0.6.2"
|
color-eyre = "0.6.2"
|
||||||
serde = { version = "1.0.183", features = ["derive"] }
|
serde = { version = "1.0.188", features = ["derive"] }
|
||||||
indexmap = "2.0.0"
|
indexmap = "2.0.0"
|
||||||
dirs = "5.0.1"
|
dirs = "5.0.1"
|
||||||
walkdir = "2.3.2"
|
walkdir = "2.4.0"
|
||||||
notify = { version = "6.0.1", default-features = false }
|
notify = { version = "6.1.1", default-features = false }
|
||||||
wayland-client = "0.30.2"
|
wayland-client = "0.30.2"
|
||||||
wayland-protocols = { version = "0.30.1", features = ["unstable", "client"] }
|
wayland-protocols = { version = "0.30.1", features = ["unstable", "client"] }
|
||||||
wayland-protocols-wlr = { version = "0.1.0", features = ["client"] }
|
wayland-protocols-wlr = { version = "0.1.0", features = ["client"] }
|
||||||
smithay-client-toolkit = { version = "0.17.0", default-features = false, features = [
|
smithay-client-toolkit = { version = "0.17.0", default-features = false, features = [
|
||||||
"calloop",
|
"calloop",
|
||||||
] }
|
] }
|
||||||
universal-config = { version = "0.4.2", default_features = false }
|
universal-config = { version = "0.4.3", default_features = false }
|
||||||
ctrlc = "3.4.0"
|
ctrlc = "3.4.1"
|
||||||
|
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
async_once = "0.2.6"
|
async_once = "0.2.6"
|
||||||
cfg-if = "1.0.0"
|
cfg-if = "1.0.0"
|
||||||
|
|
||||||
# cli
|
# cli
|
||||||
clap = { version = "4.3.21", optional = true, features = ["derive"] }
|
clap = { version = "4.4.4", optional = true, features = ["derive"] }
|
||||||
|
|
||||||
# ipc
|
# ipc
|
||||||
serde_json = { version = "1.0.104", optional = true }
|
serde_json = { version = "1.0.107", optional = true }
|
||||||
|
|
||||||
# http
|
# http
|
||||||
reqwest = { version = "0.11.18", optional = true }
|
reqwest = { version = "0.11.20", optional = true }
|
||||||
|
|
||||||
# clipboard
|
# clipboard
|
||||||
nix = { version = "0.26.2", optional = true, features = ["event"] }
|
nix = { version = "0.27.1", optional = true, features = ["event"] }
|
||||||
|
|
||||||
# clock
|
# clock
|
||||||
chrono = { version = "0.4.26", optional = true, features = ["unstable-locales"] }
|
chrono = { version = "0.4.31", optional = true, features = ["unstable-locales"] }
|
||||||
|
|
||||||
# music
|
# music
|
||||||
mpd_client = { version = "1.2.0", optional = true }
|
mpd_client = { version = "1.2.0", optional = true }
|
||||||
mpris = { version = "2.0.1", optional = true }
|
mpris = { version = "2.0.1", optional = true }
|
||||||
|
|
||||||
# sys_info
|
# sys_info
|
||||||
sysinfo = { version = "0.29.8", optional = true }
|
sysinfo = { version = "0.29.10", optional = true }
|
||||||
|
|
||||||
# tray
|
# tray
|
||||||
system-tray = { version = "0.1.4", optional = true }
|
system-tray = { version = "0.1.4", optional = true }
|
||||||
@@ -131,10 +131,10 @@ zbus = { version = "3.14.1", optional = true }
|
|||||||
|
|
||||||
# workspaces
|
# workspaces
|
||||||
swayipc-async = { version = "2.0.1", optional = true }
|
swayipc-async = { version = "2.0.1", optional = true }
|
||||||
hyprland = { version = "0.3.8", features = ["silent"], optional = true }
|
hyprland = { version = "0.3.12", features = ["silent"], optional = true }
|
||||||
futures-util = { version = "0.3.21", optional = true }
|
futures-util = { version = "0.3.21", optional = true }
|
||||||
|
|
||||||
# shared
|
# shared
|
||||||
regex = { version = "1.8.4", default-features = false, features = [
|
regex = { version = "1.9.5", default-features = false, features = [
|
||||||
"std",
|
"std",
|
||||||
], optional = true } # music, sys_info
|
], optional = true } # music, sys_info
|
||||||
12
README.md
12
README.md
@@ -75,7 +75,15 @@ cargo install ironbar
|
|||||||
yay -S ironbar-git
|
yay -S ironbar-git
|
||||||
```
|
```
|
||||||
|
|
||||||
### Nix Flake
|
### Nix
|
||||||
|
|
||||||
|
[nix package](https://search.nixos.org/packages?channel=unstable&show=ironbar)
|
||||||
|
|
||||||
|
```sh
|
||||||
|
nix-shell -p ironbar
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Flake
|
||||||
|
|
||||||
A flake is included with the repo which can be used with Home Manager.
|
A flake is included with the repo which can be used with Home Manager.
|
||||||
|
|
||||||
@@ -170,4 +178,4 @@ All are welcome, but I ask a few basic things to help make things easier. Please
|
|||||||
- [Waybar](https://github.com/Alexays/Waybar) - A lot of the initial inspiration, and a pretty great bar.
|
- [Waybar](https://github.com/Alexays/Waybar) - A lot of the initial inspiration, and a pretty great bar.
|
||||||
- [Rustbar](https://github.com/zeroeightysix/rustbar) - Served as a good demo for writing a basic GTK bar in Rust
|
- [Rustbar](https://github.com/zeroeightysix/rustbar) - Served as a good demo for writing a basic GTK bar in Rust
|
||||||
- [Smithay Client Toolkit](https://github.com/Smithay/client-toolkit) - Essential in being able to communicate to Wayland
|
- [Smithay Client Toolkit](https://github.com/Smithay/client-toolkit) - Essential in being able to communicate to Wayland
|
||||||
- [gtk-layer-shell](https://github.com/wmww/gtk-layer-shell) - Ironbar and many other projects would be impossible without this
|
- [gtk-layer-shell](https://github.com/wmww/gtk-layer-shell) - Ironbar and many other projects would be impossible without this
|
||||||
|
|||||||
@@ -10,15 +10,17 @@ which only includes a subset of the full web spec (plus a few non-standard prope
|
|||||||
The below table describes the selectors provided by the bar itself.
|
The below table describes the selectors provided by the bar itself.
|
||||||
Information on styling individual modules can be found on their pages in the sidebar.
|
Information on styling individual modules can be found on their pages in the sidebar.
|
||||||
|
|
||||||
| Selector | Description |
|
| Selector | Description |
|
||||||
|----------------|--------------------------------------------|
|
|---------------------|--------------------------------------------|
|
||||||
| `.background` | Top-level window. |
|
| `.background` | Top-level window. |
|
||||||
| `#bar` | Bar root box. |
|
| `#bar` | Bar root box. |
|
||||||
| `#bar #start` | Bar left or top modules container box. |
|
| `#bar #start` | Bar left or top modules container box. |
|
||||||
| `#bar #center` | Bar center modules container box. |
|
| `#bar #center` | Bar center modules container box. |
|
||||||
| `#bar #end` | Bar right or bottom modules container box. |
|
| `#bar #end` | Bar right or bottom modules container box. |
|
||||||
| `.container` | All of the above. |
|
| `.container` | All of the above. |
|
||||||
| `.popup` | Any popup box. |
|
| `.widget-container` | The `EventBox` wrapping any widget. |
|
||||||
|
| `.widget` | Any widget. |
|
||||||
|
| `.popup` | Any popup box. |
|
||||||
|
|
||||||
Every widget can be selected using a `kebab-case` class name matching its name.
|
Every widget can be selected using a `kebab-case` class name matching its name.
|
||||||
You can also target popups by prefixing `popup-` to the name. For example, you can use `.clock` and `.popup-clock` respectively.
|
You can also target popups by prefixing `popup-` to the name. For example, you can use `.clock` and `.popup-clock` respectively.
|
||||||
|
|||||||
@@ -103,6 +103,8 @@ end:
|
|||||||
| `.workspaces` | Workspaces widget box |
|
| `.workspaces` | Workspaces widget box |
|
||||||
| `.workspaces .item` | Workspace button |
|
| `.workspaces .item` | Workspace button |
|
||||||
| `.workspaces .item.focused` | Workspace button (workspace focused) |
|
| `.workspaces .item.focused` | Workspace button (workspace focused) |
|
||||||
|
| `.workspaces .item.visible` | Workspace button (workspace visible, including focused) |
|
||||||
|
| `.workspaces .item.inactive` | Workspace button (favourite, not currently open)
|
||||||
| `.workspaces .item .icon` | Workspace button icon (any type) |
|
| `.workspaces .item .icon` | Workspace button icon (any type) |
|
||||||
| `.workspaces .item .text-icon` | Workspace button icon (textual only) |
|
| `.workspaces .item .text-icon` | Workspace button icon (textual only) |
|
||||||
| `.workspaces .item .image` | Workspace button icon (image only) |
|
| `.workspaces .item .image` | Workspace button icon (image only) |
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ let {
|
|||||||
type = "workspaces"
|
type = "workspaces"
|
||||||
all_monitors = false
|
all_monitors = false
|
||||||
name_map = {
|
name_map = {
|
||||||
1 = "ﭮ"
|
1 = ""
|
||||||
2 = "icon:firefox"
|
2 = "icon:firefox"
|
||||||
3 = ""
|
3 = ""
|
||||||
Games = "icon:steam"
|
Games = "icon:steam"
|
||||||
@@ -67,7 +67,7 @@ let {
|
|||||||
|
|
||||||
$clipboard = { type = "clipboard" max_items = 3 truncate.mode = "end" truncate.length = 50 }
|
$clipboard = { type = "clipboard" max_items = 3 truncate.mode = "end" truncate.length = 50 }
|
||||||
|
|
||||||
$label = { type = "label" label = "random num: {{500:echo $RANDOM}}" }
|
$label = { type = "label" label = "random num: {{500:echo FIXME}}" }
|
||||||
|
|
||||||
// -- begin custom --
|
// -- begin custom --
|
||||||
$button = { type = "button" name="power-btn" label = "" on_click = "popup:toggle" }
|
$button = { type = "button" name="power-btn" label = "" on_click = "popup:toggle" }
|
||||||
|
|||||||
@@ -109,7 +109,7 @@
|
|||||||
{
|
{
|
||||||
"all_monitors": false,
|
"all_monitors": false,
|
||||||
"name_map": {
|
"name_map": {
|
||||||
"1": "ﭮ",
|
"1": "",
|
||||||
"2": "icon:firefox",
|
"2": "icon:firefox",
|
||||||
"3": "",
|
"3": "",
|
||||||
"Code": "",
|
"Code": "",
|
||||||
@@ -128,7 +128,7 @@
|
|||||||
"type": "launcher"
|
"type": "launcher"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "random num: {{500:echo $RANDOM}}",
|
"label": "random num: {{500:echo FIXME}}",
|
||||||
"type": "label"
|
"type": "label"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,41 +1,41 @@
|
|||||||
anchor_to_edges = true
|
anchor_to_edges = true
|
||||||
icon_theme = 'Paper'
|
icon_theme = "Paper"
|
||||||
position = 'bottom'
|
position = "bottom"
|
||||||
|
|
||||||
[[end]]
|
[[end]]
|
||||||
music_dir = '/home/jake/Music'
|
music_dir = "/home/jake/Music"
|
||||||
player_type = 'mpd'
|
player_type = "mpd"
|
||||||
type = 'music'
|
type = "music"
|
||||||
|
|
||||||
[end.truncate]
|
[end.truncate]
|
||||||
max_length = 100
|
max_length = 100
|
||||||
mode = 'end'
|
mode = "end"
|
||||||
|
|
||||||
[[end]]
|
[[end]]
|
||||||
host = 'chloe:6600'
|
host = "chloe:6600"
|
||||||
player_type = 'mpd'
|
player_type = "mpd"
|
||||||
truncate = 'end'
|
truncate = "end"
|
||||||
type = 'music'
|
type = "music"
|
||||||
|
|
||||||
[[end]]
|
[[end]]
|
||||||
cmd = '/home/jake/bin/phone-battery'
|
cmd = "/home/jake/bin/phone-battery"
|
||||||
type = 'script'
|
type = "script"
|
||||||
|
|
||||||
[end.show_if]
|
[end.show_if]
|
||||||
cmd = '/home/jake/bin/phone-connected'
|
cmd = "/home/jake/bin/phone-connected"
|
||||||
interval = 500
|
interval = 500
|
||||||
|
|
||||||
[[end]]
|
[[end]]
|
||||||
type = 'sys_info'
|
|
||||||
format = [
|
format = [
|
||||||
' {cpu_percent}% | {temp_c:k10temp_Tccd1}°C',
|
" {cpu_percent}% | {temp_c:k10temp_Tccd1}°C",
|
||||||
' {memory_used} / {memory_total} GB ({memory_percent}%)',
|
" {memory_used} / {memory_total} GB ({memory_percent}%)",
|
||||||
'| {swap_used} / {swap_total} GB ({swap_percent}%)',
|
"| {swap_used} / {swap_total} GB ({swap_percent}%)",
|
||||||
' {disk_used:/} / {disk_total:/} GB ({disk_percent:/}%)',
|
" {disk_used:/} / {disk_total:/} GB ({disk_percent:/}%)",
|
||||||
'李 {net_down:enp39s0} / {net_up:enp39s0} Mbps',
|
"李 {net_down:enp39s0} / {net_up:enp39s0} Mbps",
|
||||||
'猪 {load_average:1} | {load_average:5} | {load_average:15}',
|
"猪 {load_average:1} | {load_average:5} | {load_average:15}",
|
||||||
' {uptime}',
|
" {uptime}",
|
||||||
]
|
]
|
||||||
|
type = "sys_info"
|
||||||
|
|
||||||
[end.interval]
|
[end.interval]
|
||||||
cpu = 1
|
cpu = 1
|
||||||
@@ -46,77 +46,77 @@ temps = 5
|
|||||||
|
|
||||||
[[end]]
|
[[end]]
|
||||||
max_items = 3
|
max_items = 3
|
||||||
type = 'clipboard'
|
type = "clipboard"
|
||||||
|
|
||||||
[end.truncate]
|
[end.truncate]
|
||||||
length = 50
|
length = 50
|
||||||
mode = 'end'
|
mode = "end"
|
||||||
|
|
||||||
[[end]]
|
[[end]]
|
||||||
class = 'power-menu'
|
class = "power-menu"
|
||||||
tooltip = '''Up: {{30000:uptime -p | cut -d ' ' -f2-}}'''
|
tooltip = "Up: {{30000:uptime -p | cut -d ' ' -f2-}}"
|
||||||
type = 'custom'
|
type = "custom"
|
||||||
|
|
||||||
[[end.bar]]
|
[[end.bar]]
|
||||||
label = ''
|
label = ""
|
||||||
name = 'power-btn'
|
name = "power-btn"
|
||||||
on_click = 'popup:toggle'
|
on_click = "popup:toggle"
|
||||||
type = 'button'
|
type = "button"
|
||||||
|
|
||||||
[[end.popup]]
|
[[end.popup]]
|
||||||
orientation = 'vertical'
|
orientation = "vertical"
|
||||||
type = 'box'
|
type = "box"
|
||||||
|
|
||||||
[[end.popup.widgets]]
|
[[end.popup.widgets]]
|
||||||
label = 'Power menu'
|
label = "Power menu"
|
||||||
name = 'header'
|
name = "header"
|
||||||
type = 'label'
|
type = "label"
|
||||||
|
|
||||||
[[end.popup.widgets]]
|
[[end.popup.widgets]]
|
||||||
type = 'box'
|
type = "box"
|
||||||
|
|
||||||
[[end.popup.widgets.widgets]]
|
[[end.popup.widgets.widgets]]
|
||||||
class = 'power-btn'
|
class = "power-btn"
|
||||||
label = '''<span font-size='40pt'></span>'''
|
label = "<span font-size='40pt'></span>"
|
||||||
on_click = '!shutdown now'
|
on_click = "!shutdown now"
|
||||||
type = 'button'
|
type = "button"
|
||||||
|
|
||||||
[[end.popup.widgets.widgets]]
|
[[end.popup.widgets.widgets]]
|
||||||
class = 'power-btn'
|
class = "power-btn"
|
||||||
label = '''<span font-size='40pt'></span>'''
|
label = "<span font-size='40pt'></span>"
|
||||||
on_click = '!reboot'
|
on_click = "!reboot"
|
||||||
type = 'button'
|
type = "button"
|
||||||
|
|
||||||
[[end.popup.widgets]]
|
[[end.popup.widgets]]
|
||||||
label = '''Uptime: {{30000:uptime -p | cut -d ' ' -f2-}}'''
|
label = "Uptime: {{30000:uptime -p | cut -d ' ' -f2-}}"
|
||||||
name = 'uptime'
|
name = "uptime"
|
||||||
type = 'label'
|
type = "label"
|
||||||
|
|
||||||
[[end]]
|
[[end]]
|
||||||
type = 'clock'
|
type = "clock"
|
||||||
|
|
||||||
[[start]]
|
[[start]]
|
||||||
all_monitors = false
|
all_monitors = false
|
||||||
type = 'workspaces'
|
type = "workspaces"
|
||||||
|
|
||||||
[start.name_map]
|
[start.name_map]
|
||||||
1 = 'ﭮ'
|
1 = ""
|
||||||
2 = 'icon:firefox'
|
2 = "icon:firefox"
|
||||||
3 = ''
|
3 = ""
|
||||||
Code = ''
|
Code = ""
|
||||||
Games = 'icon:steam'
|
Games = "icon:steam"
|
||||||
|
|
||||||
[[start]]
|
[[start]]
|
||||||
|
favorites = [
|
||||||
|
"firefox",
|
||||||
|
"discord",
|
||||||
|
"steam",
|
||||||
|
]
|
||||||
show_icons = true
|
show_icons = true
|
||||||
show_names = false
|
show_names = false
|
||||||
type = 'launcher'
|
type = "launcher"
|
||||||
favorites = [
|
|
||||||
'firefox',
|
|
||||||
'discord',
|
|
||||||
'steam',
|
|
||||||
]
|
|
||||||
|
|
||||||
[[start]]
|
[[start]]
|
||||||
label = 'random num: {{500:echo $RANDOM}}'
|
label = "random num: {{500:echo FIXME}}"
|
||||||
type = 'label'
|
type = "label"
|
||||||
|
|
||||||
|
|||||||
@@ -1,87 +1,87 @@
|
|||||||
anchor_to_edges: true
|
anchor_to_edges: true
|
||||||
end:
|
end:
|
||||||
- music_dir: /home/jake/Music
|
- music_dir: /home/jake/Music
|
||||||
player_type: mpd
|
player_type: mpd
|
||||||
truncate:
|
truncate:
|
||||||
max_length: 100
|
max_length: 100
|
||||||
mode: end
|
mode: end
|
||||||
type: music
|
type: music
|
||||||
- host: chloe:6600
|
- host: chloe:6600
|
||||||
player_type: mpd
|
player_type: mpd
|
||||||
truncate: end
|
truncate: end
|
||||||
type: music
|
type: music
|
||||||
- cmd: /home/jake/bin/phone-battery
|
- cmd: /home/jake/bin/phone-battery
|
||||||
show_if:
|
show_if:
|
||||||
cmd: /home/jake/bin/phone-connected
|
cmd: /home/jake/bin/phone-connected
|
||||||
interval: 500
|
interval: 500
|
||||||
type: script
|
type: script
|
||||||
- format:
|
- format:
|
||||||
- {cpu_percent}% | {temp_c:k10temp_Tccd1}°C
|
- {cpu_percent}% | {temp_c:k10temp_Tccd1}°C
|
||||||
- {memory_used} / {memory_total} GB ({memory_percent}%)
|
- {memory_used} / {memory_total} GB ({memory_percent}%)
|
||||||
- '| {swap_used} / {swap_total} GB ({swap_percent}%)'
|
- '| {swap_used} / {swap_total} GB ({swap_percent}%)'
|
||||||
- {disk_used:/} / {disk_total:/} GB ({disk_percent:/}%)
|
- {disk_used:/} / {disk_total:/} GB ({disk_percent:/}%)
|
||||||
- 李 {net_down:enp39s0} / {net_up:enp39s0} Mbps
|
- 李 {net_down:enp39s0} / {net_up:enp39s0} Mbps
|
||||||
- 猪 {load_average:1} | {load_average:5} | {load_average:15}
|
- 猪 {load_average:1} | {load_average:5} | {load_average:15}
|
||||||
- {uptime}
|
- {uptime}
|
||||||
interval:
|
interval:
|
||||||
cpu: 1
|
cpu: 1
|
||||||
disks: 300
|
disks: 300
|
||||||
memory: 30
|
memory: 30
|
||||||
networks: 3
|
networks: 3
|
||||||
temps: 5
|
temps: 5
|
||||||
type: sys_info
|
type: sys_info
|
||||||
- max_items: 3
|
- max_items: 3
|
||||||
truncate:
|
truncate:
|
||||||
length: 50
|
length: 50
|
||||||
mode: end
|
mode: end
|
||||||
type: clipboard
|
type: clipboard
|
||||||
- bar:
|
- bar:
|
||||||
- label:
|
- label:
|
||||||
name: power-btn
|
name: power-btn
|
||||||
on_click: popup:toggle
|
on_click: popup:toggle
|
||||||
|
type: button
|
||||||
|
class: power-menu
|
||||||
|
popup:
|
||||||
|
- orientation: vertical
|
||||||
|
type: box
|
||||||
|
widgets:
|
||||||
|
- label: Power menu
|
||||||
|
name: header
|
||||||
|
type: label
|
||||||
|
- type: box
|
||||||
|
widgets:
|
||||||
|
- class: power-btn
|
||||||
|
label: <span font-size='40pt'></span>
|
||||||
|
on_click: '!shutdown now'
|
||||||
type: button
|
type: button
|
||||||
class: power-menu
|
- class: power-btn
|
||||||
popup:
|
label: <span font-size='40pt'></span>
|
||||||
- orientation: vertical
|
on_click: '!reboot'
|
||||||
type: box
|
type: button
|
||||||
widgets:
|
- label: 'Uptime: {{30000:uptime -p | cut -d '' '' -f2-}}'
|
||||||
- label: Power menu
|
name: uptime
|
||||||
name: header
|
type: label
|
||||||
type: label
|
tooltip: 'Up: {{30000:uptime -p | cut -d '' '' -f2-}}'
|
||||||
- type: box
|
type: custom
|
||||||
widgets:
|
- type: clock
|
||||||
- class: power-btn
|
|
||||||
label: <span font-size='40pt'></span>
|
|
||||||
on_click: '!shutdown now'
|
|
||||||
type: button
|
|
||||||
- class: power-btn
|
|
||||||
label: <span font-size='40pt'></span>
|
|
||||||
on_click: '!reboot'
|
|
||||||
type: button
|
|
||||||
- label: 'Uptime: {{30000:uptime -p | cut -d '' '' -f2-}}'
|
|
||||||
name: uptime
|
|
||||||
type: label
|
|
||||||
tooltip: 'Up: {{30000:uptime -p | cut -d '' '' -f2-}}'
|
|
||||||
type: custom
|
|
||||||
- type: clock
|
|
||||||
icon_theme: Paper
|
icon_theme: Paper
|
||||||
position: bottom
|
position: bottom
|
||||||
start:
|
start:
|
||||||
- all_monitors: false
|
- all_monitors: false
|
||||||
name_map:
|
name_map:
|
||||||
'1': ﭮ
|
'1':
|
||||||
'2': icon:firefox
|
'2': icon:firefox
|
||||||
'3':
|
'3':
|
||||||
Code:
|
Code:
|
||||||
Games: icon:steam
|
Games: icon:steam
|
||||||
type: workspaces
|
type: workspaces
|
||||||
- favorites:
|
- favorites:
|
||||||
- firefox
|
- firefox
|
||||||
- discord
|
- discord
|
||||||
- steam
|
- steam
|
||||||
show_icons: true
|
show_icons: true
|
||||||
show_names: false
|
show_names: false
|
||||||
type: launcher
|
type: launcher
|
||||||
- label: 'random num: {{500:echo $RANDOM}}'
|
- label: 'random num: {{500:echo FIXME}}'
|
||||||
type: label
|
type: label
|
||||||
|
|
||||||
|
|||||||
42
flake.lock
generated
42
flake.lock
generated
@@ -10,11 +10,11 @@
|
|||||||
"rust-overlay": "rust-overlay"
|
"rust-overlay": "rust-overlay"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1688772518,
|
"lastModified": 1693439040,
|
||||||
"narHash": "sha256-ol7gZxwvgLnxNSZwFTDJJ49xVY5teaSvF7lzlo3YQfM=",
|
"narHash": "sha256-t2nOxBcP0Q/XJt6Ild4v0hJ49OSl9F3nE1cdIT4xsDg=",
|
||||||
"owner": "ipetkov",
|
"owner": "ipetkov",
|
||||||
"repo": "crane",
|
"repo": "crane",
|
||||||
"rev": "8b08e96c9af8c6e3a2b69af5a7fa168750fcf88e",
|
"rev": "174604795d316b75777e28185c3a4918bc69b399",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -44,11 +44,11 @@
|
|||||||
"systems": "systems"
|
"systems": "systems"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1687709756,
|
"lastModified": 1689068808,
|
||||||
"narHash": "sha256-Y5wKlQSkgEK2weWdOu4J3riRd+kV/VCgHsqLNTTWQ/0=",
|
"narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "flake-utils",
|
"repo": "flake-utils",
|
||||||
"rev": "dbabf0ca0c0c4bce6ea5eaf65af5cb694d2082c7",
|
"rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -80,11 +80,11 @@
|
|||||||
"nixpkgs": "nixpkgs"
|
"nixpkgs": "nixpkgs"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1690373729,
|
"lastModified": 1692351612,
|
||||||
"narHash": "sha256-e136hTT7LqQ2QjOTZQMW+jnsevWwBpMj78u6FRUsH9I=",
|
"narHash": "sha256-KTGonidcdaLadRnv9KFgwSMh1ZbXoR/OBmPjeNMhFwU=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "naersk",
|
"repo": "naersk",
|
||||||
"rev": "d9a33d69a9c421d64c8d925428864e93be895dcc",
|
"rev": "78789c30d64dea2396c9da516bbcc8db3a475207",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -95,11 +95,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1690833316,
|
"lastModified": 1693355128,
|
||||||
"narHash": "sha256-+YU+/pTJmVKNW12R07/SJiTn7PQk90xwCI4D2PfLRPs=",
|
"narHash": "sha256-+ZoAny3ZxLcfMaUoLVgL9Ywb/57wP+EtsdNGuXUJrwg=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "9418167277f665de6f4a29f414d438cf39c55b9e",
|
"rev": "a63a64b593dcf2fe05f7c5d666eb395950f36bc9",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -109,11 +109,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs_2": {
|
"nixpkgs_2": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1690789960,
|
"lastModified": 1693377291,
|
||||||
"narHash": "sha256-3K+2HuyGTiJUSZNJxXXvc0qj4xFx1FHC/ItYtEa7/Xs=",
|
"narHash": "sha256-vYGY9bnqEeIncNarDZYhm6KdLKgXMS+HA2mTRaWEc80=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "fb942492b7accdee4e6d17f5447091c65897dde4",
|
"rev": "e7f38be3775bab9659575f192ece011c033655f0",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -143,11 +143,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1688351637,
|
"lastModified": 1691374719,
|
||||||
"narHash": "sha256-CLTufJ29VxNOIZ8UTg0lepsn3X03AmopmaLTTeHDCL4=",
|
"narHash": "sha256-HCodqnx1Mi2vN4f3hjRPc7+lSQy18vRn8xWW68GeQOg=",
|
||||||
"owner": "oxalica",
|
"owner": "oxalica",
|
||||||
"repo": "rust-overlay",
|
"repo": "rust-overlay",
|
||||||
"rev": "f9b92316727af9e6c7fee4a761242f7f46880329",
|
"rev": "b520a3889b24aaf909e287d19d406862ced9ffc9",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -164,11 +164,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1690683485,
|
"lastModified": 1693447852,
|
||||||
"narHash": "sha256-Sp/QpbMg86v12xhCsa6q0yTH8LYaJIcxzbf9LO1zFzM=",
|
"narHash": "sha256-K9npbs4S6+r51vpiElJi+0vwbAeftCAcOGbot/PCBnQ=",
|
||||||
"owner": "oxalica",
|
"owner": "oxalica",
|
||||||
"repo": "rust-overlay",
|
"repo": "rust-overlay",
|
||||||
"rev": "05d480a7aef1aae1bfb67a39134dcf48c5322528",
|
"rev": "40e851593ef4f9f8cd0b69c8cae7b722b9953a23",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|||||||
11
src/bar.rs
11
src/bar.rs
@@ -4,14 +4,13 @@ use crate::modules::{
|
|||||||
};
|
};
|
||||||
use crate::popup::Popup;
|
use crate::popup::Popup;
|
||||||
use crate::unique_id::get_unique_usize;
|
use crate::unique_id::get_unique_usize;
|
||||||
use crate::{arc_rw, Config, GlobalState};
|
use crate::{Config, GlobalState};
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
use gtk::gdk::Monitor;
|
use gtk::gdk::Monitor;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::{Application, ApplicationWindow, IconTheme, Orientation};
|
use gtk::{Application, ApplicationWindow, IconTheme, Orientation};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::{Arc, RwLock};
|
|
||||||
use tracing::{debug, info};
|
use tracing::{debug, info};
|
||||||
|
|
||||||
/// Creates a new window for a bar,
|
/// Creates a new window for a bar,
|
||||||
@@ -153,7 +152,7 @@ fn create_container(name: &str, orientation: Orientation) -> gtk::Box {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct BarLoadResult {
|
struct BarLoadResult {
|
||||||
popup: Arc<RwLock<Popup>>,
|
popup: Rc<RefCell<Popup>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Loads the configured modules onto a bar.
|
/// Loads the configured modules onto a bar.
|
||||||
@@ -186,7 +185,7 @@ fn load_modules(
|
|||||||
|
|
||||||
// popup ignores module location so can bodge this for now
|
// popup ignores module location so can bodge this for now
|
||||||
let popup = Popup::new(&info!(ModuleLocation::Left), config.popup_gap);
|
let popup = Popup::new(&info!(ModuleLocation::Left), config.popup_gap);
|
||||||
let popup = arc_rw!(popup);
|
let popup = Rc::new(RefCell::new(popup));
|
||||||
|
|
||||||
if let Some(modules) = config.start {
|
if let Some(modules) = config.start {
|
||||||
let info = info!(ModuleLocation::Left);
|
let info = info!(ModuleLocation::Left);
|
||||||
@@ -214,7 +213,7 @@ fn add_modules(
|
|||||||
content: >k::Box,
|
content: >k::Box,
|
||||||
modules: Vec<ModuleConfig>,
|
modules: Vec<ModuleConfig>,
|
||||||
info: &ModuleInfo,
|
info: &ModuleInfo,
|
||||||
popup: &Arc<RwLock<Popup>>,
|
popup: &Rc<RefCell<Popup>>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let orientation = info.bar_position.get_orientation();
|
let orientation = info.bar_position.get_orientation();
|
||||||
|
|
||||||
@@ -226,7 +225,7 @@ fn add_modules(
|
|||||||
$id,
|
$id,
|
||||||
common.name.clone(),
|
common.name.clone(),
|
||||||
&info,
|
&info,
|
||||||
&Arc::clone(&popup),
|
&Rc::clone(&popup),
|
||||||
)?;
|
)?;
|
||||||
set_widget_identifiers(&widget_parts, &common);
|
set_widget_identifiers(&widget_parts, &common);
|
||||||
|
|
||||||
|
|||||||
145
src/cached_broadcast.rs
Normal file
145
src/cached_broadcast.rs
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
use crate::{arc_rw, read_lock, send_async, write_lock};
|
||||||
|
use std::fmt::Debug;
|
||||||
|
use std::ops::Deref;
|
||||||
|
use std::sync::{Arc, RwLock};
|
||||||
|
// use std::thread::sleep;
|
||||||
|
use std::time::Duration;
|
||||||
|
use tokio::spawn;
|
||||||
|
use tokio::sync::mpsc;
|
||||||
|
use tokio::task::spawn_blocking;
|
||||||
|
use tokio::time::sleep;
|
||||||
|
use tracing::trace;
|
||||||
|
|
||||||
|
pub trait Cacheable: Debug + Clone + Send + Sync {
|
||||||
|
type Key: Debug + Clone + Send + Sync + Eq;
|
||||||
|
|
||||||
|
fn get_key(&self) -> Self::Key;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Sender<T> = mpsc::Sender<Event<T>>;
|
||||||
|
pub type Receiver<T> = mpsc::Receiver<Event<T>>;
|
||||||
|
|
||||||
|
pub struct CachedBroadcastChannel<T>
|
||||||
|
where
|
||||||
|
T: Cacheable,
|
||||||
|
{
|
||||||
|
capacity: usize,
|
||||||
|
data: Vec<T>,
|
||||||
|
channels: Arc<RwLock<Vec<mpsc::Sender<Event<T>>>>>,
|
||||||
|
base_tx: mpsc::Sender<Event<T>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum Event<T>
|
||||||
|
where
|
||||||
|
T: Cacheable,
|
||||||
|
{
|
||||||
|
Add(T),
|
||||||
|
Remove(T::Key),
|
||||||
|
Replace(T::Key, T),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> CachedBroadcastChannel<T>
|
||||||
|
where
|
||||||
|
T: Cacheable + 'static,
|
||||||
|
{
|
||||||
|
pub fn new(capacity: usize) -> Self {
|
||||||
|
let (tx, rx) = mpsc::channel::<Event<T>>(capacity);
|
||||||
|
let mut rx = DropDetector(rx);
|
||||||
|
|
||||||
|
// spawn_blocking(move || loop {
|
||||||
|
// let ev = rx.0.try_recv();
|
||||||
|
// println!("{ev:?}");
|
||||||
|
// sleep(Duration::from_secs(1))
|
||||||
|
// });
|
||||||
|
|
||||||
|
let channels = arc_rw!(Vec::<Sender<T>>::new());
|
||||||
|
|
||||||
|
let channels = Arc::clone(&channels);
|
||||||
|
spawn(async move {
|
||||||
|
println!("hello");
|
||||||
|
|
||||||
|
while let Some(event) = rx.0.recv().await {
|
||||||
|
println!("ev");
|
||||||
|
// trace!("{event:?}");
|
||||||
|
// let iter = read_lock!(channels).clone().into_iter();
|
||||||
|
// for channel in iter {
|
||||||
|
// send_async!(channel, event.clone());
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
println!("goodbye");
|
||||||
|
});
|
||||||
|
|
||||||
|
Self {
|
||||||
|
capacity,
|
||||||
|
data: vec![],
|
||||||
|
channels,
|
||||||
|
base_tx: tx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn send(&mut self, event: Event<T>) {
|
||||||
|
match event.clone() {
|
||||||
|
Event::Add(data) => {
|
||||||
|
self.data.push(data);
|
||||||
|
}
|
||||||
|
Event::Remove(key) => {
|
||||||
|
let Some(index) = self.data.iter().position(|t| t.get_key() == key) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
self.data.remove(index);
|
||||||
|
}
|
||||||
|
Event::Replace(key, data) => {
|
||||||
|
let Some(index) = self.data.iter().position(|t| t.get_key() == key) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let _ = std::mem::replace(&mut self.data[index], data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
send_async!(self.base_tx, event);
|
||||||
|
|
||||||
|
// let mut closed = vec![];
|
||||||
|
// for (i, channel) in read_lock!(self.channels).iter().enumerate() {
|
||||||
|
// if channel.is_closed() {
|
||||||
|
// closed.push(i);
|
||||||
|
// } else {
|
||||||
|
// send_async!(channel, event.clone());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// for channel in closed.into_iter().rev() {
|
||||||
|
// write_lock!(self.channels).remove(channel);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sender(&self) -> mpsc::Sender<Event<T>> {
|
||||||
|
self.base_tx.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn receiver(&mut self) -> mpsc::Receiver<Event<T>> {
|
||||||
|
let (tx, rx) = mpsc::channel(self.capacity);
|
||||||
|
write_lock!(self.channels).push(tx);
|
||||||
|
|
||||||
|
rx
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn data(&self) -> &Vec<T> {
|
||||||
|
&self.data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct DropDetector<T>(T);
|
||||||
|
|
||||||
|
impl<T> Drop for DropDetector<T> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
println!("DROPPED")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Cacheable> Drop for CachedBroadcastChannel<T> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
println!("Channel DROPPED")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
use super::{Workspace, WorkspaceClient, WorkspaceUpdate};
|
use super::{Visibility, Workspace, WorkspaceClient, WorkspaceUpdate};
|
||||||
use crate::{arc_mut, lock, send};
|
use crate::{arc_mut, lock, send};
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
use hyprland::data::{Workspace as HWorkspace, Workspaces};
|
use hyprland::data::{Workspace as HWorkspace, Workspaces};
|
||||||
@@ -52,11 +52,8 @@ impl EventClient {
|
|||||||
|
|
||||||
let workspace_name = get_workspace_name(workspace_type);
|
let workspace_name = get_workspace_name(workspace_type);
|
||||||
let prev_workspace = lock!(active);
|
let prev_workspace = lock!(active);
|
||||||
let focused = prev_workspace
|
|
||||||
.as_ref()
|
|
||||||
.map_or(false, |w| w.name == workspace_name);
|
|
||||||
|
|
||||||
let workspace = Self::get_workspace(&workspace_name, focused);
|
let workspace = Self::get_workspace(&workspace_name, prev_workspace.as_ref());
|
||||||
|
|
||||||
if let Some(workspace) = workspace {
|
if let Some(workspace) = workspace {
|
||||||
send!(tx, WorkspaceUpdate::Add(workspace));
|
send!(tx, WorkspaceUpdate::Add(workspace));
|
||||||
@@ -80,10 +77,7 @@ impl EventClient {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let workspace_name = get_workspace_name(workspace_type);
|
let workspace_name = get_workspace_name(workspace_type);
|
||||||
let focused = prev_workspace
|
let workspace = Self::get_workspace(&workspace_name, prev_workspace.as_ref());
|
||||||
.as_ref()
|
|
||||||
.map_or(false, |w| w.name == workspace_name);
|
|
||||||
let workspace = Self::get_workspace(&workspace_name, focused);
|
|
||||||
|
|
||||||
workspace.map_or_else(
|
workspace.map_or_else(
|
||||||
|| {
|
|| {
|
||||||
@@ -92,7 +86,7 @@ impl EventClient {
|
|||||||
|workspace| {
|
|workspace| {
|
||||||
// there may be another type of update so dispatch that regardless of focus change
|
// there may be another type of update so dispatch that regardless of focus change
|
||||||
send!(tx, WorkspaceUpdate::Update(workspace.clone()));
|
send!(tx, WorkspaceUpdate::Update(workspace.clone()));
|
||||||
if !focused {
|
if !workspace.visibility.is_focused() {
|
||||||
Self::send_focus_change(&mut prev_workspace, workspace, &tx);
|
Self::send_focus_change(&mut prev_workspace, workspace, &tx);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -117,12 +111,11 @@ impl EventClient {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let workspace_name = get_workspace_name(workspace_type);
|
let workspace_name = get_workspace_name(workspace_type);
|
||||||
let focused = prev_workspace
|
let workspace = Self::get_workspace(&workspace_name, prev_workspace.as_ref());
|
||||||
.as_ref()
|
|
||||||
.map_or(false, |w| w.name == workspace_name);
|
|
||||||
let workspace = Self::get_workspace(&workspace_name, focused);
|
|
||||||
|
|
||||||
if let (Some(workspace), false) = (workspace, focused) {
|
if let Some((false, workspace)) =
|
||||||
|
workspace.map(|w| (w.visibility.is_focused(), w))
|
||||||
|
{
|
||||||
Self::send_focus_change(&mut prev_workspace, workspace, &tx);
|
Self::send_focus_change(&mut prev_workspace, workspace, &tx);
|
||||||
} else {
|
} else {
|
||||||
error!("Unable to locate workspace");
|
error!("Unable to locate workspace");
|
||||||
@@ -142,15 +135,12 @@ impl EventClient {
|
|||||||
let mut prev_workspace = lock!(active);
|
let mut prev_workspace = lock!(active);
|
||||||
|
|
||||||
let workspace_name = get_workspace_name(workspace_type);
|
let workspace_name = get_workspace_name(workspace_type);
|
||||||
let focused = prev_workspace
|
let workspace = Self::get_workspace(&workspace_name, prev_workspace.as_ref());
|
||||||
.as_ref()
|
|
||||||
.map_or(false, |w| w.name == workspace_name);
|
|
||||||
let workspace = Self::get_workspace(&workspace_name, focused);
|
|
||||||
|
|
||||||
if let Some(workspace) = workspace {
|
if let Some(workspace) = workspace {
|
||||||
send!(tx, WorkspaceUpdate::Move(workspace.clone()));
|
send!(tx, WorkspaceUpdate::Move(workspace.clone()));
|
||||||
|
|
||||||
if !focused {
|
if !workspace.visibility.is_focused() {
|
||||||
Self::send_focus_change(&mut prev_workspace, workspace, &tx);
|
Self::send_focus_change(&mut prev_workspace, workspace, &tx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -180,32 +170,28 @@ impl EventClient {
|
|||||||
workspace: Workspace,
|
workspace: Workspace,
|
||||||
tx: &Sender<WorkspaceUpdate>,
|
tx: &Sender<WorkspaceUpdate>,
|
||||||
) {
|
) {
|
||||||
let old = prev_workspace
|
|
||||||
.as_ref()
|
|
||||||
.map(|w| w.name.clone())
|
|
||||||
.unwrap_or_default();
|
|
||||||
|
|
||||||
send!(
|
send!(
|
||||||
tx,
|
tx,
|
||||||
WorkspaceUpdate::Focus {
|
WorkspaceUpdate::Focus {
|
||||||
old,
|
old: prev_workspace.take(),
|
||||||
new: workspace.name.clone(),
|
new: workspace.clone(),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
prev_workspace.replace(workspace);
|
prev_workspace.replace(workspace);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a workspace by name from the server.
|
/// Gets a workspace by name from the server, given the active workspace if known.
|
||||||
///
|
fn get_workspace(name: &str, active: Option<&Workspace>) -> Option<Workspace> {
|
||||||
/// Use `focused` to manually mark the workspace as focused,
|
|
||||||
/// as this is not automatically checked.
|
|
||||||
fn get_workspace(name: &str, focused: bool) -> Option<Workspace> {
|
|
||||||
Workspaces::get()
|
Workspaces::get()
|
||||||
.expect("Failed to get workspaces")
|
.expect("Failed to get workspaces")
|
||||||
.find_map(|w| {
|
.find_map(|w| {
|
||||||
if w.name == name {
|
if w.name == name {
|
||||||
Some(Workspace::from((focused, w)))
|
let vis = Visibility::from((&w, active.map(|w| w.name.as_ref()), &|w| {
|
||||||
|
create_is_visible()(w)
|
||||||
|
}));
|
||||||
|
|
||||||
|
Some(Workspace::from((vis, w)))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@@ -214,7 +200,7 @@ impl EventClient {
|
|||||||
|
|
||||||
/// Gets the active workspace from the server.
|
/// Gets the active workspace from the server.
|
||||||
fn get_active_workspace() -> Result<Workspace> {
|
fn get_active_workspace() -> Result<Workspace> {
|
||||||
let w = HWorkspace::get_active().map(|w| Workspace::from((true, w)))?;
|
let w = HWorkspace::get_active().map(|w| Workspace::from((Visibility::focused(), w)))?;
|
||||||
Ok(w)
|
Ok(w)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -236,13 +222,16 @@ impl WorkspaceClient for EventClient {
|
|||||||
{
|
{
|
||||||
let tx = self.workspace_tx.clone();
|
let tx = self.workspace_tx.clone();
|
||||||
|
|
||||||
let active_name = HWorkspace::get_active()
|
let active_id = HWorkspace::get_active().ok().map(|active| active.name);
|
||||||
.map(|active| active.name)
|
let is_visible = create_is_visible();
|
||||||
.unwrap_or_default();
|
|
||||||
|
|
||||||
let workspaces = Workspaces::get()
|
let workspaces = Workspaces::get()
|
||||||
.expect("Failed to get workspaces")
|
.expect("Failed to get workspaces")
|
||||||
.map(|w| Workspace::from((w.name == active_name, w)))
|
.map(|w| {
|
||||||
|
let vis = Visibility::from((&w, active_id.as_deref(), &is_visible));
|
||||||
|
|
||||||
|
Workspace::from((vis, w))
|
||||||
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
send!(tx, WorkspaceUpdate::Init(workspaces));
|
send!(tx, WorkspaceUpdate::Init(workspaces));
|
||||||
@@ -271,13 +260,36 @@ fn get_workspace_name(name: WorkspaceType) -> String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<(bool, hyprland::data::Workspace)> for Workspace {
|
/// Creates a function which determines if a workspace is visible. This function makes a Hyprland call that allocates so it should be cached when possible, but it is only valid so long as workspaces do not change so it should not be stored long term
|
||||||
fn from((focused, workspace): (bool, hyprland::data::Workspace)) -> Self {
|
fn create_is_visible() -> impl Fn(&HWorkspace) -> bool {
|
||||||
|
let monitors = hyprland::data::Monitors::get().map_or(Vec::new(), |ms| ms.to_vec());
|
||||||
|
|
||||||
|
move |w| monitors.iter().any(|m| m.active_workspace.id == w.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<(Visibility, HWorkspace)> for Workspace {
|
||||||
|
fn from((visibility, workspace): (Visibility, HWorkspace)) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id: workspace.id.to_string(),
|
id: workspace.id.to_string(),
|
||||||
name: workspace.name,
|
name: workspace.name,
|
||||||
monitor: workspace.monitor,
|
monitor: workspace.monitor,
|
||||||
focused,
|
visibility,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'f, F> From<(&'a HWorkspace, Option<&str>, F)> for Visibility
|
||||||
|
where
|
||||||
|
F: FnOnce(&'f HWorkspace) -> bool,
|
||||||
|
'a: 'f,
|
||||||
|
{
|
||||||
|
fn from((workspace, active_name, is_visible): (&'a HWorkspace, Option<&str>, F)) -> Self {
|
||||||
|
if Some(workspace.name.as_str()) == active_name {
|
||||||
|
Self::focused()
|
||||||
|
} else if is_visible(workspace) {
|
||||||
|
Self::visible()
|
||||||
|
} else {
|
||||||
|
Self::Hidden
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,8 +75,38 @@ pub struct Workspace {
|
|||||||
pub name: String,
|
pub name: String,
|
||||||
/// Name of the monitor (output) the workspace is located on
|
/// Name of the monitor (output) the workspace is located on
|
||||||
pub monitor: String,
|
pub monitor: String,
|
||||||
/// Whether the workspace is in focus
|
/// How visible the workspace is
|
||||||
pub focused: bool,
|
pub visibility: Visibility,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Indicates workspace visibility. Visible workspaces have a boolean flag to indicate if they are also focused.
|
||||||
|
/// Yes, this is the same signature as Option<bool>, but it's impl is a lot more suited for our case.
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub enum Visibility {
|
||||||
|
Visible(bool),
|
||||||
|
Hidden,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Visibility {
|
||||||
|
pub fn visible() -> Self {
|
||||||
|
Self::Visible(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn focused() -> Self {
|
||||||
|
Self::Visible(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_visible(self) -> bool {
|
||||||
|
matches!(self, Self::Visible(_))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_focused(self) -> bool {
|
||||||
|
if let Self::Visible(focused) = self {
|
||||||
|
focused
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@@ -90,8 +120,8 @@ pub enum WorkspaceUpdate {
|
|||||||
Move(Workspace),
|
Move(Workspace),
|
||||||
/// Declares focus moved from the old workspace to the new.
|
/// Declares focus moved from the old workspace to the new.
|
||||||
Focus {
|
Focus {
|
||||||
old: String,
|
old: Option<Workspace>,
|
||||||
new: String,
|
new: Workspace,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use super::{Workspace, WorkspaceClient, WorkspaceUpdate};
|
use super::{Visibility, Workspace, WorkspaceClient, WorkspaceUpdate};
|
||||||
use crate::{await_sync, send};
|
use crate::{await_sync, send};
|
||||||
use async_once::AsyncOnce;
|
use async_once::AsyncOnce;
|
||||||
use color_eyre::Report;
|
use color_eyre::Report;
|
||||||
@@ -105,22 +105,50 @@ pub fn get_sub_client() -> &'static SwayEventClient {
|
|||||||
|
|
||||||
impl From<Node> for Workspace {
|
impl From<Node> for Workspace {
|
||||||
fn from(node: Node) -> Self {
|
fn from(node: Node) -> Self {
|
||||||
|
let visibility = Visibility::from(&node);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
id: node.id.to_string(),
|
id: node.id.to_string(),
|
||||||
name: node.name.unwrap_or_default(),
|
name: node.name.unwrap_or_default(),
|
||||||
monitor: node.output.unwrap_or_default(),
|
monitor: node.output.unwrap_or_default(),
|
||||||
focused: node.focused,
|
visibility,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<swayipc_async::Workspace> for Workspace {
|
impl From<swayipc_async::Workspace> for Workspace {
|
||||||
fn from(workspace: swayipc_async::Workspace) -> Self {
|
fn from(workspace: swayipc_async::Workspace) -> Self {
|
||||||
|
let visibility = Visibility::from(&workspace);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
id: workspace.id.to_string(),
|
id: workspace.id.to_string(),
|
||||||
name: workspace.name,
|
name: workspace.name,
|
||||||
monitor: workspace.output,
|
monitor: workspace.output,
|
||||||
focused: workspace.focused,
|
visibility,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&Node> for Visibility {
|
||||||
|
fn from(node: &Node) -> Self {
|
||||||
|
if node.focused {
|
||||||
|
Self::focused()
|
||||||
|
} else if node.visible.unwrap_or(false) {
|
||||||
|
Self::visible()
|
||||||
|
} else {
|
||||||
|
Self::Hidden
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&swayipc_async::Workspace> for Visibility {
|
||||||
|
fn from(workspace: &swayipc_async::Workspace) -> Self {
|
||||||
|
if workspace.focused {
|
||||||
|
Self::focused()
|
||||||
|
} else if workspace.visible {
|
||||||
|
Self::visible()
|
||||||
|
} else {
|
||||||
|
Self::Hidden
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -139,16 +167,8 @@ impl From<WorkspaceEvent> for WorkspaceUpdate {
|
|||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
),
|
),
|
||||||
WorkspaceChange::Focus => Self::Focus {
|
WorkspaceChange::Focus => Self::Focus {
|
||||||
old: event
|
old: event.old.map(Workspace::from),
|
||||||
.old
|
new: Workspace::from(event.current.expect("Missing current workspace")),
|
||||||
.expect("Missing old workspace")
|
|
||||||
.name
|
|
||||||
.unwrap_or_default(),
|
|
||||||
new: event
|
|
||||||
.current
|
|
||||||
.expect("Missing current workspace")
|
|
||||||
.name
|
|
||||||
.unwrap_or_default(),
|
|
||||||
},
|
},
|
||||||
WorkspaceChange::Move => {
|
WorkspaceChange::Move => {
|
||||||
Self::Move(event.current.expect("Missing current workspace").into())
|
Self::Move(event.current.expect("Missing current workspace").into())
|
||||||
|
|||||||
@@ -2,8 +2,9 @@ use super::wlr_foreign_toplevel::handle::ToplevelHandle;
|
|||||||
use super::wlr_foreign_toplevel::manager::ToplevelManagerState;
|
use super::wlr_foreign_toplevel::manager::ToplevelManagerState;
|
||||||
use super::wlr_foreign_toplevel::ToplevelEvent;
|
use super::wlr_foreign_toplevel::ToplevelEvent;
|
||||||
use super::Environment;
|
use super::Environment;
|
||||||
|
use crate::cached_broadcast::CachedBroadcastChannel;
|
||||||
use crate::error::ERR_CHANNEL_RECV;
|
use crate::error::ERR_CHANNEL_RECV;
|
||||||
use crate::send;
|
use crate::{cached_broadcast, send};
|
||||||
use cfg_if::cfg_if;
|
use cfg_if::cfg_if;
|
||||||
use color_eyre::Report;
|
use color_eyre::Report;
|
||||||
use smithay_client_toolkit::output::{OutputInfo, OutputState};
|
use smithay_client_toolkit::output::{OutputInfo, OutputState};
|
||||||
@@ -31,11 +32,8 @@ cfg_if! {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Request {
|
pub enum Request {
|
||||||
/// Sends a request for all the outputs.
|
|
||||||
/// These are then sent on the `output` channel.
|
|
||||||
Outputs,
|
|
||||||
/// Sends a request for all the seats.
|
/// Sends a request for all the seats.
|
||||||
/// These are then sent ont the `seat` channel.
|
/// These are then sent on the `seat` channel.
|
||||||
Seats,
|
Seats,
|
||||||
/// Sends a request for all the toplevels.
|
/// Sends a request for all the toplevels.
|
||||||
/// These are then sent on the `toplevel_init` channel.
|
/// These are then sent on the `toplevel_init` channel.
|
||||||
@@ -53,8 +51,10 @@ pub enum Request {
|
|||||||
|
|
||||||
pub struct WaylandClient {
|
pub struct WaylandClient {
|
||||||
// External channels
|
// External channels
|
||||||
|
output_channel: CachedBroadcastChannel<OutputInfo>,
|
||||||
toplevel_tx: broadcast::Sender<ToplevelEvent>,
|
toplevel_tx: broadcast::Sender<ToplevelEvent>,
|
||||||
_toplevel_rx: broadcast::Receiver<ToplevelEvent>,
|
_toplevel_rx: broadcast::Receiver<ToplevelEvent>,
|
||||||
|
|
||||||
#[cfg(feature = "clipboard")]
|
#[cfg(feature = "clipboard")]
|
||||||
clipboard_tx: broadcast::Sender<Arc<ClipboardItem>>,
|
clipboard_tx: broadcast::Sender<Arc<ClipboardItem>>,
|
||||||
#[cfg(feature = "clipboard")]
|
#[cfg(feature = "clipboard")]
|
||||||
@@ -62,7 +62,6 @@ pub struct WaylandClient {
|
|||||||
|
|
||||||
// Internal channels
|
// Internal channels
|
||||||
toplevel_init_rx: mpsc::Receiver<HashMap<usize, ToplevelHandle>>,
|
toplevel_init_rx: mpsc::Receiver<HashMap<usize, ToplevelHandle>>,
|
||||||
output_rx: mpsc::Receiver<Vec<OutputInfo>>,
|
|
||||||
seat_rx: mpsc::Receiver<Vec<WlSeat>>,
|
seat_rx: mpsc::Receiver<Vec<WlSeat>>,
|
||||||
#[cfg(feature = "clipboard")]
|
#[cfg(feature = "clipboard")]
|
||||||
clipboard_init_rx: mpsc::Receiver<Option<Arc<ClipboardItem>>>,
|
clipboard_init_rx: mpsc::Receiver<Option<Arc<ClipboardItem>>>,
|
||||||
@@ -74,10 +73,14 @@ impl WaylandClient {
|
|||||||
pub(super) fn new() -> Self {
|
pub(super) fn new() -> Self {
|
||||||
let (toplevel_tx, toplevel_rx) = broadcast::channel(32);
|
let (toplevel_tx, toplevel_rx) = broadcast::channel(32);
|
||||||
|
|
||||||
|
let mut output_channel = CachedBroadcastChannel::new(8);
|
||||||
|
let output_tx = output_channel.sender();
|
||||||
|
|
||||||
|
let tx2 = output_tx.clone();
|
||||||
|
|
||||||
let (toplevel_init_tx, toplevel_init_rx) = mpsc::channel();
|
let (toplevel_init_tx, toplevel_init_rx) = mpsc::channel();
|
||||||
#[cfg(feature = "clipboard")]
|
#[cfg(feature = "clipboard")]
|
||||||
let (clipboard_init_tx, clipboard_init_rx) = mpsc::channel();
|
let (clipboard_init_tx, clipboard_init_rx) = mpsc::channel();
|
||||||
let (output_tx, output_rx) = mpsc::channel();
|
|
||||||
let (seat_tx, seat_rx) = mpsc::channel();
|
let (seat_tx, seat_rx) = mpsc::channel();
|
||||||
|
|
||||||
let toplevel_tx2 = toplevel_tx.clone();
|
let toplevel_tx2 = toplevel_tx.clone();
|
||||||
@@ -99,6 +102,7 @@ impl WaylandClient {
|
|||||||
|
|
||||||
let conn =
|
let conn =
|
||||||
Connection::connect_to_env().expect("Failed to connect to Wayland compositor");
|
Connection::connect_to_env().expect("Failed to connect to Wayland compositor");
|
||||||
|
|
||||||
let (globals, queue) =
|
let (globals, queue) =
|
||||||
registry_queue_init(&conn).expect("Failed to retrieve Wayland globals");
|
registry_queue_init(&conn).expect("Failed to retrieve Wayland globals");
|
||||||
|
|
||||||
@@ -139,6 +143,7 @@ impl WaylandClient {
|
|||||||
handles: HashMap::new(),
|
handles: HashMap::new(),
|
||||||
#[cfg(feature = "clipboard")]
|
#[cfg(feature = "clipboard")]
|
||||||
clipboard: crate::arc_mut!(None),
|
clipboard: crate::arc_mut!(None),
|
||||||
|
output_tx,
|
||||||
toplevel_tx,
|
toplevel_tx,
|
||||||
#[cfg(feature = "clipboard")]
|
#[cfg(feature = "clipboard")]
|
||||||
clipboard_tx,
|
clipboard_tx,
|
||||||
@@ -156,11 +161,6 @@ impl WaylandClient {
|
|||||||
trace!("{event:?}");
|
trace!("{event:?}");
|
||||||
match event {
|
match event {
|
||||||
Event::Msg(Request::Roundtrip) => debug!("Received refresh event"),
|
Event::Msg(Request::Roundtrip) => debug!("Received refresh event"),
|
||||||
Event::Msg(Request::Outputs) => {
|
|
||||||
trace!("Received get outputs request");
|
|
||||||
|
|
||||||
send!(output_tx, env.output_info());
|
|
||||||
}
|
|
||||||
Event::Msg(Request::Seats) => {
|
Event::Msg(Request::Seats) => {
|
||||||
trace!("Receive get seats request");
|
trace!("Receive get seats request");
|
||||||
send!(seat_tx, env.seats.clone());
|
send!(seat_tx, env.seats.clone());
|
||||||
@@ -196,12 +196,12 @@ impl WaylandClient {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
output_channel,
|
||||||
toplevel_tx,
|
toplevel_tx,
|
||||||
_toplevel_rx: toplevel_rx,
|
_toplevel_rx: toplevel_rx,
|
||||||
toplevel_init_rx,
|
toplevel_init_rx,
|
||||||
#[cfg(feature = "clipboard")]
|
#[cfg(feature = "clipboard")]
|
||||||
clipboard_init_rx,
|
clipboard_init_rx,
|
||||||
output_rx,
|
|
||||||
seat_rx,
|
seat_rx,
|
||||||
#[cfg(feature = "clipboard")]
|
#[cfg(feature = "clipboard")]
|
||||||
clipboard_tx,
|
clipboard_tx,
|
||||||
@@ -242,6 +242,10 @@ impl WaylandClient {
|
|||||||
(rx, data)
|
(rx, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn subscribe_outputs(&mut self) -> cached_broadcast::Receiver<OutputInfo> {
|
||||||
|
self.output_channel.receiver()
|
||||||
|
}
|
||||||
|
|
||||||
/// Force a roundtrip on the wayland connection,
|
/// Force a roundtrip on the wayland connection,
|
||||||
/// flushing any queued events and immediately receiving any new ones.
|
/// flushing any queued events and immediately receiving any new ones.
|
||||||
pub fn roundtrip(&self) {
|
pub fn roundtrip(&self) {
|
||||||
@@ -249,11 +253,13 @@ impl WaylandClient {
|
|||||||
send!(self.request_tx, Request::Roundtrip);
|
send!(self.request_tx, Request::Roundtrip);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_outputs(&self) -> Vec<OutputInfo> {
|
/// Gets a list of all outputs.
|
||||||
trace!("Sending get outputs request");
|
///
|
||||||
|
/// This should only be used in a scenario
|
||||||
send!(self.request_tx, Request::Outputs);
|
/// where you need a snapshot of outputs at the current time.
|
||||||
self.output_rx.recv().expect(ERR_CHANNEL_RECV)
|
/// Prefer to listen to output events with `subscribe_output` where possible.
|
||||||
|
pub fn get_outputs(&self) -> &Vec<OutputInfo> {
|
||||||
|
self.output_channel.data()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_seats(&self) -> Vec<WlSeat> {
|
pub fn get_seats(&self) -> Vec<WlSeat> {
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ mod wl_seat;
|
|||||||
mod wlr_foreign_toplevel;
|
mod wlr_foreign_toplevel;
|
||||||
|
|
||||||
use self::wlr_foreign_toplevel::manager::ToplevelManagerState;
|
use self::wlr_foreign_toplevel::manager::ToplevelManagerState;
|
||||||
use crate::{arc_mut, delegate_foreign_toplevel_handle, delegate_foreign_toplevel_manager};
|
use crate::{arc_mut, cached_broadcast, delegate_foreign_toplevel_handle, delegate_foreign_toplevel_manager};
|
||||||
use cfg_if::cfg_if;
|
use cfg_if::cfg_if;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use smithay_client_toolkit::output::OutputState;
|
use smithay_client_toolkit::output::{OutputInfo, OutputState};
|
||||||
use smithay_client_toolkit::reexports::calloop::LoopHandle;
|
use smithay_client_toolkit::reexports::calloop::LoopHandle;
|
||||||
use smithay_client_toolkit::registry::{ProvidesRegistryState, RegistryState};
|
use smithay_client_toolkit::registry::{ProvidesRegistryState, RegistryState};
|
||||||
use smithay_client_toolkit::seat::SeatState;
|
use smithay_client_toolkit::seat::SeatState;
|
||||||
@@ -65,6 +65,7 @@ pub struct Environment {
|
|||||||
#[cfg(feature = "clipboard")]
|
#[cfg(feature = "clipboard")]
|
||||||
clipboard: Arc<Mutex<Option<Arc<ClipboardItem>>>>,
|
clipboard: Arc<Mutex<Option<Arc<ClipboardItem>>>>,
|
||||||
|
|
||||||
|
output_tx: cached_broadcast::Sender<OutputInfo>,
|
||||||
toplevel_tx: broadcast::Sender<ToplevelEvent>,
|
toplevel_tx: broadcast::Sender<ToplevelEvent>,
|
||||||
#[cfg(feature = "clipboard")]
|
#[cfg(feature = "clipboard")]
|
||||||
clipboard_tx: broadcast::Sender<Arc<ClipboardItem>>,
|
clipboard_tx: broadcast::Sender<Arc<ClipboardItem>>,
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
use super::Environment;
|
use super::Environment;
|
||||||
|
use crate::cached_broadcast::Cacheable;
|
||||||
|
use crate::{cached_broadcast, try_send};
|
||||||
use smithay_client_toolkit::output::{OutputHandler, OutputInfo, OutputState};
|
use smithay_client_toolkit::output::{OutputHandler, OutputInfo, OutputState};
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
use wayland_client::protocol::wl_output;
|
use wayland_client::protocol::wl_output;
|
||||||
@@ -31,9 +33,12 @@ impl OutputHandler for Environment {
|
|||||||
&mut self,
|
&mut self,
|
||||||
_conn: &Connection,
|
_conn: &Connection,
|
||||||
_qh: &QueueHandle<Self>,
|
_qh: &QueueHandle<Self>,
|
||||||
_output: wl_output::WlOutput,
|
output: wl_output::WlOutput,
|
||||||
) {
|
) {
|
||||||
debug!("Handler received new output");
|
debug!("Handler received new output");
|
||||||
|
if let Some(info) = self.output_state.info(&output) {
|
||||||
|
try_send!(self.output_tx, cached_broadcast::Event::Add(info));
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_output(
|
fn update_output(
|
||||||
@@ -42,14 +47,26 @@ impl OutputHandler for Environment {
|
|||||||
_qh: &QueueHandle<Self>,
|
_qh: &QueueHandle<Self>,
|
||||||
_output: wl_output::WlOutput,
|
_output: wl_output::WlOutput,
|
||||||
) {
|
) {
|
||||||
|
debug!("Handle received output update");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn output_destroyed(
|
fn output_destroyed(
|
||||||
&mut self,
|
&mut self,
|
||||||
_conn: &Connection,
|
_conn: &Connection,
|
||||||
_qh: &QueueHandle<Self>,
|
_qh: &QueueHandle<Self>,
|
||||||
_output: wl_output::WlOutput,
|
output: wl_output::WlOutput,
|
||||||
) {
|
) {
|
||||||
debug!("Handle received output destruction");
|
debug!("Handle received output destruction");
|
||||||
|
if let Some(info) = self.output_state.info(&output) {
|
||||||
|
try_send!(self.output_tx, cached_broadcast::Event::Remove(info.id));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Cacheable for OutputInfo {
|
||||||
|
type Key = u32;
|
||||||
|
|
||||||
|
fn get_key(&self) -> Self::Key {
|
||||||
|
self.id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use crate::{lock, send};
|
|||||||
use device::DataControlDevice;
|
use device::DataControlDevice;
|
||||||
use glib::Bytes;
|
use glib::Bytes;
|
||||||
use nix::fcntl::{fcntl, F_GETPIPE_SZ, F_SETPIPE_SZ};
|
use nix::fcntl::{fcntl, F_GETPIPE_SZ, F_SETPIPE_SZ};
|
||||||
use nix::sys::epoll::{epoll_create, epoll_ctl, epoll_wait, EpollEvent, EpollFlags, EpollOp};
|
use nix::sys::epoll::{Epoll, EpollCreateFlags, EpollEvent, EpollFlags};
|
||||||
use smithay_client_toolkit::data_device_manager::WritePipe;
|
use smithay_client_toolkit::data_device_manager::WritePipe;
|
||||||
use smithay_client_toolkit::reexports::calloop::RegistrationToken;
|
use smithay_client_toolkit::reexports::calloop::RegistrationToken;
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
@@ -289,23 +289,22 @@ impl DataControlSourceHandler for Environment {
|
|||||||
trace!("Num bytes: {}", bytes.len());
|
trace!("Num bytes: {}", bytes.len());
|
||||||
|
|
||||||
let mut events = (0..16).map(|_| EpollEvent::empty()).collect::<Vec<_>>();
|
let mut events = (0..16).map(|_| EpollEvent::empty()).collect::<Vec<_>>();
|
||||||
let mut epoll_event = EpollEvent::new(EpollFlags::EPOLLOUT, 0);
|
let epoll_event = EpollEvent::new(EpollFlags::EPOLLOUT, 0);
|
||||||
|
|
||||||
let epoll_fd = epoll_create().expect("to get valid file descriptor");
|
let epoll_fd =
|
||||||
epoll_ctl(
|
Epoll::new(EpollCreateFlags::empty()).expect("to get valid file descriptor");
|
||||||
epoll_fd,
|
epoll_fd
|
||||||
EpollOp::EpollCtlAdd,
|
.add(fd, epoll_event)
|
||||||
fd.as_raw_fd(),
|
.expect("to send valid epoll operation");
|
||||||
&mut epoll_event,
|
|
||||||
)
|
|
||||||
.expect("to send valid epoll operation");
|
|
||||||
|
|
||||||
while !bytes.is_empty() {
|
while !bytes.is_empty() {
|
||||||
let chunk = &bytes[..min(pipe_size as usize, bytes.len())];
|
let chunk = &bytes[..min(pipe_size as usize, bytes.len())];
|
||||||
|
|
||||||
trace!("Writing {} bytes ({} remain)", chunk.len(), bytes.len());
|
trace!("Writing {} bytes ({} remain)", chunk.len(), bytes.len());
|
||||||
|
|
||||||
epoll_wait(epoll_fd, &mut events, 100).expect("Failed to wait to epoll");
|
epoll_fd
|
||||||
|
.wait(&mut events, 100)
|
||||||
|
.expect("Failed to wait to epoll");
|
||||||
|
|
||||||
match file.write(chunk) {
|
match file.write(chunk) {
|
||||||
Ok(_) => bytes = &bytes[chunk.len()..],
|
Ok(_) => bytes = &bytes[chunk.len()..],
|
||||||
|
|||||||
@@ -109,7 +109,9 @@ fn find_desktop_file_by_filedata(app_id: &str, files: &[PathBuf]) -> Option<Path
|
|||||||
let files = files
|
let files = files
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|file| {
|
.filter_map(|file| {
|
||||||
let Some(parsed_desktop_file) = parse_desktop_file(file) else { return None };
|
let Some(parsed_desktop_file) = parse_desktop_file(file) else {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
desktop_files_cache.insert(file.clone(), parsed_desktop_file.clone());
|
desktop_files_cache.insert(file.clone(), parsed_desktop_file.clone());
|
||||||
Some((file.clone(), parsed_desktop_file))
|
Some((file.clone(), parsed_desktop_file))
|
||||||
@@ -162,7 +164,9 @@ fn parse_desktop_file(path: &Path) -> Option<DesktopFile> {
|
|||||||
|
|
||||||
file.lines()
|
file.lines()
|
||||||
.filter_map(|line| {
|
.filter_map(|line| {
|
||||||
let Some((key, value)) = line.split_once('=') else { return None };
|
let Some((key, value)) = line.split_once('=') else {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
let key = key.trim();
|
let key = key.trim();
|
||||||
let value = value.trim();
|
let value = value.trim();
|
||||||
@@ -185,7 +189,9 @@ fn parse_desktop_file(path: &Path) -> Option<DesktopFile> {
|
|||||||
|
|
||||||
/// Attempts to get the icon name from the app's `.desktop` file.
|
/// Attempts to get the icon name from the app's `.desktop` file.
|
||||||
pub fn get_desktop_icon_name(app_id: &str) -> Option<String> {
|
pub fn get_desktop_icon_name(app_id: &str) -> Option<String> {
|
||||||
let Some(path) = find_desktop_file(app_id) else { return None };
|
let Some(path) = find_desktop_file(app_id) else {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
let mut desktop_files_cache = lock!(DESKTOP_FILES);
|
let mut desktop_files_cache = lock!(DESKTOP_FILES);
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::popup::Popup;
|
use crate::popup::Popup;
|
||||||
use crate::write_lock;
|
use std::cell::{RefCell, RefMut};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::{Arc, RwLock, RwLockWriteGuard};
|
use std::rc::Rc;
|
||||||
|
|
||||||
/// Global application state shared across all bars.
|
/// Global application state shared across all bars.
|
||||||
///
|
///
|
||||||
@@ -9,7 +9,7 @@ use std::sync::{Arc, RwLock, RwLockWriteGuard};
|
|||||||
/// that is not otherwise accessible should be placed on here.
|
/// that is not otherwise accessible should be placed on here.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct GlobalState {
|
pub struct GlobalState {
|
||||||
popups: HashMap<Box<str>, Arc<RwLock<Popup>>>,
|
popups: HashMap<Box<str>, Rc<RefCell<Popup>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GlobalState {
|
impl GlobalState {
|
||||||
@@ -19,22 +19,22 @@ impl GlobalState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn popups(&self) -> &HashMap<Box<str>, Arc<RwLock<Popup>>> {
|
pub fn popups(&self) -> &HashMap<Box<str>, Rc<RefCell<Popup>>> {
|
||||||
&self.popups
|
&self.popups
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn popups_mut(&mut self) -> &mut HashMap<Box<str>, Arc<RwLock<Popup>>> {
|
pub fn popups_mut(&mut self) -> &mut HashMap<Box<str>, Rc<RefCell<Popup>>> {
|
||||||
&mut self.popups
|
&mut self.popups
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_popup_mut<F, T>(&self, monitor_name: &str, f: F) -> Option<T>
|
pub fn with_popup_mut<F, T>(&self, monitor_name: &str, f: F) -> Option<T>
|
||||||
where
|
where
|
||||||
F: FnOnce(RwLockWriteGuard<Popup>) -> T,
|
F: FnOnce(RefMut<Popup>) -> T,
|
||||||
{
|
{
|
||||||
let popup = self.popups().get(monitor_name);
|
let popup = self.popups().get(monitor_name);
|
||||||
|
|
||||||
if let Some(popup) = popup {
|
if let Some(popup) = popup {
|
||||||
let popup = write_lock!(popup);
|
let popup = popup.borrow_mut();
|
||||||
Some(f(popup))
|
Some(f(popup))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ use crate::ipc::{Command, Response};
|
|||||||
use crate::ironvar::get_variable_manager;
|
use crate::ironvar::get_variable_manager;
|
||||||
use crate::modules::PopupButton;
|
use crate::modules::PopupButton;
|
||||||
use crate::style::load_css;
|
use crate::style::load_css;
|
||||||
use crate::{read_lock, send_async, try_send, write_lock, GlobalState};
|
use crate::{await_sync, read_lock, send_async, try_send, write_lock, GlobalState};
|
||||||
|
|
||||||
use super::Ipc;
|
use super::Ipc;
|
||||||
|
|
||||||
@@ -123,14 +123,7 @@ impl Ipc {
|
|||||||
Response::Ok
|
Response::Ok
|
||||||
}
|
}
|
||||||
Command::Reload => {
|
Command::Reload => {
|
||||||
info!("Closing existing bars");
|
await_sync(async move { crate::reload(application, global_state).await }).unwrap();
|
||||||
let windows = application.windows();
|
|
||||||
for window in windows {
|
|
||||||
window.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
crate::load_interface(application, global_state);
|
|
||||||
|
|
||||||
Response::Ok
|
Response::Ok
|
||||||
}
|
}
|
||||||
Command::Set { key, value } => {
|
Command::Set { key, value } => {
|
||||||
|
|||||||
210
src/main.rs
210
src/main.rs
@@ -14,10 +14,12 @@ use clap::Parser;
|
|||||||
use color_eyre::eyre::Result;
|
use color_eyre::eyre::Result;
|
||||||
use color_eyre::Report;
|
use color_eyre::Report;
|
||||||
use dirs::config_dir;
|
use dirs::config_dir;
|
||||||
use gtk::gdk::Display;
|
use gtk::gdk::{Display, Monitor};
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::Application;
|
use gtk::Application;
|
||||||
|
use smithay_client_toolkit::output::OutputInfo;
|
||||||
use tokio::runtime::Handle;
|
use tokio::runtime::Handle;
|
||||||
|
use tokio::spawn;
|
||||||
use tokio::task::{block_in_place, spawn_blocking};
|
use tokio::task::{block_in_place, spawn_blocking};
|
||||||
use tracing::{debug, error, info, warn};
|
use tracing::{debug, error, info, warn};
|
||||||
use universal_config::ConfigLoader;
|
use universal_config::ConfigLoader;
|
||||||
@@ -25,6 +27,8 @@ use universal_config::ConfigLoader;
|
|||||||
use clients::wayland;
|
use clients::wayland;
|
||||||
|
|
||||||
use crate::bar::create_bar;
|
use crate::bar::create_bar;
|
||||||
|
use crate::bridge_channel::BridgeChannel;
|
||||||
|
use crate::cached_broadcast::Event;
|
||||||
use crate::config::{Config, MonitorConfig};
|
use crate::config::{Config, MonitorConfig};
|
||||||
use crate::error::ExitCode;
|
use crate::error::ExitCode;
|
||||||
use crate::global_state::GlobalState;
|
use crate::global_state::GlobalState;
|
||||||
@@ -32,6 +36,7 @@ use crate::style::load_css;
|
|||||||
|
|
||||||
mod bar;
|
mod bar;
|
||||||
mod bridge_channel;
|
mod bridge_channel;
|
||||||
|
mod cached_broadcast;
|
||||||
#[cfg(feature = "cli")]
|
#[cfg(feature = "cli")]
|
||||||
mod cli;
|
mod cli;
|
||||||
mod clients;
|
mod clients;
|
||||||
@@ -84,19 +89,22 @@ async fn run_with_args(global_state: Rc<RefCell<GlobalState>>) {
|
|||||||
Err(err) => error!("{err:?}"),
|
Err(err) => error!("{err:?}"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
None => start_ironbar(global_state),
|
None => start_ironbar(global_state).await,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start_ironbar(global_state: Rc<RefCell<GlobalState>>) {
|
async fn start_ironbar(global_state: Rc<RefCell<GlobalState>>) {
|
||||||
info!("Ironbar version {}", VERSION);
|
info!("Ironbar version {}", VERSION);
|
||||||
info!("Starting application");
|
info!("Starting application");
|
||||||
|
|
||||||
let app = Application::builder().application_id(GTK_APP_ID).build();
|
let app = Application::builder().application_id(GTK_APP_ID).build();
|
||||||
let _ = wayland::get_client(); // force-init
|
|
||||||
|
let output_bridge = BridgeChannel::<Event<OutputInfo>>::new();
|
||||||
|
let output_tx = output_bridge.create_sender();
|
||||||
|
|
||||||
let running = Rc::new(Cell::new(false));
|
let running = Rc::new(Cell::new(false));
|
||||||
|
|
||||||
|
let global_state2 = global_state.clone();
|
||||||
app.connect_activate(move |app| {
|
app.connect_activate(move |app| {
|
||||||
if running.get() {
|
if running.get() {
|
||||||
info!("Ironbar already running, returning");
|
info!("Ironbar already running, returning");
|
||||||
@@ -107,13 +115,11 @@ fn start_ironbar(global_state: Rc<RefCell<GlobalState>>) {
|
|||||||
|
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(feature = "ipc")] {
|
if #[cfg(feature = "ipc")] {
|
||||||
let ipc = ipc::Ipc::new(global_state.clone());
|
let ipc = ipc::Ipc::new(global_state2.clone());
|
||||||
ipc.start(app);
|
ipc.start(app);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
load_interface(app, &global_state);
|
|
||||||
|
|
||||||
let style_path = env::var("IRONBAR_CSS").ok().map_or_else(
|
let style_path = env::var("IRONBAR_CSS").ok().map_or_else(
|
||||||
|| {
|
|| {
|
||||||
config_dir().map_or_else(
|
config_dir().map_or_else(
|
||||||
@@ -147,27 +153,131 @@ fn start_ironbar(global_state: Rc<RefCell<GlobalState>>) {
|
|||||||
exit(0);
|
exit(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
ctrlc::set_handler(move || tx.send(()).expect("Could not send signal on channel."))
|
let wc = wayland::get_client();
|
||||||
.expect("Error setting Ctrl-C handler");
|
|
||||||
|
let output_tx = output_tx.clone();
|
||||||
|
let mut output_rx = lock!(wc).subscribe_outputs();
|
||||||
|
|
||||||
|
spawn(async move {
|
||||||
|
while let Some(event) = output_rx.recv().await {
|
||||||
|
try_send!(output_tx.clone(), event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ctrlc::set_handler(move || send!(tx, ())).expect("Error setting Ctrl-C handler");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let config = load_config();
|
||||||
|
|
||||||
|
{
|
||||||
|
let app = app.clone();
|
||||||
|
let global_state = global_state.clone();
|
||||||
|
|
||||||
|
output_bridge.recv(move |event: cached_broadcast::Event<_>| {
|
||||||
|
let display = get_display();
|
||||||
|
match event {
|
||||||
|
Event::Add(output) => {
|
||||||
|
debug!("Adding bar(s) for monitor {:?}", &output.name);
|
||||||
|
create_bars_for_monitor(&app, &display, &output, config.clone(), &global_state)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
// TODO: Implement
|
||||||
|
Event::Remove(_) => {}
|
||||||
|
Event::Replace(_, _) => {}
|
||||||
|
}
|
||||||
|
Continue(true)
|
||||||
|
});
|
||||||
|
}
|
||||||
// Ignore CLI args
|
// Ignore CLI args
|
||||||
// Some are provided by swaybar_config but not currently supported
|
// Some are provided by swaybar_config but not currently supported
|
||||||
app.run_with_args(&Vec::<&str>::new());
|
app.run_with_args(&Vec::<&str>::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Loads the Ironbar config and interface.
|
/// Closes all current bars and entirely reloads Ironbar.
|
||||||
pub fn load_interface(app: &Application, global_state: &Rc<RefCell<GlobalState>>) {
|
/// This re-reads the config file.
|
||||||
let display = Display::default().map_or_else(
|
pub async fn reload(app: &Application, global_state: &Rc<RefCell<GlobalState>>) -> Result<()> {
|
||||||
|
info!("Closing existing bars");
|
||||||
|
let windows = app.windows();
|
||||||
|
for window in windows {
|
||||||
|
window.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
let config = load_config();
|
||||||
|
|
||||||
|
let wl = wayland::get_client();
|
||||||
|
let wl = lock!(wl);
|
||||||
|
let outputs = wl.get_outputs();
|
||||||
|
|
||||||
|
let display = get_display();
|
||||||
|
for output in outputs.iter() {
|
||||||
|
create_bars_for_monitor(app, &display, output, config.clone(), global_state)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn create_bars_for_monitor(
|
||||||
|
app: &Application,
|
||||||
|
display: &Display,
|
||||||
|
output: &OutputInfo,
|
||||||
|
config: Config,
|
||||||
|
global_state: &Rc<RefCell<GlobalState>>,
|
||||||
|
) -> Result<()> {
|
||||||
|
let Some(monitor_name) = &output.name else {
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
|
||||||
|
let monitor = match get_monitor(&monitor_name, display) {
|
||||||
|
Ok(monitor) => monitor,
|
||||||
|
Err(err) => return Err(err),
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(monitor_config) = config.get_monitor_config(&monitor_name) else {
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
|
||||||
|
match monitor_config {
|
||||||
|
MonitorConfig::Single(config) => {
|
||||||
|
create_bar(&app, &monitor, &monitor_name, config, global_state)
|
||||||
|
}
|
||||||
|
MonitorConfig::Multiple(configs) => configs
|
||||||
|
.into_iter()
|
||||||
|
.map(|config| create_bar(&app, &monitor, &monitor_name, config, global_state))
|
||||||
|
.collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn get_display() -> Display {
|
||||||
|
Display::default().map_or_else(
|
||||||
|| {
|
|| {
|
||||||
let report = Report::msg("Failed to get default GTK display");
|
let report = Report::msg("Failed to get default GTK display");
|
||||||
error!("{:?}", report);
|
error!("{:?}", report);
|
||||||
exit(ExitCode::GtkDisplay as i32)
|
exit(ExitCode::GtkDisplay as i32)
|
||||||
},
|
},
|
||||||
|display| display,
|
|display| display,
|
||||||
);
|
)
|
||||||
|
}
|
||||||
|
|
||||||
let mut config = env::var("IRONBAR_CONFIG")
|
fn get_monitor(name: &str, display: &Display) -> Result<Monitor> {
|
||||||
|
let wl = wayland::get_client();
|
||||||
|
let wl = lock!(wl);
|
||||||
|
let outputs = wl.get_outputs();
|
||||||
|
|
||||||
|
let monitor = (0..display.n_monitors()).into_iter().find_map(|i| {
|
||||||
|
let monitor = display.monitor(i)?;
|
||||||
|
let output = outputs.get(i as usize)?;
|
||||||
|
|
||||||
|
let is_match = output.name.as_ref().map(|n| n == name).unwrap_or_default();
|
||||||
|
if is_match {
|
||||||
|
Some(monitor)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
monitor.ok_or_else(|| Report::msg(error::ERR_OUTPUTS))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_config() -> Config {
|
||||||
|
let config = env::var("IRONBAR_CONFIG")
|
||||||
.map_or_else(
|
.map_or_else(
|
||||||
|_| ConfigLoader::new("ironbar").find_and_load(),
|
|_| ConfigLoader::new("ironbar").find_and_load(),
|
||||||
ConfigLoader::load,
|
ConfigLoader::load,
|
||||||
@@ -182,77 +292,7 @@ pub fn load_interface(app: &Application, global_state: &Rc<RefCell<GlobalState>>
|
|||||||
});
|
});
|
||||||
|
|
||||||
debug!("Loaded config file");
|
debug!("Loaded config file");
|
||||||
|
config
|
||||||
#[cfg(feature = "ipc")]
|
|
||||||
if let Some(ironvars) = config.ironvar_defaults.take() {
|
|
||||||
let variable_manager = ironvar::get_variable_manager();
|
|
||||||
for (k, v) in ironvars {
|
|
||||||
if write_lock!(variable_manager).set(k.clone(), v).is_err() {
|
|
||||||
warn!("Ignoring invalid ironvar: '{k}'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Err(err) = create_bars(app, &display, &config, global_state) {
|
|
||||||
error!("{:?}", err);
|
|
||||||
exit(ExitCode::CreateBars as i32);
|
|
||||||
}
|
|
||||||
|
|
||||||
debug!("Created bars");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates each of the bars across each of the (configured) outputs.
|
|
||||||
fn create_bars(
|
|
||||||
app: &Application,
|
|
||||||
display: &Display,
|
|
||||||
config: &Config,
|
|
||||||
global_state: &Rc<RefCell<GlobalState>>,
|
|
||||||
) -> Result<()> {
|
|
||||||
let wl = wayland::get_client();
|
|
||||||
let outputs = lock!(wl).get_outputs();
|
|
||||||
|
|
||||||
debug!("Received {} outputs from Wayland", outputs.len());
|
|
||||||
debug!("Outputs: {:?}", outputs);
|
|
||||||
|
|
||||||
let num_monitors = display.n_monitors();
|
|
||||||
|
|
||||||
for i in 0..num_monitors {
|
|
||||||
let monitor = display
|
|
||||||
.monitor(i)
|
|
||||||
.ok_or_else(|| Report::msg(error::ERR_OUTPUTS))?;
|
|
||||||
let output = outputs
|
|
||||||
.get(i as usize)
|
|
||||||
.ok_or_else(|| Report::msg(error::ERR_OUTPUTS))?;
|
|
||||||
|
|
||||||
let Some(monitor_name) = &output.name else { continue };
|
|
||||||
|
|
||||||
config.monitors.as_ref().map_or_else(
|
|
||||||
|| {
|
|
||||||
info!("Creating bar on '{}'", monitor_name);
|
|
||||||
create_bar(app, &monitor, monitor_name, config.clone(), global_state)
|
|
||||||
},
|
|
||||||
|config| {
|
|
||||||
let config = config.get(monitor_name);
|
|
||||||
match &config {
|
|
||||||
Some(MonitorConfig::Single(config)) => {
|
|
||||||
info!("Creating bar on '{}'", monitor_name);
|
|
||||||
create_bar(app, &monitor, monitor_name, config.clone(), global_state)
|
|
||||||
}
|
|
||||||
Some(MonitorConfig::Multiple(configs)) => {
|
|
||||||
for config in configs {
|
|
||||||
info!("Creating bar on '{}'", monitor_name);
|
|
||||||
create_bar(app, &monitor, monitor_name, config.clone(), global_state)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
_ => Ok(()),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Blocks on a `Future` until it resolves.
|
/// Blocks on a `Future` until it resolves.
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use std::sync::{Arc, RwLock};
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
use glib::IsA;
|
use glib::IsA;
|
||||||
@@ -12,7 +13,7 @@ use crate::bridge_channel::BridgeChannel;
|
|||||||
use crate::config::{BarPosition, CommonConfig, TransitionType};
|
use crate::config::{BarPosition, CommonConfig, TransitionType};
|
||||||
use crate::gtk_helpers::{IronbarGtkExt, WidgetGeometry};
|
use crate::gtk_helpers::{IronbarGtkExt, WidgetGeometry};
|
||||||
use crate::popup::Popup;
|
use crate::popup::Popup;
|
||||||
use crate::{send, write_lock};
|
use crate::send;
|
||||||
|
|
||||||
#[cfg(feature = "clipboard")]
|
#[cfg(feature = "clipboard")]
|
||||||
pub mod clipboard;
|
pub mod clipboard;
|
||||||
@@ -178,7 +179,7 @@ pub fn create_module<TModule, TWidget, TSend, TRec>(
|
|||||||
id: usize,
|
id: usize,
|
||||||
name: Option<String>,
|
name: Option<String>,
|
||||||
info: &ModuleInfo,
|
info: &ModuleInfo,
|
||||||
popup: &Arc<RwLock<Popup>>,
|
popup: &Rc<RefCell<Popup>>,
|
||||||
) -> Result<ModuleParts<TWidget>>
|
) -> Result<ModuleParts<TWidget>>
|
||||||
where
|
where
|
||||||
TModule: Module<TWidget, SendMessage = TSend, ReceiveMessage = TRec>,
|
TModule: Module<TWidget, SendMessage = TSend, ReceiveMessage = TRec>,
|
||||||
@@ -205,7 +206,8 @@ where
|
|||||||
let instance_name = name.unwrap_or_else(|| module_name.to_string());
|
let instance_name = name.unwrap_or_else(|| module_name.to_string());
|
||||||
|
|
||||||
let module_parts = module.into_widget(context, info)?;
|
let module_parts = module.into_widget(context, info)?;
|
||||||
module_parts.widget.style_context().add_class(module_name);
|
module_parts.widget.add_class("widget");
|
||||||
|
module_parts.widget.add_class(module_name);
|
||||||
|
|
||||||
let has_popup = if let Some(popup_content) = module_parts.popup.clone() {
|
let has_popup = if let Some(popup_content) = module_parts.popup.clone() {
|
||||||
popup_content
|
popup_content
|
||||||
@@ -234,12 +236,12 @@ where
|
|||||||
|
|
||||||
/// Registers the popup content with the popup.
|
/// Registers the popup content with the popup.
|
||||||
fn register_popup_content(
|
fn register_popup_content(
|
||||||
popup: &Arc<RwLock<Popup>>,
|
popup: &Rc<RefCell<Popup>>,
|
||||||
id: usize,
|
id: usize,
|
||||||
name: String,
|
name: String,
|
||||||
popup_content: ModulePopupParts,
|
popup_content: ModulePopupParts,
|
||||||
) {
|
) {
|
||||||
write_lock!(popup).register_content(id, name, popup_content);
|
popup.borrow_mut().register_content(id, name, popup_content);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets up the bridge channel receiver
|
/// Sets up the bridge channel receiver
|
||||||
@@ -251,7 +253,7 @@ fn setup_receiver<TSend>(
|
|||||||
channel: BridgeChannel<ModuleUpdateEvent<TSend>>,
|
channel: BridgeChannel<ModuleUpdateEvent<TSend>>,
|
||||||
w_tx: glib::Sender<TSend>,
|
w_tx: glib::Sender<TSend>,
|
||||||
p_tx: glib::Sender<TSend>,
|
p_tx: glib::Sender<TSend>,
|
||||||
popup: Arc<RwLock<Popup>>,
|
popup: Rc<RefCell<Popup>>,
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
id: usize,
|
id: usize,
|
||||||
has_popup: bool,
|
has_popup: bool,
|
||||||
@@ -273,7 +275,7 @@ fn setup_receiver<TSend>(
|
|||||||
}
|
}
|
||||||
ModuleUpdateEvent::TogglePopup(button_id) => {
|
ModuleUpdateEvent::TogglePopup(button_id) => {
|
||||||
debug!("Toggling popup for {} [#{}]", name, id);
|
debug!("Toggling popup for {} [#{}]", name, id);
|
||||||
let mut popup = write_lock!(popup);
|
let mut popup = popup.borrow_mut();
|
||||||
if popup.is_visible() {
|
if popup.is_visible() {
|
||||||
popup.hide();
|
popup.hide();
|
||||||
} else {
|
} else {
|
||||||
@@ -289,7 +291,7 @@ fn setup_receiver<TSend>(
|
|||||||
ModuleUpdateEvent::OpenPopup(button_id) => {
|
ModuleUpdateEvent::OpenPopup(button_id) => {
|
||||||
debug!("Opening popup for {} [#{}]", name, id);
|
debug!("Opening popup for {} [#{}]", name, id);
|
||||||
|
|
||||||
let mut popup = write_lock!(popup);
|
let mut popup = popup.borrow_mut();
|
||||||
popup.hide();
|
popup.hide();
|
||||||
popup.show(id, button_id);
|
popup.show(id, button_id);
|
||||||
|
|
||||||
@@ -302,7 +304,7 @@ fn setup_receiver<TSend>(
|
|||||||
ModuleUpdateEvent::OpenPopupAt(geometry) => {
|
ModuleUpdateEvent::OpenPopupAt(geometry) => {
|
||||||
debug!("Opening popup for {} [#{}]", name, id);
|
debug!("Opening popup for {} [#{}]", name, id);
|
||||||
|
|
||||||
let mut popup = write_lock!(popup);
|
let mut popup = popup.borrow_mut();
|
||||||
popup.hide();
|
popup.hide();
|
||||||
popup.show_at(id, geometry);
|
popup.show_at(id, geometry);
|
||||||
|
|
||||||
@@ -315,7 +317,7 @@ fn setup_receiver<TSend>(
|
|||||||
ModuleUpdateEvent::ClosePopup => {
|
ModuleUpdateEvent::ClosePopup => {
|
||||||
debug!("Closing popup for {} [#{}]", name, id);
|
debug!("Closing popup for {} [#{}]", name, id);
|
||||||
|
|
||||||
let mut popup = write_lock!(popup);
|
let mut popup = popup.borrow_mut();
|
||||||
popup.hide();
|
popup.hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -375,6 +377,8 @@ pub fn wrap_widget<W: IsA<Widget>>(
|
|||||||
revealer.set_reveal_child(true);
|
revealer.set_reveal_child(true);
|
||||||
|
|
||||||
let container = EventBox::new();
|
let container = EventBox::new();
|
||||||
|
container.add_class("widget-container");
|
||||||
|
|
||||||
container.add_events(EventMask::SCROLL_MASK);
|
container.add_events(EventMask::SCROLL_MASK);
|
||||||
container.add(&revealer);
|
container.add(&revealer);
|
||||||
|
|
||||||
|
|||||||
@@ -216,7 +216,9 @@ impl Module<Button> for MusicModule {
|
|||||||
let tx = context.tx.clone();
|
let tx = context.tx.clone();
|
||||||
|
|
||||||
context.widget_rx.attach(None, move |event| {
|
context.widget_rx.attach(None, move |event| {
|
||||||
let ControllerEvent::Update(mut event) = event else { return Continue(true) };
|
let ControllerEvent::Update(mut event) = event else {
|
||||||
|
return Continue(true);
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(event) = event.take() {
|
if let Some(event) = event.take() {
|
||||||
label.set_label(&event.display_string);
|
label.set_label(&event.display_string);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::clients::compositor::{Compositor, Workspace, WorkspaceUpdate};
|
use crate::clients::compositor::{Compositor, Visibility, Workspace, WorkspaceUpdate};
|
||||||
use crate::config::CommonConfig;
|
use crate::config::CommonConfig;
|
||||||
use crate::image::new_icon_button;
|
use crate::image::new_icon_button;
|
||||||
use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext};
|
use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext};
|
||||||
@@ -76,8 +76,7 @@ const fn default_icon_size() -> i32 {
|
|||||||
/// Creates a button from a workspace
|
/// Creates a button from a workspace
|
||||||
fn create_button(
|
fn create_button(
|
||||||
name: &str,
|
name: &str,
|
||||||
focused: bool,
|
visibility: Visibility,
|
||||||
inactive: bool,
|
|
||||||
name_map: &HashMap<String, String>,
|
name_map: &HashMap<String, String>,
|
||||||
icon_theme: &IconTheme,
|
icon_theme: &IconTheme,
|
||||||
icon_size: i32,
|
icon_size: i32,
|
||||||
@@ -91,10 +90,12 @@ fn create_button(
|
|||||||
let style_context = button.style_context();
|
let style_context = button.style_context();
|
||||||
style_context.add_class("item");
|
style_context.add_class("item");
|
||||||
|
|
||||||
if focused {
|
if visibility.is_visible() {
|
||||||
|
style_context.add_class("visible");
|
||||||
|
}
|
||||||
|
|
||||||
|
if visibility.is_focused() {
|
||||||
style_context.add_class("focused");
|
style_context.add_class("focused");
|
||||||
} else if inactive {
|
|
||||||
style_context.add_class("inactive");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -131,7 +132,7 @@ fn reorder_workspaces(container: >k::Box) {
|
|||||||
|
|
||||||
impl WorkspacesModule {
|
impl WorkspacesModule {
|
||||||
fn show_workspace_check(&self, output: &String, work: &Workspace) -> bool {
|
fn show_workspace_check(&self, output: &String, work: &Workspace) -> bool {
|
||||||
(work.focused || !self.hidden.contains(&work.name))
|
(work.visibility.is_focused() || !self.hidden.contains(&work.name))
|
||||||
&& (self.all_monitors || output == &work.monitor)
|
&& (self.all_monitors || output == &work.monitor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -212,11 +213,10 @@ impl Module<gtk::Box> for WorkspacesModule {
|
|||||||
|
|
||||||
let mut added = HashSet::new();
|
let mut added = HashSet::new();
|
||||||
|
|
||||||
let mut add_workspace = |name: &str, focused: bool| {
|
let mut add_workspace = |name: &str, visibility: Visibility| {
|
||||||
let item = create_button(
|
let item = create_button(
|
||||||
name,
|
name,
|
||||||
focused,
|
visibility,
|
||||||
false,
|
|
||||||
&name_map,
|
&name_map,
|
||||||
&icon_theme,
|
&icon_theme,
|
||||||
icon_size,
|
icon_size,
|
||||||
@@ -230,7 +230,7 @@ impl Module<gtk::Box> for WorkspacesModule {
|
|||||||
// add workspaces from client
|
// add workspaces from client
|
||||||
for workspace in &workspaces {
|
for workspace in &workspaces {
|
||||||
if self.show_workspace_check(&output_name, workspace) {
|
if self.show_workspace_check(&output_name, workspace) {
|
||||||
add_workspace(&workspace.name, workspace.focused);
|
add_workspace(&workspace.name, workspace.visibility);
|
||||||
added.insert(workspace.name.to_string());
|
added.insert(workspace.name.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -238,7 +238,7 @@ impl Module<gtk::Box> for WorkspacesModule {
|
|||||||
let mut add_favourites = |names: &Vec<String>| {
|
let mut add_favourites = |names: &Vec<String>| {
|
||||||
for name in names {
|
for name in names {
|
||||||
if !added.contains(name) {
|
if !added.contains(name) {
|
||||||
add_workspace(name, false);
|
add_workspace(name, Visibility::Hidden);
|
||||||
added.insert(name.to_string());
|
added.insert(name.to_string());
|
||||||
fav_names.push(name.to_string());
|
fav_names.push(name.to_string());
|
||||||
}
|
}
|
||||||
@@ -264,14 +264,20 @@ impl Module<gtk::Box> for WorkspacesModule {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
WorkspaceUpdate::Focus { old, new } => {
|
WorkspaceUpdate::Focus { old, new } => {
|
||||||
let old = button_map.get(&old);
|
if let Some(btn) = old.as_ref().and_then(|w| button_map.get(&w.name)) {
|
||||||
if let Some(old) = old {
|
if Some(new.monitor) == old.map(|w| w.monitor) {
|
||||||
old.style_context().remove_class("focused");
|
btn.style_context().remove_class("visible");
|
||||||
|
}
|
||||||
|
|
||||||
|
btn.style_context().remove_class("focused");
|
||||||
}
|
}
|
||||||
|
|
||||||
let new = button_map.get(&new);
|
let new = button_map.get(&new.name);
|
||||||
if let Some(new) = new {
|
if let Some(btn) = new {
|
||||||
new.style_context().add_class("focused");
|
let style = btn.style_context();
|
||||||
|
|
||||||
|
style.add_class("visible");
|
||||||
|
style.add_class("focused");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WorkspaceUpdate::Add(workspace) => {
|
WorkspaceUpdate::Add(workspace) => {
|
||||||
@@ -284,8 +290,7 @@ impl Module<gtk::Box> for WorkspacesModule {
|
|||||||
let name = workspace.name;
|
let name = workspace.name;
|
||||||
let item = create_button(
|
let item = create_button(
|
||||||
&name,
|
&name,
|
||||||
workspace.focused,
|
workspace.visibility,
|
||||||
false,
|
|
||||||
&name_map,
|
&name_map,
|
||||||
&icon_theme,
|
&icon_theme,
|
||||||
icon_size,
|
icon_size,
|
||||||
@@ -310,8 +315,7 @@ impl Module<gtk::Box> for WorkspacesModule {
|
|||||||
let name = workspace.name;
|
let name = workspace.name;
|
||||||
let item = create_button(
|
let item = create_button(
|
||||||
&name,
|
&name,
|
||||||
workspace.focused,
|
workspace.visibility,
|
||||||
false,
|
|
||||||
&name_map,
|
&name_map,
|
||||||
&icon_theme,
|
&icon_theme,
|
||||||
icon_size,
|
icon_size,
|
||||||
|
|||||||
Reference in New Issue
Block a user