diff --git a/Cargo.lock b/Cargo.lock index ea685d4..67cdc4d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,15 +8,6 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "330223a1aecc308757b9926e9391c9b47f8ef2dbd8aea9df88312aea18c5e8d6" -[[package]] -name = "aho-corasick" -version = "0.7.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" -dependencies = [ - "memchr", -] - [[package]] name = "android_system_properties" version = "0.1.5" @@ -26,89 +17,6 @@ dependencies = [ "libc", ] -[[package]] -name = "async-broadcast" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b19760fa2b7301cf235360ffd6d3558b1ed4249edd16d6cca8d690cee265b95" -dependencies = [ - "event-listener", - "futures-core", - "parking_lot", -] - -[[package]] -name = "async-executor" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b" -dependencies = [ - "async-lock", - "async-task", - "concurrent-queue", - "fastrand", - "futures-lite", - "slab", -] - -[[package]] -name = "async-io" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794" -dependencies = [ - "async-lock", - "autocfg", - "concurrent-queue", - "futures-lite", - "libc", - "log", - "parking", - "polling", - "slab", - "socket2", - "waker-fn", - "windows-sys", -] - -[[package]] -name = "async-lock" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685" -dependencies = [ - "event-listener", - "futures-lite", -] - -[[package]] -name = "async-recursion" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b015a331cc64ebd1774ba119538573603427eaace0a1950c423ab971f903796" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "async-task" -version = "4.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524" - -[[package]] -name = "async-trait" -version = "0.1.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eff18d764974428cf3a9328e23fc5c986f5fbed46e6cd4cdf42544df5d297ec1" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "autocfg" version = "1.1.0" @@ -136,18 +44,6 @@ version = "3.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "bytes" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" - [[package]] name = "calloop" version = "0.10.5" @@ -198,15 +94,6 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "concurrent-queue" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c278839b831783b70278b14df4d45e1beb1aad306c07bb796637de9a0e323e8e" -dependencies = [ - "crossbeam-utils", -] - [[package]] name = "const-cstr" version = "0.3.0" @@ -228,15 +115,6 @@ dependencies = [ "libc", ] -[[package]] -name = "crossbeam-utils" -version = "0.8.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" -dependencies = [ - "cfg-if", -] - [[package]] name = "crypto-common" version = "0.1.6" @@ -292,14 +170,14 @@ dependencies = [ ] [[package]] -name = "derivative" -version = "2.2.0" +name = "dbus" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +checksum = "1bb21987b9fb1613058ba3843121dd18b163b254d8a6e797e144cbac14d96d1b" dependencies = [ - "proc-macro2", - "quote", - "syn", + "libc", + "libdbus-sys", + "winapi", ] [[package]] @@ -312,26 +190,6 @@ dependencies = [ "crypto-common", ] -[[package]] -name = "dirs" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" -dependencies = [ - "dirs-sys", -] - -[[package]] -name = "dirs-sys" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - [[package]] name = "dlib" version = "0.5.0" @@ -353,42 +211,6 @@ version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" -[[package]] -name = "enumflags2" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e75d4cd21b95383444831539909fbb14b9dc3fdceb2a6f5d36577329a1f55ccb" -dependencies = [ - "enumflags2_derive", - "serde", -] - -[[package]] -name = "enumflags2_derive" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f58dc3c5e468259f19f2d46304a6b28f1c3d034442e14b322d2b850e36f6d5ae" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "event-listener" -version = "2.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - -[[package]] -name = "fastrand" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" -dependencies = [ - "instant", -] - [[package]] name = "fontconfig" version = "0.6.0" @@ -398,59 +220,6 @@ dependencies = [ "yeslogic-fontconfig-sys", ] -[[package]] -name = "futures-core" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" - -[[package]] -name = "futures-io" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" - -[[package]] -name = "futures-lite" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" -dependencies = [ - "fastrand", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] - -[[package]] -name = "futures-sink" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" - -[[package]] -name = "futures-task" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" - -[[package]] -name = "futures-util" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" -dependencies = [ - "futures-core", - "futures-sink", - "futures-task", - "pin-project-lite", - "pin-utils", - "slab", -] - [[package]] name = "fuzzy-matcher" version = "0.3.7" @@ -470,23 +239,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "getrandom" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", -] - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - [[package]] name = "iana-time-zone" version = "0.1.53" @@ -511,15 +263,6 @@ dependencies = [ "cxx-build", ] -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - [[package]] name = "io-lifetimes" version = "1.0.3" @@ -551,6 +294,15 @@ version = "0.2.138" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" +[[package]] +name = "libdbus-sys" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f8d7ae751e1cb825c840ae5e682f59b098cdfd213c350ac268b61449a5f58a0" +dependencies = [ + "pkg-config", +] + [[package]] name = "libloading" version = "0.7.4" @@ -597,16 +349,6 @@ dependencies = [ "cc", ] -[[package]] -name = "lock_api" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" -dependencies = [ - "autocfg", - "scopeguard", -] - [[package]] name = "log" version = "0.4.17" @@ -659,18 +401,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "mio" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" -dependencies = [ - "libc", - "log", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", -] - [[package]] name = "nix" version = "0.25.1" @@ -682,7 +412,6 @@ dependencies = [ "cfg-if", "libc", "memoffset 0.6.5", - "pin-utils", ] [[package]] @@ -768,16 +497,6 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" -[[package]] -name = "ordered-stream" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4eb9ba3f3e42dbdd3b7b122de5ca169c81e93d561eb900da3a8c99bcfcf381a" -dependencies = [ - "futures-core", - "pin-project-lite", -] - [[package]] name = "owned_ttf_parser" version = "0.15.2" @@ -787,35 +506,6 @@ dependencies = [ "ttf-parser", ] -[[package]] -name = "parking" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" - -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba1ef8814b5c993410bb3adfad7a5ed269563e4a2f90c41f5d85be7fb47133bf" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-sys", -] - [[package]] name = "pest" version = "2.5.2" @@ -860,12 +550,6 @@ dependencies = [ "sha1", ] -[[package]] -name = "pin-project-lite" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" - [[package]] name = "pin-utils" version = "0.1.0" @@ -878,37 +562,6 @@ version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" -[[package]] -name = "polling" -version = "2.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22122d5ec4f9fe1b3916419b76be1e80bcb93f618d071d2edf841b137b2a2bd6" -dependencies = [ - "autocfg", - "cfg-if", - "libc", - "log", - "wepoll-ffi", - "windows-sys", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "proc-macro-crate" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9" -dependencies = [ - "once_cell", - "thiserror", - "toml", -] - [[package]] name = "proc-macro2" version = "1.0.47" @@ -936,36 +589,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "rand" -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", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - [[package]] name = "rcalc_lib" version = "1.0.0" @@ -982,52 +605,6 @@ dependencies = [ "pest_derive", ] -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags", -] - -[[package]] -name = "redox_users" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" -dependencies = [ - "getrandom", - "redox_syscall", - "thiserror", -] - -[[package]] -name = "regex" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.6.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" - -[[package]] -name = "remove_dir_all" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] - [[package]] name = "rusttype" version = "0.9.3" @@ -1053,49 +630,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - [[package]] name = "scratch" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" -[[package]] -name = "serde" -version = "1.0.152" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.152" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_repr" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a5ec9fa74a20ebbe5d9ac23dac1fc96ba0ecfe9f50f2843b52e537b10fbcb4e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "sha1" version = "0.10.5" @@ -1113,15 +653,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" -[[package]] -name = "slab" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" -dependencies = [ - "autocfg", -] - [[package]] name = "slotmap" version = "1.0.6" @@ -1137,16 +668,6 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" -[[package]] -name = "socket2" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "static_assertions" version = "1.1.0" @@ -1164,20 +685,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "tempfile" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" -dependencies = [ - "cfg-if", - "fastrand", - "libc", - "redox_syscall", - "remove_dir_all", - "winapi", -] - [[package]] name = "termcolor" version = "1.1.3" @@ -1223,79 +730,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" dependencies = [ "libc", - "wasi 0.10.0+wasi-snapshot-preview1", + "wasi", "winapi", ] -[[package]] -name = "tokio" -version = "1.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a12a59981d9e3c38d216785b0c37399f6e415e8d0712047620f189371b0bb" -dependencies = [ - "autocfg", - "bytes", - "libc", - "memchr", - "mio", - "pin-project-lite", - "socket2", - "tracing", - "windows-sys", -] - -[[package]] -name = "tokio-stream" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "toml" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" -dependencies = [ - "serde", -] - -[[package]] -name = "tracing" -version = "0.1.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" -dependencies = [ - "cfg-if", - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tracing-core" -version = "0.1.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" -dependencies = [ - "once_cell", -] - [[package]] name = "ttf-parser" version = "0.15.2" @@ -1314,16 +752,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" -[[package]] -name = "uds_windows" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce65604324d3cce9b966701489fbd0cf318cb1f7bd9dd07ac9a4ee6fb791930d" -dependencies = [ - "tempfile", - "winapi", -] - [[package]] name = "unicode-ident" version = "1.0.5" @@ -1342,17 +770,6 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" -[[package]] -name = "upower_dbus" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0b1d77de98ab2e5187f5fa2b045b8c4eecfc49e5ccd07f16f4c89f008116f8c" -dependencies = [ - "serde", - "serde_repr", - "zbus", -] - [[package]] name = "vec_map" version = "0.8.2" @@ -1365,12 +782,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[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.3.2" @@ -1388,12 +799,6 @@ 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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - [[package]] name = "wasm-bindgen" version = "0.2.83" @@ -1524,15 +929,6 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "wepoll-ffi" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" -dependencies = [ - "cc", -] - [[package]] name = "winapi" version = "0.3.9" @@ -1628,6 +1024,7 @@ dependencies = [ "bitflags", "calloop", "chrono", + "dbus", "fontconfig", "fuzzy-matcher", "libpulse-binding", @@ -1636,16 +1033,12 @@ dependencies = [ "rcalc_lib", "rusttype", "shlex", - "tokio", - "tokio-stream", "unicode-segmentation", - "upower_dbus", "walkdir", "wayland-client", "wayland-protocols", "wayland-protocols-wlr", "xkbcommon", - "zbus", ] [[package]] @@ -1669,93 +1062,3 @@ dependencies = [ "once_cell", "pkg-config", ] - -[[package]] -name = "zbus" -version = "3.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "379d587c0ccb632d1179cf44082653f682842f0535f0fdfaefffc34849cc855e" -dependencies = [ - "async-broadcast", - "async-executor", - "async-io", - "async-lock", - "async-recursion", - "async-task", - "async-trait", - "byteorder", - "derivative", - "dirs", - "enumflags2", - "event-listener", - "futures-core", - "futures-sink", - "futures-util", - "hex", - "lazy_static", - "nix 0.25.1", - "once_cell", - "ordered-stream", - "rand", - "serde", - "serde_repr", - "sha1", - "static_assertions", - "tokio", - "tracing", - "uds_windows", - "winapi", - "zbus_macros", - "zbus_names", - "zvariant", -] - -[[package]] -name = "zbus_macros" -version = "3.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66492a2e90c0df7190583eccb8424aa12eb7ff06edea415a4fff6688fae18cf8" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "regex", - "syn", -] - -[[package]] -name = "zbus_names" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f34f314916bd89bdb9934154627fab152f4f28acdda03e7c4c68181b214fe7e3" -dependencies = [ - "serde", - "static_assertions", - "zvariant", -] - -[[package]] -name = "zvariant" -version = "3.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576cc41e65c7f283e5460f5818073e68fb1f1631502b969ef228c2e03c862efb" -dependencies = [ - "byteorder", - "enumflags2", - "libc", - "serde", - "static_assertions", - "zvariant_derive", -] - -[[package]] -name = "zvariant_derive" -version = "3.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fd4aafc0dee96ae7242a24249ce9babf21e1562822f03df650d4e68c20e41ed" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", -] diff --git a/Cargo.toml b/Cargo.toml index c218727..9580b5a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,11 +31,9 @@ fuzzy-matcher = "0.3" shlex = "1.1" xkbcommon = { version = "0.5", features = ["wayland"] } -upower_dbus = "0.3" -zbus = { version = "3.7", default-features = false, features = ["tokio"] } -tokio = { version = "1.24", default-features = false, features = ["rt"] } -tokio-stream = "0.1" rcalc_lib = "1.0" +#alsa = { version = "0.7", optional = true } +dbus = "0.9" libpulse-binding = "2.26" diff --git a/src/buffer.rs b/src/buffer.rs index 4be85fa..07117a8 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -244,31 +244,30 @@ impl<'a> BufferView<'a> { } } - pub fn limit(&mut self, dimensions: (u32, u32)) -> BufferView { - let bounds = self.get_bounds(); - if cfg!(debug_assertions) && (dimensions.0 > bounds.2 || dimensions.1 > bounds.3) { - panic!("cannot create offset outside buffer: {:?} > {:?}", dimensions, bounds); - } - - BufferView { - view: self.view, - dimensions: self.dimensions, - subdimensions: Some((bounds.0, bounds.1, dimensions.0, dimensions.1)), - } - } - pub fn memset(&mut self, c: Color) { if let Some(subdim) = self.subdimensions { for y in subdim.1..(subdim.1 + subdim.3) { - for x in subdim.0..(subdim.0 + subdim.2) { - self.view[(x + y * self.dimensions.0) as usize] = c.0; - } + let start = (subdim.0 + y * self.dimensions.0) as usize; + let end = start + subdim.2 as usize; + self.view[start..end].fill(c.0); } } else { self.view.fill(c.0); } } + pub fn clear(&mut self) { + if let Some(subdim) = self.subdimensions { + for y in subdim.1..(subdim.1 + subdim.3) { + let start = (subdim.0 + y * self.dimensions.0) as usize; + let end = start + subdim.2 as usize; + self.view[start..end].fill(0x0); + } + } else { + self.view.fill(0x0); + } + } + pub fn put(&mut self, pos: (u32, u32), c: Color) { let true_pos = if let Some(subdim) = self.subdimensions { if cfg!(debug_assertions) && (pos.0 >= subdim.2 || pos.1 >= subdim.3) { diff --git a/src/color.rs b/src/color.rs index f911120..88d5989 100644 --- a/src/color.rs +++ b/src/color.rs @@ -75,18 +75,11 @@ fn blend_f32(a: f32, b: f32, r: f32) -> f32 { a + ((b - a) * r) } */ -#[inline] -fn blend_u8(a: u8, b: u8, r: f32) -> u32 { - let af = a as f32; - let bf = b as f32; - (af + ((bf - af) * r)) as u32 -} #[derive(Copy, Clone)] pub struct Color(pub u32); impl Color { - pub const BLACK: Color = Color(0xFF000000); pub const WHITE: Color = Color(0xFFFFFFFF); pub const GREY50: Color = Color(0xFF7F7F7F); pub const GREY75: Color = Color(0xFFBFBFBF); @@ -104,17 +97,17 @@ impl Color { Color((opacity as u32) << 24 | (red as u32) << 16 | (green as u32) << 8 | (blue as u32)) } - fn opacity(self) -> u8 {((self.0 >> 24) & 0xFF) as u8 } fn red(self) -> u8 {((self.0 >> 16) & 0xFF) as u8 } fn green(self) -> u8 {((self.0 >> 8) & 0xFF) as u8 } fn blue(self) -> u8 {(self.0 & 0xFF) as u8 } - pub fn blend(self, other: Color, ratio: f32) -> Color { - Color( - blend_u8(self.opacity(), other.opacity(), ratio) << 24 | - blend_u8(self.red(), other.red(), ratio) << 16 | - blend_u8(self.green(), other.green(), ratio) << 8 | - blend_u8(self.blue(), other.blue(), ratio) - ) + pub fn alpha(self, alpha: f32) -> Color { + unsafe { + Color( + (255. * alpha).to_int_unchecked::() << 24 | + (self.red() as f32 * alpha).to_int_unchecked::() << 16 | + (self.green() as f32 * alpha).to_int_unchecked::() << 8 | + (self.blue() as f32 * alpha).to_int_unchecked::()) + } } } diff --git a/src/draw.rs b/src/draw.rs index 3bafd4a..37b71d8 100644 --- a/src/draw.rs +++ b/src/draw.rs @@ -47,7 +47,7 @@ impl CachedGlyph { } } - fn draw(&self, buf: &mut BufferView, pos: (i32, i32), bg: Color, c: Color) { + fn draw(&self, buf: &mut BufferView, pos: (i32, i32), c: Color) { let mut x = 0; let mut y = 0; for v in &self.render { @@ -56,7 +56,7 @@ impl CachedGlyph { (x + pos.0 + self.origin.0) as u32, (y + pos.1 + self.origin.1) as u32, ), - bg.blend(c, *v), + c.alpha(*v) ); if x == self.dimensions.0 as i32 - 1 { @@ -102,7 +102,6 @@ impl<'a> Font<'a> { pub fn draw_text( &self, buf: &mut BufferView, - bg: Color, c: Color, s: &str, ) -> Result<(u32, u32), ::std::io::Error> { @@ -125,7 +124,7 @@ impl<'a> Font<'a> { } } for glyph in glyphs { - glyph.draw(buf, (x_off, -off), bg, c); + glyph.draw(buf, (x_off, -off), c); x_off += glyph.advance; } @@ -135,7 +134,6 @@ impl<'a> Font<'a> { pub fn draw_text_with_cursor( &self, buf: &mut BufferView, - bg: Color, c: Color, s: &str, cursor: usize, @@ -164,7 +162,7 @@ impl<'a> Font<'a> { if i == cursor { self.draw_cursor(buf, c, x_off as u32, height)?; } - glyph.draw(buf, (x_off, -off), bg, c); + glyph.draw(buf, (x_off, -off), c); x_off += glyph.advance; } if cursor == glyphs.len() { @@ -212,30 +210,27 @@ impl<'a> Font<'a> { pub fn auto_draw_text( &mut self, buf: &mut BufferView, - bg: Color, c: Color, s: &str, ) -> Result<(u32, u32), ::std::io::Error> { self.add_str_to_cache(s); - self.draw_text(buf, bg, c, s) + self.draw_text(buf, c, s) } pub fn auto_draw_text_with_cursor( &mut self, buf: &mut BufferView, - bg: Color, c: Color, s: &str, cursor: usize, ) -> Result<(u32, u32), ::std::io::Error> { self.add_str_to_cache(s); - self.draw_text_with_cursor(buf, bg, c, s, cursor) + self.draw_text_with_cursor(buf, c, s, cursor) } pub fn draw_text_fixed_width( &self, buf: &mut BufferView, - bg: Color, c: Color, distances: &[u32], s: &str, @@ -259,7 +254,7 @@ impl<'a> Font<'a> { } } for (idx, glyph) in glyphs.into_iter().enumerate() { - glyph.draw(buf, (x_off, -off), bg, c); + glyph.draw(buf, (x_off, -off), c); x_off += distances[idx] as i32; } @@ -269,7 +264,6 @@ impl<'a> Font<'a> { pub fn draw_text_individual_colors( &self, buf: &mut BufferView, - bg: Color, color: &[Color], s: &str, ) -> Result<(u32, u32), ::std::io::Error> { @@ -292,7 +286,7 @@ impl<'a> Font<'a> { } } for (idx, glyph) in glyphs.into_iter().enumerate() { - glyph.draw(buf, (x_off, -off), bg, color[idx]); + glyph.draw(buf, (x_off, -off), color[idx]); x_off += glyph.advance; } @@ -302,12 +296,11 @@ impl<'a> Font<'a> { pub fn auto_draw_text_individual_colors( &mut self, buf: &mut BufferView, - bg: Color, color: &[Color], s: &str, ) -> Result<(u32, u32), ::std::io::Error> { self.add_str_to_cache(s); - self.draw_text_individual_colors(buf, bg, color, s) + self.draw_text_individual_colors(buf, color, s) } } diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index 3786d8a..aef408b 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -40,20 +40,18 @@ pub struct KeyEvent { pub struct Keyboard { state: Option, + fd: Option<(OwnedFd, u32)>, } impl Keyboard { pub fn new() -> Keyboard { - Keyboard { state: None } + Keyboard { state: None, fd: None, } } pub fn keymap(&mut self, format: WEnum, fd: OwnedFd, size: u32) { match format { WEnum::Value(wl_keyboard::KeymapFormat::XkbV1) => { - self.state = Some( - KbState::new_from_fd(fd.as_raw_fd(), size as usize) - .expect("unable to load keymap"), - ); + self.fd = Some((fd, size)); } WEnum::Value(wl_keyboard::KeymapFormat::NoKeymap) => { // TODO: how to handle this (hopefully never occuring) case? @@ -62,6 +60,19 @@ impl Keyboard { } } + pub fn realize(&mut self) { + if self.state.is_some() { + return; + } + + if let Some((fd, size)) = &self.fd { + self.state = Some( + KbState::new_from_fd(fd.as_raw_fd(), *size as usize) + .expect("unable to load keymap"), + ); + } + } + pub fn key( &mut self, serial: u32, diff --git a/src/main.rs b/src/main.rs index bb25b62..043d357 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,12 +17,11 @@ use calloop::{ use chrono::{Duration, Local, Timelike}; use buffer::BufferView; -use color::Color; use fonts::{FontMap, MaybeFontMap}; use state::{State, OperationMode}; use event::{Event, Events}; use widgets::{ - Audio, Backlight, Battery, Calendar, Clock, Date, Geometry, HorizontalLayout, IndexedLayout, + PulseAudio, Backlight, Battery, Calendar, Clock, Date, Geometry, HorizontalLayout, IndexedLayout, Interface, InvertedHorizontalLayout, Line, Margin, VerticalLayout, Widget, Layout, }; @@ -38,8 +37,6 @@ enum UIVersion { } fn main() { -// let now = Local::now(); - let mut args = env::args(); // Skip program name _ = args.next(); @@ -135,7 +132,7 @@ fn main() { let launcher = Box::new(Interface::new(events.clone(), &mut fm, "monospace", 32.)); let battery = Box::new(Battery::new(events.clone(), &mut fm, "sans", 24.)); let backlight = Box::new(Backlight::new("intel_backlight", &mut fm, "sans", 24.)); - let audio = Box::new(Audio::new(events.clone(), &mut fm, "sans", 24.)); + let audio = Box::new(PulseAudio::new(events.clone(), &mut fm, "sans", 24.)); let v: Vec> = vec![clock, date, battery, backlight, audio, calendar, launcher]; let l = Rc::new(Margin::new( @@ -168,7 +165,7 @@ fn main() { let launcher = Box::new(Interface::new(events.clone(), &mut fm, "monospace", 32.)); let battery = Box::new(Battery::new(events.clone(), &mut fm, "sans", 24.)); let backlight = Box::new(Backlight::new("intel_backlight", &mut fm, "sans", 24.)); - let audio = Box::new(Audio::new(events.clone(), &mut fm, "sans", 24.)); + let audio = Box::new(PulseAudio::new(events.clone(), &mut fm, "sans", 24.)); let v: Vec> = vec![clock, date, battery, backlight, audio, line, calendar, launcher]; let l = Rc::new(VerticalLayout::new(vec![ HorizontalLayout::new(vec![ @@ -232,30 +229,24 @@ fn main() { (state.dimensions.0 as u32, state.dimensions.1 as u32), ); -// eprintln!("time: {}", (Local::now() - now).num_milliseconds()); - - let surface = state.base_surface.as_ref().unwrap().clone(); + let surface = state.main_surface.wl_surface.as_ref().unwrap().clone(); if force { - if state.needs_memset { - bufview.memset(Color::BLACK); - } for (idx, widget) in state.widgets.iter_mut().enumerate() { if force || widget.get_dirty() { let geo = widget.geometry(); let mut subview = bufview.subgeometry(geo); damage[idx] = widget.draw(&mut state.fonts.unwrap().borrow_mut(), &mut subview); - //draw_box(&mut subview, &Color::new(1.0, 0.5, 0.0, 1.0), (geo.width, geo.height)); } } surface.damage_buffer(0, 0, 0x7FFFFFFF, 0x7FFFFFFF) } else { let mut drew = false; for (idx, widget) in state.widgets.iter_mut().enumerate() { - if force || widget.get_dirty() { + if widget.get_dirty() { drew = true; let old_damage = damage[idx]; - bufview.subgeometry(old_damage).memset(Color::BLACK); + bufview.subgeometry(old_damage).clear(); let geo = widget.geometry(); let mut subview = bufview.subgeometry(geo); @@ -271,7 +262,6 @@ fn main() { combined_damage.width as i32, combined_damage.height as i32, ); - //draw_box(&mut subview, &Color::new(1.0, 0.5, 0.0, 1.0), (geo.width, geo.height)); } } if !drew { @@ -282,7 +272,7 @@ fn main() { surface.attach(Some(&buf.buffer), 0, 0); surface.commit(); -// eprintln!("draw time: {}", (Local::now() - now).num_milliseconds()); -// std::process::exit(0); + conn.flush().unwrap(); + state.keyboard.realize(); } } diff --git a/src/state.rs b/src/state.rs index a60343d..5831c38 100644 --- a/src/state.rs +++ b/src/state.rs @@ -3,19 +3,29 @@ use std::{ process::exit, rc::Rc, sync::{Arc, Mutex}, + default::Default, }; use wayland_client::{ protocol::{ - wl_buffer, wl_compositor, wl_keyboard, wl_registry, wl_seat, wl_shm, wl_shm_pool, - wl_surface, wl_pointer, + wl_buffer, wl_compositor, wl_subcompositor, wl_keyboard, wl_registry, wl_seat, wl_shm, wl_shm_pool, + wl_surface, wl_subsurface, wl_pointer, }, Connection, Dispatch, QueueHandle, WEnum, }; -use wayland_protocols::xdg::{ - activation::v1::client::{xdg_activation_token_v1, xdg_activation_v1}, - shell::client::{xdg_surface, xdg_toplevel, xdg_wm_base}, +use wayland_protocols::{ + xdg::{ + activation::v1::client::{xdg_activation_token_v1, xdg_activation_v1}, + shell::client::{xdg_surface, xdg_toplevel, xdg_wm_base}, + }, + wp::{ + single_pixel_buffer::v1::client::wp_single_pixel_buffer_manager_v1, + viewporter::client::{ + wp_viewport, + wp_viewporter, + }, + }, }; use wayland_protocols_wlr::layer_shell::v1::client::{ @@ -30,29 +40,46 @@ use crate::{ event::{Event, Events, PointerEvent, PointerButton}, }; +#[derive(Debug)] pub enum OperationMode { LayerSurface((u32, u32)), XdgToplevel, } +#[derive(Default)] +pub struct MainSurface { + pub wl_surface: Option, + xdg_surface: Option<(xdg_surface::XdgSurface, xdg_toplevel::XdgToplevel)>, + layer_surface: Option, +} + +#[derive(Default)] +pub struct BackgroundSurface { + wl_surface: Option, + subsurface: Option, + viewport: Option, +} + +#[derive(Default)] +pub struct Protocols { + wl_shm: Option, + xdg_activation: Option, + viewporter: Option, +} + pub struct State { mode: OperationMode, + pub main_surface: MainSurface, + pub bg_surface: BackgroundSurface, + pub protocols: Protocols, pub running: bool, pub dirty: bool, activated: bool, - pub needs_memset: bool, - pub base_surface: Option, - layer_shell: Option, - layer_surface: Option, - wm_base: Option, - xdg_surface: Option<(xdg_surface::XdgSurface, xdg_toplevel::XdgToplevel)>, - wl_shm: Option, - xdg_activation: Option, pub configured: bool, pub dimensions: (i32, i32), pub bufmgr: BufferManager, pub widgets: Vec>, - keyboard: Keyboard, + pub keyboard: Keyboard, pointer: Option<(f64, f64)>, pub fonts: MaybeFontMap, pub events: Arc>, @@ -68,17 +95,12 @@ impl State { events: Arc>, ) -> State { State { + protocols: Default::default(), + bg_surface: Default::default(), + main_surface: Default::default(), running: true, dirty: true, activated: false, - needs_memset: true, - base_surface: None, - layer_shell: None, - layer_surface: None, - wm_base: None, - xdg_surface: None, - wl_shm: None, - xdg_activation: None, configured: false, dimensions: (320, 240), bufmgr: BufferManager::new(), @@ -94,7 +116,7 @@ impl State { pub fn add_buffer(&mut self, qh: &QueueHandle) { self.bufmgr.add_buffer( - self.wl_shm.as_ref().expect("missing wl_shm"), + self.protocols.wl_shm.as_ref().expect("missing wl_shm"), self.dimensions, qh, ); @@ -105,7 +127,7 @@ impl State { Ok(token) => token, Err(_) => return, }; - match (&self.base_surface, &self.xdg_activation) { + match (&self.main_surface.wl_surface, &self.protocols.xdg_activation) { (Some(surface), Some(activation)) => { activation.activate(key, surface); let activation_token = activation.get_activation_token(qh, ()); @@ -115,31 +137,6 @@ impl State { _ => (), } } - - fn init_xdg_surface(&mut self, qh: &QueueHandle) { - let wm_base = self.wm_base.as_ref().unwrap(); - let base_surface = self.base_surface.as_ref().unwrap(); - - let xdg_surface = wm_base.get_xdg_surface(base_surface, qh, ()); - let toplevel = xdg_surface.get_toplevel(qh, ()); - toplevel.set_title("wldash".into()); - - base_surface.commit(); - - self.xdg_surface = Some((xdg_surface, toplevel)); - } - - fn init_layer_surface(&mut self, qh: &QueueHandle, size: (u32, u32)) { - let layer_shell = self.layer_shell.as_ref().unwrap(); - let base_surface = self.base_surface.as_ref().unwrap(); - - let layer_surface = layer_shell.get_layer_surface(base_surface, None, zwlr_layer_shell_v1::Layer::Top, "launcher".to_string(), qh, ()); - layer_surface.set_keyboard_interactivity(zwlr_layer_surface_v1::KeyboardInteractivity::Exclusive); - layer_surface.set_size(size.0, size.1); - - base_surface.commit(); - self.layer_surface = Some(layer_surface); - } } impl WidgetUpdater for State { @@ -170,54 +167,88 @@ impl Dispatch for State { "wl_compositor" => { let compositor = registry.bind::(name, 5, qh, ()); - let surface = compositor.create_surface(qh, ()); - state.base_surface = Some(surface); + let main_surface = compositor.create_surface(qh, ()); + let bg_surface = compositor.create_surface(qh, ()); + state.main_surface.wl_surface = Some(main_surface); + state.bg_surface.wl_surface = Some(bg_surface); state.activate(qh); + } + "wl_subcompositor" => { + let subcompositor = + registry.bind::(name, 1, qh, ()); - if state.wm_base.is_some() && state.xdg_surface.is_none() && state.layer_surface.is_none() { - match state.mode { - OperationMode::XdgToplevel => state.init_xdg_surface(qh), - OperationMode::LayerSurface(size) => state.init_layer_surface(qh, size), - } + match (&state.main_surface.wl_surface, &state.bg_surface.wl_surface) { + (Some(parent), Some(child)) => { + let subsurface = subcompositor.get_subsurface(child, parent, qh, ()); + subsurface.place_below(parent); + state.bg_surface.subsurface = Some(subsurface); + }, + _ => todo!("handle early subcompositor creation"), } } "wl_shm" => { - state.wl_shm = Some(registry.bind::(name, 1, qh, ())); + state.protocols.wl_shm = Some(registry.bind::(name, 1, qh, ())); } "wl_seat" => { registry.bind::(name, 8, qh, ()); } "xdg_wm_base" => if let OperationMode::XdgToplevel = state.mode { let wm_base = registry.bind::(name, 2, qh, ()); - state.wm_base = Some(wm_base); - if state.base_surface.is_some() && state.xdg_surface.is_none() { - state.init_xdg_surface(qh); + match &state.main_surface.wl_surface { + Some(surface) => { + let xdg_surface = wm_base.get_xdg_surface(surface, qh, ()); + let toplevel = xdg_surface.get_toplevel(qh, ()); + toplevel.set_title("wldash".into()); + + surface.commit(); + + state.main_surface.xdg_surface = Some((xdg_surface, toplevel)); + } + _ => todo!("handle early xdg_shell creation"), } } "xdg_activation_v1" => { - state.xdg_activation = Some( + state.protocols.xdg_activation = Some( registry.bind::(name, 1, qh, ()), ); state.activate(qh); } "zwlr_layer_shell_v1" => if let OperationMode::LayerSurface(size) = state.mode { - state.layer_shell = Some( - registry.bind::(name, 4, qh, ()), - ); - if state.base_surface.is_some() && state.layer_surface.is_none() { - state.init_layer_surface(qh, size); + let layer_shell = registry.bind::(name, 4, qh, ()); + match &state.main_surface.wl_surface { + Some(surface) => { + let layer_surface = layer_shell.get_layer_surface(surface, None, zwlr_layer_shell_v1::Layer::Top, "launcher".to_string(), qh, ()); + layer_surface.set_keyboard_interactivity(zwlr_layer_surface_v1::KeyboardInteractivity::Exclusive); + layer_surface.set_size(size.0, size.1); + + surface.commit(); + state.main_surface.layer_surface = Some(layer_surface); + } + _ => todo!("handle early layer_shell creation"), } }, - "clay_control_v1" => { - // Buffers are zeroed by default, which is equivalent to zero alpha black. This - // is not a particularly good background, but memsetting is slow. On clay, - // toplevels that adhere to their requested dimensions only have black behind - // them, so we can save the memset in this case, speeding things up. - if let OperationMode::XdgToplevel = state.mode { - state.needs_memset = false; + "wp_viewporter" => { + let viewporter = registry.bind::(name, 1, qh, ()); + match &state.bg_surface.wl_surface { + Some(surface) => { + state.bg_surface.viewport = Some(viewporter.get_viewport(surface, qh, ())); + }, + _ => todo!("handle early viewporter creation"), } - } + state.protocols.viewporter = Some(viewporter); + }, + "wp_single_pixel_buffer_manager_v1" => { + let singlepixel = registry.bind::(name, 1, qh, ()); + match &state.bg_surface.wl_surface { + Some(surface) => { + let buffer = singlepixel.create_u32_rgba_buffer(0, 0, 0, 0xFFFFFFFF, qh, ()); + surface.attach(Some(&buffer), 0, 0); + surface.damage_buffer(0, 0, 1, 1); + }, + _ => todo!("handle early single_pixel_buffer creation"), + } + }, _ => {} } } @@ -236,6 +267,18 @@ impl Dispatch for State { } } +impl Dispatch for State { + fn event( + _: &mut Self, + _: &wl_subcompositor::WlSubcompositor, + _: wl_subcompositor::Event, + _: &(), + _: &Connection, + _: &QueueHandle, + ) { + } +} + impl Dispatch for State { fn event( _: &mut Self, @@ -248,6 +291,18 @@ impl Dispatch for State { } } +impl Dispatch for State { + fn event( + _: &mut Self, + _: &wl_subsurface::WlSubsurface, + _: wl_subsurface::Event, + _: &(), + _: &Connection, + _: &QueueHandle, + ) { + } +} + impl Dispatch for State { fn event( _: &mut Self, @@ -317,22 +372,33 @@ impl Dispatch for State { state.configured = true; state.dirty = true; - if state.dimensions != (width as i32, height as i32) { - state.bufmgr.clear_buffers(); - state.dimensions = (width as i32, height as i32); - state.fonts.resolve(); - let fonts = state.fonts.unwrap(); - let layout = state.layout.clone(); - layout.geometry_update( - &mut fonts.borrow_mut(), - &Geometry { - x: 0, - y: 0, - width: width as u32, - height: height as u32, - }, - state, - ); + let dim = (width as i32, height as i32); + + if state.dimensions == dim { + return; + } + state.bufmgr.clear_buffers(); + state.dimensions = dim; + state.fonts.resolve(); + let fonts = state.fonts.unwrap(); + let layout = state.layout.clone(); + layout.geometry_update( + &mut fonts.borrow_mut(), + &Geometry { + x: 0, + y: 0, + width: width as u32, + height: height as u32, + }, + state, + ); + + match (&state.bg_surface.wl_surface, &state.bg_surface.viewport) { + (Some(surface), Some(viewport)) => { + viewport.set_destination(dim.0, dim.1); + surface.commit(); + }, + _ => todo!("handle early layer shell creation"), } } } @@ -496,6 +562,7 @@ impl Dispatch for State { } } +// TODO: Move to dedicated pointer module const BTN_LEFT: u32 = 0x110; const BTN_RIGHT: u32 = 0x111; const BTN_MIDDLE: u32 = 0x112; @@ -574,6 +641,42 @@ impl Dispatch for State { } } +impl Dispatch for State { + fn event( + _: &mut Self, + _: &wp_single_pixel_buffer_manager_v1::WpSinglePixelBufferManagerV1, + _: wp_single_pixel_buffer_manager_v1::Event, + _: &(), + _: &Connection, + _: &QueueHandle, + ) { + } +} + +impl Dispatch for State { + fn event( + _: &mut Self, + _: &wp_viewporter::WpViewporter, + _: wp_viewporter::Event, + _: &(), + _: &Connection, + _: &QueueHandle, + ) { + } +} + +impl Dispatch for State { + fn event( + _: &mut Self, + _: &wp_viewport::WpViewport, + _: wp_viewport::Event, + _: &(), + _: &Connection, + _: &QueueHandle, + ) { + } +} + impl Dispatch for State { fn event( _: &mut Self, diff --git a/src/widgets/alsaaudio.rs b/src/widgets/alsaaudio.rs new file mode 100644 index 0000000..4ca6291 --- /dev/null +++ b/src/widgets/alsaaudio.rs @@ -0,0 +1,112 @@ +use std::{ + thread, + sync::{Arc, Mutex}, +}; + +use crate::{ + color::Color, + fonts::FontMap, + event::{Event, Events, PointerButton}, + widgets::bar_widget::{BarWidget, BarWidgetImpl}, +}; + +use alsa::mixer::{ + Mixer, Selem, SelemChannelId, SelemId, +}; + +#[inline] +fn alsa_volume_to_f32(volume: i64, min: i64, max: i64) -> f32 { + (volume - min) as f32 / (max - min) as f32 +} + +#[inline] +fn f32_to_alsa_volume(volume: f32, min: i64, max: i64) -> i64 { + min + ((max - min) as f32 * volume) as i64 +} + +fn get_master_volume(selem: &mut Selem) -> f32 { + let (min, max) = selem.get_playback_volume_range(); + selem + .get_playback_volume(SelemChannelId::mono()) + .map(|volume| alsa_volume_to_f32(volume, min, max)) + .unwrap() +} + +fn get_mute(selem: &mut Selem) -> bool { + let res = selem.get_playback_switch(SelemChannelId::FrontLeft); + false +} + +fn set_master_volume(selem: &mut Selem, volume: f32) { + let (min, max) = selem.get_playback_volume_range(); + let volume = f32_to_alsa_volume(volume, min, max); + selem.set_playback_volume_all(volume).unwrap(); +} + +fn start_monitor(inner: Arc>) { + thread::Builder::new() + .name("audiomon".to_string()) + .spawn(move || { + let mixer = Mixer::new("default", true).unwrap(); + let id = SelemId::new("Master", 0); + let mut selem = mixer.find_selem(&id).unwrap(); + + let mut inner = inner.lock().unwrap(); + inner.volume = get_master_volume(&mut selem); + inner.mute = get_mute(&mut selem); + }) + .unwrap(); +} + +struct Inner { + volume: f32, + mute: bool, +} + +pub struct AlsaAudio { + inner: Arc>, +} + +impl AlsaAudio { + pub fn new(fm: &mut FontMap, font: &'static str, size: f32) -> BarWidget { + let inner = Arc::new(Mutex::new(Inner{ + mute: false, + volume: 0., + })); + start_monitor(inner.clone()); + let dev = AlsaAudio{ inner }; + BarWidget::new(Box::new(dev), fm, font, size) + } +} + +impl BarWidgetImpl for AlsaAudio { + fn name(&self) -> &'static str { + "audio" + } + fn get_dirty(&self) -> bool { + true + } + fn value(&mut self) -> f32 { + let inner = self.inner.lock().unwrap(); + inner.volume + } + fn color(&self) -> Color { + let inner = self.inner.lock().unwrap(); + if inner.mute { + Color::DARKORANGE + } else { + Color::WHITE + } + } + fn click(&mut self, pos: f32, btn: PointerButton) { + let inner = self.inner.lock().unwrap(); + match btn { +// PointerButton::Left => inner.set_master_volume(pos), + //PointerButton::Right => Some(Change::ToggleMute), + //PointerButton::ScrollVertical(val) => Some(Change::VolumeInc((val / 512.) as f32)), + //PointerButton::ScrollHorizontal(val) => Some(Change::VolumeInc((val / 100.) as f32)), + _ => (), + }; + } + +} diff --git a/src/widgets/backlight.rs b/src/widgets/backlight.rs index 947134d..e13a771 100644 --- a/src/widgets/backlight.rs +++ b/src/widgets/backlight.rs @@ -45,7 +45,7 @@ impl BarWidgetImpl for Backlight { fn name(&self) -> &'static str { "backlight" } - fn value(&self) -> f32 { + fn value(&mut self) -> f32 { if self.cur > self.max { // what. return 1.0; diff --git a/src/widgets/bar_widget.rs b/src/widgets/bar_widget.rs index 2338938..6ee3f39 100644 --- a/src/widgets/bar_widget.rs +++ b/src/widgets/bar_widget.rs @@ -14,7 +14,7 @@ pub trait BarWidgetImpl { false } fn name(&self) -> &'static str; - fn value(&self) -> f32; + fn value(&mut self) -> f32; fn color(&self) -> Color; fn click(&mut self, _pos: f32, _btn: PointerButton) {} } @@ -50,9 +50,8 @@ impl Widget for BarWidget { fn draw(&mut self, fonts: &mut FontMap, view: &mut BufferView) -> Geometry { let font = fonts.get_font(self.font, self.size); let fg = Color::WHITE; - let bg = Color::BLACK; - font.draw_text(view, bg, fg, self.inner_widget.name()) + font.draw_text(view, fg, self.inner_widget.name()) .unwrap(); let size = self.size.ceil() as u32; let bar_offset = 4 * size; diff --git a/src/widgets/battery.rs b/src/widgets/battery.rs index 77209b9..69cca10 100644 --- a/src/widgets/battery.rs +++ b/src/widgets/battery.rs @@ -1,81 +1,111 @@ use std::{ sync::{Arc, Mutex}, thread, - error::Error, + time::Duration, +}; + +use dbus::blocking::{ + stdintf::org_freedesktop_dbus::{Properties, PropertiesPropertiesChanged}, + LocalConnection, }; use crate::{ color::Color, - event::{Event, Events}, fonts::FontMap, + event::{Event, Events}, widgets::bar_widget::{BarWidget, BarWidgetImpl}, }; -use upower_dbus::BatteryState; +enum UpowerBatteryState { + Charging, + Discharging, + Empty, + Full, + NotCharging, + Unknown, +} struct InnerBattery { value: f32, - state: BatteryState, + state: UpowerBatteryState, dirty: bool, } -async fn monitor(inner: Arc>, events: Arc>) -> Result<(), Box> { - use zbus::Connection; - use upower_dbus::UPowerProxy; - use tokio_stream::StreamExt; - - let conn = Connection::system().await?; - let proxy = UPowerProxy::new(&conn).await?; - - let device = proxy.get_display_device().await?; - - let local_inner = inner.clone(); - let local_events = events.clone(); - let mut percent_stream = device.receive_percentage_changed().await; - let a = tokio::spawn(async move { - while let Some(percent) = percent_stream.next().await { - let percent = percent.get().await.unwrap() as f32 / 100.; - let mut inner = local_inner.lock().unwrap(); - inner.value = percent; - inner.dirty = true; - drop(inner); - - let mut events = local_events.lock().unwrap(); - events.add_event(Event::PowerUpdate); - } - }); - - let local_inner = inner.clone(); - let local_events = events.clone(); - let mut state_stream = device.receive_state_changed().await; - let b = tokio::spawn(async move { - while let Some(state) = state_stream.next().await { - let state = state.get().await.unwrap(); - let mut inner = local_inner.lock().unwrap(); - inner.state = state; - inner.dirty = true; - drop(inner); - - let mut events = local_events.lock().unwrap(); - events.add_event(Event::PowerUpdate); - } - }); - a.await?; - b.await?; - - Ok(()) -} - fn start_monitor(inner: Arc>, events: Arc>) { - use tokio::runtime; thread::Builder::new() .name("battmon".to_string()) .spawn(move || { - let rt = runtime::Builder::new_current_thread() - .enable_io() - .build() + let conn = LocalConnection::new_system().unwrap(); + let device_path = "/org/freedesktop/UPower/devices/DisplayDevice"; + let proxy = conn.with_proxy( + "org.freedesktop.UPower", + device_path, + Duration::from_millis(500), + ); + + let capacity: f64 = proxy + .get("org.freedesktop.UPower.Device", "Percentage") + .expect("unable to get property"); + let state: u32 = proxy + .get("org.freedesktop.UPower.Device", "State") + .expect("unable to get state"); + + { + let mut inner = inner.lock().unwrap(); + inner.value = capacity as f32 / 100.; + inner.state = match state { + 1 => UpowerBatteryState::Charging, + 2 => UpowerBatteryState::Discharging, + 3 => UpowerBatteryState::Empty, + 4 => UpowerBatteryState::Full, + 5 => UpowerBatteryState::NotCharging, + 6 => UpowerBatteryState::Discharging, + _ => UpowerBatteryState::Unknown, + } + } + + proxy + .match_signal( + move |c: PropertiesPropertiesChanged, + _: &LocalConnection, + _: &dbus::Message| { + if c.interface_name != "org.freedesktop.UPower.Device" { + return true; + } + let mut inner = inner.lock().unwrap(); + for (key, value) in c.changed_properties { + match key.as_str() { + "State" => { + inner.state = match value.0.as_u64().unwrap() { + 1 => UpowerBatteryState::Charging, + 2 => UpowerBatteryState::Discharging, + 3 => UpowerBatteryState::Empty, + 4 => UpowerBatteryState::Full, + 5 => UpowerBatteryState::NotCharging, + 6 => UpowerBatteryState::Discharging, + _ => UpowerBatteryState::Unknown, + }; + inner.dirty = true; + let mut events = events.lock().unwrap(); + events.add_event(Event::PowerUpdate); + } + "Percentage" => { + inner.value = value.0.as_f64().unwrap() as f32 / 100.; + inner.dirty = true; + let mut events = events.lock().unwrap(); + events.add_event(Event::PowerUpdate); + } + _ => (), + } + } + true + }, + ) .unwrap(); - rt.block_on(async move { monitor(inner, events).await }).unwrap(); + + loop { + conn.process(Duration::from_millis(60000)).unwrap(); + } }) .unwrap(); } @@ -89,7 +119,7 @@ impl Battery { let battery = Battery { inner: Arc::new(Mutex::new(InnerBattery { value: 0., - state: BatteryState::Unknown, + state: UpowerBatteryState::Unknown, dirty: false, })), }; @@ -105,7 +135,7 @@ impl BarWidgetImpl for Battery { fn name(&self) -> &'static str { "battery" } - fn value(&self) -> f32 { + fn value(&mut self) -> f32 { let mut inner = self.inner.lock().unwrap(); inner.dirty = false; inner.value @@ -113,15 +143,11 @@ impl BarWidgetImpl for Battery { fn color(&self) -> Color { let inner = self.inner.lock().unwrap(); match inner.state { - BatteryState::Charging | BatteryState::FullyCharged => Color::LIGHTGREEN, - BatteryState::PendingCharge => Color::LIGHTRED, - _ => if inner.value > 0.25 { - Color::WHITE - } else if inner.value > 0.1 { - Color::DARKORANGE - } else { - Color::RED - } + UpowerBatteryState::Charging | UpowerBatteryState::Full => Color::LIGHTGREEN, + UpowerBatteryState::NotCharging => Color::LIGHTRED, + _ if inner.value > 0.25 => Color::WHITE, + _ if inner.value > 0.1 => Color::DARKORANGE, + _ => Color::RED, } } } diff --git a/src/widgets/calendar.rs b/src/widgets/calendar.rs index 68e3832..79b2d8f 100644 --- a/src/widgets/calendar.rs +++ b/src/widgets/calendar.rs @@ -52,7 +52,6 @@ impl Calendar { orig: NaiveDate, mut time: NaiveDate, ) { - let black = Color::BLACK; let white = Color::WHITE; let dim = Color::GREY80; let dimmer = Color::GREY75; @@ -85,7 +84,6 @@ impl Calendar { y_off * (self.size * LINE_HEIGHT).ceil() as u32 + (self.size * 1.).ceil() as u32, )), - black, white, &wk_chr, ) @@ -100,7 +98,6 @@ impl Calendar { year_font .draw_text( &mut view.offset(((self.size * 17.).ceil() as u32, 0)), - black, dim, &format!("{:}", time.year()), ) @@ -124,7 +121,7 @@ impl Calendar { _ => panic!("impossible value"), }; cal_font - .draw_text(&mut view, black, white, month_str) + .draw_text(&mut view, white, month_str) .unwrap(); let mut done = false; @@ -152,7 +149,6 @@ impl Calendar { y_off * (self.size * LINE_HEIGHT).ceil() as u32 + (self.size * MONTH_FACTOR).ceil() as u32, )), - black, dimmer, &format!("{:02}", wk.week()), ) @@ -177,7 +173,6 @@ impl Calendar { y_off * (self.size * LINE_HEIGHT).ceil() as u32 + (self.size * MONTH_FACTOR).ceil() as u32, )), - black, c, &format!("{:02}", time.day()), ) diff --git a/src/widgets/clock.rs b/src/widgets/clock.rs index 8af1941..074a151 100644 --- a/src/widgets/clock.rs +++ b/src/widgets/clock.rs @@ -54,14 +54,12 @@ impl<'a> Widget for Clock { fn draw(&mut self, fonts: &mut FontMap, view: &mut BufferView) -> Geometry { let time = Local::now().naive_local(); let fg = Color::WHITE; - let bg = Color::BLACK; let digit = self.digit_width; let colon = self.colon_width; let font = fonts.get_font(self.font, self.size); font.draw_text_fixed_width( view, - bg, fg, &[digit, digit, colon, digit, digit], &format!("{:02}:{:02}", time.hour(), time.minute()), diff --git a/src/widgets/date.rs b/src/widgets/date.rs index cf67bc6..ee89797 100644 --- a/src/widgets/date.rs +++ b/src/widgets/date.rs @@ -50,11 +50,9 @@ impl<'a> Widget for Date { fn draw(&mut self, fonts: &mut FontMap, view: &mut BufferView) -> Geometry { let time = Local::now().naive_local(); let fg = Color::WHITE; - let bg = Color::BLACK; let font = fonts.get_font(self.font, self.size); font.draw_text( view, - bg, fg, &format!( "{}, {:02}/{:02}/{:4}", diff --git a/src/widgets/launcher.rs b/src/widgets/launcher.rs index bcdadb5..0884327 100644 --- a/src/widgets/launcher.rs +++ b/src/widgets/launcher.rs @@ -287,7 +287,6 @@ impl InterfaceWidget for Launcher { view: &mut BufferView, ) -> Geometry { let fg = Color::WHITE; - let bg = Color::BLACK; let line_height = intf.size.ceil() as u32; @@ -299,14 +298,13 @@ impl InterfaceWidget for Launcher { let mut x_max = font .auto_draw_text_with_cursor( &mut prompt_line, - bg, fg, &format!(" {}", &intf.prompt.input), intf.prompt.cursor + 3, ) .unwrap(); - font.auto_draw_text(&mut prompt_line, bg, fg, ">") + font.auto_draw_text(&mut prompt_line, fg, ">") .unwrap(); // Draw entries @@ -336,13 +334,13 @@ impl InterfaceWidget for Launcher { } x_max = max( x_max, - font.auto_draw_text_individual_colors(&mut line, bg, &colors, &m.name) + font.auto_draw_text_individual_colors(&mut line, &colors, &m.name) .unwrap(), ); } else { x_max = max( x_max, - font.auto_draw_text(&mut line, bg, dimfg, &m.name) + font.auto_draw_text(&mut line, dimfg, &m.name) .unwrap(), ); } @@ -386,7 +384,6 @@ impl InterfaceWidget for Shell { view: &mut BufferView, ) -> Geometry { let fg = Color::WHITE; - let bg = Color::BLACK; let line_height = intf.size.ceil() as u32; @@ -399,13 +396,12 @@ impl InterfaceWidget for Shell { let x_max = font .auto_draw_text_with_cursor( &mut prompt_line, - bg, fg, &format!(" {}", &intf.prompt.input), intf.prompt.cursor + 3, ) .unwrap(); - font.auto_draw_text(&mut prompt_line, bg, Color::BUFF, "!") + font.auto_draw_text(&mut prompt_line, Color::BUFF, "!") .unwrap(); Geometry { @@ -447,7 +443,6 @@ impl InterfaceWidget for Calc { view: &mut BufferView, ) -> Geometry { let fg = Color::WHITE; - let bg = Color::BLACK; let line_height = intf.size.ceil() as u32; @@ -460,20 +455,19 @@ impl InterfaceWidget for Calc { let res_off = font .auto_draw_text_with_cursor( &mut prompt_line, - bg, fg, &format!(" {} ", &intf.prompt.input), intf.prompt.cursor + 3, ) .unwrap(); - font.auto_draw_text(&mut prompt_line, bg, Color::BUFF, "=") + font.auto_draw_text(&mut prompt_line, Color::BUFF, "=") .unwrap(); if let Some(res) = &self.result { let resfg = Color::LIGHTORANGE; let mut result_line = view.offset((res_off.0, prompt_offset)); - font.auto_draw_text(&mut result_line, bg, resfg, &format!(" = {}", &res)) + font.auto_draw_text(&mut result_line, resfg, &format!(" = {}", &res)) .unwrap(); } @@ -484,7 +478,7 @@ impl InterfaceWidget for Calc { } prompt_offset -= line_height; let mut result_line = view.offset((0, prompt_offset)); - font.auto_draw_text(&mut result_line, bg, dimfg, &m) + font.auto_draw_text(&mut result_line, dimfg, &m) .unwrap(); } diff --git a/src/widgets/mod.rs b/src/widgets/mod.rs index eb74676..6f51598 100644 --- a/src/widgets/mod.rs +++ b/src/widgets/mod.rs @@ -1,4 +1,5 @@ -mod audio; +//mod alsaaudio; +mod pulseaudio; mod backlight; mod bar_widget; mod battery; @@ -10,7 +11,8 @@ mod line; mod widget; mod layout; -pub use audio::Audio; +//pub use alsaaudio::AlsaAudio; +pub use pulseaudio::PulseAudio; pub use backlight::Backlight; pub use battery::Battery; pub use calendar::Calendar; diff --git a/src/widgets/audio.rs b/src/widgets/pulseaudio.rs similarity index 96% rename from src/widgets/audio.rs rename to src/widgets/pulseaudio.rs index 99c0f3c..b59f952 100644 --- a/src/widgets/audio.rs +++ b/src/widgets/pulseaudio.rs @@ -177,7 +177,7 @@ enum Change { ToggleMute, } -pub struct InnerAudio { +struct InnerAudio { volume: f32, channel_volume: Option, mute: bool, @@ -186,14 +186,14 @@ pub struct InnerAudio { pipe: RawFd, } -pub struct Audio { +pub struct PulseAudio { inner: Arc>, } -impl Audio { +impl PulseAudio { pub fn new(events: Arc>, fm: &mut FontMap, font: &'static str, size: f32) -> BarWidget { let (a, b) = pipe().unwrap(); - let audio = Audio { + let audio = PulseAudio { inner: Arc::new(Mutex::new(InnerAudio{ volume: 0.0, channel_volume: None, @@ -208,15 +208,17 @@ impl Audio { } } -impl BarWidgetImpl for Audio { +impl BarWidgetImpl for PulseAudio { fn get_dirty(&self) -> bool { self.inner.lock().unwrap().dirty } fn name(&self) -> &'static str { "volume" } - fn value(&self) -> f32 { - self.inner.lock().unwrap().volume + fn value(&mut self) -> f32 { + let mut inner = self.inner.lock().unwrap(); + inner.dirty = false; + inner.volume } fn color(&self) -> Color { match self.inner.lock().unwrap().mute {