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/),
|
||||
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
|
||||
### :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))*:
|
||||
@@ -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.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.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]]
|
||||
name = "anstream"
|
||||
version = "0.3.2"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163"
|
||||
checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
"anstyle-query",
|
||||
"anstyle-wincon",
|
||||
"colorchoice",
|
||||
"is-terminal",
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
@@ -94,9 +93,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "1.0.2"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c677ab05e09154296dd37acecd46420c17b9713e8366facafa8fc0885167cf4c"
|
||||
checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"windows-sys 0.48.0",
|
||||
@@ -169,7 +168,7 @@ dependencies = [
|
||||
"log",
|
||||
"parking",
|
||||
"polling",
|
||||
"rustix 0.37.11",
|
||||
"rustix",
|
||||
"slab",
|
||||
"socket2 0.4.9",
|
||||
"waker-fn",
|
||||
@@ -207,7 +206,7 @@ dependencies = [
|
||||
"cfg-if",
|
||||
"event-listener",
|
||||
"futures-lite",
|
||||
"rustix 0.37.11",
|
||||
"rustix",
|
||||
"signal-hook",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
@@ -424,36 +423,34 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.26"
|
||||
version = "0.4.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5"
|
||||
checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
"num-traits",
|
||||
"pure-rust-locales",
|
||||
"time 0.1.45",
|
||||
"wasm-bindgen",
|
||||
"winapi",
|
||||
"windows-targets 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.3.21"
|
||||
version = "4.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c27cdf28c0f604ba3f512b0c9a409f8de8513e4816705deb0498b627e7c3a3fd"
|
||||
checksum = "b1d7b8d5ec32af0fadc644bf1fd509a688c2103b185644bb1e29d164e0703136"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.3.21"
|
||||
version = "4.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08a9f1ab5e9f01a9b81f202e8562eb9a10de70abf9eaeac1be465c28b75aa4aa"
|
||||
checksum = "5179bb514e4d7c2051749d8fcefa2ed6d06a9f4e6d69faf3805f5d80b8cf8d56"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
@@ -463,9 +460,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.3.12"
|
||||
version = "4.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050"
|
||||
checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873"
|
||||
dependencies = [
|
||||
"heck 0.4.1",
|
||||
"proc-macro2",
|
||||
@@ -617,11 +614,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ctrlc"
|
||||
version = "3.4.0"
|
||||
version = "3.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a011bbe2c35ce9c1f143b7af6f94f29a167beb4cd1d29e6740ce836f723120e"
|
||||
checksum = "82e95fbd621905b854affdc67943b043a0fbb6ed7385fd5a25650d19a8a6cfdf"
|
||||
dependencies = [
|
||||
"nix 0.26.2",
|
||||
"nix 0.27.1",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
@@ -913,13 +910,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "filetime"
|
||||
version = "0.2.21"
|
||||
version = "0.2.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153"
|
||||
checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall 0.2.16",
|
||||
"redox_syscall 0.3.5",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
@@ -1156,7 +1153,7 @@ checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1480,9 +1477,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hyprland"
|
||||
version = "0.3.8"
|
||||
version = "0.3.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a84219159a2b7df96e2e6a8b8806d97c94d7ba2f661a0d4dd843d66b59f0ca28"
|
||||
checksum = "dfa94ae7899f3f1bdcad21dcd50366a60f323375a25610889246f276d7f9fb06"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"derive_more",
|
||||
@@ -1625,7 +1622,7 @@ checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f"
|
||||
|
||||
[[package]]
|
||||
name = "ironbar"
|
||||
version = "0.13.0"
|
||||
version = "0.14.0-pre"
|
||||
dependencies = [
|
||||
"async_once",
|
||||
"cfg-if",
|
||||
@@ -1644,7 +1641,7 @@ dependencies = [
|
||||
"lazy_static",
|
||||
"mpd_client",
|
||||
"mpris",
|
||||
"nix 0.26.2",
|
||||
"nix 0.27.1",
|
||||
"notify",
|
||||
"regex",
|
||||
"reqwest",
|
||||
@@ -1669,17 +1666,6 @@ dependencies = [
|
||||
"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]]
|
||||
name = "itoa"
|
||||
version = "1.0.6"
|
||||
@@ -1729,9 +1715,9 @@ checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
||||
|
||||
[[package]]
|
||||
name = "libcorn"
|
||||
version = "0.8.0"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a60c31be9f9db3b90d3d8da252357c5acb20af985843db75ed6223b5bf1bec60"
|
||||
checksum = "07283e36c1e48784b5e24e27fd4f6deabd83ebfa05648316dcead505ecbab40f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"pest",
|
||||
@@ -1774,12 +1760,6 @@ version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.9"
|
||||
@@ -1810,9 +1790,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.5.0"
|
||||
version = "2.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c"
|
||||
|
||||
[[package]]
|
||||
name = "memmap2"
|
||||
@@ -1879,7 +1859,7 @@ checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"wasi",
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
@@ -1954,16 +1934,25 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.26.2"
|
||||
version = "0.26.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a"
|
||||
checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"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]]
|
||||
@@ -1978,18 +1967,19 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "notify"
|
||||
version = "6.0.1"
|
||||
version = "6.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5738a2795d57ea20abec2d6d76c6081186709c0024187cd5977265eda6598b51"
|
||||
checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"bitflags 2.4.0",
|
||||
"filetime",
|
||||
"inotify",
|
||||
"kqueue",
|
||||
"libc",
|
||||
"log",
|
||||
"mio",
|
||||
"walkdir",
|
||||
"windows-sys 0.45.0",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2313,9 +2303,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pure-rust-locales"
|
||||
version = "0.5.6"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b45c49fc4f91f35bae654f85ebb3a44d60ac64f11b3166ffa609def390c732d8"
|
||||
checksum = "ed02a829e62dc2715ceb8afb4f80e298148e1345749ceb369540fe0eb3368432"
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
@@ -2424,14 +2414,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.9.3"
|
||||
version = "1.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a"
|
||||
checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata 0.3.6",
|
||||
"regex-syntax 0.7.4",
|
||||
"regex-automata 0.3.8",
|
||||
"regex-syntax 0.7.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2445,13 +2435,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.3.6"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69"
|
||||
checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax 0.7.4",
|
||||
"regex-syntax 0.7.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2462,15 +2452,15 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.7.4"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2"
|
||||
checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.11.18"
|
||||
version = "0.11.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55"
|
||||
checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1"
|
||||
dependencies = [
|
||||
"base64 0.21.0",
|
||||
"bytes",
|
||||
@@ -2539,20 +2529,7 @@ dependencies = [
|
||||
"errno",
|
||||
"io-lifetimes",
|
||||
"libc",
|
||||
"linux-raw-sys 0.3.1",
|
||||
"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",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
@@ -2635,18 +2612,18 @@ checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.183"
|
||||
version = "1.0.188"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c"
|
||||
checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.183"
|
||||
version = "1.0.188"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816"
|
||||
checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.32",
|
||||
@@ -2655,9 +2632,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.104"
|
||||
version = "1.0.107"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c"
|
||||
checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
@@ -2795,7 +2772,7 @@ dependencies = [
|
||||
"lazy_static",
|
||||
"log",
|
||||
"memmap2",
|
||||
"nix 0.26.2",
|
||||
"nix 0.26.4",
|
||||
"thiserror",
|
||||
"wayland-backend",
|
||||
"wayland-client",
|
||||
@@ -2848,24 +2825,24 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "strum"
|
||||
version = "0.24.1"
|
||||
version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
|
||||
checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125"
|
||||
dependencies = [
|
||||
"strum_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strum_macros"
|
||||
version = "0.24.3"
|
||||
version = "0.25.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59"
|
||||
checksum = "ad8d03b598d3d0fff69bf533ee3ef19b8eeb342729596df84bcc7e1f96ec4059"
|
||||
dependencies = [
|
||||
"heck 0.4.1",
|
||||
"proc-macro2",
|
||||
"quote 1.0.32",
|
||||
"rustversion",
|
||||
"syn 1.0.109",
|
||||
"syn 2.0.28",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2937,9 +2914,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sysinfo"
|
||||
version = "0.29.8"
|
||||
version = "0.29.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d10ed79c22663a35a255d289a7fdcb43559fc77ff15df5ce6c341809e7867528"
|
||||
checksum = "0a18d114d420ada3a891e6bc8e96a2023402203296a47cdd65083377dad18ba5"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"core-foundation-sys",
|
||||
@@ -2990,7 +2967,7 @@ dependencies = [
|
||||
"cfg-if",
|
||||
"fastrand",
|
||||
"redox_syscall 0.3.5",
|
||||
"rustix 0.37.11",
|
||||
"rustix",
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
@@ -3033,17 +3010,6 @@ dependencies = [
|
||||
"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]]
|
||||
name = "time"
|
||||
version = "0.3.20"
|
||||
@@ -3088,9 +3054,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.31.0"
|
||||
version = "1.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40de3a2ba249dcb097e01be5e67a5ff53cf250397715a071a81543e8a832a920"
|
||||
checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
@@ -3211,7 +3177,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09d48f71a791638519505cefafe162606f706c25592e4bde4d97600c0195312e"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"time 0.3.20",
|
||||
"time",
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
@@ -3344,9 +3310,9 @@ checksum = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
|
||||
|
||||
[[package]]
|
||||
name = "universal-config"
|
||||
version = "0.4.2"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfede7e084d97dec87efe3cee5712ec22d97edc5bc73e61337e8914e33fd425e"
|
||||
checksum = "4e41ae277cedae5c3a4d6dbe5d7ad5068cdbcd9e7005de28996cada89c28c776"
|
||||
dependencies = [
|
||||
"dirs",
|
||||
"libcorn",
|
||||
@@ -3451,9 +3417,9 @@ checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.3.3"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698"
|
||||
checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi-util",
|
||||
@@ -3469,12 +3435,6 @@ dependencies = [
|
||||
"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]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
@@ -3556,7 +3516,7 @@ dependencies = [
|
||||
"cc",
|
||||
"downcast-rs",
|
||||
"io-lifetimes",
|
||||
"nix 0.26.2",
|
||||
"nix 0.26.4",
|
||||
"scoped-tls",
|
||||
"smallvec",
|
||||
"wayland-sys",
|
||||
@@ -3570,7 +3530,7 @@ checksum = "489c9654770f674fc7e266b3c579f4053d7551df0ceb392f153adb1f9ed06ac8"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"calloop",
|
||||
"nix 0.26.2",
|
||||
"nix 0.26.4",
|
||||
"wayland-backend",
|
||||
"wayland-scanner",
|
||||
]
|
||||
@@ -3581,7 +3541,7 @@ version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d0c3a0d5b4b688b07b0442362d3ed6bf04724fcc16cd69ab6285b90dbc487aa"
|
||||
dependencies = [
|
||||
"nix 0.26.2",
|
||||
"nix 0.26.4",
|
||||
"wayland-client",
|
||||
"xcursor",
|
||||
]
|
||||
@@ -3841,11 +3801,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.10.1"
|
||||
version = "0.50.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d"
|
||||
checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
"cfg-if",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3863,7 +3824,7 @@ version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2769203cd13a0c6015d515be729c526d041e9cf2c0cc478d57faee85f40c6dcd"
|
||||
dependencies = [
|
||||
"nix 0.26.2",
|
||||
"nix 0.26.4",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
@@ -3891,7 +3852,7 @@ dependencies = [
|
||||
"futures-sink",
|
||||
"futures-util",
|
||||
"hex",
|
||||
"nix 0.26.2",
|
||||
"nix 0.26.4",
|
||||
"once_cell",
|
||||
"ordered-stream",
|
||||
"rand",
|
||||
|
||||
30
Cargo.toml
30
Cargo.toml
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ironbar"
|
||||
version = "0.13.0"
|
||||
version = "0.14.0-pre"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
description = "Customisable GTK Layer Shell wlroots/sway bar"
|
||||
@@ -66,7 +66,7 @@ workspaces = ["futures-util"]
|
||||
gtk = "0.17.0"
|
||||
gtk-layer-shell = "0.6.0"
|
||||
glib = "0.17.10"
|
||||
tokio = { version = "1.31.0", features = [
|
||||
tokio = { version = "1.32.0", features = [
|
||||
"macros",
|
||||
"rt-multi-thread",
|
||||
"time",
|
||||
@@ -81,45 +81,45 @@ tracing-error = "0.2.0"
|
||||
tracing-appender = "0.2.2"
|
||||
strip-ansi-escapes = "0.2.0"
|
||||
color-eyre = "0.6.2"
|
||||
serde = { version = "1.0.183", features = ["derive"] }
|
||||
serde = { version = "1.0.188", features = ["derive"] }
|
||||
indexmap = "2.0.0"
|
||||
dirs = "5.0.1"
|
||||
walkdir = "2.3.2"
|
||||
notify = { version = "6.0.1", default-features = false }
|
||||
walkdir = "2.4.0"
|
||||
notify = { version = "6.1.1", default-features = false }
|
||||
wayland-client = "0.30.2"
|
||||
wayland-protocols = { version = "0.30.1", features = ["unstable", "client"] }
|
||||
wayland-protocols-wlr = { version = "0.1.0", features = ["client"] }
|
||||
smithay-client-toolkit = { version = "0.17.0", default-features = false, features = [
|
||||
"calloop",
|
||||
] }
|
||||
universal-config = { version = "0.4.2", default_features = false }
|
||||
ctrlc = "3.4.0"
|
||||
universal-config = { version = "0.4.3", default_features = false }
|
||||
ctrlc = "3.4.1"
|
||||
|
||||
lazy_static = "1.4.0"
|
||||
async_once = "0.2.6"
|
||||
cfg-if = "1.0.0"
|
||||
|
||||
# cli
|
||||
clap = { version = "4.3.21", optional = true, features = ["derive"] }
|
||||
clap = { version = "4.4.4", optional = true, features = ["derive"] }
|
||||
|
||||
# ipc
|
||||
serde_json = { version = "1.0.104", optional = true }
|
||||
serde_json = { version = "1.0.107", optional = true }
|
||||
|
||||
# http
|
||||
reqwest = { version = "0.11.18", optional = true }
|
||||
reqwest = { version = "0.11.20", optional = true }
|
||||
|
||||
# clipboard
|
||||
nix = { version = "0.26.2", optional = true, features = ["event"] }
|
||||
nix = { version = "0.27.1", optional = true, features = ["event"] }
|
||||
|
||||
# clock
|
||||
chrono = { version = "0.4.26", optional = true, features = ["unstable-locales"] }
|
||||
chrono = { version = "0.4.31", optional = true, features = ["unstable-locales"] }
|
||||
|
||||
# music
|
||||
mpd_client = { version = "1.2.0", optional = true }
|
||||
mpris = { version = "2.0.1", optional = true }
|
||||
|
||||
# sys_info
|
||||
sysinfo = { version = "0.29.8", optional = true }
|
||||
sysinfo = { version = "0.29.10", optional = true }
|
||||
|
||||
# tray
|
||||
system-tray = { version = "0.1.4", optional = true }
|
||||
@@ -131,10 +131,10 @@ zbus = { version = "3.14.1", optional = true }
|
||||
|
||||
# workspaces
|
||||
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 }
|
||||
|
||||
# shared
|
||||
regex = { version = "1.8.4", default-features = false, features = [
|
||||
regex = { version = "1.9.5", default-features = false, features = [
|
||||
"std",
|
||||
], optional = true } # music, sys_info
|
||||
12
README.md
12
README.md
@@ -75,7 +75,15 @@ cargo install ironbar
|
||||
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.
|
||||
|
||||
@@ -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.
|
||||
- [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
|
||||
- [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.
|
||||
Information on styling individual modules can be found on their pages in the sidebar.
|
||||
|
||||
| Selector | Description |
|
||||
|----------------|--------------------------------------------|
|
||||
| `.background` | Top-level window. |
|
||||
| `#bar` | Bar root box. |
|
||||
| `#bar #start` | Bar left or top modules container box. |
|
||||
| `#bar #center` | Bar center modules container box. |
|
||||
| `#bar #end` | Bar right or bottom modules container box. |
|
||||
| `.container` | All of the above. |
|
||||
| `.popup` | Any popup box. |
|
||||
| Selector | Description |
|
||||
|---------------------|--------------------------------------------|
|
||||
| `.background` | Top-level window. |
|
||||
| `#bar` | Bar root box. |
|
||||
| `#bar #start` | Bar left or top modules container box. |
|
||||
| `#bar #center` | Bar center modules container box. |
|
||||
| `#bar #end` | Bar right or bottom modules container box. |
|
||||
| `.container` | All of the above. |
|
||||
| `.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.
|
||||
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 .item` | Workspace button |
|
||||
| `.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 .text-icon` | Workspace button icon (textual only) |
|
||||
| `.workspaces .item .image` | Workspace button icon (image only) |
|
||||
|
||||
@@ -3,7 +3,7 @@ let {
|
||||
type = "workspaces"
|
||||
all_monitors = false
|
||||
name_map = {
|
||||
1 = "ﭮ"
|
||||
1 = ""
|
||||
2 = "icon:firefox"
|
||||
3 = ""
|
||||
Games = "icon:steam"
|
||||
@@ -67,7 +67,7 @@ let {
|
||||
|
||||
$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 --
|
||||
$button = { type = "button" name="power-btn" label = "" on_click = "popup:toggle" }
|
||||
|
||||
@@ -109,7 +109,7 @@
|
||||
{
|
||||
"all_monitors": false,
|
||||
"name_map": {
|
||||
"1": "ﭮ",
|
||||
"1": "",
|
||||
"2": "icon:firefox",
|
||||
"3": "",
|
||||
"Code": "",
|
||||
@@ -128,7 +128,7 @@
|
||||
"type": "launcher"
|
||||
},
|
||||
{
|
||||
"label": "random num: {{500:echo $RANDOM}}",
|
||||
"label": "random num: {{500:echo FIXME}}",
|
||||
"type": "label"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,41 +1,41 @@
|
||||
anchor_to_edges = true
|
||||
icon_theme = 'Paper'
|
||||
position = 'bottom'
|
||||
icon_theme = "Paper"
|
||||
position = "bottom"
|
||||
|
||||
[[end]]
|
||||
music_dir = '/home/jake/Music'
|
||||
player_type = 'mpd'
|
||||
type = 'music'
|
||||
music_dir = "/home/jake/Music"
|
||||
player_type = "mpd"
|
||||
type = "music"
|
||||
|
||||
[end.truncate]
|
||||
max_length = 100
|
||||
mode = 'end'
|
||||
mode = "end"
|
||||
|
||||
[[end]]
|
||||
host = 'chloe:6600'
|
||||
player_type = 'mpd'
|
||||
truncate = 'end'
|
||||
type = 'music'
|
||||
host = "chloe:6600"
|
||||
player_type = "mpd"
|
||||
truncate = "end"
|
||||
type = "music"
|
||||
|
||||
[[end]]
|
||||
cmd = '/home/jake/bin/phone-battery'
|
||||
type = 'script'
|
||||
cmd = "/home/jake/bin/phone-battery"
|
||||
type = "script"
|
||||
|
||||
[end.show_if]
|
||||
cmd = '/home/jake/bin/phone-connected'
|
||||
cmd = "/home/jake/bin/phone-connected"
|
||||
interval = 500
|
||||
|
||||
[[end]]
|
||||
type = 'sys_info'
|
||||
format = [
|
||||
' {cpu_percent}% | {temp_c:k10temp_Tccd1}°C',
|
||||
' {memory_used} / {memory_total} GB ({memory_percent}%)',
|
||||
'| {swap_used} / {swap_total} GB ({swap_percent}%)',
|
||||
' {disk_used:/} / {disk_total:/} GB ({disk_percent:/}%)',
|
||||
'李 {net_down:enp39s0} / {net_up:enp39s0} Mbps',
|
||||
'猪 {load_average:1} | {load_average:5} | {load_average:15}',
|
||||
' {uptime}',
|
||||
" {cpu_percent}% | {temp_c:k10temp_Tccd1}°C",
|
||||
" {memory_used} / {memory_total} GB ({memory_percent}%)",
|
||||
"| {swap_used} / {swap_total} GB ({swap_percent}%)",
|
||||
" {disk_used:/} / {disk_total:/} GB ({disk_percent:/}%)",
|
||||
"李 {net_down:enp39s0} / {net_up:enp39s0} Mbps",
|
||||
"猪 {load_average:1} | {load_average:5} | {load_average:15}",
|
||||
" {uptime}",
|
||||
]
|
||||
type = "sys_info"
|
||||
|
||||
[end.interval]
|
||||
cpu = 1
|
||||
@@ -46,77 +46,77 @@ temps = 5
|
||||
|
||||
[[end]]
|
||||
max_items = 3
|
||||
type = 'clipboard'
|
||||
type = "clipboard"
|
||||
|
||||
[end.truncate]
|
||||
length = 50
|
||||
mode = 'end'
|
||||
mode = "end"
|
||||
|
||||
[[end]]
|
||||
class = 'power-menu'
|
||||
tooltip = '''Up: {{30000:uptime -p | cut -d ' ' -f2-}}'''
|
||||
type = 'custom'
|
||||
class = "power-menu"
|
||||
tooltip = "Up: {{30000:uptime -p | cut -d ' ' -f2-}}"
|
||||
type = "custom"
|
||||
|
||||
[[end.bar]]
|
||||
label = ''
|
||||
name = 'power-btn'
|
||||
on_click = 'popup:toggle'
|
||||
type = 'button'
|
||||
label = ""
|
||||
name = "power-btn"
|
||||
on_click = "popup:toggle"
|
||||
type = "button"
|
||||
|
||||
[[end.popup]]
|
||||
orientation = 'vertical'
|
||||
type = 'box'
|
||||
orientation = "vertical"
|
||||
type = "box"
|
||||
|
||||
[[end.popup.widgets]]
|
||||
label = 'Power menu'
|
||||
name = 'header'
|
||||
type = 'label'
|
||||
label = "Power menu"
|
||||
name = "header"
|
||||
type = "label"
|
||||
|
||||
[[end.popup.widgets]]
|
||||
type = 'box'
|
||||
type = "box"
|
||||
|
||||
[[end.popup.widgets.widgets]]
|
||||
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 = "!shutdown now"
|
||||
type = "button"
|
||||
|
||||
[[end.popup.widgets.widgets]]
|
||||
class = 'power-btn'
|
||||
label = '''<span font-size='40pt'></span>'''
|
||||
on_click = '!reboot'
|
||||
type = 'button'
|
||||
class = "power-btn"
|
||||
label = "<span font-size='40pt'></span>"
|
||||
on_click = "!reboot"
|
||||
type = "button"
|
||||
|
||||
[[end.popup.widgets]]
|
||||
label = '''Uptime: {{30000:uptime -p | cut -d ' ' -f2-}}'''
|
||||
name = 'uptime'
|
||||
type = 'label'
|
||||
label = "Uptime: {{30000:uptime -p | cut -d ' ' -f2-}}"
|
||||
name = "uptime"
|
||||
type = "label"
|
||||
|
||||
[[end]]
|
||||
type = 'clock'
|
||||
type = "clock"
|
||||
|
||||
[[start]]
|
||||
all_monitors = false
|
||||
type = 'workspaces'
|
||||
type = "workspaces"
|
||||
|
||||
[start.name_map]
|
||||
1 = 'ﭮ'
|
||||
2 = 'icon:firefox'
|
||||
3 = ''
|
||||
Code = ''
|
||||
Games = 'icon:steam'
|
||||
1 = ""
|
||||
2 = "icon:firefox"
|
||||
3 = ""
|
||||
Code = ""
|
||||
Games = "icon:steam"
|
||||
|
||||
[[start]]
|
||||
favorites = [
|
||||
"firefox",
|
||||
"discord",
|
||||
"steam",
|
||||
]
|
||||
show_icons = true
|
||||
show_names = false
|
||||
type = 'launcher'
|
||||
favorites = [
|
||||
'firefox',
|
||||
'discord',
|
||||
'steam',
|
||||
]
|
||||
type = "launcher"
|
||||
|
||||
[[start]]
|
||||
label = 'random num: {{500:echo $RANDOM}}'
|
||||
type = 'label'
|
||||
label = "random num: {{500:echo FIXME}}"
|
||||
type = "label"
|
||||
|
||||
|
||||
@@ -1,87 +1,87 @@
|
||||
anchor_to_edges: true
|
||||
end:
|
||||
- music_dir: /home/jake/Music
|
||||
player_type: mpd
|
||||
truncate:
|
||||
max_length: 100
|
||||
mode: end
|
||||
type: music
|
||||
- host: chloe:6600
|
||||
player_type: mpd
|
||||
truncate: end
|
||||
type: music
|
||||
- cmd: /home/jake/bin/phone-battery
|
||||
show_if:
|
||||
cmd: /home/jake/bin/phone-connected
|
||||
interval: 500
|
||||
type: script
|
||||
- format:
|
||||
- {cpu_percent}% | {temp_c:k10temp_Tccd1}°C
|
||||
- {memory_used} / {memory_total} GB ({memory_percent}%)
|
||||
- '| {swap_used} / {swap_total} GB ({swap_percent}%)'
|
||||
- {disk_used:/} / {disk_total:/} GB ({disk_percent:/}%)
|
||||
- 李 {net_down:enp39s0} / {net_up:enp39s0} Mbps
|
||||
- 猪 {load_average:1} | {load_average:5} | {load_average:15}
|
||||
- {uptime}
|
||||
interval:
|
||||
cpu: 1
|
||||
disks: 300
|
||||
memory: 30
|
||||
networks: 3
|
||||
temps: 5
|
||||
type: sys_info
|
||||
- max_items: 3
|
||||
truncate:
|
||||
length: 50
|
||||
mode: end
|
||||
type: clipboard
|
||||
- bar:
|
||||
- label:
|
||||
name: power-btn
|
||||
on_click: popup:toggle
|
||||
- music_dir: /home/jake/Music
|
||||
player_type: mpd
|
||||
truncate:
|
||||
max_length: 100
|
||||
mode: end
|
||||
type: music
|
||||
- host: chloe:6600
|
||||
player_type: mpd
|
||||
truncate: end
|
||||
type: music
|
||||
- cmd: /home/jake/bin/phone-battery
|
||||
show_if:
|
||||
cmd: /home/jake/bin/phone-connected
|
||||
interval: 500
|
||||
type: script
|
||||
- format:
|
||||
- {cpu_percent}% | {temp_c:k10temp_Tccd1}°C
|
||||
- {memory_used} / {memory_total} GB ({memory_percent}%)
|
||||
- '| {swap_used} / {swap_total} GB ({swap_percent}%)'
|
||||
- {disk_used:/} / {disk_total:/} GB ({disk_percent:/}%)
|
||||
- 李 {net_down:enp39s0} / {net_up:enp39s0} Mbps
|
||||
- 猪 {load_average:1} | {load_average:5} | {load_average:15}
|
||||
- {uptime}
|
||||
interval:
|
||||
cpu: 1
|
||||
disks: 300
|
||||
memory: 30
|
||||
networks: 3
|
||||
temps: 5
|
||||
type: sys_info
|
||||
- max_items: 3
|
||||
truncate:
|
||||
length: 50
|
||||
mode: end
|
||||
type: clipboard
|
||||
- bar:
|
||||
- label:
|
||||
name: power-btn
|
||||
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
|
||||
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
|
||||
- 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
|
||||
- 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
|
||||
position: bottom
|
||||
start:
|
||||
- all_monitors: false
|
||||
name_map:
|
||||
'1': ﭮ
|
||||
'2': icon:firefox
|
||||
'3':
|
||||
Code:
|
||||
Games: icon:steam
|
||||
type: workspaces
|
||||
- favorites:
|
||||
- firefox
|
||||
- discord
|
||||
- steam
|
||||
show_icons: true
|
||||
show_names: false
|
||||
type: launcher
|
||||
- label: 'random num: {{500:echo $RANDOM}}'
|
||||
type: label
|
||||
- all_monitors: false
|
||||
name_map:
|
||||
'1':
|
||||
'2': icon:firefox
|
||||
'3':
|
||||
Code:
|
||||
Games: icon:steam
|
||||
type: workspaces
|
||||
- favorites:
|
||||
- firefox
|
||||
- discord
|
||||
- steam
|
||||
show_icons: true
|
||||
show_names: false
|
||||
type: launcher
|
||||
- label: 'random num: {{500:echo FIXME}}'
|
||||
type: label
|
||||
|
||||
|
||||
42
flake.lock
generated
42
flake.lock
generated
@@ -10,11 +10,11 @@
|
||||
"rust-overlay": "rust-overlay"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1688772518,
|
||||
"narHash": "sha256-ol7gZxwvgLnxNSZwFTDJJ49xVY5teaSvF7lzlo3YQfM=",
|
||||
"lastModified": 1693439040,
|
||||
"narHash": "sha256-t2nOxBcP0Q/XJt6Ild4v0hJ49OSl9F3nE1cdIT4xsDg=",
|
||||
"owner": "ipetkov",
|
||||
"repo": "crane",
|
||||
"rev": "8b08e96c9af8c6e3a2b69af5a7fa168750fcf88e",
|
||||
"rev": "174604795d316b75777e28185c3a4918bc69b399",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -44,11 +44,11 @@
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1687709756,
|
||||
"narHash": "sha256-Y5wKlQSkgEK2weWdOu4J3riRd+kV/VCgHsqLNTTWQ/0=",
|
||||
"lastModified": 1689068808,
|
||||
"narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "dbabf0ca0c0c4bce6ea5eaf65af5cb694d2082c7",
|
||||
"rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -80,11 +80,11 @@
|
||||
"nixpkgs": "nixpkgs"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1690373729,
|
||||
"narHash": "sha256-e136hTT7LqQ2QjOTZQMW+jnsevWwBpMj78u6FRUsH9I=",
|
||||
"lastModified": 1692351612,
|
||||
"narHash": "sha256-KTGonidcdaLadRnv9KFgwSMh1ZbXoR/OBmPjeNMhFwU=",
|
||||
"owner": "nix-community",
|
||||
"repo": "naersk",
|
||||
"rev": "d9a33d69a9c421d64c8d925428864e93be895dcc",
|
||||
"rev": "78789c30d64dea2396c9da516bbcc8db3a475207",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -95,11 +95,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1690833316,
|
||||
"narHash": "sha256-+YU+/pTJmVKNW12R07/SJiTn7PQk90xwCI4D2PfLRPs=",
|
||||
"lastModified": 1693355128,
|
||||
"narHash": "sha256-+ZoAny3ZxLcfMaUoLVgL9Ywb/57wP+EtsdNGuXUJrwg=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "9418167277f665de6f4a29f414d438cf39c55b9e",
|
||||
"rev": "a63a64b593dcf2fe05f7c5d666eb395950f36bc9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -109,11 +109,11 @@
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1690789960,
|
||||
"narHash": "sha256-3K+2HuyGTiJUSZNJxXXvc0qj4xFx1FHC/ItYtEa7/Xs=",
|
||||
"lastModified": 1693377291,
|
||||
"narHash": "sha256-vYGY9bnqEeIncNarDZYhm6KdLKgXMS+HA2mTRaWEc80=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "fb942492b7accdee4e6d17f5447091c65897dde4",
|
||||
"rev": "e7f38be3775bab9659575f192ece011c033655f0",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -143,11 +143,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1688351637,
|
||||
"narHash": "sha256-CLTufJ29VxNOIZ8UTg0lepsn3X03AmopmaLTTeHDCL4=",
|
||||
"lastModified": 1691374719,
|
||||
"narHash": "sha256-HCodqnx1Mi2vN4f3hjRPc7+lSQy18vRn8xWW68GeQOg=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "f9b92316727af9e6c7fee4a761242f7f46880329",
|
||||
"rev": "b520a3889b24aaf909e287d19d406862ced9ffc9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -164,11 +164,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1690683485,
|
||||
"narHash": "sha256-Sp/QpbMg86v12xhCsa6q0yTH8LYaJIcxzbf9LO1zFzM=",
|
||||
"lastModified": 1693447852,
|
||||
"narHash": "sha256-K9npbs4S6+r51vpiElJi+0vwbAeftCAcOGbot/PCBnQ=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "05d480a7aef1aae1bfb67a39134dcf48c5322528",
|
||||
"rev": "40e851593ef4f9f8cd0b69c8cae7b722b9953a23",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
||||
11
src/bar.rs
11
src/bar.rs
@@ -4,14 +4,13 @@ use crate::modules::{
|
||||
};
|
||||
use crate::popup::Popup;
|
||||
use crate::unique_id::get_unique_usize;
|
||||
use crate::{arc_rw, Config, GlobalState};
|
||||
use crate::{Config, GlobalState};
|
||||
use color_eyre::Result;
|
||||
use gtk::gdk::Monitor;
|
||||
use gtk::prelude::*;
|
||||
use gtk::{Application, ApplicationWindow, IconTheme, Orientation};
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use std::sync::{Arc, RwLock};
|
||||
use tracing::{debug, info};
|
||||
|
||||
/// Creates a new window for a bar,
|
||||
@@ -153,7 +152,7 @@ fn create_container(name: &str, orientation: Orientation) -> gtk::Box {
|
||||
|
||||
#[derive(Debug)]
|
||||
struct BarLoadResult {
|
||||
popup: Arc<RwLock<Popup>>,
|
||||
popup: Rc<RefCell<Popup>>,
|
||||
}
|
||||
|
||||
/// Loads the configured modules onto a bar.
|
||||
@@ -186,7 +185,7 @@ fn load_modules(
|
||||
|
||||
// popup ignores module location so can bodge this for now
|
||||
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 {
|
||||
let info = info!(ModuleLocation::Left);
|
||||
@@ -214,7 +213,7 @@ fn add_modules(
|
||||
content: >k::Box,
|
||||
modules: Vec<ModuleConfig>,
|
||||
info: &ModuleInfo,
|
||||
popup: &Arc<RwLock<Popup>>,
|
||||
popup: &Rc<RefCell<Popup>>,
|
||||
) -> Result<()> {
|
||||
let orientation = info.bar_position.get_orientation();
|
||||
|
||||
@@ -226,7 +225,7 @@ fn add_modules(
|
||||
$id,
|
||||
common.name.clone(),
|
||||
&info,
|
||||
&Arc::clone(&popup),
|
||||
&Rc::clone(&popup),
|
||||
)?;
|
||||
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 color_eyre::Result;
|
||||
use hyprland::data::{Workspace as HWorkspace, Workspaces};
|
||||
@@ -52,11 +52,8 @@ impl EventClient {
|
||||
|
||||
let workspace_name = get_workspace_name(workspace_type);
|
||||
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 {
|
||||
send!(tx, WorkspaceUpdate::Add(workspace));
|
||||
@@ -80,10 +77,7 @@ impl EventClient {
|
||||
);
|
||||
|
||||
let workspace_name = get_workspace_name(workspace_type);
|
||||
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());
|
||||
|
||||
workspace.map_or_else(
|
||||
|| {
|
||||
@@ -92,7 +86,7 @@ impl EventClient {
|
||||
|workspace| {
|
||||
// there may be another type of update so dispatch that regardless of focus change
|
||||
send!(tx, WorkspaceUpdate::Update(workspace.clone()));
|
||||
if !focused {
|
||||
if !workspace.visibility.is_focused() {
|
||||
Self::send_focus_change(&mut prev_workspace, workspace, &tx);
|
||||
}
|
||||
},
|
||||
@@ -117,12 +111,11 @@ impl EventClient {
|
||||
);
|
||||
|
||||
let workspace_name = get_workspace_name(workspace_type);
|
||||
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), 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);
|
||||
} else {
|
||||
error!("Unable to locate workspace");
|
||||
@@ -142,15 +135,12 @@ impl EventClient {
|
||||
let mut prev_workspace = lock!(active);
|
||||
|
||||
let workspace_name = get_workspace_name(workspace_type);
|
||||
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 {
|
||||
send!(tx, WorkspaceUpdate::Move(workspace.clone()));
|
||||
|
||||
if !focused {
|
||||
if !workspace.visibility.is_focused() {
|
||||
Self::send_focus_change(&mut prev_workspace, workspace, &tx);
|
||||
}
|
||||
}
|
||||
@@ -180,32 +170,28 @@ impl EventClient {
|
||||
workspace: Workspace,
|
||||
tx: &Sender<WorkspaceUpdate>,
|
||||
) {
|
||||
let old = prev_workspace
|
||||
.as_ref()
|
||||
.map(|w| w.name.clone())
|
||||
.unwrap_or_default();
|
||||
|
||||
send!(
|
||||
tx,
|
||||
WorkspaceUpdate::Focus {
|
||||
old,
|
||||
new: workspace.name.clone(),
|
||||
old: prev_workspace.take(),
|
||||
new: workspace.clone(),
|
||||
}
|
||||
);
|
||||
|
||||
prev_workspace.replace(workspace);
|
||||
}
|
||||
|
||||
/// Gets a workspace by name from the server.
|
||||
///
|
||||
/// Use `focused` to manually mark the workspace as focused,
|
||||
/// as this is not automatically checked.
|
||||
fn get_workspace(name: &str, focused: bool) -> Option<Workspace> {
|
||||
/// Gets a workspace by name from the server, given the active workspace if known.
|
||||
fn get_workspace(name: &str, active: Option<&Workspace>) -> Option<Workspace> {
|
||||
Workspaces::get()
|
||||
.expect("Failed to get workspaces")
|
||||
.find_map(|w| {
|
||||
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 {
|
||||
None
|
||||
}
|
||||
@@ -214,7 +200,7 @@ impl EventClient {
|
||||
|
||||
/// Gets the active workspace from the server.
|
||||
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)
|
||||
}
|
||||
}
|
||||
@@ -236,13 +222,16 @@ impl WorkspaceClient for EventClient {
|
||||
{
|
||||
let tx = self.workspace_tx.clone();
|
||||
|
||||
let active_name = HWorkspace::get_active()
|
||||
.map(|active| active.name)
|
||||
.unwrap_or_default();
|
||||
let active_id = HWorkspace::get_active().ok().map(|active| active.name);
|
||||
let is_visible = create_is_visible();
|
||||
|
||||
let workspaces = Workspaces::get()
|
||||
.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();
|
||||
|
||||
send!(tx, WorkspaceUpdate::Init(workspaces));
|
||||
@@ -271,13 +260,36 @@ fn get_workspace_name(name: WorkspaceType) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(bool, hyprland::data::Workspace)> for Workspace {
|
||||
fn from((focused, workspace): (bool, hyprland::data::Workspace)) -> Self {
|
||||
/// 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 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 {
|
||||
id: workspace.id.to_string(),
|
||||
name: workspace.name,
|
||||
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,
|
||||
/// Name of the monitor (output) the workspace is located on
|
||||
pub monitor: String,
|
||||
/// Whether the workspace is in focus
|
||||
pub focused: bool,
|
||||
/// How visible the workspace is
|
||||
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)]
|
||||
@@ -90,8 +120,8 @@ pub enum WorkspaceUpdate {
|
||||
Move(Workspace),
|
||||
/// Declares focus moved from the old workspace to the new.
|
||||
Focus {
|
||||
old: String,
|
||||
new: String,
|
||||
old: Option<Workspace>,
|
||||
new: Workspace,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use super::{Workspace, WorkspaceClient, WorkspaceUpdate};
|
||||
use super::{Visibility, Workspace, WorkspaceClient, WorkspaceUpdate};
|
||||
use crate::{await_sync, send};
|
||||
use async_once::AsyncOnce;
|
||||
use color_eyre::Report;
|
||||
@@ -105,22 +105,50 @@ pub fn get_sub_client() -> &'static SwayEventClient {
|
||||
|
||||
impl From<Node> for Workspace {
|
||||
fn from(node: Node) -> Self {
|
||||
let visibility = Visibility::from(&node);
|
||||
|
||||
Self {
|
||||
id: node.id.to_string(),
|
||||
name: node.name.unwrap_or_default(),
|
||||
monitor: node.output.unwrap_or_default(),
|
||||
focused: node.focused,
|
||||
visibility,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<swayipc_async::Workspace> for Workspace {
|
||||
fn from(workspace: swayipc_async::Workspace) -> Self {
|
||||
let visibility = Visibility::from(&workspace);
|
||||
|
||||
Self {
|
||||
id: workspace.id.to_string(),
|
||||
name: workspace.name,
|
||||
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(),
|
||||
),
|
||||
WorkspaceChange::Focus => Self::Focus {
|
||||
old: event
|
||||
.old
|
||||
.expect("Missing old workspace")
|
||||
.name
|
||||
.unwrap_or_default(),
|
||||
new: event
|
||||
.current
|
||||
.expect("Missing current workspace")
|
||||
.name
|
||||
.unwrap_or_default(),
|
||||
old: event.old.map(Workspace::from),
|
||||
new: Workspace::from(event.current.expect("Missing current workspace")),
|
||||
},
|
||||
WorkspaceChange::Move => {
|
||||
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::ToplevelEvent;
|
||||
use super::Environment;
|
||||
use crate::cached_broadcast::CachedBroadcastChannel;
|
||||
use crate::error::ERR_CHANNEL_RECV;
|
||||
use crate::send;
|
||||
use crate::{cached_broadcast, send};
|
||||
use cfg_if::cfg_if;
|
||||
use color_eyre::Report;
|
||||
use smithay_client_toolkit::output::{OutputInfo, OutputState};
|
||||
@@ -31,11 +32,8 @@ cfg_if! {
|
||||
|
||||
#[derive(Debug)]
|
||||
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.
|
||||
/// These are then sent ont the `seat` channel.
|
||||
/// These are then sent on the `seat` channel.
|
||||
Seats,
|
||||
/// Sends a request for all the toplevels.
|
||||
/// These are then sent on the `toplevel_init` channel.
|
||||
@@ -53,8 +51,10 @@ pub enum Request {
|
||||
|
||||
pub struct WaylandClient {
|
||||
// External channels
|
||||
output_channel: CachedBroadcastChannel<OutputInfo>,
|
||||
toplevel_tx: broadcast::Sender<ToplevelEvent>,
|
||||
_toplevel_rx: broadcast::Receiver<ToplevelEvent>,
|
||||
|
||||
#[cfg(feature = "clipboard")]
|
||||
clipboard_tx: broadcast::Sender<Arc<ClipboardItem>>,
|
||||
#[cfg(feature = "clipboard")]
|
||||
@@ -62,7 +62,6 @@ pub struct WaylandClient {
|
||||
|
||||
// Internal channels
|
||||
toplevel_init_rx: mpsc::Receiver<HashMap<usize, ToplevelHandle>>,
|
||||
output_rx: mpsc::Receiver<Vec<OutputInfo>>,
|
||||
seat_rx: mpsc::Receiver<Vec<WlSeat>>,
|
||||
#[cfg(feature = "clipboard")]
|
||||
clipboard_init_rx: mpsc::Receiver<Option<Arc<ClipboardItem>>>,
|
||||
@@ -74,10 +73,14 @@ impl WaylandClient {
|
||||
pub(super) fn new() -> Self {
|
||||
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();
|
||||
#[cfg(feature = "clipboard")]
|
||||
let (clipboard_init_tx, clipboard_init_rx) = mpsc::channel();
|
||||
let (output_tx, output_rx) = mpsc::channel();
|
||||
let (seat_tx, seat_rx) = mpsc::channel();
|
||||
|
||||
let toplevel_tx2 = toplevel_tx.clone();
|
||||
@@ -99,6 +102,7 @@ impl WaylandClient {
|
||||
|
||||
let conn =
|
||||
Connection::connect_to_env().expect("Failed to connect to Wayland compositor");
|
||||
|
||||
let (globals, queue) =
|
||||
registry_queue_init(&conn).expect("Failed to retrieve Wayland globals");
|
||||
|
||||
@@ -139,6 +143,7 @@ impl WaylandClient {
|
||||
handles: HashMap::new(),
|
||||
#[cfg(feature = "clipboard")]
|
||||
clipboard: crate::arc_mut!(None),
|
||||
output_tx,
|
||||
toplevel_tx,
|
||||
#[cfg(feature = "clipboard")]
|
||||
clipboard_tx,
|
||||
@@ -156,11 +161,6 @@ impl WaylandClient {
|
||||
trace!("{event:?}");
|
||||
match 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) => {
|
||||
trace!("Receive get seats request");
|
||||
send!(seat_tx, env.seats.clone());
|
||||
@@ -196,12 +196,12 @@ impl WaylandClient {
|
||||
});
|
||||
|
||||
Self {
|
||||
output_channel,
|
||||
toplevel_tx,
|
||||
_toplevel_rx: toplevel_rx,
|
||||
toplevel_init_rx,
|
||||
#[cfg(feature = "clipboard")]
|
||||
clipboard_init_rx,
|
||||
output_rx,
|
||||
seat_rx,
|
||||
#[cfg(feature = "clipboard")]
|
||||
clipboard_tx,
|
||||
@@ -242,6 +242,10 @@ impl WaylandClient {
|
||||
(rx, data)
|
||||
}
|
||||
|
||||
pub fn subscribe_outputs(&mut self) -> cached_broadcast::Receiver<OutputInfo> {
|
||||
self.output_channel.receiver()
|
||||
}
|
||||
|
||||
/// Force a roundtrip on the wayland connection,
|
||||
/// flushing any queued events and immediately receiving any new ones.
|
||||
pub fn roundtrip(&self) {
|
||||
@@ -249,11 +253,13 @@ impl WaylandClient {
|
||||
send!(self.request_tx, Request::Roundtrip);
|
||||
}
|
||||
|
||||
pub fn get_outputs(&self) -> Vec<OutputInfo> {
|
||||
trace!("Sending get outputs request");
|
||||
|
||||
send!(self.request_tx, Request::Outputs);
|
||||
self.output_rx.recv().expect(ERR_CHANNEL_RECV)
|
||||
/// Gets a list of all outputs.
|
||||
///
|
||||
/// This should only be used in a scenario
|
||||
/// where you need a snapshot of outputs at the current time.
|
||||
/// 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> {
|
||||
|
||||
@@ -6,10 +6,10 @@ mod wl_seat;
|
||||
mod wlr_foreign_toplevel;
|
||||
|
||||
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 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::registry::{ProvidesRegistryState, RegistryState};
|
||||
use smithay_client_toolkit::seat::SeatState;
|
||||
@@ -65,6 +65,7 @@ pub struct Environment {
|
||||
#[cfg(feature = "clipboard")]
|
||||
clipboard: Arc<Mutex<Option<Arc<ClipboardItem>>>>,
|
||||
|
||||
output_tx: cached_broadcast::Sender<OutputInfo>,
|
||||
toplevel_tx: broadcast::Sender<ToplevelEvent>,
|
||||
#[cfg(feature = "clipboard")]
|
||||
clipboard_tx: broadcast::Sender<Arc<ClipboardItem>>,
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
use super::Environment;
|
||||
use crate::cached_broadcast::Cacheable;
|
||||
use crate::{cached_broadcast, try_send};
|
||||
use smithay_client_toolkit::output::{OutputHandler, OutputInfo, OutputState};
|
||||
use tracing::debug;
|
||||
use wayland_client::protocol::wl_output;
|
||||
@@ -31,9 +33,12 @@ impl OutputHandler for Environment {
|
||||
&mut self,
|
||||
_conn: &Connection,
|
||||
_qh: &QueueHandle<Self>,
|
||||
_output: wl_output::WlOutput,
|
||||
output: wl_output::WlOutput,
|
||||
) {
|
||||
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(
|
||||
@@ -42,14 +47,26 @@ impl OutputHandler for Environment {
|
||||
_qh: &QueueHandle<Self>,
|
||||
_output: wl_output::WlOutput,
|
||||
) {
|
||||
debug!("Handle received output update");
|
||||
}
|
||||
|
||||
fn output_destroyed(
|
||||
&mut self,
|
||||
_conn: &Connection,
|
||||
_qh: &QueueHandle<Self>,
|
||||
_output: wl_output::WlOutput,
|
||||
output: wl_output::WlOutput,
|
||||
) {
|
||||
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 glib::Bytes;
|
||||
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::reexports::calloop::RegistrationToken;
|
||||
use std::cmp::min;
|
||||
@@ -289,23 +289,22 @@ impl DataControlSourceHandler for Environment {
|
||||
trace!("Num bytes: {}", bytes.len());
|
||||
|
||||
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");
|
||||
epoll_ctl(
|
||||
epoll_fd,
|
||||
EpollOp::EpollCtlAdd,
|
||||
fd.as_raw_fd(),
|
||||
&mut epoll_event,
|
||||
)
|
||||
.expect("to send valid epoll operation");
|
||||
let epoll_fd =
|
||||
Epoll::new(EpollCreateFlags::empty()).expect("to get valid file descriptor");
|
||||
epoll_fd
|
||||
.add(fd, epoll_event)
|
||||
.expect("to send valid epoll operation");
|
||||
|
||||
while !bytes.is_empty() {
|
||||
let chunk = &bytes[..min(pipe_size as usize, 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) {
|
||||
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
|
||||
.iter()
|
||||
.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());
|
||||
Some((file.clone(), parsed_desktop_file))
|
||||
@@ -162,7 +164,9 @@ fn parse_desktop_file(path: &Path) -> Option<DesktopFile> {
|
||||
|
||||
file.lines()
|
||||
.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 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.
|
||||
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);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::popup::Popup;
|
||||
use crate::write_lock;
|
||||
use std::cell::{RefCell, RefMut};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, RwLock, RwLockWriteGuard};
|
||||
use std::rc::Rc;
|
||||
|
||||
/// 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.
|
||||
#[derive(Debug)]
|
||||
pub struct GlobalState {
|
||||
popups: HashMap<Box<str>, Arc<RwLock<Popup>>>,
|
||||
popups: HashMap<Box<str>, Rc<RefCell<Popup>>>,
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
pub fn with_popup_mut<F, T>(&self, monitor_name: &str, f: F) -> Option<T>
|
||||
where
|
||||
F: FnOnce(RwLockWriteGuard<Popup>) -> T,
|
||||
F: FnOnce(RefMut<Popup>) -> T,
|
||||
{
|
||||
let popup = self.popups().get(monitor_name);
|
||||
|
||||
if let Some(popup) = popup {
|
||||
let popup = write_lock!(popup);
|
||||
let popup = popup.borrow_mut();
|
||||
Some(f(popup))
|
||||
} else {
|
||||
None
|
||||
|
||||
@@ -18,7 +18,7 @@ use crate::ipc::{Command, Response};
|
||||
use crate::ironvar::get_variable_manager;
|
||||
use crate::modules::PopupButton;
|
||||
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;
|
||||
|
||||
@@ -123,14 +123,7 @@ impl Ipc {
|
||||
Response::Ok
|
||||
}
|
||||
Command::Reload => {
|
||||
info!("Closing existing bars");
|
||||
let windows = application.windows();
|
||||
for window in windows {
|
||||
window.close();
|
||||
}
|
||||
|
||||
crate::load_interface(application, global_state);
|
||||
|
||||
await_sync(async move { crate::reload(application, global_state).await }).unwrap();
|
||||
Response::Ok
|
||||
}
|
||||
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::Report;
|
||||
use dirs::config_dir;
|
||||
use gtk::gdk::Display;
|
||||
use gtk::gdk::{Display, Monitor};
|
||||
use gtk::prelude::*;
|
||||
use gtk::Application;
|
||||
use smithay_client_toolkit::output::OutputInfo;
|
||||
use tokio::runtime::Handle;
|
||||
use tokio::spawn;
|
||||
use tokio::task::{block_in_place, spawn_blocking};
|
||||
use tracing::{debug, error, info, warn};
|
||||
use universal_config::ConfigLoader;
|
||||
@@ -25,6 +27,8 @@ use universal_config::ConfigLoader;
|
||||
use clients::wayland;
|
||||
|
||||
use crate::bar::create_bar;
|
||||
use crate::bridge_channel::BridgeChannel;
|
||||
use crate::cached_broadcast::Event;
|
||||
use crate::config::{Config, MonitorConfig};
|
||||
use crate::error::ExitCode;
|
||||
use crate::global_state::GlobalState;
|
||||
@@ -32,6 +36,7 @@ use crate::style::load_css;
|
||||
|
||||
mod bar;
|
||||
mod bridge_channel;
|
||||
mod cached_broadcast;
|
||||
#[cfg(feature = "cli")]
|
||||
mod cli;
|
||||
mod clients;
|
||||
@@ -84,19 +89,22 @@ async fn run_with_args(global_state: Rc<RefCell<GlobalState>>) {
|
||||
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!("Starting application");
|
||||
|
||||
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 global_state2 = global_state.clone();
|
||||
app.connect_activate(move |app| {
|
||||
if running.get() {
|
||||
info!("Ironbar already running, returning");
|
||||
@@ -107,13 +115,11 @@ fn start_ironbar(global_state: Rc<RefCell<GlobalState>>) {
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "ipc")] {
|
||||
let ipc = ipc::Ipc::new(global_state.clone());
|
||||
let ipc = ipc::Ipc::new(global_state2.clone());
|
||||
ipc.start(app);
|
||||
}
|
||||
}
|
||||
|
||||
load_interface(app, &global_state);
|
||||
|
||||
let style_path = env::var("IRONBAR_CSS").ok().map_or_else(
|
||||
|| {
|
||||
config_dir().map_or_else(
|
||||
@@ -147,27 +153,131 @@ fn start_ironbar(global_state: Rc<RefCell<GlobalState>>) {
|
||||
exit(0);
|
||||
});
|
||||
|
||||
ctrlc::set_handler(move || tx.send(()).expect("Could not send signal on channel."))
|
||||
.expect("Error setting Ctrl-C handler");
|
||||
let wc = wayland::get_client();
|
||||
|
||||
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
|
||||
// Some are provided by swaybar_config but not currently supported
|
||||
app.run_with_args(&Vec::<&str>::new());
|
||||
}
|
||||
|
||||
/// Loads the Ironbar config and interface.
|
||||
pub fn load_interface(app: &Application, global_state: &Rc<RefCell<GlobalState>>) {
|
||||
let display = Display::default().map_or_else(
|
||||
/// Closes all current bars and entirely reloads Ironbar.
|
||||
/// This re-reads the config file.
|
||||
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");
|
||||
error!("{:?}", report);
|
||||
exit(ExitCode::GtkDisplay as i32)
|
||||
},
|
||||
|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(
|
||||
|_| ConfigLoader::new("ironbar").find_and_load(),
|
||||
ConfigLoader::load,
|
||||
@@ -182,77 +292,7 @@ pub fn load_interface(app: &Application, global_state: &Rc<RefCell<GlobalState>>
|
||||
});
|
||||
|
||||
debug!("Loaded config file");
|
||||
|
||||
#[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(())
|
||||
config
|
||||
}
|
||||
|
||||
/// 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 glib::IsA;
|
||||
@@ -12,7 +13,7 @@ use crate::bridge_channel::BridgeChannel;
|
||||
use crate::config::{BarPosition, CommonConfig, TransitionType};
|
||||
use crate::gtk_helpers::{IronbarGtkExt, WidgetGeometry};
|
||||
use crate::popup::Popup;
|
||||
use crate::{send, write_lock};
|
||||
use crate::send;
|
||||
|
||||
#[cfg(feature = "clipboard")]
|
||||
pub mod clipboard;
|
||||
@@ -178,7 +179,7 @@ pub fn create_module<TModule, TWidget, TSend, TRec>(
|
||||
id: usize,
|
||||
name: Option<String>,
|
||||
info: &ModuleInfo,
|
||||
popup: &Arc<RwLock<Popup>>,
|
||||
popup: &Rc<RefCell<Popup>>,
|
||||
) -> Result<ModuleParts<TWidget>>
|
||||
where
|
||||
TModule: Module<TWidget, SendMessage = TSend, ReceiveMessage = TRec>,
|
||||
@@ -205,7 +206,8 @@ where
|
||||
let instance_name = name.unwrap_or_else(|| module_name.to_string());
|
||||
|
||||
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() {
|
||||
popup_content
|
||||
@@ -234,12 +236,12 @@ where
|
||||
|
||||
/// Registers the popup content with the popup.
|
||||
fn register_popup_content(
|
||||
popup: &Arc<RwLock<Popup>>,
|
||||
popup: &Rc<RefCell<Popup>>,
|
||||
id: usize,
|
||||
name: String,
|
||||
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
|
||||
@@ -251,7 +253,7 @@ fn setup_receiver<TSend>(
|
||||
channel: BridgeChannel<ModuleUpdateEvent<TSend>>,
|
||||
w_tx: glib::Sender<TSend>,
|
||||
p_tx: glib::Sender<TSend>,
|
||||
popup: Arc<RwLock<Popup>>,
|
||||
popup: Rc<RefCell<Popup>>,
|
||||
name: &'static str,
|
||||
id: usize,
|
||||
has_popup: bool,
|
||||
@@ -273,7 +275,7 @@ fn setup_receiver<TSend>(
|
||||
}
|
||||
ModuleUpdateEvent::TogglePopup(button_id) => {
|
||||
debug!("Toggling popup for {} [#{}]", name, id);
|
||||
let mut popup = write_lock!(popup);
|
||||
let mut popup = popup.borrow_mut();
|
||||
if popup.is_visible() {
|
||||
popup.hide();
|
||||
} else {
|
||||
@@ -289,7 +291,7 @@ fn setup_receiver<TSend>(
|
||||
ModuleUpdateEvent::OpenPopup(button_id) => {
|
||||
debug!("Opening popup for {} [#{}]", name, id);
|
||||
|
||||
let mut popup = write_lock!(popup);
|
||||
let mut popup = popup.borrow_mut();
|
||||
popup.hide();
|
||||
popup.show(id, button_id);
|
||||
|
||||
@@ -302,7 +304,7 @@ fn setup_receiver<TSend>(
|
||||
ModuleUpdateEvent::OpenPopupAt(geometry) => {
|
||||
debug!("Opening popup for {} [#{}]", name, id);
|
||||
|
||||
let mut popup = write_lock!(popup);
|
||||
let mut popup = popup.borrow_mut();
|
||||
popup.hide();
|
||||
popup.show_at(id, geometry);
|
||||
|
||||
@@ -315,7 +317,7 @@ fn setup_receiver<TSend>(
|
||||
ModuleUpdateEvent::ClosePopup => {
|
||||
debug!("Closing popup for {} [#{}]", name, id);
|
||||
|
||||
let mut popup = write_lock!(popup);
|
||||
let mut popup = popup.borrow_mut();
|
||||
popup.hide();
|
||||
}
|
||||
}
|
||||
@@ -375,6 +377,8 @@ pub fn wrap_widget<W: IsA<Widget>>(
|
||||
revealer.set_reveal_child(true);
|
||||
|
||||
let container = EventBox::new();
|
||||
container.add_class("widget-container");
|
||||
|
||||
container.add_events(EventMask::SCROLL_MASK);
|
||||
container.add(&revealer);
|
||||
|
||||
|
||||
@@ -216,7 +216,9 @@ impl Module<Button> for MusicModule {
|
||||
let tx = context.tx.clone();
|
||||
|
||||
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() {
|
||||
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::image::new_icon_button;
|
||||
use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext};
|
||||
@@ -76,8 +76,7 @@ const fn default_icon_size() -> i32 {
|
||||
/// Creates a button from a workspace
|
||||
fn create_button(
|
||||
name: &str,
|
||||
focused: bool,
|
||||
inactive: bool,
|
||||
visibility: Visibility,
|
||||
name_map: &HashMap<String, String>,
|
||||
icon_theme: &IconTheme,
|
||||
icon_size: i32,
|
||||
@@ -91,10 +90,12 @@ fn create_button(
|
||||
let style_context = button.style_context();
|
||||
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");
|
||||
} else if inactive {
|
||||
style_context.add_class("inactive");
|
||||
}
|
||||
|
||||
{
|
||||
@@ -131,7 +132,7 @@ fn reorder_workspaces(container: >k::Box) {
|
||||
|
||||
impl WorkspacesModule {
|
||||
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)
|
||||
}
|
||||
}
|
||||
@@ -212,11 +213,10 @@ impl Module<gtk::Box> for WorkspacesModule {
|
||||
|
||||
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(
|
||||
name,
|
||||
focused,
|
||||
false,
|
||||
visibility,
|
||||
&name_map,
|
||||
&icon_theme,
|
||||
icon_size,
|
||||
@@ -230,7 +230,7 @@ impl Module<gtk::Box> for WorkspacesModule {
|
||||
// add workspaces from client
|
||||
for workspace in &workspaces {
|
||||
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());
|
||||
}
|
||||
}
|
||||
@@ -238,7 +238,7 @@ impl Module<gtk::Box> for WorkspacesModule {
|
||||
let mut add_favourites = |names: &Vec<String>| {
|
||||
for name in names {
|
||||
if !added.contains(name) {
|
||||
add_workspace(name, false);
|
||||
add_workspace(name, Visibility::Hidden);
|
||||
added.insert(name.to_string());
|
||||
fav_names.push(name.to_string());
|
||||
}
|
||||
@@ -264,14 +264,20 @@ impl Module<gtk::Box> for WorkspacesModule {
|
||||
}
|
||||
}
|
||||
WorkspaceUpdate::Focus { old, new } => {
|
||||
let old = button_map.get(&old);
|
||||
if let Some(old) = old {
|
||||
old.style_context().remove_class("focused");
|
||||
if let Some(btn) = old.as_ref().and_then(|w| button_map.get(&w.name)) {
|
||||
if Some(new.monitor) == old.map(|w| w.monitor) {
|
||||
btn.style_context().remove_class("visible");
|
||||
}
|
||||
|
||||
btn.style_context().remove_class("focused");
|
||||
}
|
||||
|
||||
let new = button_map.get(&new);
|
||||
if let Some(new) = new {
|
||||
new.style_context().add_class("focused");
|
||||
let new = button_map.get(&new.name);
|
||||
if let Some(btn) = new {
|
||||
let style = btn.style_context();
|
||||
|
||||
style.add_class("visible");
|
||||
style.add_class("focused");
|
||||
}
|
||||
}
|
||||
WorkspaceUpdate::Add(workspace) => {
|
||||
@@ -284,8 +290,7 @@ impl Module<gtk::Box> for WorkspacesModule {
|
||||
let name = workspace.name;
|
||||
let item = create_button(
|
||||
&name,
|
||||
workspace.focused,
|
||||
false,
|
||||
workspace.visibility,
|
||||
&name_map,
|
||||
&icon_theme,
|
||||
icon_size,
|
||||
@@ -310,8 +315,7 @@ impl Module<gtk::Box> for WorkspacesModule {
|
||||
let name = workspace.name;
|
||||
let item = create_button(
|
||||
&name,
|
||||
workspace.focused,
|
||||
false,
|
||||
workspace.visibility,
|
||||
&name_map,
|
||||
&icon_theme,
|
||||
icon_size,
|
||||
|
||||
Reference in New Issue
Block a user