From 1b819fb6469a3fb7fa9eb39d73eaefeb768be027 Mon Sep 17 00:00:00 2001 From: Temmie <13449732+ralismark@users.noreply.github.com> Date: Sat, 30 Mar 2024 20:55:01 +1100 Subject: [PATCH] System Tray (#743) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Allow tokio on gtk thread * Basic notifier host implementation * Implement systray widget * Use dbusmenu-gtk3 * Update flake.nix * US spelling of license * Fix possible TOCTOU * Change how hosts are started * Add watcher * Bunch of refactor * Handle errors better * Refactor service parsing * Avoid duplicate dbus connections * Fix watcher producing bad items * Handle zbus::Error::NameTaken * Refactor icon loading & don't panic on zoom * Implement pixbuf icons Co-authored-by: Bojan Nemčić * Don't panic on icon/menu error * Improve icon error handling to make discord work * Update comments * Big refactor into actor model * Reword error messages * Remove redundant watcher_on function * Big icon handling refactor * Don't unnecessarily wrap StatusNotifierItem * cargo fmt * Documentation * Avoid registering to StatusNotifierWatcher multiple times * None theme means default theme * Add dbus logging * Add libdbusmenu-gtk3 dependency to docs * Some code tidying * Make Item more clearer * Make clippy happy * Systray widget improvements * Remove unwraps from dbus state * Temporarily add libdbusmenu-gtk3 to flake buildInputs * Fix blurry tray icon for HiDPI display * feat: dynamic icons * fix: don't cache IconPixmap property this fixes dynamic icons for some icons, e.g. syncthingtray * fixup! feat: dynamic icons * Fix unused borrow warning * Add some documentation to notifier_host * Rename notifier_host::dbus to more descriptive notifier_host::proxy * fixup! Rename notifier_host::dbus to more descriptive notifier_host::proxy * fixup! Merge remote-tracking branch 'upstream/master' into tray-3 * fixup! Merge remote-tracking branch 'upstream/master' into tray-3 * Remove commented out fields of DBusSession * Refactor host * Remove git conflict marker * Various improvements * Icon documentation * cargo fmt * Add dependency to CI --------- Co-authored-by: Bojan Nemčić Co-authored-by: MoetaYuko Co-authored-by: hylo --- .github/workflows/build.yml | 2 +- CHANGELOG.md | 3 + Cargo.lock | 1445 +++++++++++++---- Cargo.toml | 1 + crates/eww/Cargo.toml | 4 + crates/eww/src/main.rs | 5 +- crates/eww/src/server.rs | 22 +- crates/eww/src/widgets/def_widget_macro.rs | 2 + crates/eww/src/widgets/mod.rs | 1 + crates/eww/src/widgets/systray.rs | 203 +++ crates/eww/src/widgets/widget_definitions.rs | 41 +- crates/notifier_host/Cargo.toml | 18 + crates/notifier_host/src/host.rs | 135 ++ crates/notifier_host/src/icon.rs | 207 +++ crates/notifier_host/src/item.rs | 97 ++ crates/notifier_host/src/lib.rs | 52 + crates/notifier_host/src/proxy/dbus_menu.xml | 69 + .../src/proxy/dbus_status_notifier_item.rs | 114 ++ .../src/proxy/dbus_status_notifier_item.xml | 49 + .../src/proxy/dbus_status_notifier_watcher.rs | 53 + .../proxy/dbus_status_notifier_watcher.xml | 52 + crates/notifier_host/src/proxy/mod.rs | 16 + crates/notifier_host/src/watcher.rs | 299 ++++ docs/src/eww.md | 1 + flake.nix | 6 + 25 files changed, 2574 insertions(+), 323 deletions(-) create mode 100644 crates/eww/src/widgets/systray.rs create mode 100644 crates/notifier_host/Cargo.toml create mode 100644 crates/notifier_host/src/host.rs create mode 100644 crates/notifier_host/src/icon.rs create mode 100644 crates/notifier_host/src/item.rs create mode 100644 crates/notifier_host/src/lib.rs create mode 100644 crates/notifier_host/src/proxy/dbus_menu.xml create mode 100644 crates/notifier_host/src/proxy/dbus_status_notifier_item.rs create mode 100644 crates/notifier_host/src/proxy/dbus_status_notifier_item.xml create mode 100644 crates/notifier_host/src/proxy/dbus_status_notifier_watcher.rs create mode 100644 crates/notifier_host/src/proxy/dbus_status_notifier_watcher.xml create mode 100644 crates/notifier_host/src/proxy/mod.rs create mode 100644 crates/notifier_host/src/watcher.rs diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 011ac1475..98a89a259 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Install dependencies - run: sudo apt-get update && sudo apt-get install libgtk-3-dev libgtk-layer-shell-dev + run: sudo apt-get update && sudo apt-get install libgtk-3-dev libgtk-layer-shell-dev libdbusmenu-gtk3-dev - uses: actions/checkout@v4 diff --git a/CHANGELOG.md b/CHANGELOG.md index bc4409fdd..bc9215bc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,9 @@ All notable changes to eww will be listed here, starting at changes since versio - Fix nix flake - Fix `jq` (By: w-lfchen) +### Features +- Add `systray` widget (By: ralismark) + ## [0.5.0] (17.02.2024) ### BREAKING CHANGES diff --git a/Cargo.lock b/Cargo.lock index 55fef71c6..0ab6a1877 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" dependencies = [ "gimli", ] @@ -19,9 +19,20 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "ahash" -version = "0.8.8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + +[[package]] +name = "ahash" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42cd52102d3df161c77a887b608d7a4897d7cc112886a9537b738a887a03aaff" +checksum = "d713b3834d76b85304d4d525563c1276e2e30dc97cc67bfb4585a4a29fc2c89f" dependencies = [ "cfg-if", "getrandom", @@ -32,9 +43,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "6748e8def348ed4d14996fa801f4122cd763fff530258cdc03f64b25f89d3a5a" dependencies = [ "memchr", ] @@ -62,9 +73,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.11" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5" +checksum = "96b09b5178381e0874812a9b157f7fe84982617e48f71f4e3235482775e5b540" dependencies = [ "anstyle", "anstyle-parse", @@ -76,26 +87,26 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.48.0", ] [[package]] @@ -110,9 +121,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.79" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" +checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" [[package]] name = "ascii-canvas" @@ -123,6 +134,102 @@ dependencies = [ "term", ] +[[package]] +name = "async-broadcast" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c48ccdbf6ca6b121e0f586cbc0e73ae440e56c67c30fa0873b4e110d9c26d2b" +dependencies = [ + "event-listener", + "futures-core", +] + +[[package]] +name = "async-channel" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +dependencies = [ + "concurrent-queue", + "event-listener", + "futures-core", +] + +[[package]] +name = "async-io" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +dependencies = [ + "async-lock", + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-lite", + "log", + "parking", + "polling", + "rustix 0.37.23", + "slab", + "socket2 0.4.9", + "waker-fn", +] + +[[package]] +name = "async-lock" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +dependencies = [ + "event-listener", +] + +[[package]] +name = "async-process" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a9d28b1d97e08915212e2e45310d47854eafa69600756fc735fb788f75199c9" +dependencies = [ + "async-io", + "async-lock", + "autocfg", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "rustix 0.37.23", + "signal-hook", + "windows-sys 0.48.0", +] + +[[package]] +name = "async-recursion" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e97ce7de6cf12de5d7226c73f5ba9811622f4db3a5b91b55c53e987e5f91cba" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.50", +] + +[[package]] +name = "async-task" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae" + +[[package]] +name = "async-trait" +version = "0.1.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.50", +] + [[package]] name = "atk" version = "0.17.1" @@ -147,6 +254,12 @@ dependencies = [ "system-deps", ] +[[package]] +name = "atomic-waker" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3" + [[package]] name = "autocfg" version = "1.1.0" @@ -155,9 +268,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" dependencies = [ "addr2line", "cc", @@ -206,21 +319,51 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "blocking" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "77231a1c8f801696fc0123ec6150ce92cffb8e164a02afb9c8ddee0e9b65ad65" +dependencies = [ + "async-channel", + "async-lock", + "async-task", + "atomic-waker", + "fastrand 1.9.0", + "futures-lite", + "log", +] [[package]] name = "bumpalo" -version = "3.15.0" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" + +[[package]] +name = "byteorder" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32a994c2b3ca201d9b263612a374263f05e7adde37c4707f693dcd375076d1f" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.5.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" [[package]] name = "cached" @@ -228,7 +371,7 @@ version = "0.48.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "355face540df58778b96814c48abb3c2ed67c4878a8087ab1819c1fedeec505f" dependencies = [ - "ahash", + "ahash 0.8.9", "cached_proc_macro", "cached_proc_macro_types", "hashbrown 0.14.3", @@ -282,18 +425,18 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.83" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01" dependencies = [ "libc", ] [[package]] name = "cfg-expr" -version = "0.15.7" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa50868b64a9a6fda9d593ce778849ea8715cd2a3d2cc17ffdb4a2f2f2f1961d" +checksum = "b40ccee03b5175c18cde8f37e7d2a33bcef6f8ec8f7cc0d81090d1bb380949c9" dependencies = [ "smallvec", "target-lexicon", @@ -307,37 +450,38 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.34" +version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b" +checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", + "time 0.1.45", "wasm-bindgen", - "windows-targets 0.52.0", + "winapi", ] [[package]] name = "chrono-tz" -version = "0.8.6" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59ae0466b83e838b81a54256c39d5d7c20b9d7daa10510a242d9b75abd5936e" +checksum = "f1369bc6b9e9a7dfdae2055f6ec151fe9c554a9d23d357c0237cee2e25eaabb7" dependencies = [ "chrono", "chrono-tz-build", - "phf", + "phf 0.11.2", ] [[package]] name = "chrono-tz-build" -version = "0.2.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "433e39f13c9a060046954e0592a8d0a4bcb1040125cbf91cb8ee58964cfb350f" +checksum = "e2f5ebdc942f57ed96d560a6d1a459bae5851102a25d5bf89dc04ae453e31ecf" dependencies = [ "parse-zoneinfo", - "phf", + "phf 0.11.2", "phf_codegen", ] @@ -390,7 +534,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.50", ] [[package]] @@ -421,16 +565,25 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "concurrent-queue" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "console" -version = "0.15.8" +version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" dependencies = [ "encode_unicode", "lazy_static", "libc", - "windows-sys 0.52.0", + "windows-sys 0.45.0", ] [[package]] @@ -441,43 +594,61 @@ checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + +[[package]] +name = "cpufeatures" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +dependencies = [ + "libc", +] [[package]] name = "crossbeam-channel" -version = "0.5.11" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176dc175b78f56c0f321911d9c8eb2b77a78a4860b9c19db83835fea1a46649b" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" dependencies = [ + "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.5" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" dependencies = [ + "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.18" +version = "0.9.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" dependencies = [ + "autocfg", + "cfg-if", "crossbeam-utils", + "memoffset 0.9.0", + "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +dependencies = [ + "cfg-if", +] [[package]] name = "crunchy" @@ -485,6 +656,16 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "darling" version = "0.14.4" @@ -520,6 +701,59 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "dbusmenu-glib" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd1629dccc5775e0668eb9f07e78d1b88392a63efc34033a18c87ea44318b894" +dependencies = [ + "dbusmenu-glib-sys", + "glib", + "libc", +] + +[[package]] +name = "dbusmenu-glib-sys" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ff9ed40330718c94342b953c997ac19d840db07a7710fe35b45a5d3a3a1d6eb" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "dbusmenu-gtk3" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15e02bf53eed790cee4d6111643529bf2fdb82c9e61242407d254612f98436e" +dependencies = [ + "atk", + "dbusmenu-glib", + "dbusmenu-gtk3-sys", + "glib", + "gtk", + "libc", +] + +[[package]] +name = "dbusmenu-gtk3-sys" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f30ba5f8aec0e38a84c579bc8ee3db6f6417b201e729fdd96a23d1f61cb6eca" +dependencies = [ + "dbusmenu-glib-sys", + "gdk-pixbuf-sys", + "gdk-sys", + "glib-sys", + "gobject-sys", + "gtk-sys", + "libc", + "system-deps", +] + [[package]] name = "deranged" version = "0.3.11" @@ -529,6 +763,17 @@ dependencies = [ "powerfmt", ] +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -548,6 +793,16 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + [[package]] name = "dirs-next" version = "2.0.0" @@ -571,15 +826,15 @@ dependencies = [ [[package]] name = "dyn-clone" -version = "1.0.16" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" +checksum = "304e6508efa593091e97a9abbc10f90aa7ca635b6d2784feff3c89d41dd12272" [[package]] name = "either" -version = "1.10.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "ena" @@ -596,11 +851,32 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" +[[package]] +name = "enumflags2" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c041f5090df68b32bcd905365fd51769c8b9d553fe87fde0b683534f10c01bd2" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e9a1f9f7d83e59740248a6e14ecf93929ade55027844dfcea78beafccc15745" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.50", +] + [[package]] name = "env_logger" -version = "0.10.2" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" dependencies = [ "humantime", "is-terminal", @@ -615,6 +891,33 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "errno" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + [[package]] name = "eww" version = "0.5.0" @@ -644,8 +947,10 @@ dependencies = [ "log", "maplit", "nix 0.27.1", + "notifier_host", "notify", "once_cell", + "ordered-stream", "pretty_env_logger", "regex", "serde", @@ -659,6 +964,7 @@ dependencies = [ "wait-timeout", "x11rb", "yuck", + "zbus", ] [[package]] @@ -678,9 +984,24 @@ checksum = "311a6d2f1f9d60bff73d2c78a0af97ed27f79672f15c238192a5bbb64db56d00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.50", +] + +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", ] +[[package]] +name = "fastrand" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" + [[package]] name = "field-offset" version = "0.3.6" @@ -693,14 +1014,14 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.23" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" +checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" dependencies = [ "cfg-if", "libc", - "redox_syscall", - "windows-sys 0.52.0", + "redox_syscall 0.3.5", + "windows-sys 0.48.0", ] [[package]] @@ -726,9 +1047,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.30" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" dependencies = [ "futures-channel", "futures-core", @@ -741,9 +1062,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" dependencies = [ "futures-core", "futures-sink", @@ -751,15 +1072,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" dependencies = [ "futures-core", "futures-task", @@ -768,38 +1089,53 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" + +[[package]] +name = "futures-lite" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand 1.9.0", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.50", ] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" dependencies = [ "futures-channel", "futures-core", @@ -900,6 +1236,16 @@ dependencies = [ "x11", ] +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "gethostname" version = "0.2.3" @@ -912,20 +1258,20 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", ] [[package]] name = "gimli" -version = "0.28.1" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" [[package]] name = "gio" @@ -1021,24 +1367,24 @@ dependencies = [ [[package]] name = "grass" -version = "0.13.2" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b89786a806d5b192cf4e573f9831c847a455a142d000c922bdfc1e5edad14303" +checksum = "7746cd9bf09f9bb7d98638774a70642000356f543898d9a352cd043f82744528" dependencies = [ "grass_compiler", ] [[package]] name = "grass_compiler" -version = "0.13.2" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cf7d155dd7cef20195016d01005033a5521aad307033f0f8e8bf0a02f5f7554" +checksum = "187adfc0b34289c7f8f3819453ce9da3177c3d73f40ac74bb17faba578813d45" dependencies = [ "codemap", - "indexmap", + "indexmap 1.9.3", "lasso", "once_cell", - "phf", + "phf 0.10.1", ] [[package]] @@ -1070,7 +1416,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "992f5fedb31835424a5280acd162bf348995f617d26969fde8d3dfd389b3ff5f" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.4.0", "gdk", "glib", "glib-sys", @@ -1126,20 +1472,26 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.13.2" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" dependencies = [ - "ahash", + "ahash 0.7.6", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hashbrown" version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" dependencies = [ - "ahash", + "ahash 0.8.9", "allocator-api2", ] @@ -1151,9 +1503,15 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.3.6" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" + +[[package]] +name = "hex" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd5256b483761cd23699d0da46cc6fd2ee3be420bbe6d020ae4a091e70b7e9fd" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hifijson" @@ -1169,16 +1527,16 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core", + "windows 0.48.0", ] [[package]] @@ -1198,9 +1556,19 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "indexmap" -version = "2.2.3" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177" +checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" dependencies = [ "equivalent", "hashbrown 0.14.3", @@ -1228,9 +1596,9 @@ dependencies = [ [[package]] name = "insta" -version = "1.34.0" +version = "1.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d64600be34b2fcfc267740a243fa7744441bb4947a619ac4e5bb6507f35fbfc" +checksum = "a0770b0a3d4c70567f0d58331f3088b0e4c4f56c9b8d764efe654b4a5d46de3a" dependencies = [ "console", "lazy_static", @@ -1249,14 +1617,25 @@ dependencies = [ ] [[package]] -name = "is-terminal" -version = "0.4.12" +name = "io-lifetimes" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.52.0", + "windows-sys 0.48.0", +] + +[[package]] +name = "is-terminal" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +dependencies = [ + "hermit-abi", + "rustix 0.38.8", + "windows-sys 0.48.0", ] [[package]] @@ -1279,9 +1658,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "jaq-core" @@ -1296,7 +1675,7 @@ dependencies = [ "libm", "log", "regex", - "time", + "time 0.3.34", "urlencoding", ] @@ -1306,10 +1685,10 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f569e38e5fc677db8dfda89ee0b4c25b3f53e811b16434fd14bdc5b43fc362ac" dependencies = [ - "ahash", + "ahash 0.8.9", "dyn-clone", "hifijson", - "indexmap", + "indexmap 2.0.0", "jaq-syn", "once_cell", "serde_json", @@ -1347,9 +1726,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.68" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" dependencies = [ "wasm-bindgen", ] @@ -1390,7 +1769,7 @@ dependencies = [ "petgraph", "pico-args", "regex", - "regex-syntax 0.7.5", + "regex-syntax 0.7.4", "string_cache", "term", "tiny-keccak", @@ -1408,11 +1787,11 @@ dependencies = [ [[package]] name = "lasso" -version = "0.7.2" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4644821e1c3d7a560fe13d842d13f587c07348a1a05d3a797152d41c90c56df2" +checksum = "aeb7b21a526375c5ca55f1a6dfd4e1fad9fa4edd750f530252a718a44b2608f0" dependencies = [ - "hashbrown 0.13.2", + "hashbrown 0.11.2", ] [[package]] @@ -1433,28 +1812,29 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" -[[package]] -name = "libredox" -version = "0.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" -dependencies = [ - "bitflags 2.4.2", - "libc", - "redox_syscall", -] - [[package]] name = "linked-hash-map" version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + +[[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.11" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" dependencies = [ "autocfg", "scopeguard", @@ -1487,6 +1867,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + [[package]] name = "memoffset" version = "0.9.0" @@ -1498,9 +1887,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" dependencies = [ "adler", ] @@ -1513,7 +1902,7 @@ checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" dependencies = [ "libc", "log", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.48.0", ] @@ -1536,24 +1925,49 @@ dependencies = [ "memoffset 0.6.5", ] +[[package]] +name = "nix" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", + "memoffset 0.7.1", + "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.2", + "bitflags 2.4.0", "cfg-if", "libc", ] +[[package]] +name = "notifier_host" +version = "0.1.0" +dependencies = [ + "dbusmenu-gtk3", + "gtk", + "log", + "thiserror", + "tokio", + "zbus", +] + [[package]] name = "notify" version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.4.0", "crossbeam-channel", "filetime", "fsevent-sys", @@ -1583,9 +1997,9 @@ checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" dependencies = [ "autocfg", ] @@ -1602,9 +2016,9 @@ dependencies = [ [[package]] name = "object" -version = "0.32.2" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" dependencies = [ "memchr", ] @@ -1615,6 +2029,16 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + [[package]] name = "pango" version = "0.17.10" @@ -1641,6 +2065,12 @@ dependencies = [ "system-deps", ] +[[package]] +name = "parking" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" + [[package]] name = "parking_lot" version = "0.12.1" @@ -1653,15 +2083,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.3.5", "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.48.2", ] [[package]] @@ -1675,12 +2105,23 @@ dependencies = [ [[package]] name = "petgraph" -version = "0.6.4" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" +checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" dependencies = [ "fixedbitset", - "indexmap", + "indexmap 1.9.3", +] + +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_macros", + "phf_shared 0.10.0", + "proc-macro-hack", ] [[package]] @@ -1689,7 +2130,6 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ - "phf_macros", "phf_shared 0.11.2", ] @@ -1699,10 +2139,20 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" dependencies = [ - "phf_generator", + "phf_generator 0.11.2", "phf_shared 0.11.2", ] +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand", +] + [[package]] name = "phf_generator" version = "0.11.2" @@ -1715,15 +2165,16 @@ dependencies = [ [[package]] name = "phf_macros" -version = "0.11.2" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0" dependencies = [ - "phf_generator", - "phf_shared 0.11.2", + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro-hack", "proc-macro2", "quote", - "syn 2.0.49", + "syn 1.0.109", ] [[package]] @@ -1752,9 +2203,9 @@ checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "12cc1b0bf1727a77a54b6654e7b5f1af8604923edc8b81885f8ec92f9e3f0a05" [[package]] name = "pin-utils" @@ -1764,9 +2215,25 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" + +[[package]] +name = "polling" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if", + "concurrent-queue", + "libc", + "log", + "pin-project-lite", + "windows-sys 0.48.0", +] [[package]] name = "powerfmt" @@ -1774,6 +2241,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + [[package]] name = "precomputed-hash" version = "0.1.1" @@ -1807,7 +2280,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ "once_cell", - "toml_edit 0.19.15", + "toml_edit", ] [[package]] @@ -1834,6 +2307,12 @@ dependencies = [ "version_check", ] +[[package]] +name = "proc-macro-hack" +version = "0.5.20+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" + [[package]] name = "proc-macro2" version = "1.0.78" @@ -1858,6 +2337,18 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", "rand_core", ] @@ -1866,6 +2357,9 @@ name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] [[package]] name = "rayon" @@ -1889,21 +2383,30 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "redox_users" -version = "0.4.4" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ "getrandom", - "libredox", + "redox_syscall 0.2.16", "thiserror", ] @@ -1924,7 +2427,7 @@ checksum = "5fddb4f8d99b0a2ebafc65a87a69a7b9875e4b1ae1f00db265d300ef7f28bccc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.50", ] [[package]] @@ -1952,9 +2455,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.7.5" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" [[package]] name = "regex-syntax" @@ -1977,6 +2480,33 @@ dependencies = [ "semver", ] +[[package]] +name = "rustix" +version = "0.37.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" +dependencies = [ + "bitflags 1.3.2", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys 0.3.8", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustix" +version = "0.38.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f" +dependencies = [ + "bitflags 2.4.0", + "errno", + "libc", + "linux-raw-sys 0.4.5", + "windows-sys 0.48.0", +] + [[package]] name = "rustversion" version = "1.0.14" @@ -1985,9 +2515,9 @@ checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "ryu" -version = "1.0.16" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "same-file" @@ -2006,50 +2536,82 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "1.0.21" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" +checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" [[package]] name = "serde" -version = "1.0.196" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.196" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.50", ] [[package]] name = "serde_json" -version = "1.0.113" +version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" +checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360" dependencies = [ "itoa", "ryu", "serde", ] +[[package]] +name = "serde_repr" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.50", +] + [[package]] name = "serde_spanned" -version = "0.6.5" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" dependencies = [ "serde", ] +[[package]] +name = "sha1" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "signal-hook" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +dependencies = [ + "libc", + "signal-hook-registry", +] + [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -2061,9 +2623,9 @@ dependencies = [ [[package]] name = "similar" -version = "2.4.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32fea41aca09ee824cc9724996433064c89f7777e60762749a4170a14abbfa21" +checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf" [[package]] name = "simple-signal" @@ -2104,24 +2666,24 @@ dependencies = [ [[package]] name = "siphasher" -version = "0.3.11" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" [[package]] name = "slab" -version = "0.4.9" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" dependencies = [ "autocfg", ] [[package]] name = "smallvec" -version = "1.13.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" [[package]] name = "smart-default" @@ -2131,17 +2693,27 @@ checksum = "0eb01866308440fc64d6c44d9e86c5cc17adfe33c4d6eed55da9145044d0ffc1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.50", ] [[package]] name = "socket2" -version = "0.5.5" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" dependencies = [ "libc", - "windows-sys 0.48.0", + "winapi", +] + +[[package]] +name = "socket2" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +dependencies = [ + "libc", + "windows-sys 0.52.0", ] [[package]] @@ -2194,7 +2766,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.49", + "syn 2.0.50", ] [[package]] @@ -2210,9 +2782,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.49" +version = "2.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915aea9e586f80826ee59f8453c1101f9d1c4b3964cd2460185ee8e299ada496" +checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb" dependencies = [ "proc-macro2", "quote", @@ -2231,14 +2803,14 @@ dependencies = [ "ntapi", "once_cell", "rayon", - "windows", + "windows 0.52.0", ] [[package]] name = "system-deps" -version = "6.2.0" +version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2d580ff6a20c55dfb86be5f9c238f67835d0e81cbdea8bf5680e0897320331" +checksum = "30c2de8a4d8f4b823d634affc9cd2a74ec98c53a756f317e529a48046cbf71f3" dependencies = [ "cfg-expr", "heck", @@ -2249,9 +2821,22 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.13" +version = "0.12.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d0e916b1148c8e263850e1ebcbd046f333e0683c724876bb0da63ea4373dc8a" + +[[package]] +name = "tempfile" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69758bda2e78f098e4ccb393021a0963bb3442eac05f135c30f61b7370bbafae" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +dependencies = [ + "cfg-if", + "fastrand 2.0.0", + "redox_syscall 0.3.5", + "rustix 0.38.8", + "windows-sys 0.48.0", +] [[package]] name = "term" @@ -2266,31 +2851,42 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.4.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" dependencies = [ "winapi-util", ] [[package]] name = "thiserror" -version = "1.0.57" +version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" +checksum = "d9207952ae1a003f42d3d5e892dac3c6ba42aa6ac0c79a6a91a2b5cb4253e75c" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.57" +version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" +checksum = "f1728216d3244de4f14f14f8c15c79be1a7c67867d28d69b719690e2a19fb445" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.50", +] + +[[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]] @@ -2347,8 +2943,9 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2", + "socket2 0.5.6", "tokio-macros", + "tracing", "windows-sys 0.48.0", ] @@ -2360,14 +2957,14 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.50", ] [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" dependencies = [ "bytes", "futures-core", @@ -2378,47 +2975,84 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.10" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a9aad4a3066010876e8dcf5a8a06e70a558751117a145c6ce2b82c2e2054290" +checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.6", + "toml_edit", ] [[package]] name = "toml_datetime" -version = "0.6.5" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.19.15" +version = "0.19.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" dependencies = [ - "indexmap", + "indexmap 2.0.0", + "serde", + "serde_spanned", "toml_datetime", - "winnow 0.5.40", + "winnow", ] [[package]] -name = "toml_edit" -version = "0.22.6" +name = "tracing" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c1b5fd4128cc8d3e0cb74d4ed9a9cc7c7284becd4df68f5f940e1ad123606f6" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ - "indexmap", - "serde", - "serde_spanned", - "toml_datetime", - "winnow 0.6.1", + "cfg-if", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.50", +] + +[[package]] +name = "tracing-core" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "uds_windows" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce65604324d3cce9b966701489fbd0cf318cb1f7bd9dd07ac9a4ee6fb791930d" +dependencies = [ + "tempfile", + "winapi", ] [[package]] @@ -2429,15 +3063,15 @@ checksum = "ccb97dac3243214f8d8507998906ca3e2e0b900bf9bf4870477f125b82e68f6e" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "unicode-xid" @@ -2478,16 +3112,28 @@ dependencies = [ "libc", ] +[[package]] +name = "waker-fn" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" + [[package]] name = "walkdir" -version = "2.4.0" +version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" dependencies = [ "same-file", "winapi-util", ] +[[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" @@ -2496,9 +3142,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.91" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -2506,24 +3152,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.91" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.50", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.91" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2531,22 +3177,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.91" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.50", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.91" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "winapi" @@ -2566,9 +3212,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ "winapi", ] @@ -2588,6 +3234,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets 0.48.2", +] + [[package]] name = "windows" version = "0.52.0" @@ -2595,7 +3250,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ "windows-core", - "windows-targets 0.52.0", + "windows-targets 0.52.3", ] [[package]] @@ -2604,7 +3259,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.3", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", ] [[package]] @@ -2613,7 +3277,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.5", + "windows-targets 0.48.2", ] [[package]] @@ -2622,137 +3286,185 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.3", ] [[package]] name = "windows-targets" -version = "0.48.5" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", ] [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.48.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1eeca1c172a285ee6c2c84c341ccea837e7c01b12fbb2d0fe3c9e550ce49ec8" +dependencies = [ + "windows_aarch64_gnullvm 0.48.2", + "windows_aarch64_msvc 0.48.2", + "windows_i686_gnu 0.48.2", + "windows_i686_msvc 0.48.2", + "windows_x86_64_gnu 0.48.2", + "windows_x86_64_gnullvm 0.48.2", + "windows_x86_64_msvc 0.48.2", +] + +[[package]] +name = "windows-targets" +version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "d380ba1dc7187569a8a9e91ed34b8ccfc33123bbacb8c0aed2d1ad7f3ef2dc5f" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.3", + "windows_aarch64_msvc 0.52.3", + "windows_i686_gnu 0.52.3", + "windows_i686_msvc 0.52.3", + "windows_x86_64_gnu 0.52.3", + "windows_x86_64_gnullvm 0.52.3", + "windows_x86_64_msvc 0.52.3", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.5" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.48.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b10d0c968ba7f6166195e13d593af609ec2e3d24f916f081690695cf5eaffb2f" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "68e5dcfb9413f53afd9c8f86e56a7b4d86d9a2fa26090ea2dc9e40fba56c6ec6" [[package]] name = "windows_aarch64_msvc" -version = "0.48.5" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.48.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "571d8d4e62f26d4932099a9efe89660e8bd5087775a2ab5cdd8b747b811f1058" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8dab469ebbc45798319e69eebf92308e541ce46760b49b18c6b3fe5e8965b30f" [[package]] name = "windows_i686_gnu" -version = "0.48.5" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.48.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2229ad223e178db5fbbc8bd8d3835e51e566b8474bfca58d2e6150c48bb723cd" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "2a4e9b6a7cac734a8b4138a4e1044eac3404d8326b6c0f939276560687a033fb" [[package]] name = "windows_i686_msvc" -version = "0.48.5" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.48.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "600956e2d840c194eedfc5d18f8242bc2e17c7775b6684488af3a9fff6fe3287" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "28b0ec9c422ca95ff34a78755cfa6ad4a51371da2a5ace67500cf7ca5f232c58" [[package]] name = "windows_x86_64_gnu" -version = "0.48.5" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.48.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "ea99ff3f8b49fb7a8e0d305e5aec485bd068c2ba691b6e277d29eaeac945868a" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "704131571ba93e89d7cd43482277d6632589b18ecf4468f591fbae0a8b101614" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.5" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.48.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1a05a1ece9a7a0d5a7ccf30ba2c33e3a61a30e042ffd247567d1de1d94120d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "42079295511643151e98d61c38c0acc444e52dd42ab456f7ccfd5152e8ecf21c" [[package]] name = "windows_x86_64_msvc" -version = "0.48.5" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.48.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "d419259aba16b663966e29e6d7c6ecfa0bb8425818bb96f6f1f3c3eb71a6e7b9" [[package]] -name = "winnow" -version = "0.5.40" +name = "windows_x86_64_msvc" +version = "0.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" -dependencies = [ - "memchr", -] +checksum = "0770833d60a970638e989b3fa9fd2bb1aaadcf88963d1659fd7d9990196ed2d6" [[package]] name = "winnow" -version = "0.6.1" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d90f4e0f530c4c69f62b80d839e9ef3855edc9cba471a160c4d692deed62b401" +checksum = "1e461589e194280efaa97236b73623445efa195aa633fd7004f39805707a9d53" dependencies = [ "memchr", ] @@ -2789,6 +3501,16 @@ dependencies = [ "nix 0.25.1", ] +[[package]] +name = "xdg-home" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2769203cd13a0c6015d515be729c526d041e9cf2c0cc478d57faee85f40c6dcd" +dependencies = [ + "nix 0.26.2", + "winapi", +] + [[package]] name = "yaml-rust" version = "0.4.5" @@ -2828,6 +3550,67 @@ dependencies = [ "thiserror", ] +[[package]] +name = "zbus" +version = "3.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31de390a2d872e4cd04edd71b425e29853f786dc99317ed72d73d6fcf5ebb948" +dependencies = [ + "async-broadcast", + "async-process", + "async-recursion", + "async-trait", + "byteorder", + "derivative", + "enumflags2", + "event-listener", + "futures-core", + "futures-sink", + "futures-util", + "hex", + "nix 0.26.2", + "once_cell", + "ordered-stream", + "rand", + "serde", + "serde_repr", + "sha1", + "static_assertions", + "tokio", + "tracing", + "uds_windows", + "winapi", + "xdg-home", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "3.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d1794a946878c0e807f55a397187c11fc7a038ba5d868e7db4f3bd7760bc9d" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "regex", + "syn 1.0.109", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb80bb776dbda6e23d705cf0123c3b95df99c4ebeaec6c2599d4a5419902b4a9" +dependencies = [ + "serde", + "static_assertions", + "zvariant", +] + [[package]] name = "zerocopy" version = "0.7.32" @@ -2845,5 +3628,43 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.50", +] + +[[package]] +name = "zvariant" +version = "3.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44b291bee0d960c53170780af148dca5fa260a63cdd24f1962fa82e03e53338c" +dependencies = [ + "byteorder", + "enumflags2", + "libc", + "serde", + "static_assertions", + "zvariant_derive", +] + +[[package]] +name = "zvariant_derive" +version = "3.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "934d7a7dfc310d6ee06c87ffe88ef4eca7d3e37bb251dece2ef93da8f17d8ecd" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7234f0d811589db492d16893e3f21e8e2fd282e6d01b0cddee310322062cc200" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", ] diff --git a/Cargo.toml b/Cargo.toml index 3262870d1..c886a8724 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ resolver = "2" simplexpr = { version = "0.1.0", path = "crates/simplexpr" } eww_shared_util = { version = "0.1.0", path = "crates/eww_shared_util" } yuck = { version = "0.1.0", path = "crates/yuck", default-features = false} +notifier_host = { version = "0.1.0", path = "crates/notifier_host" } anyhow = "1.0.79" bincode = "1.3.3" diff --git a/crates/eww/Cargo.toml b/crates/eww/Cargo.toml index 554fd86de..2aa461a46 100644 --- a/crates/eww/Cargo.toml +++ b/crates/eww/Cargo.toml @@ -19,6 +19,7 @@ wayland = ["gtk-layer-shell"] simplexpr.workspace = true eww_shared_util.workspace = true yuck.workspace = true +notifier_host.workspace = true gtk = "0.17.1" gdk = "0.17.1" @@ -34,6 +35,9 @@ gtk-layer-shell = { version = "0.6.1", optional = true } gdkx11 = { version = "0.17", optional = true } x11rb = { version = "0.11.1", features = ["randr"], optional = true } +zbus = { version = "3.7.0", default-features = false, features = ["tokio"] } +ordered-stream = "0.2.0" + anyhow.workspace = true bincode.workspace = true chrono.workspace = true diff --git a/crates/eww/src/main.rs b/crates/eww/src/main.rs index 848c055be..0db2b975f 100644 --- a/crates/eww/src/main.rs +++ b/crates/eww/src/main.rs @@ -42,7 +42,10 @@ fn main() { if std::env::var("RUST_LOG").is_ok() { pretty_env_logger::init_timed(); } else { - pretty_env_logger::formatted_timed_builder().filter(Some("eww"), log_level_filter).init(); + pretty_env_logger::formatted_timed_builder() + .filter(Some("eww"), log_level_filter) + .filter(Some("notifier_host"), log_level_filter) + .init(); } if let opts::Action::ShellCompletions { shell } = opts.action { diff --git a/crates/eww/src/server.rs b/crates/eww/src/server.rs index be00db3af..50b24b2fa 100644 --- a/crates/eww/src/server.rs +++ b/crates/eww/src/server.rs @@ -103,7 +103,7 @@ pub fn initialize_server( } // initialize all the handlers and tasks running asyncronously - init_async_part(app.paths.clone(), ui_send); + let tokio_handle = init_async_part(app.paths.clone(), ui_send); glib::MainContext::default().spawn_local(async move { // if an action was given to the daemon initially, execute it first. @@ -124,22 +124,26 @@ pub fn initialize_server( } }); + // allow the GTK main thread to do tokio things + let _g = tokio_handle.enter(); + gtk::main(); log::info!("main application thread finished"); Ok(ForkResult::Child) } -fn init_async_part(paths: EwwPaths, ui_send: UnboundedSender) { +fn init_async_part(paths: EwwPaths, ui_send: UnboundedSender) -> tokio::runtime::Handle { + let rt = tokio::runtime::Builder::new_multi_thread() + .thread_name("main-async-runtime") + .enable_all() + .build() + .expect("Failed to initialize tokio runtime"); + let handle = rt.handle().clone(); + std::thread::Builder::new() .name("outer-main-async-runtime".to_string()) .spawn(move || { - let rt = tokio::runtime::Builder::new_multi_thread() - .thread_name("main-async-runtime") - .enable_all() - .build() - .expect("Failed to initialize tokio runtime"); - rt.block_on(async { let filewatch_join_handle = { let ui_send = ui_send.clone(); @@ -171,6 +175,8 @@ fn init_async_part(paths: EwwPaths, ui_send: UnboundedSender }) }) .expect("Failed to start outer-main-async-runtime thread"); + + handle } /// Watch configuration files for changes, sending reload events to the eww app when the files change. diff --git a/crates/eww/src/widgets/def_widget_macro.rs b/crates/eww/src/widgets/def_widget_macro.rs index 311ce6f85..44a1faf25 100644 --- a/crates/eww/src/widgets/def_widget_macro.rs +++ b/crates/eww/src/widgets/def_widget_macro.rs @@ -53,6 +53,8 @@ macro_rules! def_widget { // values is a map of all the variables that are required to evaluate the // attributes expression. + // allow $gtk_widget to never be used, by creating a reference that gets immediately discarded + {let _ = &$gtk_widget;}; // We first initialize all the local variables for all the expected attributes in scope $( diff --git a/crates/eww/src/widgets/mod.rs b/crates/eww/src/widgets/mod.rs index 6e7c6c933..35d05cf2a 100644 --- a/crates/eww/src/widgets/mod.rs +++ b/crates/eww/src/widgets/mod.rs @@ -4,6 +4,7 @@ pub mod build_widget; pub mod circular_progressbar; pub mod def_widget_macro; pub mod graph; +mod systray; pub mod transform; pub mod widget_definitions; diff --git a/crates/eww/src/widgets/systray.rs b/crates/eww/src/widgets/systray.rs new file mode 100644 index 000000000..bd3f28e41 --- /dev/null +++ b/crates/eww/src/widgets/systray.rs @@ -0,0 +1,203 @@ +use futures::StreamExt; +use gtk::{cairo::Surface, gdk::ffi::gdk_cairo_surface_create_from_pixbuf, prelude::*}; +use notifier_host; + +// DBus state shared between systray instances, to avoid creating too many connections etc. +struct DBusSession { + snw: notifier_host::proxy::StatusNotifierWatcherProxy<'static>, +} + +async fn dbus_session() -> zbus::Result<&'static DBusSession> { + // TODO make DBusSession reference counted so it's dropped when not in use? + + static DBUS_STATE: tokio::sync::OnceCell = tokio::sync::OnceCell::const_new(); + DBUS_STATE + .get_or_try_init(|| async { + let con = zbus::Connection::session().await?; + notifier_host::Watcher::new().attach_to(&con).await?; + + let (_, snw) = notifier_host::register_as_host(&con).await?; + + Ok(DBusSession { snw }) + }) + .await +} + +pub struct Props { + icon_size_tx: tokio::sync::watch::Sender, +} + +impl Props { + pub fn new() -> Self { + let (icon_size_tx, _) = tokio::sync::watch::channel(24); + Self { icon_size_tx } + } + + pub fn icon_size(&self, value: i32) { + let _ = self.icon_size_tx.send_if_modified(|x| { + if *x == value { + false + } else { + *x = value; + true + } + }); + } +} + +struct Tray { + menubar: gtk::MenuBar, + items: std::collections::HashMap, + + icon_size: tokio::sync::watch::Receiver, +} + +pub fn spawn_systray(menubar: >k::MenuBar, props: &Props) { + let mut systray = Tray { menubar: menubar.clone(), items: Default::default(), icon_size: props.icon_size_tx.subscribe() }; + + let task = glib::MainContext::default().spawn_local(async move { + let s = match dbus_session().await { + Ok(x) => x, + Err(e) => { + log::error!("could not initialise dbus connection for tray: {}", e); + return; + } + }; + + systray.menubar.show(); + let e = notifier_host::run_host(&mut systray, &s.snw).await; + log::error!("notifier host error: {}", e); + }); + + // stop the task when the widget is dropped + menubar.connect_destroy(move |_| { + task.abort(); + }); +} + +impl notifier_host::Host for Tray { + fn add_item(&mut self, id: &str, item: notifier_host::Item) { + let item = Item::new(id.to_owned(), item, self.icon_size.clone()); + self.menubar.add(&item.widget); + if let Some(old_item) = self.items.insert(id.to_string(), item) { + self.menubar.remove(&old_item.widget); + } + } + + fn remove_item(&mut self, id: &str) { + if let Some(item) = self.items.get(id) { + self.menubar.remove(&item.widget); + } else { + log::warn!("Tried to remove nonexistent item {:?} from systray", id); + } + } +} + +/// Item represents a single icon being shown in the system tray. +struct Item { + /// Main widget representing this tray item. + widget: gtk::MenuItem, + + /// Async task to stop when this item gets removed. + task: Option>, +} + +impl Drop for Item { + fn drop(&mut self) { + if let Some(task) = &self.task { + task.abort(); + } + } +} + +impl Item { + fn new(id: String, item: notifier_host::Item, icon_size: tokio::sync::watch::Receiver) -> Self { + let widget = gtk::MenuItem::new(); + let out_widget = widget.clone(); // copy so we can return it + + let task = glib::MainContext::default().spawn_local(async move { + if let Err(e) = Item::maintain(widget.clone(), item, icon_size).await { + log::error!("error for systray item {}: {}", id, e); + } + }); + + Self { widget: out_widget, task: Some(task) } + } + + async fn maintain( + widget: gtk::MenuItem, + item: notifier_host::Item, + mut icon_size: tokio::sync::watch::Receiver, + ) -> zbus::Result<()> { + // init icon + let icon = gtk::Image::new(); + widget.add(&icon); + icon.show(); + + // init menu + match item.menu().await { + Ok(m) => widget.set_submenu(Some(&m)), + Err(e) => log::warn!("failed to get menu: {}", e), + } + + // TODO this is a lot of code duplication unfortunately, i'm not really sure how to + // refactor without making the borrow checker angry + + // set status + match item.status().await? { + notifier_host::Status::Passive => widget.hide(), + notifier_host::Status::Active | notifier_host::Status::NeedsAttention => widget.show(), + } + + // set title + widget.set_tooltip_text(Some(&item.sni.title().await?)); + + // set icon + let scale = icon.scale_factor(); + load_icon_for_item(&icon, &item, *icon_size.borrow_and_update(), scale).await; + + // updates + let mut status_updates = item.sni.receive_new_status().await?; + let mut title_updates = item.sni.receive_new_status().await?; + let mut icon_updates = item.sni.receive_new_icon().await?; + + loop { + tokio::select! { + Some(_) = status_updates.next() => { + // set status + match item.status().await? { + notifier_host::Status::Passive => widget.hide(), + notifier_host::Status::Active | notifier_host::Status::NeedsAttention => widget.show(), + } + } + Ok(_) = icon_size.changed() => { + // set icon + load_icon_for_item(&icon, &item, *icon_size.borrow_and_update(), scale).await; + } + Some(_) = title_updates.next() => { + // set title + widget.set_tooltip_text(Some(&item.sni.title().await?)); + } + Some(_) = icon_updates.next() => { + // set icon + load_icon_for_item(&icon, &item, *icon_size.borrow_and_update(), scale).await; + } + } + } + } +} + +async fn load_icon_for_item(icon: >k::Image, item: ¬ifier_host::Item, size: i32, scale: i32) { + if let Some(pixbuf) = item.icon(size, scale).await { + let surface = unsafe { + // gtk::cairo::Surface will destroy the underlying surface on drop + let ptr = gdk_cairo_surface_create_from_pixbuf( + pixbuf.as_ptr(), + scale, + icon.window().map_or(std::ptr::null_mut(), |v| v.as_ptr()), + ); + Surface::from_raw_full(ptr) + }; + icon.set_from_surface(surface.ok().as_ref()); + } +} diff --git a/crates/eww/src/widgets/widget_definitions.rs b/crates/eww/src/widgets/widget_definitions.rs index a390c0de5..015344c4e 100644 --- a/crates/eww/src/widgets/widget_definitions.rs +++ b/crates/eww/src/widgets/widget_definitions.rs @@ -3,7 +3,7 @@ use super::{build_widget::BuilderArgs, circular_progressbar::*, run_command, tra use crate::{ def_widget, enum_parse, error_handling_ctx, util::{self, list_difference}, - widgets::build_widget::build_gtk_widget, + widgets::{build_widget::build_gtk_widget, systray}, }; use anyhow::{anyhow, Context, Result}; use codespan_reporting::diagnostic::Severity; @@ -82,6 +82,7 @@ pub const BUILTIN_WIDGET_NAMES: &[&str] = &[ WIDGET_NAME_SCROLL, WIDGET_NAME_OVERLAY, WIDGET_NAME_STACK, + WIDGET_NAME_SYSTRAY, ]; /// widget definitions @@ -111,6 +112,7 @@ pub(super) fn widget_use_to_gtk_widget(bargs: &mut BuilderArgs) -> Result build_gtk_scrolledwindow(bargs)?.upcast(), WIDGET_NAME_OVERLAY => build_gtk_overlay(bargs)?.upcast(), WIDGET_NAME_STACK => build_gtk_stack(bargs)?.upcast(), + WIDGET_NAME_SYSTRAY => build_systray(bargs)?.upcast(), _ => { return Err(DiagError(gen_diagnostic! { msg = format!("referenced unknown widget `{}`", bargs.widget_use.name), @@ -1133,6 +1135,33 @@ fn build_graph(bargs: &mut BuilderArgs) -> Result { Ok(w) } +const WIDGET_NAME_SYSTRAY: &str = "systray"; +/// @widget systray +/// @desc Tray for system notifier icons +fn build_systray(bargs: &mut BuilderArgs) -> Result { + let gtk_widget = gtk::MenuBar::new(); + let props = Rc::new(systray::Props::new()); + let props_clone = props.clone(); + + // copies for def_widget + def_widget!(bargs, _g, gtk_widget, { + // @prop icon-size - size of icons in the tray + prop(icon_size: as_i32) { + if icon_size <= 0 { + log::warn!("Icon size is not a positive number"); + } else { + props.icon_size(icon_size); + } + }, + // @prop pack-direction - how to arrange tray items + prop(pack_direction: as_string) { gtk_widget.set_pack_direction(parse_packdirection(&pack_direction)?); }, + }); + + systray::spawn_systray(>k_widget, &props_clone); + + Ok(gtk_widget) +} + /// @var orientation - "vertical", "v", "horizontal", "h" fn parse_orientation(o: &str) -> Result { enum_parse! { "orientation", o, @@ -1210,6 +1239,16 @@ fn parse_gravity(g: &str) -> Result { } } +/// @var pack-direction - "right", "ltr", "left", "rtl", "down", "ttb", "up", "btt" +fn parse_packdirection(o: &str) -> Result { + enum_parse! { "packdirection", o, + "right" | "ltr" => gtk::PackDirection::Ltr, + "left" | "rtl" => gtk::PackDirection::Rtl, + "down" | "ttb" => gtk::PackDirection::Ttb, + "up" | "btt" => gtk::PackDirection::Btt, + } +} + /// Connect a function to the first map event of a widget. After that first map, the handler will get disconnected. fn connect_first_map, F: Fn(&W) + 'static>(widget: &W, func: F) { let signal_handler_id = std::rc::Rc::new(std::cell::RefCell::new(None)); diff --git a/crates/notifier_host/Cargo.toml b/crates/notifier_host/Cargo.toml new file mode 100644 index 000000000..a03a2a2ff --- /dev/null +++ b/crates/notifier_host/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "notifier_host" +version = "0.1.0" +authors = ["elkowar <5300871+elkowar@users.noreply.github.com>"] +edition = "2021" +license = "MIT" +description = "SystemNotifierHost implementation" +repository = "https://github.com/elkowar/eww" +homepage = "https://github.com/elkowar/eww" + +[dependencies] +gtk = "0.17.1" +zbus = { version = "3.7.0", default-features = false, features = ["tokio"] } +dbusmenu-gtk3 = "0.1.0" + +log.workspace = true +thiserror.workspace = true +tokio = { workspace = true, features = ["full"] } diff --git a/crates/notifier_host/src/host.rs b/crates/notifier_host/src/host.rs new file mode 100644 index 000000000..b937395cb --- /dev/null +++ b/crates/notifier_host/src/host.rs @@ -0,0 +1,135 @@ +use crate::*; + +use zbus::export::ordered_stream::{self, OrderedStreamExt}; + +/// Trait for system tray implementations, to be notified of changes to what items are in the tray. +pub trait Host { + /// Called when an item is added to the tray. This is also called for all existing items when + /// starting [`run_host`]. + fn add_item(&mut self, id: &str, item: Item); + + /// Called when an item is removed from the tray. + fn remove_item(&mut self, id: &str); +} + +// TODO We aren't really thinking about what happens when we shut down a host. Currently, we don't +// provide a way to unregister as a host. +// +// It would also be good to combine `register_as_host` and `run_host`, so that we're only +// registered while we're running. + +/// Register this DBus connection as a StatusNotifierHost (i.e. system tray). +/// +/// This associates with the DBus connection new name of the format +/// `org.freedesktop.StatusNotifierHost-{pid}-{nr}`, and registers it to active +/// StatusNotifierWatcher. The name and the StatusNotifierWatcher proxy are returned. +/// +/// You still need to call [`run_host`] to have the instance of [`Host`] be notified of new and +/// removed items. +pub async fn register_as_host( + con: &zbus::Connection, +) -> zbus::Result<(zbus::names::WellKnownName<'static>, proxy::StatusNotifierWatcherProxy<'static>)> { + let snw = proxy::StatusNotifierWatcherProxy::new(con).await?; + + // get a well-known name + let pid = std::process::id(); + let mut i = 0; + let wellknown = loop { + use zbus::fdo::RequestNameReply::*; + + i += 1; + let wellknown = format!("org.freedesktop.StatusNotifierHost-{}-{}", pid, i); + let wellknown: zbus::names::WellKnownName = wellknown.try_into().expect("generated well-known name is invalid"); + + let flags = [zbus::fdo::RequestNameFlags::DoNotQueue]; + match con.request_name_with_flags(&wellknown, flags.into_iter().collect()).await? { + PrimaryOwner => break wellknown, + Exists => {} + AlreadyOwner => {} + InQueue => unreachable!("request_name_with_flags returned InQueue even though we specified DoNotQueue"), + }; + }; + + // register it to the StatusNotifierWatcher, so that they know there is a systray on the system + snw.register_status_notifier_host(&wellknown).await?; + + Ok((wellknown, snw)) +} + +/// Run the Host forever, calling its methods as signals are received from the StatusNotifierWatcher. +/// +/// Before calling this, you should have called [`register_as_host`] (which returns an instance of +/// [`proxy::StatusNotifierWatcherProxy`]). +/// +/// This async function runs forever, and only returns if it gets an error! As such, it is +/// recommended to call this via something like `tokio::spawn` that runs this in the +/// background. +pub async fn run_host(host: &mut dyn Host, snw: &proxy::StatusNotifierWatcherProxy<'static>) -> zbus::Error { + // Replacement for ? operator since we're not returning a Result. + macro_rules! try_ { + ($e:expr) => { + match $e { + Ok(x) => x, + Err(e) => return e, + } + }; + } + + enum ItemEvent { + NewItem(proxy::StatusNotifierItemRegistered), + GoneItem(proxy::StatusNotifierItemUnregistered), + } + + // start listening to these streams + let new_items = try_!(snw.receive_status_notifier_item_registered().await); + let gone_items = try_!(snw.receive_status_notifier_item_unregistered().await); + + let mut item_names = std::collections::HashSet::new(); + + // initial items first + for svc in try_!(snw.registered_status_notifier_items().await) { + match Item::from_address(snw.connection(), &svc).await { + Ok(item) => { + item_names.insert(svc.to_owned()); + host.add_item(&svc, item); + } + Err(e) => { + log::warn!("Could not create StatusNotifierItem from address {:?}: {:?}", svc, e); + } + } + } + + let mut ev_stream = ordered_stream::join( + OrderedStreamExt::map(new_items, ItemEvent::NewItem), + OrderedStreamExt::map(gone_items, ItemEvent::GoneItem), + ); + while let Some(ev) = ev_stream.next().await { + match ev { + ItemEvent::NewItem(sig) => { + let svc = try_!(sig.args()).service; + if item_names.contains(svc) { + log::info!("Got duplicate new item: {:?}", svc); + } else { + match Item::from_address(snw.connection(), svc).await { + Ok(item) => { + item_names.insert(svc.to_owned()); + host.add_item(svc, item); + } + Err(e) => { + log::warn!("Could not create StatusNotifierItem from address {:?}: {:?}", svc, e); + } + } + } + } + ItemEvent::GoneItem(sig) => { + let svc = try_!(sig.args()).service; + if item_names.remove(svc) { + host.remove_item(svc); + } + } + } + } + + // I do not know whether this is possible to reach or not. + unreachable!("StatusNotifierWatcher stopped producing events") +} diff --git a/crates/notifier_host/src/icon.rs b/crates/notifier_host/src/icon.rs new file mode 100644 index 000000000..45057e41a --- /dev/null +++ b/crates/notifier_host/src/icon.rs @@ -0,0 +1,207 @@ +use crate::*; + +use gtk::{self, prelude::*}; + +#[derive(thiserror::Error, Debug)] +enum IconError { + #[error("while fetching icon name: {0}")] + DBusIconName(#[source] zbus::Error), + #[error("while fetching icon theme path: {0}")] + DBusTheme(#[source] zbus::Error), + #[error("while fetching pixmap: {0}")] + DBusPixmap(#[source] zbus::Error), + #[error("loading icon from file {path:?}")] + LoadIconFromFile { + path: String, + #[source] + source: gtk::glib::Error, + }, + #[error("loading icon {icon_name:?} from theme {}", .theme_path.as_ref().unwrap_or(&"(default)".to_owned()))] + LoadIconFromTheme { + icon_name: String, + theme_path: Option, + #[source] + source: gtk::glib::Error, + }, + #[error("no icon available")] + NotAvailable, +} + +/// Get the fallback GTK icon, as a final fallback if the tray item has no icon. +async fn fallback_icon(size: i32, scale: i32) -> Option { + let theme = gtk::IconTheme::default().expect("Could not get default gtk theme"); + match theme.load_icon_for_scale("image-missing", size, scale, gtk::IconLookupFlags::FORCE_SIZE) { + Ok(pb) => pb, + Err(e) => { + log::error!("failed to load \"image-missing\" from default theme: {}", e); + None + } + } +} + +/// Load a pixbuf from StatusNotifierItem's [Icon format]. +/// +/// [Icon format]: https://freedesktop.org/wiki/Specifications/StatusNotifierItem/Icons/ +fn icon_from_pixmap(width: i32, height: i32, mut data: Vec) -> gtk::gdk_pixbuf::Pixbuf { + // We need to convert data from ARGB32 to RGBA32, since that's the only one that gdk-pixbuf + // understands. + for chunk in data.chunks_exact_mut(4) { + let a = chunk[0]; + let r = chunk[1]; + let g = chunk[2]; + let b = chunk[3]; + chunk[0] = r; + chunk[1] = g; + chunk[2] = b; + chunk[3] = a; + } + + gtk::gdk_pixbuf::Pixbuf::from_bytes( + >k::glib::Bytes::from_owned(data), + gtk::gdk_pixbuf::Colorspace::Rgb, + true, + 8, + width, + height, + width * 4, + ) +} + +/// From a list of pixmaps, create an icon from the most appropriately sized one. +/// +/// This function returns None if and only if no pixmaps are provided. +fn icon_from_pixmaps(pixmaps: Vec<(i32, i32, Vec)>, size: i32) -> Option { + pixmaps + .into_iter() + .max_by(|(w1, h1, _), (w2, h2, _)| { + // take smallest one bigger than requested size, otherwise take biggest + let a = size * size; + let a1 = w1 * h1; + let a2 = w2 * h2; + match (a1 >= a, a2 >= a) { + (true, true) => a2.cmp(&a1), + (true, false) => std::cmp::Ordering::Greater, + (false, true) => std::cmp::Ordering::Less, + (false, false) => a1.cmp(&a2), + } + }) + .and_then(|(w, h, d)| { + let pixbuf = icon_from_pixmap(w, h, d); + if w != size || h != size { + pixbuf.scale_simple(size, size, gtk::gdk_pixbuf::InterpType::Bilinear) + } else { + Some(pixbuf) + } + }) +} + +/// Load an icon with a given name from either the default (if `theme_path` is `None`), or from the +/// theme at a path. +fn icon_from_name( + icon_name: &str, + theme_path: Option<&str>, + size: i32, + scale: i32, +) -> std::result::Result { + let theme = if let Some(path) = theme_path { + let theme = gtk::IconTheme::new(); + theme.prepend_search_path(&path); + theme + } else { + gtk::IconTheme::default().expect("Could not get default gtk theme") + }; + + match theme.load_icon_for_scale(icon_name, size, scale, gtk::IconLookupFlags::FORCE_SIZE) { + Ok(pb) => Ok(pb.expect("no pixbuf from theme.load_icon despite no error")), + Err(e) => Err(IconError::LoadIconFromTheme { + icon_name: icon_name.to_owned(), + theme_path: theme_path.map(str::to_owned), + source: e, + }), + } +} + +pub async fn load_icon_from_sni( + sni: &proxy::StatusNotifierItemProxy<'_>, + size: i32, + scale: i32, +) -> Option { + // "Visualizations are encouraged to prefer icon names over icon pixmaps if both are + // available." + + let scaled_size = size * scale; + + // First, see if we can get an icon from the name they provide, using either the theme they + // specify or the default. + let icon_from_name: std::result::Result = (async { + // fetch icon name + let icon_name = sni.icon_name().await; + log::debug!("dbus: {} icon_name -> {:?}", sni.destination(), icon_name); + let icon_name = match icon_name { + Ok(s) if s.is_empty() => return Err(IconError::NotAvailable), + Ok(s) => s, + Err(e) => return Err(IconError::DBusIconName(e)), + }; + + // interpret it as an absolute path if we can + let icon_path = std::path::Path::new(&icon_name); + if icon_path.is_absolute() && icon_path.is_file() { + return gtk::gdk_pixbuf::Pixbuf::from_file_at_size(icon_path, scaled_size, scaled_size) + .map_err(|e| IconError::LoadIconFromFile { path: icon_name, source: e }); + } + + // otherwise, fetch icon theme and lookup using icon_from_name + let icon_theme_path = sni.icon_theme_path().await; + log::debug!("dbus: {} icon_theme_path -> {:?}", sni.destination(), icon_theme_path); + let icon_theme_path = match icon_theme_path { + Ok(p) if p.is_empty() => None, + Ok(p) => Some(p), + // treat property not existing as the same as it being empty i.e. to use the default + // system theme + Err(zbus::Error::FDO(e)) => match *e { + zbus::fdo::Error::UnknownProperty(_) | zbus::fdo::Error::InvalidArgs(_) => None, + // this error is reported by discord, blueman-applet + zbus::fdo::Error::Failed(msg) if msg == "error occurred in Get" => None, + _ => return Err(IconError::DBusTheme(zbus::Error::FDO(e))), + }, + Err(e) => return Err(IconError::DBusTheme(e)), + }; + + let icon_theme_path: Option<&str> = match &icon_theme_path { + // this looks weird but this converts &String to &str + Some(s) => Some(s), + None => None, + }; + icon_from_name(&icon_name, icon_theme_path, size, scale) + }) + .await; + + match icon_from_name { + Ok(p) => return Some(p), // got an icon! + Err(IconError::NotAvailable) => {} // this error is expected, don't log + Err(e) => log::warn!("failed to get icon by name for {}: {}", sni.destination(), e), + }; + + // Can't get it from name + theme, try the pixmap + let icon_from_pixmaps = match sni.icon_pixmap().await { + Ok(ps) => match icon_from_pixmaps(ps, scaled_size) { + Some(p) => Ok(p), + None => Err(IconError::NotAvailable), + }, + Err(zbus::Error::FDO(e)) => match *e { + // property not existing is an expected error + zbus::fdo::Error::UnknownProperty(_) | zbus::fdo::Error::InvalidArgs(_) => Err(IconError::NotAvailable), + + _ => Err(IconError::DBusPixmap(zbus::Error::FDO(e))), + }, + Err(e) => Err(IconError::DBusPixmap(e)), + }; + match icon_from_pixmaps { + Ok(p) => return Some(p), + Err(IconError::NotAvailable) => {} + Err(e) => log::warn!("failed to get icon pixmap for {}: {}", sni.destination(), e), + }; + + // Tray didn't provide a valid icon so use the default fallback one. + fallback_icon(size, scale).await +} diff --git a/crates/notifier_host/src/item.rs b/crates/notifier_host/src/item.rs new file mode 100644 index 000000000..c258957e7 --- /dev/null +++ b/crates/notifier_host/src/item.rs @@ -0,0 +1,97 @@ +use crate::*; + +use gtk::{self, prelude::*}; + +/// Recognised values of [`org.freedesktop.StatusNotifierItem.Status`]. +/// +/// [`org.freedesktop.StatusNotifierItem.Status`]: https://www.freedesktop.org/wiki/Specifications/StatusNotifierItem/StatusNotifierItem/#org.freedesktop.statusnotifieritem.status +#[derive(Debug, Clone, Copy)] +pub enum Status { + /// The item doesn't convey important information to the user, it can be considered an "idle" + /// status and is likely that visualizations will chose to hide it. + Passive, + /// The item is active, is more important that the item will be shown in some way to the user. + Active, + /// The item carries really important information for the user, such as battery charge running + /// out and is wants to incentive the direct user intervention. Visualizations should emphasize + /// in some way the items with NeedsAttention status. + NeedsAttention, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub struct ParseStatusError; + +impl std::str::FromStr for Status { + type Err = ParseStatusError; + + fn from_str(s: &str) -> std::result::Result { + match s { + "Passive" => Ok(Status::Passive), + "Active" => Ok(Status::Active), + "NeedsAttention" => Ok(Status::NeedsAttention), + _ => Err(ParseStatusError), + } + } +} + +/// A StatusNotifierItem (SNI). +/// +/// At the moment, this does not wrap much of the SNI's properties and methods. As such, you should +/// directly access the `sni` member as needed for functionalty that is not provided. +pub struct Item { + /// The StatusNotifierItem that is wrapped by this instance. + pub sni: proxy::StatusNotifierItemProxy<'static>, +} + +impl Item { + /// Create an instance from the service's address. + /// + /// The format of `addr` is `{bus}{object_path}` (e.g. + /// `:1.50/org/ayatana/NotificationItem/nm_applet`), which is the format that is used for + /// StatusNotifierWatcher's [RegisteredStatusNotifierItems property][rsni]). + /// + /// [rsni]: https://freedesktop.org/wiki/Specifications/StatusNotifierItem/StatusNotifierWatcher/#registeredstatusnotifieritems + pub async fn from_address(con: &zbus::Connection, service: &str) -> zbus::Result { + let (addr, path) = { + // Based on + // + // TODO is the service name format actually documented anywhere? + if let Some((addr, path)) = service.split_once('/') { + (addr.to_owned(), format!("/{}", path)) + } else if service.starts_with(':') { + (service[0..6].to_owned(), names::ITEM_OBJECT.to_owned()) + } else { + return Err(zbus::Error::Address(service.to_owned())); + } + }; + + let sni = proxy::StatusNotifierItemProxy::builder(con).destination(addr)?.path(path)?.build().await?; + + Ok(Item { sni }) + } + + /// Get the current status of the item. + pub async fn status(&self) -> zbus::Result { + let status = self.sni.status().await?; + match status.parse() { + Ok(s) => Ok(s), + Err(_) => Err(zbus::Error::Failure(format!("Invalid status {:?}", status))), + } + } + + /// Get the menu of this item. + pub async fn menu(&self) -> zbus::Result { + // TODO document what this returns if there is no menu. + let menu = dbusmenu_gtk3::Menu::new(self.sni.destination(), &self.sni.menu().await?); + Ok(menu.upcast()) + } + + /// Get the current icon. + pub async fn icon(&self, size: i32, scale: i32) -> Option { + // TODO explain what size and scale mean here + + // see icon.rs + load_icon_from_sni(&self.sni, size, scale).await + } +} diff --git a/crates/notifier_host/src/lib.rs b/crates/notifier_host/src/lib.rs new file mode 100644 index 000000000..8a8c46dd3 --- /dev/null +++ b/crates/notifier_host/src/lib.rs @@ -0,0 +1,52 @@ +//! The system tray side of the [notifier host DBus +//! protocols](https://freedesktop.org/wiki/Specifications/StatusNotifierItem/StatusNotifierHost/), +//! implementing most of the relevant DBus protocol logic so system tray implementations (e.g. eww) +//! don't need to care about them. +//! +//! This crate does not implement the tray icon side of the protocol. For that, see, for example, +//! the [ksni](https://crates.io/crates/ksni) crate. +//! +//! # Overview / Notes for Contributors +//! +//! This crate makes extensive use of the `zbus` library to interact with DBus. You should read +//! through the [zbus tutorial](https://dbus2.github.io/zbus/) if you aren't familiar with DBus or +//! `zbus`. +//! +//! There are two separate services that are required for the tray side of the protocol: +//! +//! - `StatusNotifierWatcher`, a service which tracks what items and trays there are but doesn't do +//! any rendering. This is implemented by [`Watcher`] (see that for further details), and +//! should always be started alongside the `StatusNotifierHost`. +//! +//! - `StatusNotifierHost`, the actual tray, which registers itself to the StatusNotifierHost and +//! subscribes to its signals to know what items exist. This DBus service has a completely +//! empty interface, but is mainly by StatusNotifierWatcher to know when trays disappear. This +//! is represented by the [`Host`] trait. +//! +//! The actual tray implements the [`Host`] trait to be notified of when items (called +//! `StatusNotifierItem` in the spec and represented by [`Item`]) appear and disappear, then calls +//! [`run_host`] to run the DBus side of the protocol. +//! +//! If there are multiple trays running on the system, there can be multiple `StatusNotifierHost`s, +//! but only one `StatusNotifierWatcher` (usually from whatever tray was started first). + +pub mod proxy; + +mod host; +pub use host::*; + +mod icon; +pub use icon::*; + +mod item; +pub use item::*; + +mod watcher; +pub use watcher::*; + +pub(crate) mod names { + pub const WATCHER_BUS: &str = "org.kde.StatusNotifierWatcher"; + pub const WATCHER_OBJECT: &str = "/StatusNotifierWatcher"; + + pub const ITEM_OBJECT: &str = "/StatusNotifierItem"; +} diff --git a/crates/notifier_host/src/proxy/dbus_menu.xml b/crates/notifier_host/src/proxy/dbus_menu.xml new file mode 100644 index 000000000..ae5d79067 --- /dev/null +++ b/crates/notifier_host/src/proxy/dbus_menu.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/crates/notifier_host/src/proxy/dbus_status_notifier_item.rs b/crates/notifier_host/src/proxy/dbus_status_notifier_item.rs new file mode 100644 index 000000000..5c57b2a15 --- /dev/null +++ b/crates/notifier_host/src/proxy/dbus_status_notifier_item.rs @@ -0,0 +1,114 @@ +//! # DBus interface proxy for: `org.kde.StatusNotifierItem` +//! +//! This code was generated by `zbus-xmlgen` `3.1.0` from DBus introspection data. +//! Source: `dbus-status-notifier-item.xml`. +//! +//! You may prefer to adapt it, instead of using it verbatim. +//! +//! More information can be found in the +//! [Writing a client proxy](https://dbus.pages.freedesktop.org/zbus/client.html) +//! section of the zbus documentation. + +// suppress warning from generated code +#![allow(clippy::type_complexity)] + +use zbus::dbus_proxy; + +#[dbus_proxy(interface = "org.kde.StatusNotifierItem", assume_defaults = true)] +trait StatusNotifierItem { + /// Activate method + fn activate(&self, x: i32, y: i32) -> zbus::Result<()>; + + /// ContextMenu method + fn context_menu(&self, x: i32, y: i32) -> zbus::Result<()>; + + /// Scroll method + fn scroll(&self, delta: i32, orientation: &str) -> zbus::Result<()>; + + /// SecondaryActivate method + fn secondary_activate(&self, x: i32, y: i32) -> zbus::Result<()>; + + /// NewAttentionIcon signal + #[dbus_proxy(signal)] + fn new_attention_icon(&self) -> zbus::Result<()>; + + /// NewIcon signal + #[dbus_proxy(signal)] + fn new_icon(&self) -> zbus::Result<()>; + + /// NewOverlayIcon signal + #[dbus_proxy(signal)] + fn new_overlay_icon(&self) -> zbus::Result<()>; + + /// NewStatus signal + #[dbus_proxy(signal)] + fn new_status(&self, status: &str) -> zbus::Result<()>; + + /// NewTitle signal + #[dbus_proxy(signal)] + fn new_title(&self) -> zbus::Result<()>; + + /// NewToolTip signal + #[dbus_proxy(signal)] + fn new_tool_tip(&self) -> zbus::Result<()>; + + /// AttentionIconName property + #[dbus_proxy(property)] + fn attention_icon_name(&self) -> zbus::Result; + + /// AttentionIconPixmap property + #[dbus_proxy(property)] + fn attention_icon_pixmap(&self) -> zbus::Result)>>; + + /// AttentionMovieName property + #[dbus_proxy(property)] + fn attention_movie_name(&self) -> zbus::Result; + + /// Category property + #[dbus_proxy(property)] + fn category(&self) -> zbus::Result; + + /// IconName property + #[dbus_proxy(property(emits_changed_signal = "false"))] + fn icon_name(&self) -> zbus::Result; + + /// IconPixmap property + #[dbus_proxy(property(emits_changed_signal = "false"))] + fn icon_pixmap(&self) -> zbus::Result)>>; + + /// IconThemePath property + #[dbus_proxy(property)] + fn icon_theme_path(&self) -> zbus::Result; + + /// Id property + #[dbus_proxy(property)] + fn id(&self) -> zbus::Result; + + /// ItemIsMenu property + #[dbus_proxy(property)] + fn item_is_menu(&self) -> zbus::Result; + + /// Menu property + #[dbus_proxy(property)] + fn menu(&self) -> zbus::Result; + + /// OverlayIconName property + #[dbus_proxy(property)] + fn overlay_icon_name(&self) -> zbus::Result; + + /// OverlayIconPixmap property + #[dbus_proxy(property)] + fn overlay_icon_pixmap(&self) -> zbus::Result)>>; + + /// Status property + #[dbus_proxy(property)] + fn status(&self) -> zbus::Result; + + /// Title property + #[dbus_proxy(property)] + fn title(&self) -> zbus::Result; + + /// ToolTip property + #[dbus_proxy(property)] + fn tool_tip(&self) -> zbus::Result<(String, Vec<(i32, i32, Vec)>)>; +} diff --git a/crates/notifier_host/src/proxy/dbus_status_notifier_item.xml b/crates/notifier_host/src/proxy/dbus_status_notifier_item.xml new file mode 100644 index 000000000..c33cd8460 --- /dev/null +++ b/crates/notifier_host/src/proxy/dbus_status_notifier_item.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/crates/notifier_host/src/proxy/dbus_status_notifier_watcher.rs b/crates/notifier_host/src/proxy/dbus_status_notifier_watcher.rs new file mode 100644 index 000000000..9ac2eaa9c --- /dev/null +++ b/crates/notifier_host/src/proxy/dbus_status_notifier_watcher.rs @@ -0,0 +1,53 @@ +//! # DBus interface proxy for: `org.kde.StatusNotifierWatcher` +//! +//! This code was generated by `zbus-xmlgen` `3.1.0` from DBus introspection data. +//! Source: `dbus-status-notifier-watcher.xml`. +//! +//! You may prefer to adapt it, instead of using it verbatim. +//! +//! More information can be found in the +//! [Writing a client proxy](https://dbus.pages.freedesktop.org/zbus/client.html) +//! section of the zbus documentation. + +use zbus::dbus_proxy; + +#[dbus_proxy( + default_service = "org.kde.StatusNotifierWatcher", + interface = "org.kde.StatusNotifierWatcher", + default_path = "/StatusNotifierWatcher" +)] +trait StatusNotifierWatcher { + /// RegisterStatusNotifierHost method + fn register_status_notifier_host(&self, service: &str) -> zbus::Result<()>; + + /// RegisterStatusNotifierItem method + fn register_status_notifier_item(&self, service: &str) -> zbus::Result<()>; + + /// StatusNotifierHostRegistered signal + #[dbus_proxy(signal)] + fn status_notifier_host_registered(&self) -> zbus::Result<()>; + + /// StatusNotifierHostUnregistered signal + #[dbus_proxy(signal)] + fn status_notifier_host_unregistered(&self) -> zbus::Result<()>; + + /// StatusNotifierItemRegistered signal + #[dbus_proxy(signal)] + fn status_notifier_item_registered(&self, service: &str) -> zbus::Result<()>; + + /// StatusNotifierItemUnregistered signal + #[dbus_proxy(signal)] + fn status_notifier_item_unregistered(&self, service: &str) -> zbus::Result<()>; + + /// IsStatusNotifierHostRegistered property + #[dbus_proxy(property)] + fn is_status_notifier_host_registered(&self) -> zbus::Result; + + /// ProtocolVersion property + #[dbus_proxy(property)] + fn protocol_version(&self) -> zbus::Result; + + /// RegisteredStatusNotifierItems property + #[dbus_proxy(property)] + fn registered_status_notifier_items(&self) -> zbus::Result>; +} diff --git a/crates/notifier_host/src/proxy/dbus_status_notifier_watcher.xml b/crates/notifier_host/src/proxy/dbus_status_notifier_watcher.xml new file mode 100644 index 000000000..6370e4dd2 --- /dev/null +++ b/crates/notifier_host/src/proxy/dbus_status_notifier_watcher.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/crates/notifier_host/src/proxy/mod.rs b/crates/notifier_host/src/proxy/mod.rs new file mode 100644 index 000000000..8c8e9dfbd --- /dev/null +++ b/crates/notifier_host/src/proxy/mod.rs @@ -0,0 +1,16 @@ +//! Proxies for DBus services, so we can call them. +//! +//! The interface XML files were taken from +//! [Waybar](https://github.com/Alexays/Waybar/tree/master/protocol), and the proxies were +//! generated with [zbus-xmlgen](https://docs.rs/crate/zbus_xmlgen/latest) by running `zbus-xmlgen +//! dbus_status_notifier_item.xml` and `zbus-xmlgen dbus_status_notifier_watcher.xml`. At the +//! moment, `dbus_menu.xml` isn't used. +//! +//! For more information, see ["Writing a client proxy" in the zbus +//! tutorial](https://dbus2.github.io/zbus/). + +mod dbus_status_notifier_item; +pub use dbus_status_notifier_item::*; + +mod dbus_status_notifier_watcher; +pub use dbus_status_notifier_watcher::*; diff --git a/crates/notifier_host/src/watcher.rs b/crates/notifier_host/src/watcher.rs new file mode 100644 index 000000000..a0e7c139a --- /dev/null +++ b/crates/notifier_host/src/watcher.rs @@ -0,0 +1,299 @@ +use crate::names; +use zbus::{dbus_interface, export::ordered_stream::OrderedStreamExt, Interface}; + +/// An instance of [`org.kde.StatusNotifierWatcher`]. It only tracks what tray items and trays +/// exist, and doesn't have any logic for displaying items (for that, see [`Host`][`crate::Host`]). +/// +/// While this is usually run alongside the tray, it can also be used standalone. +/// +/// [`org.kde.StatusNotifierWatcher`]: https://freedesktop.org/wiki/Specifications/StatusNotifierItem/StatusNotifierWatcher/ +#[derive(Debug, Default)] +pub struct Watcher { + tasks: tokio::task::JoinSet<()>, + + // Intentionally using std::sync::Mutex instead of tokio's async mutex, since we don't need to + // hold the mutex across an await. + // + // See + hosts: std::sync::Arc>>, + items: std::sync::Arc>>, +} + +/// Implementation of the `StatusNotifierWatcher` service. +/// +/// Methods and properties correspond to methods and properties on the DBus service that can be +/// used by others, while signals are events that we generate that other services listen to. +#[dbus_interface(name = "org.kde.StatusNotifierWatcher")] +impl Watcher { + /// RegisterStatusNotifierHost method + async fn register_status_notifier_host( + &mut self, + service: &str, + #[zbus(header)] hdr: zbus::MessageHeader<'_>, + #[zbus(connection)] con: &zbus::Connection, + #[zbus(signal_context)] ctxt: zbus::SignalContext<'_>, + ) -> zbus::fdo::Result<()> { + // TODO right now, we convert everything to the unique bus name (something like :1.234). + // However, it might make more sense to listen to the actual name they give us, so that if + // the connection dissociates itself from the org.kde.StatusNotifierHost-{pid}-{nr} name + // but still remains around, we drop them as a host. + // + // (This also applies to RegisterStatusNotifierItem) + + let (service, _) = parse_service(service, hdr, con).await?; + log::info!("new host: {}", service); + + let added_first = { + // scoped around locking of hosts + let mut hosts = self.hosts.lock().unwrap(); // unwrap: mutex poisoning is okay + if !hosts.insert(service.to_string()) { + // we're already tracking them + return Ok(()); + } + hosts.len() == 1 + }; + + if added_first { + self.is_status_notifier_host_registered_changed(&ctxt).await?; + } + Watcher::status_notifier_host_registered(&ctxt).await?; + + self.tasks.spawn({ + let hosts = self.hosts.clone(); + let ctxt = ctxt.to_owned(); + let con = con.to_owned(); + async move { + if let Err(e) = wait_for_service_exit(&con, service.as_ref().into()).await { + log::error!("failed to wait for service exit: {}", e); + } + log::info!("lost host: {}", service); + + let removed_last = { + let mut hosts = hosts.lock().unwrap(); // unwrap: mutex poisoning is okay + let did_remove = hosts.remove(service.as_str()); + did_remove && hosts.is_empty() + }; + + if removed_last { + if let Err(e) = Watcher::is_status_notifier_host_registered_refresh(&ctxt).await { + log::error!("failed to signal Watcher: {}", e); + } + } + if let Err(e) = Watcher::status_notifier_host_unregistered(&ctxt).await { + log::error!("failed to signal Watcher: {}", e); + } + } + }); + + Ok(()) + } + + /// StatusNotifierHostRegistered signal. + #[dbus_interface(signal)] + async fn status_notifier_host_registered(ctxt: &zbus::SignalContext<'_>) -> zbus::Result<()>; + + /// StatusNotifierHostUnregistered signal + #[dbus_interface(signal)] + async fn status_notifier_host_unregistered(ctxt: &zbus::SignalContext<'_>) -> zbus::Result<()>; + + /// IsStatusNotifierHostRegistered property + #[dbus_interface(property)] + async fn is_status_notifier_host_registered(&self) -> bool { + let hosts = self.hosts.lock().unwrap(); // unwrap: mutex poisoning is okay + !hosts.is_empty() + } + + // ------------------------------------------------------------------------ + + /// RegisterStatusNotifierItem method + async fn register_status_notifier_item( + &mut self, + service: &str, + #[zbus(header)] hdr: zbus::MessageHeader<'_>, + #[zbus(connection)] con: &zbus::Connection, + #[zbus(signal_context)] ctxt: zbus::SignalContext<'_>, + ) -> zbus::fdo::Result<()> { + let (service, objpath) = parse_service(service, hdr, con).await?; + let service = zbus::names::BusName::Unique(service); + + let item = format!("{}{}", service, objpath); + + { + let mut items = self.items.lock().unwrap(); // unwrap: mutex poisoning is okay + if !items.insert(item.clone()) { + // we're already tracking them + log::info!("new item: {} (duplicate)", item); + return Ok(()); + } + } + log::info!("new item: {}", item); + + self.registered_status_notifier_items_changed(&ctxt).await?; + Watcher::status_notifier_item_registered(&ctxt, item.as_ref()).await?; + + self.tasks.spawn({ + let items = self.items.clone(); + let ctxt = ctxt.to_owned(); + let con = con.to_owned(); + async move { + if let Err(e) = wait_for_service_exit(&con, service.as_ref()).await { + log::error!("failed to wait for service exit: {}", e); + } + println!("gone item: {}", &item); + + { + let mut items = items.lock().unwrap(); // unwrap: mutex poisoning is okay + items.remove(&item); + } + + if let Err(e) = Watcher::registered_status_notifier_items_refresh(&ctxt).await { + log::error!("failed to signal Watcher: {}", e); + } + if let Err(e) = Watcher::status_notifier_item_unregistered(&ctxt, item.as_ref()).await { + log::error!("failed to signal Watcher: {}", e); + } + } + }); + + Ok(()) + } + + /// StatusNotifierItemRegistered signal + #[dbus_interface(signal)] + async fn status_notifier_item_registered(ctxt: &zbus::SignalContext<'_>, service: &str) -> zbus::Result<()>; + + /// StatusNotifierItemUnregistered signal + #[dbus_interface(signal)] + async fn status_notifier_item_unregistered(ctxt: &zbus::SignalContext<'_>, service: &str) -> zbus::Result<()>; + + /// RegisteredStatusNotifierItems property + #[dbus_interface(property)] + async fn registered_status_notifier_items(&self) -> Vec { + let items = self.items.lock().unwrap(); // unwrap: mutex poisoning is okay + items.iter().cloned().collect() + } + + // ------------------------------------------------------------------------ + + /// ProtocolVersion property + #[dbus_interface(property)] + fn protocol_version(&self) -> i32 { + 0 + } +} + +impl Watcher { + /// Create a new Watcher. + pub fn new() -> Watcher { + Default::default() + } + + /// Attach and run the Watcher (in the background) on a connection. + pub async fn attach_to(self, con: &zbus::Connection) -> zbus::Result<()> { + if !con.object_server().at(names::WATCHER_OBJECT, self).await? { + return Err(zbus::Error::Failure(format!( + "Object already exists at {} on this connection -- is StatusNotifierWatcher already running?", + names::WATCHER_OBJECT + ))); + } + + // not AllowReplacement, not ReplaceExisting, not DoNotQueue + let flags: [zbus::fdo::RequestNameFlags; 0] = []; + match con.request_name_with_flags(names::WATCHER_BUS, flags.into_iter().collect()).await { + Ok(zbus::fdo::RequestNameReply::PrimaryOwner) => Ok(()), + Ok(_) | Err(zbus::Error::NameTaken) => Ok(()), // defer to existing + Err(e) => Err(e), + } + } + + /// Equivalent to `is_status_notifier_host_registered_invalidate`, but without requiring + /// `self`. + async fn is_status_notifier_host_registered_refresh(ctxt: &zbus::SignalContext<'_>) -> zbus::Result<()> { + zbus::fdo::Properties::properties_changed( + ctxt, + Self::name(), + &std::collections::HashMap::new(), + &["IsStatusNotifierHostRegistered"], + ) + .await + } + + /// Equivalent to `registered_status_notifier_items_invalidate`, but without requiring `self`. + async fn registered_status_notifier_items_refresh(ctxt: &zbus::SignalContext<'_>) -> zbus::Result<()> { + zbus::fdo::Properties::properties_changed( + ctxt, + Self::name(), + &std::collections::HashMap::new(), + &["RegisteredStatusNotifierItems"], + ) + .await + } +} + +/// Decode the service name that others give to us, into the [bus +/// name](https://dbus2.github.io/zbus/concepts.html#bus-name--service-name) and the [object +/// path](https://dbus2.github.io/zbus/concepts.html#objects-and-object-paths) within the +/// connection. +/// +/// The freedesktop.org specification has the format of this be just the bus name, however some +/// status items pass non-conforming values. One common one is just the object path. +async fn parse_service<'a>( + service: &'a str, + hdr: zbus::MessageHeader<'_>, + con: &zbus::Connection, +) -> zbus::fdo::Result<(zbus::names::UniqueName<'static>, &'a str)> { + if service.starts_with('/') { + // they sent us just the object path + if let Some(sender) = hdr.sender()? { + Ok((sender.to_owned(), service)) + } else { + log::warn!("unknown sender"); + Err(zbus::fdo::Error::InvalidArgs("Unknown bus address".into())) + } + } else { + // parse the bus name they gave us + let busname: zbus::names::BusName = match service.try_into() { + Ok(x) => x, + Err(e) => { + log::warn!("received invalid bus name {:?}: {}", service, e); + return Err(zbus::fdo::Error::InvalidArgs(e.to_string())); + } + }; + + if let zbus::names::BusName::Unique(unique) = busname { + Ok((unique.to_owned(), names::ITEM_OBJECT)) + } else { + // they gave us a "well-known name" like org.kde.StatusNotifierHost-81830-0, we need to + // convert this into the actual identifier for their bus (e.g. :1.234), so that even if + // they remove that well-known name it's fine. + let dbus = zbus::fdo::DBusProxy::new(con).await?; + match dbus.get_name_owner(busname).await { + Ok(owner) => Ok((owner.into_inner(), names::ITEM_OBJECT)), + Err(e) => { + log::warn!("failed to get owner of {:?}: {}", service, e); + Err(e) + } + } + } + } +} + +/// Wait for a DBus service to disappear +async fn wait_for_service_exit(con: &zbus::Connection, service: zbus::names::BusName<'_>) -> zbus::fdo::Result<()> { + let dbus = zbus::fdo::DBusProxy::new(con).await?; + let mut owner_changes = dbus.receive_name_owner_changed_with_args(&[(0, &service)]).await?; + + if !dbus.name_has_owner(service.as_ref()).await? { + // service has already disappeared + return Ok(()); + } + + while let Some(sig) = owner_changes.next().await { + let args = sig.args()?; + if args.new_owner().is_none() { + break; + } + } + + Ok(()) +} diff --git a/docs/src/eww.md b/docs/src/eww.md index f9c938586..ea571768a 100644 --- a/docs/src/eww.md +++ b/docs/src/eww.md @@ -29,6 +29,7 @@ The following list of package names should work for arch linux: - gtk-layer-shell (only on Wayland) - pango (libpango) - gdk-pixbuf2 (libgdk_pixbuf-2) +- libdbusmenu-gtk3 - cairo (libcairo, libcairo-gobject) - glib2 (libgio, libglib-2, libgobject-2) - gcc-libs (libgcc) diff --git a/flake.nix b/flake.nix index 21b522d78..ef574e15a 100644 --- a/flake.nix +++ b/flake.nix @@ -42,6 +42,8 @@ cargoDeps = rustPlatform.importCargoLock { lockFile = ./Cargo.lock; }; patches = [ ]; + # remove this when nixpkgs includes it + buildInputs = old.buildInputs ++ [ final.libdbusmenu-gtk3 ]; }); eww-wayland = final.eww; @@ -63,6 +65,10 @@ rust rust-analyzer-unwrapped gcc + glib + gdk-pixbuf + librsvg + libdbusmenu-gtk3 gtk3 gtk-layer-shell pkg-config