Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6bb65c28c7 | ||
|
|
64ddb16147 | ||
|
|
1c02bfd339 |
Generated
-67
@@ -1,25 +1,5 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
[[package]]
|
|
||||||
name = "alsa"
|
|
||||||
version = "0.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"alsa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "alsa-sys"
|
|
||||||
version = "0.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "andrew"
|
name = "andrew"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
@@ -54,11 +34,6 @@ name = "autocfg"
|
|||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bitflags"
|
|
||||||
version = "0.9.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@@ -225,11 +200,6 @@ dependencies = [
|
|||||||
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "linked-hash-map"
|
|
||||||
version = "0.5.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "maplit"
|
name = "maplit"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
@@ -506,17 +476,6 @@ dependencies = [
|
|||||||
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde_yaml"
|
|
||||||
version = "0.8.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha-1"
|
name = "sha-1"
|
||||||
version = "0.8.1"
|
version = "0.8.1"
|
||||||
@@ -586,14 +545,6 @@ dependencies = [
|
|||||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "timerfd"
|
|
||||||
version = "1.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.11.2"
|
version = "1.11.2"
|
||||||
@@ -713,7 +664,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
name = "wldash"
|
name = "wldash"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"alsa 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"dbus 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"dbus 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -728,10 +678,8 @@ dependencies = [
|
|||||||
"rusttype 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rusttype 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"smithay-client-toolkit 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"smithay-client-toolkit 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"timerfd 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"wayland-client 0.23.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"wayland-client 0.23.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"wayland-protocols 0.23.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"wayland-protocols 0.23.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
@@ -746,22 +694,11 @@ name = "xml-rs"
|
|||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "yaml-rust"
|
|
||||||
version = "0.4.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
dependencies = [
|
|
||||||
"linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
"checksum alsa 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fe6a5e4eb4879d7cb8d19161927fbf825f0d89761776359c9cf4f9c9c2f35c52"
|
|
||||||
"checksum alsa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b0edcbbf9ef68f15ae1b620f722180b82a98b6f0628d30baa6b8d2a5abc87d58"
|
|
||||||
"checksum andrew 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9b7f09f89872c2b6b29e319377b1fbe91c6f5947df19a25596e121cf19a7b35e"
|
"checksum andrew 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9b7f09f89872c2b6b29e319377b1fbe91c6f5947df19a25596e121cf19a7b35e"
|
||||||
"checksum approx 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0e60b75072ecd4168020818c0107f2857bb6c4e64252d8d3983f6263b40a5c3"
|
"checksum approx 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0e60b75072ecd4168020818c0107f2857bb6c4e64252d8d3983f6263b40a5c3"
|
||||||
"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba"
|
"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba"
|
||||||
"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875"
|
"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875"
|
||||||
"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
|
|
||||||
"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd"
|
"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd"
|
||||||
"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
|
"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
|
||||||
"checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09"
|
"checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09"
|
||||||
@@ -786,7 +723,6 @@ dependencies = [
|
|||||||
"checksum libpulse-binding 2.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e7712e3c895da914d7d969475238cc43933c5c4cf7ef3654106be9db2b327cbb"
|
"checksum libpulse-binding 2.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e7712e3c895da914d7d969475238cc43933c5c4cf7ef3654106be9db2b327cbb"
|
||||||
"checksum libpulse-sys 1.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "67df96705dc149577155690c05e067334d1d8a62bcac1a1611ef28eaaeb76354"
|
"checksum libpulse-sys 1.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "67df96705dc149577155690c05e067334d1d8a62bcac1a1611ef28eaaeb76354"
|
||||||
"checksum line_drawing 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5cc7ad3d82c845bdb5dde34ffdcc7a5fb4d2996e1e1ee0f19c33bc80e15196b9"
|
"checksum line_drawing 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5cc7ad3d82c845bdb5dde34ffdcc7a5fb4d2996e1e1ee0f19c33bc80e15196b9"
|
||||||
"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83"
|
|
||||||
"checksum maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
|
"checksum maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
|
||||||
"checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
|
"checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
|
||||||
"checksum nix 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4dbdc256eaac2e3bd236d93ad999d3479ef775c863dbda3068c4006a92eec51b"
|
"checksum nix 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4dbdc256eaac2e3bd236d93ad999d3479ef775c863dbda3068c4006a92eec51b"
|
||||||
@@ -819,7 +755,6 @@ dependencies = [
|
|||||||
"checksum serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "fec2851eb56d010dc9a21b89ca53ee75e6528bab60c11e89d38390904982da9f"
|
"checksum serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "fec2851eb56d010dc9a21b89ca53ee75e6528bab60c11e89d38390904982da9f"
|
||||||
"checksum serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "cb4dc18c61206b08dc98216c98faa0232f4337e1e1b8574551d5bad29ea1b425"
|
"checksum serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "cb4dc18c61206b08dc98216c98faa0232f4337e1e1b8574551d5bad29ea1b425"
|
||||||
"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704"
|
"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704"
|
||||||
"checksum serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "38b08a9a90e5260fe01c6480ec7c811606df6d3a660415808c3c3fa8ed95b582"
|
|
||||||
"checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68"
|
"checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68"
|
||||||
"checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
|
"checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
|
||||||
"checksum smithay-client-toolkit 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "93960e8975909fcb14cc755de93af2149d8b8f4eb368315537d40cfd0f324054"
|
"checksum smithay-client-toolkit 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "93960e8975909fcb14cc755de93af2149d8b8f4eb368315537d40cfd0f324054"
|
||||||
@@ -827,7 +762,6 @@ dependencies = [
|
|||||||
"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
|
"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
|
||||||
"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf"
|
"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf"
|
||||||
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
|
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
|
||||||
"checksum timerfd 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6c9a7822e546fa39d0b5ae14a93a33903975b62af6597288aea77f0580a6abbe"
|
|
||||||
"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9"
|
"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9"
|
||||||
"checksum ucd-trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8f00ed7be0c1ff1e24f46c3d2af4859f7e863672ba3a6e92e7cff702bf9f06c2"
|
"checksum ucd-trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8f00ed7be0c1ff1e24f46c3d2af4859f7e863672ba3a6e92e7cff702bf9f06c2"
|
||||||
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||||
@@ -845,4 +779,3 @@ dependencies = [
|
|||||||
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
"checksum xdg 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57"
|
"checksum xdg 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57"
|
||||||
"checksum xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "541b12c998c5b56aa2b4e6f18f03664eef9a4fd0a246a55594efae6cc2d964b5"
|
"checksum xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "541b12c998c5b56aa2b4e6f18f03664eef9a4fd0a246a55594efae6cc2d964b5"
|
||||||
"checksum yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d"
|
|
||||||
|
|||||||
+3
-15
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "wldash"
|
name = "wldash"
|
||||||
version = "0.2.0"
|
version = "0.2.1"
|
||||||
authors = ["Kenny Levinsen <kl@kl.wtf>"]
|
authors = ["Kenny Levinsen <kl@kl.wtf>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
@@ -8,15 +8,8 @@ edition = "2018"
|
|||||||
lto = "fat"
|
lto = "fat"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["alsa-widget", "pulseaudio-widget", "yaml-cfg", "json-cfg"]
|
|
||||||
damage_debug = []
|
damage_debug = []
|
||||||
|
|
||||||
yaml-cfg = ["serde_yaml"]
|
|
||||||
json-cfg = ["serde_json"]
|
|
||||||
|
|
||||||
alsa-widget = ["alsa"]
|
|
||||||
pulseaudio-widget = ["libpulse-binding"]
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
smithay-client-toolkit = "0.6.4"
|
smithay-client-toolkit = "0.6.4"
|
||||||
byteorder = "1.3"
|
byteorder = "1.3"
|
||||||
@@ -27,17 +20,12 @@ memmap = "0.7"
|
|||||||
os_pipe = "0.8"
|
os_pipe = "0.8"
|
||||||
wayland-client = { version = "0.23", features = ["dlopen"] }
|
wayland-client = { version = "0.23", features = ["dlopen"] }
|
||||||
wayland-protocols = { version = "0.23", features = ["client", "unstable_protocols"] }
|
wayland-protocols = { version = "0.23", features = ["client", "unstable_protocols"] }
|
||||||
|
libpulse-binding = { version = "2.11"}
|
||||||
dbus = "0.6"
|
dbus = "0.6"
|
||||||
fuzzy-matcher = "0.2"
|
fuzzy-matcher = "0.2"
|
||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
rcalc_lib = { version = "0.9" }
|
rcalc_lib = { version = "0.9" }
|
||||||
rust-ini = "0.13"
|
rust-ini = "0.13"
|
||||||
shlex = "0.1"
|
shlex = "0.1"
|
||||||
timerfd = "1.0.0"
|
serde_json = "1.0"
|
||||||
|
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = { version = "1.0", optional = true }
|
|
||||||
serde_yaml = { version = "0.8", optional = true }
|
|
||||||
|
|
||||||
libpulse-binding = { version = "2.11", optional = true }
|
|
||||||
alsa = { version = "0.3.0", optional = true }
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ Consider this alpha-quality: While it works, *everything* is subject to change w
|
|||||||
3. Put somewhere: `cp target/release/wldash /usr/local/bin/wldash`
|
3. Put somewhere: `cp target/release/wldash /usr/local/bin/wldash`
|
||||||
4. Run: `wldash`
|
4. Run: `wldash`
|
||||||
|
|
||||||
To see the default configuration, run `wldash print-config`. To configure, place a file in `$XDG_CONFIG_HOME/wldash/config.yaml` (or if `XDG_CONFIG_HOME` is not set, `~/.config/wldash/config.yaml`). JSON is also currently supported.
|
To see the default configuration, run `wldash print-config`. To configure, place a file in `$XDG_CONFIG_HOME/wldash/config.json` (or if `XDG_CONFIG_HOME` is not set, `~/.config/wldash/config.json`).
|
||||||
|
|
||||||
Notable settings: `outptuMode` can be `active` or `all`, `scale` can be set to `2` to half the buffer size, and the widgets (and their layout) can be configured.
|
Notable settings: `outptuMode` can be `active` or `all`, `scale` can be set to `2` to half the buffer size, and the widgets (and their layout) can be configured.
|
||||||
|
|
||||||
@@ -62,4 +62,4 @@ The launcher also accepts prefix operators to change its mode:
|
|||||||
- Scaling of any kind - all sizes are currently hardcoded in pixels
|
- Scaling of any kind - all sizes are currently hardcoded in pixels
|
||||||
- Configurability
|
- Configurability
|
||||||
- Cleanup and reorganization
|
- Cleanup and reorganization
|
||||||
- Proper line editor for the launcher
|
- Proper line editor for the launcher
|
||||||
+1
-7
@@ -34,13 +34,7 @@
|
|||||||
}
|
}
|
||||||
]},
|
]},
|
||||||
{"calendar": {"font_size": 16.0,"sections": 3}},
|
{"calendar": {"font_size": 16.0,"sections": 3}},
|
||||||
{"launcher": {
|
{"launcher": {"font_size": 32.0,"length": 1200}}
|
||||||
"font_size": 32.0,
|
|
||||||
"length": 1200,
|
|
||||||
"app_opener": "swaymsg exec ",
|
|
||||||
"term_opener": "alacritty -e ",
|
|
||||||
"url_opener": "xdg-open "
|
|
||||||
}}
|
|
||||||
]}
|
]}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
-49
@@ -1,49 +0,0 @@
|
|||||||
outputMode: active
|
|
||||||
scale: 1
|
|
||||||
background:
|
|
||||||
red: 0.0
|
|
||||||
green: 0.0
|
|
||||||
blue: 0.0
|
|
||||||
opacity: 0.9
|
|
||||||
widget:
|
|
||||||
margin:
|
|
||||||
margins: [20, 20, 20, 20]
|
|
||||||
widget:
|
|
||||||
verticalLayout:
|
|
||||||
- horizontalLayout:
|
|
||||||
- margin:
|
|
||||||
margins: [0, 88, 0, 32]
|
|
||||||
widget:
|
|
||||||
verticalLayout:
|
|
||||||
- date:
|
|
||||||
font_size: 64.0
|
|
||||||
- clock:
|
|
||||||
font_size: 256.0
|
|
||||||
- verticalLayout:
|
|
||||||
- margin:
|
|
||||||
margins: [0, 0, 0, 8]
|
|
||||||
widget:
|
|
||||||
battery:
|
|
||||||
font_size: 24.0
|
|
||||||
length: 600
|
|
||||||
- margin:
|
|
||||||
margins: [0, 0, 0, 8]
|
|
||||||
widget:
|
|
||||||
backlight:
|
|
||||||
font_size: 24.0
|
|
||||||
length: 600
|
|
||||||
- margin:
|
|
||||||
margins: [0, 0, 0, 8]
|
|
||||||
widget:
|
|
||||||
pulseAudio:
|
|
||||||
font_size: 24.0
|
|
||||||
length: 600
|
|
||||||
- calendar:
|
|
||||||
font_size: 16.0
|
|
||||||
sections: 3
|
|
||||||
- launcher:
|
|
||||||
font_size: 32.0
|
|
||||||
length: 1200
|
|
||||||
app_opener: "swaymsg exec "
|
|
||||||
term_opener: "alacritty -e "
|
|
||||||
url_opener: "xdg-open "
|
|
||||||
+52
-70
@@ -21,7 +21,6 @@ use crate::widget::{DrawContext, Widget};
|
|||||||
use crate::cmd::Cmd;
|
use crate::cmd::Cmd;
|
||||||
use crate::doublemempool::DoubleMemPool;
|
use crate::doublemempool::DoubleMemPool;
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum OutputMode {
|
pub enum OutputMode {
|
||||||
Active,
|
Active,
|
||||||
All,
|
All,
|
||||||
@@ -124,49 +123,47 @@ impl AppInner {
|
|||||||
|
|
||||||
self.configured_surfaces = Arc::new(Mutex::new(0));
|
self.configured_surfaces = Arc::new(Mutex::new(0));
|
||||||
|
|
||||||
if !self.visible {
|
if self.visible {
|
||||||
self.surfaces = Vec::new();
|
match self.output_mode {
|
||||||
self.shell_surfaces = Vec::new();
|
OutputMode::Active => {
|
||||||
return;
|
if self.shell_surfaces.len() > 0 {
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
match self.output_mode {
|
|
||||||
OutputMode::Active => {
|
|
||||||
if self.shell_surfaces.len() > 0 {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let (surface, shell_surface) = AppInner::add_shell_surface(
|
|
||||||
&compositor,
|
|
||||||
&shell,
|
|
||||||
self.scale,
|
|
||||||
self.configured_surfaces.clone(),
|
|
||||||
self.draw_tx.clone(),
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
self.surfaces = vec![surface];
|
|
||||||
self.shell_surfaces = vec![shell_surface];
|
|
||||||
}
|
|
||||||
OutputMode::All => {
|
|
||||||
let mut surfaces = Vec::new();
|
|
||||||
let mut shell_surfaces = Vec::new();
|
|
||||||
for output in self.outputs.iter() {
|
|
||||||
let (surface, shell_surface) = AppInner::add_shell_surface(
|
let (surface, shell_surface) = AppInner::add_shell_surface(
|
||||||
&compositor,
|
&compositor,
|
||||||
&shell,
|
&shell,
|
||||||
self.scale,
|
self.scale,
|
||||||
self.configured_surfaces.clone(),
|
self.configured_surfaces.clone(),
|
||||||
self.draw_tx.clone(),
|
self.draw_tx.clone(),
|
||||||
Some(&output.1),
|
None,
|
||||||
);
|
);
|
||||||
surfaces.push(surface);
|
self.surfaces = vec![surface];
|
||||||
shell_surfaces.push(shell_surface);
|
self.shell_surfaces = vec![shell_surface];
|
||||||
|
}
|
||||||
|
OutputMode::All => {
|
||||||
|
let mut surfaces = Vec::new();
|
||||||
|
let mut shell_surfaces = Vec::new();
|
||||||
|
for output in self.outputs.iter() {
|
||||||
|
let (surface, shell_surface) = AppInner::add_shell_surface(
|
||||||
|
&compositor,
|
||||||
|
&shell,
|
||||||
|
self.scale,
|
||||||
|
self.configured_surfaces.clone(),
|
||||||
|
self.draw_tx.clone(),
|
||||||
|
Some(&output.1),
|
||||||
|
);
|
||||||
|
surfaces.push(surface);
|
||||||
|
shell_surfaces.push(shell_surface);
|
||||||
|
}
|
||||||
|
self.surfaces = surfaces;
|
||||||
|
self.shell_surfaces = shell_surfaces;
|
||||||
}
|
}
|
||||||
self.surfaces = surfaces;
|
|
||||||
self.shell_surfaces = shell_surfaces;
|
|
||||||
}
|
}
|
||||||
|
self.draw_tx.send(Cmd::ForceDraw).unwrap();
|
||||||
|
} else {
|
||||||
|
self.surfaces = Vec::new();
|
||||||
|
self.shell_surfaces = Vec::new();
|
||||||
}
|
}
|
||||||
self.draw_tx.send(Cmd::ForceDraw).unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_output(&mut self, id: u32, output: wl_output::WlOutput) {
|
fn add_output(&mut self, id: u32, output: wl_output::WlOutput) {
|
||||||
@@ -213,7 +210,7 @@ pub struct App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
pub fn redraw(&mut self, force: bool) -> Result<(), ::std::io::Error> {
|
pub fn redraw(&mut self, mut force: bool) -> Result<(), ::std::io::Error> {
|
||||||
let widget = match self.widget {
|
let widget = match self.widget {
|
||||||
Some(ref mut widget) => widget,
|
Some(ref mut widget) => widget,
|
||||||
None => return Ok(()),
|
None => return Ok(()),
|
||||||
@@ -222,10 +219,7 @@ impl App {
|
|||||||
let inner = self.inner.lock().unwrap();
|
let inner = self.inner.lock().unwrap();
|
||||||
let time = Local::now();
|
let time = Local::now();
|
||||||
|
|
||||||
if !inner.visible
|
if inner.shell_surfaces.len() != *inner.configured_surfaces.lock().unwrap() {
|
||||||
|| inner.shell_surfaces.len() != *inner.configured_surfaces.lock().unwrap()
|
|
||||||
|| inner.surfaces.len() == 0
|
|
||||||
{
|
|
||||||
// Not ready yet
|
// Not ready yet
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@@ -237,7 +231,6 @@ impl App {
|
|||||||
|
|
||||||
let size = widget.size();
|
let size = widget.size();
|
||||||
let size_changed = self.last_dim != size;
|
let size_changed = self.last_dim != size;
|
||||||
let force = force | size_changed;
|
|
||||||
|
|
||||||
// resize the pool if relevant
|
// resize the pool if relevant
|
||||||
pool.resize((4 * size.0 * size.1) as usize)
|
pool.resize((4 * size.0 * size.1) as usize)
|
||||||
@@ -246,8 +239,8 @@ impl App {
|
|||||||
let mut buf = Buffer::new(mmap, size);
|
let mut buf = Buffer::new(mmap, size);
|
||||||
|
|
||||||
// Copy old damage
|
// Copy old damage
|
||||||
let force = match (force, &self.last_damage) {
|
if let Some(d) = &self.last_damage {
|
||||||
(false, Some(d)) => {
|
if !size_changed {
|
||||||
let lastmmap = last.mmap();
|
let lastmmap = last.mmap();
|
||||||
let last = Buffer::new(lastmmap, size);
|
let last = Buffer::new(lastmmap, size);
|
||||||
|
|
||||||
@@ -257,10 +250,12 @@ impl App {
|
|||||||
for d in d {
|
for d in d {
|
||||||
last.copy_to(&mut buf, d.clone());
|
last.copy_to(&mut buf, d.clone());
|
||||||
}
|
}
|
||||||
false
|
} else {
|
||||||
|
force = true;
|
||||||
}
|
}
|
||||||
_ => true,
|
} else {
|
||||||
};
|
force = true;
|
||||||
|
}
|
||||||
|
|
||||||
if force {
|
if force {
|
||||||
buf.memset(&self.bg);
|
buf.memset(&self.bg);
|
||||||
@@ -277,9 +272,8 @@ impl App {
|
|||||||
|
|
||||||
mmap.flush().unwrap();
|
mmap.flush().unwrap();
|
||||||
|
|
||||||
if !force && !report.full_damage && report.damage.len() == 0 {
|
if !size_changed && !report.full_damage && report.damage.len() == 0 {
|
||||||
// Nothing to do
|
// Nothing to do
|
||||||
self.pools.never_mind();
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,17 +310,9 @@ impl App {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hide(&mut self) {
|
pub fn toggle_visible(&mut self) {
|
||||||
let mut inner = self.inner.lock().unwrap();
|
let mut inner = self.inner.lock().unwrap();
|
||||||
inner.visible = false;
|
inner.visible = !inner.visible;
|
||||||
self.last_dim = (0, 0);
|
|
||||||
inner.outputs_changed();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn show(&mut self) {
|
|
||||||
let mut inner = self.inner.lock().unwrap();
|
|
||||||
inner.visible = true;
|
|
||||||
self.last_dim = (0, 0);
|
|
||||||
inner.outputs_changed();
|
inner.outputs_changed();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -436,14 +422,6 @@ impl App {
|
|||||||
// Keyboard processing
|
// Keyboard processing
|
||||||
//
|
//
|
||||||
let kbd_clone = cmd_queue.clone();
|
let kbd_clone = cmd_queue.clone();
|
||||||
let modifiers_state = Arc::new(Mutex::new(ModifiersState {
|
|
||||||
ctrl: false,
|
|
||||||
alt: false,
|
|
||||||
shift: false,
|
|
||||||
caps_lock: false,
|
|
||||||
logo: false,
|
|
||||||
num_lock: false,
|
|
||||||
}));
|
|
||||||
map_keyboard_auto(&seat, move |event: KbEvent, _| match event {
|
map_keyboard_auto(&seat, move |event: KbEvent, _| match event {
|
||||||
KbEvent::Key {
|
KbEvent::Key {
|
||||||
keysym,
|
keysym,
|
||||||
@@ -453,19 +431,22 @@ impl App {
|
|||||||
} => match state {
|
} => match state {
|
||||||
KeyState::Pressed => match keysym {
|
KeyState::Pressed => match keysym {
|
||||||
keysyms::XKB_KEY_Escape => kbd_clone.lock().unwrap().push_back(Cmd::Exit),
|
keysyms::XKB_KEY_Escape => kbd_clone.lock().unwrap().push_back(Cmd::Exit),
|
||||||
keysyms::XKB_KEY_c if modifiers_state.lock().unwrap().ctrl => {
|
|
||||||
kbd_clone.lock().unwrap().push_back(Cmd::Exit)
|
|
||||||
}
|
|
||||||
v => kbd_clone.lock().unwrap().push_back(Cmd::Keyboard {
|
v => kbd_clone.lock().unwrap().push_back(Cmd::Keyboard {
|
||||||
key: v,
|
key: v,
|
||||||
key_state: state,
|
key_state: state,
|
||||||
modifiers_state: modifiers_state.lock().unwrap().clone(),
|
modifiers_state: ModifiersState {
|
||||||
|
ctrl: false,
|
||||||
|
alt: false,
|
||||||
|
shift: false,
|
||||||
|
caps_lock: false,
|
||||||
|
logo: false,
|
||||||
|
num_lock: false,
|
||||||
|
},
|
||||||
interpreted: utf8,
|
interpreted: utf8,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
KbEvent::Modifiers { modifiers } => *modifiers_state.lock().unwrap() = modifiers,
|
|
||||||
_ => (),
|
_ => (),
|
||||||
})
|
})
|
||||||
.expect("Failed to map keyboard");
|
.expect("Failed to map keyboard");
|
||||||
@@ -486,6 +467,7 @@ impl App {
|
|||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|
||||||
|
inner.lock().unwrap().outputs_changed();
|
||||||
event_queue.sync_roundtrip().unwrap();
|
event_queue.sync_roundtrip().unwrap();
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|||||||
+39
-42
@@ -10,27 +10,55 @@ pub struct Color {
|
|||||||
|
|
||||||
impl Color {
|
impl Color {
|
||||||
pub fn new(red: f32, green: f32, blue: f32, opacity: f32) -> Color {
|
pub fn new(red: f32, green: f32, blue: f32, opacity: f32) -> Color {
|
||||||
let (red, green, blue, opacity) = clamp(red, green, blue, opacity);
|
|
||||||
Color {
|
Color {
|
||||||
red,
|
red: if red > 1.0 {
|
||||||
green,
|
1.0
|
||||||
blue,
|
} else if red < 0.0 {
|
||||||
opacity,
|
0.0
|
||||||
|
} else {
|
||||||
|
red
|
||||||
|
},
|
||||||
|
green: if green > 1.0 {
|
||||||
|
1.0
|
||||||
|
} else if green < 0.0 {
|
||||||
|
0.0
|
||||||
|
} else {
|
||||||
|
green
|
||||||
|
},
|
||||||
|
blue: if blue > 1.0 {
|
||||||
|
1.0
|
||||||
|
} else if blue < 0.0 {
|
||||||
|
0.0
|
||||||
|
} else {
|
||||||
|
blue
|
||||||
|
},
|
||||||
|
opacity: if opacity > 1.0 {
|
||||||
|
1.0
|
||||||
|
} else if opacity < 0.0 {
|
||||||
|
0.0
|
||||||
|
} else {
|
||||||
|
opacity
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn blend(&self, other: &Color, ratio: f32) -> Color {
|
pub fn blend(&self, other: &Color, ratio: f32) -> Color {
|
||||||
let ratio = clamp_f32(ratio, 0.0, 1.0);
|
let ratio = if ratio > 1.0 {
|
||||||
|
1.0
|
||||||
|
} else if ratio < 0.0 {
|
||||||
|
0.0
|
||||||
|
} else {
|
||||||
|
ratio
|
||||||
|
};
|
||||||
|
|
||||||
Color {
|
Color {
|
||||||
red: blend_f32(self.red, other.red, ratio),
|
red: self.red + ((other.red - self.red) * ratio),
|
||||||
green: blend_f32(self.green, other.green, ratio),
|
green: self.green + ((other.green - self.green) * ratio),
|
||||||
blue: blend_f32(self.blue, other.blue, ratio),
|
blue: self.blue + ((other.blue - self.blue) * ratio),
|
||||||
opacity: blend_f32(self.opacity, other.opacity, ratio),
|
opacity: self.opacity + ((other.opacity - self.opacity) * ratio),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn as_argb8888(&self) -> u32 {
|
pub fn as_argb8888(&self) -> u32 {
|
||||||
((255.0 * self.opacity) as u32 & 0xFF) << 24
|
((255.0 * self.opacity) as u32 & 0xFF) << 24
|
||||||
| ((255.0 * self.red) as u32 & 0xFF) << 16
|
| ((255.0 * self.red) as u32 & 0xFF) << 16
|
||||||
@@ -38,34 +66,3 @@ impl Color {
|
|||||||
| ((255.0 * self.blue) as u32 & 0xFF)
|
| ((255.0 * self.blue) as u32 & 0xFF)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn clamp(r: f32, g: f32, b: f32, o: f32) -> (f32, f32, f32, f32) {
|
|
||||||
clamp_naive(r, g, b, o)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn clamp_naive(r: f32, g: f32, b: f32, o: f32) -> (f32, f32, f32, f32) {
|
|
||||||
(
|
|
||||||
clamp_f32(r, 0.0, 1.0),
|
|
||||||
clamp_f32(g, 0.0, 1.0),
|
|
||||||
clamp_f32(b, 0.0, 1.0),
|
|
||||||
clamp_f32(o, 0.0, 1.0),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn clamp_f32(v: f32, a: f32, b: f32) -> f32 {
|
|
||||||
if v > b {
|
|
||||||
b
|
|
||||||
} else if v < a {
|
|
||||||
a
|
|
||||||
} else {
|
|
||||||
v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn blend_f32(a: f32, b: f32, r: f32) -> f32 {
|
|
||||||
a + ((b - a) * r)
|
|
||||||
}
|
|
||||||
|
|||||||
+3
-18
@@ -48,16 +48,10 @@ pub enum Widget {
|
|||||||
font_size: f32,
|
font_size: f32,
|
||||||
length: u32,
|
length: u32,
|
||||||
},
|
},
|
||||||
#[cfg(feature = "pulseaudio-widget")]
|
|
||||||
PulseAudio {
|
PulseAudio {
|
||||||
font_size: f32,
|
font_size: f32,
|
||||||
length: u32,
|
length: u32,
|
||||||
},
|
},
|
||||||
#[cfg(feature = "alsa-widget")]
|
|
||||||
AlsaSound {
|
|
||||||
font_size: f32,
|
|
||||||
length: u32,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Widget {
|
impl Widget {
|
||||||
@@ -91,7 +85,7 @@ impl Widget {
|
|||||||
.map(|x| x.unwrap())
|
.map(|x| x.unwrap())
|
||||||
.collect(),
|
.collect(),
|
||||||
)),
|
)),
|
||||||
Widget::Clock { font_size } => Some(widgets::clock::Clock::new(font_size)),
|
Widget::Clock { font_size } => Some(widgets::clock::Clock::new(font_size, tx.clone())),
|
||||||
Widget::Date { font_size } => Some(widgets::date::Date::new(font_size)),
|
Widget::Date { font_size } => Some(widgets::date::Date::new(font_size)),
|
||||||
Widget::Calendar {
|
Widget::Calendar {
|
||||||
font_size,
|
font_size,
|
||||||
@@ -127,16 +121,8 @@ impl Widget {
|
|||||||
Err(_) => None,
|
Err(_) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(feature = "pulseaudio-widget")]
|
|
||||||
Widget::PulseAudio { font_size, length } => {
|
Widget::PulseAudio { font_size, length } => {
|
||||||
match widgets::audio::PulseAudio::new(font_size, length, tx.clone()) {
|
match widgets::sound::PulseAudio::new(font_size, length, tx.clone()) {
|
||||||
Ok(w) => Some(w),
|
|
||||||
Err(_) => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(feature = "alsa-widget")]
|
|
||||||
Widget::AlsaSound { font_size, length } => {
|
|
||||||
match widgets::audio::Alsa::new(font_size, length) {
|
|
||||||
Ok(w) => Some(w),
|
Ok(w) => Some(w),
|
||||||
Err(_) => None,
|
Err(_) => None,
|
||||||
}
|
}
|
||||||
@@ -161,10 +147,10 @@ impl Default for OutputMode {
|
|||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
|
pub widget: Widget,
|
||||||
pub output_mode: OutputMode,
|
pub output_mode: OutputMode,
|
||||||
pub scale: u32,
|
pub scale: u32,
|
||||||
pub background: Color,
|
pub background: Color,
|
||||||
pub widget: Widget,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
@@ -196,7 +182,6 @@ impl Default for Config {
|
|||||||
length: 600,
|
length: 600,
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
#[cfg(feature = "pulseaudio-widget")]
|
|
||||||
Box::new(Widget::Margin {
|
Box::new(Widget::Margin {
|
||||||
margins: (0, 0, 0, 8),
|
margins: (0, 0, 0, 8),
|
||||||
widget: Box::new(Widget::PulseAudio {
|
widget: Box::new(Widget::PulseAudio {
|
||||||
|
|||||||
@@ -1,61 +0,0 @@
|
|||||||
use serde::{de::DeserializeOwned, Serialize};
|
|
||||||
use std::io::BufRead;
|
|
||||||
|
|
||||||
pub enum ConfigFmt {
|
|
||||||
#[cfg(feature = "yaml-cfg")]
|
|
||||||
Yaml,
|
|
||||||
#[cfg(feature = "json-cfg")]
|
|
||||||
Json,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const CONFIG_NAMES: &'static [&'static str] = &[
|
|
||||||
#[cfg(feature = "yaml-cfg")]
|
|
||||||
"config.yaml",
|
|
||||||
#[cfg(feature = "json-cfg")]
|
|
||||||
"config.json",
|
|
||||||
];
|
|
||||||
|
|
||||||
impl ConfigFmt {
|
|
||||||
#[inline]
|
|
||||||
pub fn new(ext: &str) -> Option<Self> {
|
|
||||||
match ext {
|
|
||||||
#[cfg(feature = "yaml-cfg")]
|
|
||||||
"yaml" => Some(ConfigFmt::Yaml),
|
|
||||||
#[cfg(feature = "json-cfg")]
|
|
||||||
"json" => Some(ConfigFmt::Json),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub fn from_reader<B: BufRead, T: DeserializeOwned>(&self, r: B) -> T {
|
|
||||||
match self {
|
|
||||||
#[cfg(feature = "yaml-cfg")]
|
|
||||||
ConfigFmt::Yaml => serde_yaml::from_reader(r).unwrap(),
|
|
||||||
#[cfg(feature = "json-cfg")]
|
|
||||||
ConfigFmt::Json => serde_json::from_reader(r).unwrap(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub fn to_string<T: Serialize + ?Sized>(&self, src: &T) -> String {
|
|
||||||
match self {
|
|
||||||
#[cfg(feature = "yaml-cfg")]
|
|
||||||
ConfigFmt::Yaml => serde_yaml::to_string(&src).unwrap(),
|
|
||||||
#[cfg(feature = "json-cfg")]
|
|
||||||
ConfigFmt::Json => serde_json::to_string_pretty(&src).unwrap(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for ConfigFmt {
|
|
||||||
fn default() -> Self {
|
|
||||||
// attributes require curly braces to work
|
|
||||||
#[cfg(feature = "yaml-cfg")]
|
|
||||||
{
|
|
||||||
ConfigFmt::Yaml
|
|
||||||
}
|
|
||||||
#[cfg(all(feature = "json-cfg", not(feature = "yaml-cfg")))]
|
|
||||||
{
|
|
||||||
ConfigFmt::Json
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+2
-2
@@ -27,7 +27,7 @@ impl Desktop {
|
|||||||
enabled_escape: false,
|
enabled_escape: false,
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
match file.section(Some("Desktop Entry")) {
|
match file.section(Some("Desktop Entry").to_owned()) {
|
||||||
Some(desktop) => Ok(Desktop {
|
Some(desktop) => Ok(Desktop {
|
||||||
entry_type: desktop.get("Type").unwrap_or(&"".to_string()).to_string(),
|
entry_type: desktop.get("Type").unwrap_or(&"".to_string()).to_string(),
|
||||||
name: desktop.get("Name").unwrap_or(&"".to_string()).to_string(),
|
name: desktop.get("Name").unwrap_or(&"".to_string()).to_string(),
|
||||||
@@ -45,7 +45,7 @@ impl Desktop {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_dir(d: &str) -> Result<Vec<Desktop>, Box<dyn Error>> {
|
fn parse_dir(d: &str) -> Result<Vec<Desktop>, Box<dyn Error>> {
|
||||||
let mut files: Vec<Desktop> = Vec::with_capacity(16);
|
let mut files: Vec<Desktop> = Vec::new();
|
||||||
for entry in fs::read_dir(d)? {
|
for entry in fs::read_dir(d)? {
|
||||||
let entry = entry?;
|
let entry = entry?;
|
||||||
let path = entry.path();
|
let path = entry.path();
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ impl DoubleMemPool {
|
|||||||
pub fn pool(&mut self) -> Option<(&mut MemPool, &mut MemPool)> {
|
pub fn pool(&mut self) -> Option<(&mut MemPool, &mut MemPool)> {
|
||||||
let switch = self.switch;
|
let switch = self.switch;
|
||||||
self.switch = !self.switch;
|
self.switch = !self.switch;
|
||||||
let (last, cur) = if !switch {
|
let (last, cur) = if switch {
|
||||||
(&mut self.pool2, &mut self.pool1)
|
(&mut self.pool2, &mut self.pool1)
|
||||||
} else {
|
} else {
|
||||||
(&mut self.pool1, &mut self.pool2)
|
(&mut self.pool1, &mut self.pool2)
|
||||||
@@ -31,8 +31,4 @@ impl DoubleMemPool {
|
|||||||
Some((last, cur))
|
Some((last, cur))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn never_mind(&mut self) {
|
|
||||||
self.switch = !self.switch;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+69
-161
@@ -1,3 +1,4 @@
|
|||||||
|
use std::default::Default;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{BufRead, BufReader, Read, Write};
|
use std::io::{BufRead, BufReader, Read, Write};
|
||||||
@@ -5,17 +6,14 @@ use std::os::unix::io::AsRawFd;
|
|||||||
use std::os::unix::net::{UnixListener, UnixStream};
|
use std::os::unix::net::{UnixListener, UnixStream};
|
||||||
use std::sync::mpsc::channel;
|
use std::sync::mpsc::channel;
|
||||||
|
|
||||||
use timerfd::{TimerFd, TimerState, SetTimeFlags};
|
|
||||||
use nix::poll::{poll, PollFd, PollFlags};
|
use nix::poll::{poll, PollFd, PollFlags};
|
||||||
use os_pipe::pipe;
|
use os_pipe::pipe;
|
||||||
use chrono::{Local, Duration};
|
|
||||||
|
|
||||||
mod app;
|
mod app;
|
||||||
mod buffer;
|
mod buffer;
|
||||||
mod cmd;
|
mod cmd;
|
||||||
mod color;
|
mod color;
|
||||||
mod config;
|
mod config;
|
||||||
mod configfmt;
|
|
||||||
mod desktop;
|
mod desktop;
|
||||||
mod doublemempool;
|
mod doublemempool;
|
||||||
mod draw;
|
mod draw;
|
||||||
@@ -24,16 +22,12 @@ mod widgets;
|
|||||||
|
|
||||||
use app::{App, OutputMode};
|
use app::{App, OutputMode};
|
||||||
use cmd::Cmd;
|
use cmd::Cmd;
|
||||||
use config::Config;
|
|
||||||
use configfmt::ConfigFmt;
|
|
||||||
use widget::WaitContext;
|
|
||||||
|
|
||||||
enum Mode {
|
enum Mode {
|
||||||
Start,
|
Start,
|
||||||
Daemonize,
|
|
||||||
StartOrKill,
|
StartOrKill,
|
||||||
ToggleVisible,
|
ToggleVisible,
|
||||||
PrintConfig(ConfigFmt),
|
PrintConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
@@ -49,69 +43,34 @@ fn main() {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// From all existing files take the first readable one and write it's extension to `ext`
|
let config: config::Config = match File::open(config_home + "/config.json") {
|
||||||
let mut ext = [0x0; 8];
|
Ok(f) => {
|
||||||
let file = configfmt::CONFIG_NAMES
|
let reader = BufReader::new(f);
|
||||||
.iter()
|
serde_json::from_reader(reader).unwrap()
|
||||||
.map(|name| std::path::Path::new(&config_home).join(name))
|
}
|
||||||
.filter_map(|path| {
|
Err(_) => Default::default(),
|
||||||
match File::open(&path) {
|
};
|
||||||
Ok(file) => {
|
|
||||||
let e = path.extension().and_then(|e| e.to_str())?;
|
|
||||||
let len = e.len();
|
|
||||||
let from = len.saturating_sub(8); // the longest possible extension
|
|
||||||
ext[0..len - from].copy_from_slice(&e.as_bytes()[from..]);
|
|
||||||
Some(file)
|
|
||||||
}
|
|
||||||
Err(_) => None,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.next();
|
|
||||||
|
|
||||||
let fmt = std::str::from_utf8(&ext)
|
|
||||||
.ok()
|
|
||||||
.and_then(ConfigFmt::new)
|
|
||||||
.unwrap_or_default();
|
|
||||||
|
|
||||||
let config: Config = file
|
|
||||||
.map(|f| fmt.from_reader(BufReader::new(f)))
|
|
||||||
.unwrap_or_default();
|
|
||||||
|
|
||||||
let scale = config.scale;
|
let scale = config.scale;
|
||||||
|
|
||||||
let mut args = env::args();
|
let args: Vec<String> = env::args().collect();
|
||||||
let _ = args.next();
|
let mode = match args.len() {
|
||||||
let mode = match args.next() {
|
1 => Mode::Start,
|
||||||
Some(arg) => match arg.as_str() {
|
2 => match args[1].as_str() {
|
||||||
"start" => Mode::Daemonize,
|
"start" => Mode::Start,
|
||||||
"start-or-kill" => Mode::StartOrKill,
|
"start-or-kill" => Mode::StartOrKill,
|
||||||
"toggle-visible" => Mode::ToggleVisible,
|
"toggle-visible" => Mode::ToggleVisible,
|
||||||
"print-config" => Mode::PrintConfig(fmt),
|
"print-config" => Mode::PrintConfig,
|
||||||
s => {
|
s => {
|
||||||
let p = "print-config-";
|
eprintln!("unsupported sub-command {}", s);
|
||||||
let l = p.len();
|
std::process::exit(1);
|
||||||
let fmt = if s.starts_with(p) {
|
|
||||||
ConfigFmt::new(&s[l..])
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
if let Some(fmt) = fmt {
|
|
||||||
Mode::PrintConfig(fmt)
|
|
||||||
} else {
|
|
||||||
eprintln!("unsupported sub-command {}", s);
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => Mode::Start,
|
v => {
|
||||||
|
eprintln!("expected 0 or 1 arguments, got {}", v);
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
if let Some(_) = args.next() {
|
|
||||||
// total = args.count + 2 (the two we skipped + the rest)
|
|
||||||
eprintln!("expected 0 or 1 arguments, got {}", args.count() + 2);
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut daemon = false;
|
|
||||||
|
|
||||||
match mode {
|
match mode {
|
||||||
Mode::ToggleVisible => {
|
Mode::ToggleVisible => {
|
||||||
@@ -134,15 +93,8 @@ fn main() {
|
|||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Mode::Daemonize => {
|
Mode::PrintConfig => {
|
||||||
if let Ok(_) = UnixStream::connect(socket_path.clone()) {
|
println!("{}", serde_json::to_string_pretty(&config).unwrap());
|
||||||
eprintln!("wldash is already running");
|
|
||||||
std::process::exit(1);
|
|
||||||
};
|
|
||||||
daemon = true;
|
|
||||||
}
|
|
||||||
Mode::PrintConfig(fmt) => {
|
|
||||||
println!("{}", fmt.to_string(&config));
|
|
||||||
std::process::exit(0);
|
std::process::exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -169,11 +121,6 @@ fn main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let mut app = App::new(tx_draw, output_mode, background, scale);
|
let mut app = App::new(tx_draw, output_mode, background, scale);
|
||||||
if daemon {
|
|
||||||
app.hide();
|
|
||||||
} else {
|
|
||||||
app.show();
|
|
||||||
}
|
|
||||||
let widget = mod_rx.recv().unwrap();
|
let widget = mod_rx.recv().unwrap();
|
||||||
app.set_widget(widget).unwrap();
|
app.set_widget(widget).unwrap();
|
||||||
|
|
||||||
@@ -189,20 +136,49 @@ fn main() {
|
|||||||
tx_pipe.write_all(&[0x1]).unwrap();
|
tx_pipe.write_all(&[0x1]).unwrap();
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut timer = TimerFd::new().unwrap();
|
let ipc_queue = app.cmd_queue();
|
||||||
let ev_fd = PollFd::new(app.event_queue().get_connection_fd(), PollFlags::POLLIN);
|
let _ = std::thread::Builder::new()
|
||||||
let rx_fd = PollFd::new(rx_pipe.as_raw_fd(), PollFlags::POLLIN);
|
.name("ipc_server".to_string())
|
||||||
let tm_fd = PollFd::new(timer.as_raw_fd(), PollFlags::POLLIN);
|
.spawn(move || loop {
|
||||||
let ipc_fd = PollFd::new(listener.as_raw_fd(), PollFlags::POLLIN);
|
for stream in listener.incoming() {
|
||||||
|
match stream {
|
||||||
|
Ok(stream) => {
|
||||||
|
let client_queue = ipc_queue.clone();
|
||||||
|
let mut client_pipe = ipc_pipe.try_clone().unwrap();
|
||||||
|
let _ = std::thread::Builder::new()
|
||||||
|
.name("ipc_client".to_string())
|
||||||
|
.spawn(move || {
|
||||||
|
let r = BufReader::new(stream);
|
||||||
|
for line in r.lines() {
|
||||||
|
match line {
|
||||||
|
Ok(v) => match v.as_str() {
|
||||||
|
"kill" => {
|
||||||
|
client_queue.lock().unwrap().push_back(Cmd::Exit)
|
||||||
|
}
|
||||||
|
"toggle_visible" => client_queue
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.push_back(Cmd::ToggleVisible),
|
||||||
|
v => eprintln!("unknown command: {}", v),
|
||||||
|
},
|
||||||
|
Err(_) => return,
|
||||||
|
}
|
||||||
|
client_pipe.write_all(&[0x1]).unwrap();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Err(_) => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut fds = [
|
||||||
|
PollFd::new(app.event_queue().get_connection_fd(), PollFlags::POLLIN),
|
||||||
|
PollFd::new(rx_pipe.as_raw_fd(), PollFlags::POLLIN),
|
||||||
|
];
|
||||||
|
|
||||||
app.cmd_queue().lock().unwrap().push_back(Cmd::Draw);
|
app.cmd_queue().lock().unwrap().push_back(Cmd::Draw);
|
||||||
|
|
||||||
let mut visible = !daemon;
|
|
||||||
let mut wait_ctx = WaitContext{
|
|
||||||
fds: Vec::new(),
|
|
||||||
target_time: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let q = app.cmd_queue();
|
let q = app.cmd_queue();
|
||||||
loop {
|
loop {
|
||||||
let cmd = q.lock().unwrap().pop_front();
|
let cmd = q.lock().unwrap().pop_front();
|
||||||
@@ -235,53 +211,19 @@ fn main() {
|
|||||||
q.lock().unwrap().push_back(Cmd::Draw);
|
q.lock().unwrap().push_back(Cmd::Draw);
|
||||||
}
|
}
|
||||||
Cmd::ToggleVisible => {
|
Cmd::ToggleVisible => {
|
||||||
visible = !visible;
|
app.toggle_visible();
|
||||||
if visible {
|
|
||||||
app.get_widget().enter();
|
|
||||||
app.show();
|
|
||||||
} else {
|
|
||||||
app.hide();
|
|
||||||
app.get_widget().leave();
|
|
||||||
}
|
|
||||||
app.flush_display();
|
|
||||||
}
|
}
|
||||||
Cmd::Exit => {
|
Cmd::Exit => {
|
||||||
if daemon {
|
let _ = std::fs::remove_file(socket_path);
|
||||||
visible = false;
|
return;
|
||||||
app.hide();
|
|
||||||
app.get_widget().leave();
|
|
||||||
app.flush_display();
|
|
||||||
} else {
|
|
||||||
let _ = std::fs::remove_file(socket_path);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
app.flush_display();
|
app.flush_display();
|
||||||
|
|
||||||
wait_ctx.fds.clear();
|
poll(&mut fds, -1).unwrap();
|
||||||
wait_ctx.fds.push(ev_fd);
|
|
||||||
wait_ctx.fds.push(rx_fd);
|
|
||||||
wait_ctx.fds.push(ipc_fd);
|
|
||||||
wait_ctx.target_time = None;
|
|
||||||
|
|
||||||
app.get_widget().wait(&mut wait_ctx);
|
if fds[0].revents().unwrap().contains(PollFlags::POLLIN) {
|
||||||
|
|
||||||
if let Some(target_time) = wait_ctx.target_time {
|
|
||||||
let n = Local::now();
|
|
||||||
let sleep = if target_time > n {
|
|
||||||
target_time - n
|
|
||||||
} else {
|
|
||||||
Duration::seconds(0)
|
|
||||||
};
|
|
||||||
timer.set_state(TimerState::Oneshot(sleep.to_std().unwrap()), SetTimeFlags::Default);
|
|
||||||
wait_ctx.fds.push(tm_fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
poll(&mut wait_ctx.fds, -1).unwrap();
|
|
||||||
|
|
||||||
if wait_ctx.fds[0].revents().unwrap().contains(PollFlags::POLLIN) {
|
|
||||||
if let Some(guard) = app.event_queue().prepare_read() {
|
if let Some(guard) = app.event_queue().prepare_read() {
|
||||||
if let Err(e) = guard.read_events() {
|
if let Err(e) = guard.read_events() {
|
||||||
if e.kind() != ::std::io::ErrorKind::WouldBlock {
|
if e.kind() != ::std::io::ErrorKind::WouldBlock {
|
||||||
@@ -298,44 +240,10 @@ fn main() {
|
|||||||
.expect("Failed to dispatch all messages.");
|
.expect("Failed to dispatch all messages.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if wait_ctx.fds[1].revents().unwrap().contains(PollFlags::POLLIN) {
|
if fds[1].revents().unwrap().contains(PollFlags::POLLIN) {
|
||||||
let mut v = [0x00];
|
let mut v = [0x00];
|
||||||
rx_pipe.read_exact(&mut v).unwrap();
|
rx_pipe.read_exact(&mut v).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
if wait_ctx.fds[2].revents().unwrap().contains(PollFlags::POLLIN) {
|
|
||||||
if let Ok((stream, _)) = listener.accept() {
|
|
||||||
let client_queue = q.clone();
|
|
||||||
let mut client_pipe = ipc_pipe.try_clone().unwrap();
|
|
||||||
let _ = std::thread::Builder::new()
|
|
||||||
.name("ipc_client".to_string())
|
|
||||||
.spawn(move || {
|
|
||||||
let r = BufReader::new(stream);
|
|
||||||
for line in r.lines() {
|
|
||||||
match line {
|
|
||||||
Ok(v) => match v.as_str() {
|
|
||||||
"kill" => {
|
|
||||||
client_queue.lock().unwrap().push_back(Cmd::Exit)
|
|
||||||
}
|
|
||||||
"toggle_visible" => client_queue
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.push_back(Cmd::ToggleVisible),
|
|
||||||
v => eprintln!("unknown command: {}", v),
|
|
||||||
},
|
|
||||||
Err(_) => return,
|
|
||||||
}
|
|
||||||
client_pipe.write_all(&[0x1]).unwrap();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if wait_ctx.target_time.is_some() &&
|
|
||||||
wait_ctx.fds[wait_ctx.fds.len()-1].revents().unwrap().contains(PollFlags::POLLIN) {
|
|
||||||
timer.read();
|
|
||||||
q.lock().unwrap().push_back(Cmd::Draw);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use nix::poll::{PollFd};
|
|
||||||
use crate::buffer::Buffer;
|
use crate::buffer::Buffer;
|
||||||
use crate::color::Color;
|
use crate::color::Color;
|
||||||
use chrono::{DateTime, Local};
|
use chrono::{DateTime, Local};
|
||||||
@@ -30,27 +29,7 @@ impl DrawReport {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WaitContext {
|
|
||||||
pub fds: Vec<PollFd>,
|
|
||||||
pub target_time: Option<DateTime<Local>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WaitContext {
|
|
||||||
pub fn set_time(&mut self, new_time: DateTime<Local>) {
|
|
||||||
if let Some(ot) = self.target_time {
|
|
||||||
if new_time < ot {
|
|
||||||
self.target_time = Some(new_time);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.target_time = Some(new_time);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Widget {
|
pub trait Widget {
|
||||||
fn wait(&mut self, ctx: &mut WaitContext);
|
|
||||||
fn enter(&mut self);
|
|
||||||
fn leave(&mut self);
|
|
||||||
fn size(&self) -> (u32, u32);
|
fn size(&self) -> (u32, u32);
|
||||||
fn draw(
|
fn draw(
|
||||||
&mut self,
|
&mut self,
|
||||||
@@ -81,21 +60,6 @@ impl VerticalLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for VerticalLayout {
|
impl Widget for VerticalLayout {
|
||||||
fn wait(&mut self, ctx: &mut WaitContext) {
|
|
||||||
for child in &mut self.children {
|
|
||||||
child.wait(ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn enter(&mut self) {
|
|
||||||
for child in &mut self.children {
|
|
||||||
child.enter();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn leave(&mut self) {
|
|
||||||
for child in &mut self.children {
|
|
||||||
child.leave();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn size(&self) -> (u32, u32) {
|
fn size(&self) -> (u32, u32) {
|
||||||
let mut width = 0;
|
let mut width = 0;
|
||||||
let mut height = 0;
|
let mut height = 0;
|
||||||
@@ -192,21 +156,6 @@ impl HorizontalLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for HorizontalLayout {
|
impl Widget for HorizontalLayout {
|
||||||
fn wait(&mut self, ctx: &mut WaitContext) {
|
|
||||||
for child in &mut self.children {
|
|
||||||
child.wait(ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn enter(&mut self) {
|
|
||||||
for child in &mut self.children {
|
|
||||||
child.enter();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn leave(&mut self) {
|
|
||||||
for child in &mut self.children {
|
|
||||||
child.leave();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn size(&self) -> (u32, u32) {
|
fn size(&self) -> (u32, u32) {
|
||||||
let mut width = 0;
|
let mut width = 0;
|
||||||
let mut height = 0;
|
let mut height = 0;
|
||||||
@@ -309,15 +258,6 @@ impl Margin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for Margin {
|
impl Widget for Margin {
|
||||||
fn wait(&mut self, ctx: &mut WaitContext) {
|
|
||||||
self.child.wait(ctx)
|
|
||||||
}
|
|
||||||
fn enter(&mut self) {
|
|
||||||
self.child.enter()
|
|
||||||
}
|
|
||||||
fn leave(&mut self) {
|
|
||||||
self.child.leave()
|
|
||||||
}
|
|
||||||
fn size(&self) -> (u32, u32) {
|
fn size(&self) -> (u32, u32) {
|
||||||
let size = self.child.size();
|
let size = self.child.size();
|
||||||
(
|
(
|
||||||
@@ -386,15 +326,6 @@ impl Fixed {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for Fixed {
|
impl Widget for Fixed {
|
||||||
fn wait(&mut self, ctx: &mut WaitContext) {
|
|
||||||
self.child.wait(ctx)
|
|
||||||
}
|
|
||||||
fn enter(&mut self) {
|
|
||||||
self.child.enter()
|
|
||||||
}
|
|
||||||
fn leave(&mut self) {
|
|
||||||
self.child.leave()
|
|
||||||
}
|
|
||||||
fn size(&self) -> (u32, u32) {
|
fn size(&self) -> (u32, u32) {
|
||||||
self.size
|
self.size
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,111 +0,0 @@
|
|||||||
use crate::color::Color;
|
|
||||||
use crate::widgets::bar_widget::{BarWidget, BarWidgetImpl};
|
|
||||||
use crate::widget::WaitContext;
|
|
||||||
|
|
||||||
use alsa::mixer::{Mixer, Selem, SelemChannelId, SelemId};
|
|
||||||
|
|
||||||
const CARD_NAME: &'static str = "default";
|
|
||||||
const SELEM_NAME: &'static str = "Master";
|
|
||||||
const SELEM_ID: u32 = 0u32;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn alsa_error_to_io_error(fail: &'static str, err: &alsa::Error) -> ::std::io::Error {
|
|
||||||
let kind = ::std::io::ErrorKind::Other;
|
|
||||||
let func = err.func();
|
|
||||||
let errno = err
|
|
||||||
.errno()
|
|
||||||
.map(|errno| format!("; errno = {}", errno))
|
|
||||||
.unwrap_or(String::new());
|
|
||||||
return ::std::io::Error::new(kind, format!("{}: {}{}", fail, func, errno));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Alsa {
|
|
||||||
pub mixer: Mixer,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Alsa {
|
|
||||||
pub fn new(font_size: f32, length: u32) -> ::std::io::Result<Box<BarWidget>> {
|
|
||||||
let mixer = Mixer::new(CARD_NAME, true)
|
|
||||||
.map_err(|err| alsa_error_to_io_error("Failed to create ALSA mixer", &err))?;
|
|
||||||
let mixer = Self { mixer };
|
|
||||||
mixer.get_master_volume()?; // probing
|
|
||||||
Ok(BarWidget::new_simple(font_size, length, Box::new(mixer)))
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub fn get_master<'a>(&'a self) -> ::std::io::Result<Selem<'a>> {
|
|
||||||
let master_id = SelemId::new(SELEM_NAME, SELEM_ID);
|
|
||||||
match self.mixer.find_selem(&master_id) {
|
|
||||||
Some(master) => Ok(master),
|
|
||||||
None => {
|
|
||||||
let kind = ::std::io::ErrorKind::NotFound;
|
|
||||||
let desc = "`Master` not found";
|
|
||||||
Err(::std::io::Error::new(kind, desc))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn get_master_volume(&self) -> ::std::io::Result<f32> {
|
|
||||||
let master = self.get_master()?;
|
|
||||||
let (min, max) = master.get_playback_volume_range();
|
|
||||||
master
|
|
||||||
.get_playback_volume(SelemChannelId::mono())
|
|
||||||
.map(|volume| alsa_volume_to_f32(volume, min, max))
|
|
||||||
.map_err(|e| alsa_error_to_io_error("Failed to get `Master` volume", &e))
|
|
||||||
}
|
|
||||||
pub fn set_master_volume(&self, volume: f32) -> ::std::io::Result<()> {
|
|
||||||
let master = self.get_master()?;
|
|
||||||
let (min, max) = master.get_playback_volume_range();
|
|
||||||
let volume = f32_to_alsa_volume(volume, min, max);
|
|
||||||
master
|
|
||||||
.set_playback_volume_all(volume)
|
|
||||||
.map_err(|e| alsa_error_to_io_error("Failed to set `Master` volume", &e))
|
|
||||||
}
|
|
||||||
pub fn inc_master_volume(&self, diff: f32) -> ::std::io::Result<()> {
|
|
||||||
let master = self.get_master()?;
|
|
||||||
let (min, max) = master.get_playback_volume_range();
|
|
||||||
master
|
|
||||||
.get_playback_volume(SelemChannelId::mono())
|
|
||||||
.and_then(|volume| {
|
|
||||||
let volume = alsa_volume_to_f32(volume, min, max);
|
|
||||||
let volume = f32_to_alsa_volume(volume + diff, min, max);
|
|
||||||
master.set_playback_volume_all(volume)
|
|
||||||
})
|
|
||||||
.map_err(|e| alsa_error_to_io_error("Failed to inc/dec `Master` volume", &e))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BarWidgetImpl for Alsa {
|
|
||||||
fn wait(&mut self, _: &mut WaitContext) {}
|
|
||||||
fn name(&self) -> &str {
|
|
||||||
"volume"
|
|
||||||
}
|
|
||||||
fn value(&self) -> f32 {
|
|
||||||
match self.get_master_volume() {
|
|
||||||
Ok(v) => v,
|
|
||||||
Err(e) => panic!(e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn color(&self) -> Color {
|
|
||||||
Color::new(1.0, 1.0, 1.0, 1.0)
|
|
||||||
}
|
|
||||||
fn inc(&mut self, diff: f32) {
|
|
||||||
if let Err(e) = self.inc_master_volume(diff) {
|
|
||||||
panic!(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn set(&mut self, abs: f32) {
|
|
||||||
if let Err(e) = self.set_master_volume(abs) {
|
|
||||||
panic!(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn toggle(&mut self) {}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
#[cfg(feature = "alsa-widget")]
|
|
||||||
mod alsa_sound;
|
|
||||||
#[cfg(feature = "alsa-widget")]
|
|
||||||
pub use alsa_sound::Alsa;
|
|
||||||
|
|
||||||
#[cfg(feature = "pulseaudio-widget")]
|
|
||||||
mod pulse_sound;
|
|
||||||
#[cfg(feature = "pulseaudio-widget")]
|
|
||||||
pub use pulse_sound::PulseAudio;
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
use crate::color::Color;
|
use crate::color::Color;
|
||||||
use crate::widgets::bar_widget::{BarWidget, BarWidgetImpl};
|
use crate::widgets::bar_widget::{BarWidget, BarWidgetImpl};
|
||||||
use crate::widget::WaitContext;
|
|
||||||
|
|
||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
use std::io::{Error, ErrorKind};
|
use std::io::{Error, ErrorKind};
|
||||||
@@ -94,7 +93,6 @@ impl Backlight {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BarWidgetImpl for Backlight {
|
impl BarWidgetImpl for Backlight {
|
||||||
fn wait(&mut self, _: &mut WaitContext) {}
|
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"backlight"
|
"backlight"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
use crate::color::Color;
|
use crate::color::Color;
|
||||||
use crate::draw::{draw_bar, draw_box, Font, ROBOTO_REGULAR};
|
use crate::draw::{draw_bar, draw_box, Font, ROBOTO_REGULAR};
|
||||||
use crate::widget::{DrawContext, DrawReport, KeyState, ModifiersState, Widget, WaitContext};
|
use crate::widget::{DrawContext, DrawReport, KeyState, ModifiersState, Widget};
|
||||||
|
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
pub trait BarWidgetImpl {
|
pub trait BarWidgetImpl {
|
||||||
fn wait(&mut self, ctx: &mut WaitContext);
|
|
||||||
fn name(&self) -> &str;
|
fn name(&self) -> &str;
|
||||||
fn value(&self) -> f32;
|
fn value(&self) -> f32;
|
||||||
fn color(&self) -> Color;
|
fn color(&self) -> Color;
|
||||||
@@ -62,14 +61,10 @@ impl BarWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for BarWidget {
|
impl Widget for BarWidget {
|
||||||
fn wait(&mut self, ctx: &mut WaitContext) {
|
|
||||||
self.bar_impl.wait(ctx);
|
|
||||||
}
|
|
||||||
fn enter(&mut self) {}
|
|
||||||
fn leave(&mut self) {}
|
|
||||||
fn size(&self) -> (u32, u32) {
|
fn size(&self) -> (u32, u32) {
|
||||||
(self.length, self.font_size)
|
(self.length, self.font_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw(
|
fn draw(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &mut DrawContext,
|
ctx: &mut DrawContext,
|
||||||
|
|||||||
+71
-86
@@ -1,12 +1,10 @@
|
|||||||
use crate::cmd::Cmd;
|
use crate::cmd::Cmd;
|
||||||
use crate::color::Color;
|
use crate::color::Color;
|
||||||
use crate::widgets::bar_widget::{BarWidget, BarWidgetImpl};
|
use crate::widgets::bar_widget::{BarWidget, BarWidgetImpl};
|
||||||
use crate::widget::WaitContext;
|
|
||||||
|
|
||||||
use std::sync::mpsc::Sender;
|
use std::sync::mpsc::Sender;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
use std::thread;
|
||||||
use nix::poll::{PollFd, PollFlags};
|
|
||||||
|
|
||||||
use dbus;
|
use dbus;
|
||||||
|
|
||||||
@@ -30,34 +28,21 @@ fn get_upower_property(
|
|||||||
.append2(
|
.append2(
|
||||||
dbus::MessageItem::Str("org.freedesktop.UPower.Device".to_string()),
|
dbus::MessageItem::Str("org.freedesktop.UPower.Device".to_string()),
|
||||||
dbus::MessageItem::Str(property.to_string()),
|
dbus::MessageItem::Str(property.to_string()),
|
||||||
);
|
);;
|
||||||
|
|
||||||
con.send_with_reply_and_block(msg, 1000).map_err(|_| {
|
con.send_with_reply_and_block(msg, 1000).map_err(|_| {
|
||||||
::std::io::Error::new(::std::io::ErrorKind::Other, "could not send dbus message")
|
::std::io::Error::new(::std::io::ErrorKind::Other, "could not send dbus message")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// The widget is created on a different thread than where it will be used, so
|
|
||||||
// we need it to be Send. However, dbus::Connection has a void*, so it's not
|
|
||||||
// auto-derived. So, we make a small wrapper where we make it Send.
|
|
||||||
struct DbusConnection(dbus::Connection);
|
|
||||||
|
|
||||||
impl std::convert::AsRef<dbus::Connection> for DbusConnection {
|
|
||||||
fn as_ref(&self) -> &dbus::Connection {
|
|
||||||
return &self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe impl Send for DbusConnection {}
|
|
||||||
|
|
||||||
pub struct UpowerBattery {
|
pub struct UpowerBattery {
|
||||||
device_path: String,
|
device_path: String,
|
||||||
sender: Sender<Cmd>,
|
inner: Arc<Mutex<UpowerBatteryInner>>,
|
||||||
dirty: Arc<Mutex<bool>>,
|
}
|
||||||
|
|
||||||
|
pub struct UpowerBatteryInner {
|
||||||
state: UpowerBatteryState,
|
state: UpowerBatteryState,
|
||||||
capacity: f64,
|
capacity: f64,
|
||||||
con: DbusConnection,
|
|
||||||
watch: dbus::Watch,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum UpowerBatteryState {
|
enum UpowerBatteryState {
|
||||||
@@ -70,26 +55,12 @@ enum UpowerBatteryState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl UpowerBattery {
|
impl UpowerBattery {
|
||||||
pub fn from_device(dirty: Arc<Mutex<bool>>, sender: Sender<Cmd>, device: &str) -> Result<Self, ::std::io::Error> {
|
pub fn from_device(device: &str) -> Result<Self, ::std::io::Error> {
|
||||||
let con = dbus::Connection::get_private(dbus::BusType::System)
|
|
||||||
.map_err(|_| ::std::io::Error::new(
|
|
||||||
::std::io::ErrorKind::Other,
|
|
||||||
"unable to open dbus",
|
|
||||||
))?;
|
|
||||||
let device_path = format!("/org/freedesktop/UPower/devices/battery_{}", device);
|
let device_path = format!("/org/freedesktop/UPower/devices/battery_{}", device);
|
||||||
|
let con = dbus::Connection::get_private(dbus::BusType::System).map_err(|_| {
|
||||||
|
::std::io::Error::new(::std::io::ErrorKind::Other, "could not get dbus connection")
|
||||||
|
})?;
|
||||||
|
|
||||||
let rule = format!(
|
|
||||||
"type='signal',\
|
|
||||||
path='{}',\
|
|
||||||
interface='org.freedesktop.DBus.Properties',\
|
|
||||||
member='PropertiesChanged'",
|
|
||||||
&device_path
|
|
||||||
);
|
|
||||||
con.add_match(&rule)
|
|
||||||
.map_err(|_| ::std::io::Error::new(
|
|
||||||
::std::io::ErrorKind::Other,
|
|
||||||
"unable to add match rule to dbus connection",
|
|
||||||
))?;
|
|
||||||
let upower_type: dbus::arg::Variant<u32> =
|
let upower_type: dbus::arg::Variant<u32> =
|
||||||
match get_upower_property(&con, &device_path, "Type")?.get1() {
|
match get_upower_property(&con, &device_path, "Type")?.get1() {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
@@ -140,22 +111,12 @@ impl UpowerBattery {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let fds = con.watch_fds();
|
|
||||||
if fds.len() != 1 {
|
|
||||||
return Err(::std::io::Error::new(
|
|
||||||
::std::io::ErrorKind::Other,
|
|
||||||
"expected 1 watch fd from dbus",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(UpowerBattery {
|
Ok(UpowerBattery {
|
||||||
device_path,
|
device_path,
|
||||||
con: DbusConnection(con),
|
inner: Arc::new(Mutex::new(UpowerBatteryInner {
|
||||||
dirty,
|
capacity: capacity,
|
||||||
sender,
|
state: state,
|
||||||
capacity: capacity,
|
})),
|
||||||
state: state,
|
|
||||||
watch: fds[0],
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,52 +126,76 @@ impl UpowerBattery {
|
|||||||
sender: Sender<Cmd>,
|
sender: Sender<Cmd>,
|
||||||
) -> Result<Box<BarWidget>, ::std::io::Error> {
|
) -> Result<Box<BarWidget>, ::std::io::Error> {
|
||||||
BarWidget::new(font_size, length, move |dirty| {
|
BarWidget::new(font_size, length, move |dirty| {
|
||||||
let d = UpowerBattery::from_device(dirty, sender, "BAT0")?;
|
let d = UpowerBattery::from_device("BAT0")?;
|
||||||
|
let path = d.device_path.clone();
|
||||||
|
let inner = d.inner.clone();
|
||||||
|
let _ = thread::Builder::new()
|
||||||
|
.name("battery_monitor".to_string())
|
||||||
|
.spawn(move || {
|
||||||
|
let con = dbus::Connection::get_private(dbus::BusType::System)
|
||||||
|
.expect("Failed to establish D-Bus connection.");
|
||||||
|
let rule = format!(
|
||||||
|
"type='signal',\
|
||||||
|
path='{}',\
|
||||||
|
interface='org.freedesktop.DBus.Properties',\
|
||||||
|
member='PropertiesChanged'",
|
||||||
|
path
|
||||||
|
);
|
||||||
|
|
||||||
|
// First we're going to get an (irrelevant) NameAcquired event.
|
||||||
|
con.incoming(10_000).next();
|
||||||
|
|
||||||
|
con.add_match(&rule)
|
||||||
|
.expect("Failed to add D-Bus match rule.");
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if con.incoming(10_000).next().is_some() {
|
||||||
|
let capacity = get_upower_property(&con, &path, "Percentage")
|
||||||
|
.unwrap()
|
||||||
|
.get1::<dbus::arg::Variant<f64>>()
|
||||||
|
.unwrap()
|
||||||
|
.0;
|
||||||
|
let state = match get_upower_property(&con, &path, "State")
|
||||||
|
.unwrap()
|
||||||
|
.get1::<dbus::arg::Variant<u32>>()
|
||||||
|
.unwrap()
|
||||||
|
.0
|
||||||
|
{
|
||||||
|
1 => UpowerBatteryState::Charging,
|
||||||
|
2 => UpowerBatteryState::Discharging,
|
||||||
|
3 => UpowerBatteryState::Empty,
|
||||||
|
4 => UpowerBatteryState::Full,
|
||||||
|
5 => UpowerBatteryState::NotCharging,
|
||||||
|
6 => UpowerBatteryState::Discharging,
|
||||||
|
_ => UpowerBatteryState::Unknown,
|
||||||
|
};
|
||||||
|
let mut inner = inner.lock().unwrap();
|
||||||
|
inner.state = state;
|
||||||
|
inner.capacity = capacity;
|
||||||
|
*dirty.lock().unwrap() = true;
|
||||||
|
sender.send(Cmd::Draw).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Ok(Box::new(d))
|
Ok(Box::new(d))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BarWidgetImpl for UpowerBattery {
|
impl BarWidgetImpl for UpowerBattery {
|
||||||
fn wait(&mut self, ctx: &mut WaitContext) {
|
|
||||||
for _ in self.con.as_ref().watch_handle(self.watch.fd(), dbus::WatchEvent::Readable as u32) {
|
|
||||||
let capacity = get_upower_property(self.con.as_ref(), &self.device_path, "Percentage")
|
|
||||||
.unwrap()
|
|
||||||
.get1::<dbus::arg::Variant<f64>>()
|
|
||||||
.unwrap()
|
|
||||||
.0;
|
|
||||||
let state = match get_upower_property(self.con.as_ref(), &self.device_path, "State")
|
|
||||||
.unwrap()
|
|
||||||
.get1::<dbus::arg::Variant<u32>>()
|
|
||||||
.unwrap()
|
|
||||||
.0
|
|
||||||
{
|
|
||||||
1 => UpowerBatteryState::Charging,
|
|
||||||
2 => UpowerBatteryState::Discharging,
|
|
||||||
3 => UpowerBatteryState::Empty,
|
|
||||||
4 => UpowerBatteryState::Full,
|
|
||||||
5 => UpowerBatteryState::NotCharging,
|
|
||||||
6 => UpowerBatteryState::Discharging,
|
|
||||||
_ => UpowerBatteryState::Unknown,
|
|
||||||
};
|
|
||||||
self.state = state;
|
|
||||||
self.capacity = capacity;
|
|
||||||
*self.dirty.lock().unwrap() = true;
|
|
||||||
self.sender.send(Cmd::Draw).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.fds.push(PollFd::new(self.watch.fd(), PollFlags::POLLIN));
|
|
||||||
}
|
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"battery"
|
"battery"
|
||||||
}
|
}
|
||||||
fn value(&self) -> f32 {
|
fn value(&self) -> f32 {
|
||||||
(self.capacity as f32) / 100.0
|
let inner = self.inner.lock().unwrap();
|
||||||
|
(inner.capacity as f32) / 100.0
|
||||||
}
|
}
|
||||||
fn color(&self) -> Color {
|
fn color(&self) -> Color {
|
||||||
match self.state {
|
let inner = self.inner.lock().unwrap();
|
||||||
|
match inner.state {
|
||||||
UpowerBatteryState::Discharging | UpowerBatteryState::Unknown => {
|
UpowerBatteryState::Discharging | UpowerBatteryState::Unknown => {
|
||||||
if self.capacity > 10.0 {
|
if inner.capacity > 10.0 {
|
||||||
Color::new(1.0, 1.0, 1.0, 1.0)
|
Color::new(1.0, 1.0, 1.0, 1.0)
|
||||||
} else {
|
} else {
|
||||||
Color::new(1.0, 0.5, 0.0, 1.0)
|
Color::new(1.0, 0.5, 0.0, 1.0)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::buffer::Buffer;
|
use crate::buffer::Buffer;
|
||||||
use crate::color::Color;
|
use crate::color::Color;
|
||||||
use crate::draw::{Font, DEJAVUSANS_MONO, ROBOTO_REGULAR};
|
use crate::draw::{Font, DEJAVUSANS_MONO, ROBOTO_REGULAR};
|
||||||
use crate::widget::{DrawContext, DrawReport, KeyState, ModifiersState, Widget, WaitContext};
|
use crate::widget::{DrawContext, DrawReport, KeyState, ModifiersState, Widget};
|
||||||
|
|
||||||
use chrono::{Date, Datelike, Local};
|
use chrono::{Date, Datelike, Local};
|
||||||
|
|
||||||
@@ -177,10 +177,6 @@ impl Calendar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for Calendar {
|
impl Widget for Calendar {
|
||||||
fn wait(&mut self, _: &mut WaitContext) {}
|
|
||||||
fn enter(&mut self) {}
|
|
||||||
fn leave(&mut self) {}
|
|
||||||
|
|
||||||
fn size(&self) -> (u32, u32) {
|
fn size(&self) -> (u32, u32) {
|
||||||
let cal_width = 7 * self.font_size * 3 + self.font_size * 2;
|
let cal_width = 7 * self.font_size * 3 + self.font_size * 2;
|
||||||
let cal_pad = self.font_size * 3;
|
let cal_pad = self.font_size * 3;
|
||||||
|
|||||||
+22
-13
@@ -1,6 +1,9 @@
|
|||||||
|
use crate::cmd::Cmd;
|
||||||
use crate::color::Color;
|
use crate::color::Color;
|
||||||
use crate::draw::{Font, ROBOTO_REGULAR};
|
use crate::draw::{Font, ROBOTO_REGULAR};
|
||||||
use crate::widget::{DrawContext, DrawReport, KeyState, ModifiersState, Widget, WaitContext};
|
use crate::widget::{DrawContext, DrawReport, KeyState, ModifiersState, Widget};
|
||||||
|
|
||||||
|
use std::sync::mpsc::Sender;
|
||||||
|
|
||||||
use chrono::{DateTime, Datelike, Duration, Local, Timelike};
|
use chrono::{DateTime, Datelike, Duration, Local, Timelike};
|
||||||
|
|
||||||
@@ -11,7 +14,23 @@ pub struct Clock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Clock {
|
impl Clock {
|
||||||
pub fn new(size: f32) -> Box<Clock> {
|
pub fn new(size: f32, ch: Sender<Cmd>) -> Box<Clock> {
|
||||||
|
let _ = std::thread::Builder::new()
|
||||||
|
.name("clock_ticker".to_string())
|
||||||
|
.spawn(move || loop {
|
||||||
|
let n = Local::now();
|
||||||
|
let target = (n + Duration::seconds(60))
|
||||||
|
.with_second(0)
|
||||||
|
.unwrap()
|
||||||
|
.with_nanosecond(0)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let d = target - n;
|
||||||
|
|
||||||
|
std::thread::sleep(d.to_std().unwrap());
|
||||||
|
ch.send(Cmd::Draw).unwrap();
|
||||||
|
});
|
||||||
|
|
||||||
let mut clock_cache = Font::new(&ROBOTO_REGULAR, size);
|
let mut clock_cache = Font::new(&ROBOTO_REGULAR, size);
|
||||||
clock_cache.add_str_to_cache("0123456789:");
|
clock_cache.add_str_to_cache("0123456789:");
|
||||||
|
|
||||||
@@ -26,16 +45,6 @@ impl Clock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for Clock {
|
impl Widget for Clock {
|
||||||
fn wait(&mut self, ctx: &mut WaitContext) {
|
|
||||||
let target = (self.cur_time + Duration::seconds(60))
|
|
||||||
.with_second(0)
|
|
||||||
.unwrap()
|
|
||||||
.with_nanosecond(0)
|
|
||||||
.unwrap();
|
|
||||||
ctx.set_time(target);
|
|
||||||
}
|
|
||||||
fn enter(&mut self) {}
|
|
||||||
fn leave(&mut self) {}
|
|
||||||
fn size(&self) -> (u32, u32) {
|
fn size(&self) -> (u32, u32) {
|
||||||
let digit = (self.size * 0.45).ceil() as u32;
|
let digit = (self.size * 0.45).ceil() as u32;
|
||||||
let colon = (self.size * 0.20).ceil() as u32;
|
let colon = (self.size * 0.20).ceil() as u32;
|
||||||
@@ -63,7 +72,7 @@ impl Widget for Clock {
|
|||||||
|
|
||||||
let digit = (self.size * 0.45).ceil() as u32;
|
let digit = (self.size * 0.45).ceil() as u32;
|
||||||
let colon = (self.size * 0.20).ceil() as u32;
|
let colon = (self.size * 0.20).ceil() as u32;
|
||||||
self.clock_cache.draw_text_fixed_width(
|
let dim = self.clock_cache.draw_text_fixed_width(
|
||||||
buf,
|
buf,
|
||||||
ctx.bg,
|
ctx.bg,
|
||||||
&Color::new(1.0, 1.0, 1.0, 1.0),
|
&Color::new(1.0, 1.0, 1.0, 1.0),
|
||||||
|
|||||||
+1
-4
@@ -1,6 +1,6 @@
|
|||||||
use crate::color::Color;
|
use crate::color::Color;
|
||||||
use crate::draw::{Font, ROBOTO_REGULAR};
|
use crate::draw::{Font, ROBOTO_REGULAR};
|
||||||
use crate::widget::{DrawContext, DrawReport, KeyState, ModifiersState, Widget, WaitContext};
|
use crate::widget::{DrawContext, DrawReport, KeyState, ModifiersState, Widget};
|
||||||
|
|
||||||
use chrono::{DateTime, Datelike, Local};
|
use chrono::{DateTime, Datelike, Local};
|
||||||
|
|
||||||
@@ -27,9 +27,6 @@ impl Date {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for Date {
|
impl Widget for Date {
|
||||||
fn wait(&mut self, _: &mut WaitContext) {}
|
|
||||||
fn enter(&mut self) {}
|
|
||||||
fn leave(&mut self) {}
|
|
||||||
fn size(&self) -> (u32, u32) {
|
fn size(&self) -> (u32, u32) {
|
||||||
((6.5 * self.size).ceil() as u32, self.size.ceil() as u32)
|
((6.5 * self.size).ceil() as u32, self.size.ceil() as u32)
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-14
@@ -3,7 +3,7 @@ use crate::cmd::Cmd;
|
|||||||
use crate::color::Color;
|
use crate::color::Color;
|
||||||
use crate::desktop::{load_desktop_files, Desktop};
|
use crate::desktop::{load_desktop_files, Desktop};
|
||||||
use crate::draw::{Font, ROBOTO_REGULAR};
|
use crate::draw::{Font, ROBOTO_REGULAR};
|
||||||
use crate::widget::{DrawContext, DrawReport, KeyState, ModifiersState, Widget, WaitContext};
|
use crate::widget::{DrawContext, DrawReport, KeyState, ModifiersState, Widget};
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
@@ -101,8 +101,8 @@ impl Launcher {
|
|||||||
)?
|
)?
|
||||||
};
|
};
|
||||||
|
|
||||||
x_off += size.0 + self.font_size / 2;
|
x_off += size.0 + self.font_size / 4;
|
||||||
width_remaining -= (size.0 + self.font_size / 2) as i32;
|
width_remaining -= (size.0 + self.font_size / 4) as i32;
|
||||||
|
|
||||||
if width_remaining < 0 {
|
if width_remaining < 0 {
|
||||||
break;
|
break;
|
||||||
@@ -192,15 +192,6 @@ fn wlcopy(s: &str) -> Result<(), String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for Launcher {
|
impl Widget for Launcher {
|
||||||
fn wait(&mut self, _: &mut WaitContext) {}
|
|
||||||
fn enter(&mut self) {}
|
|
||||||
fn leave(&mut self) {
|
|
||||||
self.input = "".to_string();
|
|
||||||
self.offset = 0;
|
|
||||||
self.result = None;
|
|
||||||
self.dirty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn size(&self) -> (u32, u32) {
|
fn size(&self) -> (u32, u32) {
|
||||||
(self.length, self.font_size)
|
(self.length, self.font_size)
|
||||||
}
|
}
|
||||||
@@ -278,12 +269,11 @@ impl Widget for Launcher {
|
|||||||
fn keyboard_input(
|
fn keyboard_input(
|
||||||
&mut self,
|
&mut self,
|
||||||
key: u32,
|
key: u32,
|
||||||
modifiers: ModifiersState,
|
_: ModifiersState,
|
||||||
_: KeyState,
|
_: KeyState,
|
||||||
interpreted: Option<String>,
|
interpreted: Option<String>,
|
||||||
) {
|
) {
|
||||||
match key {
|
match key {
|
||||||
keysyms::XKB_KEY_u if modifiers.ctrl => self.leave(),
|
|
||||||
keysyms::XKB_KEY_BackSpace => {
|
keysyms::XKB_KEY_BackSpace => {
|
||||||
if self.input.len() > 0 {
|
if self.input.len() > 0 {
|
||||||
self.input = self.input[..self.input.len() - 1].to_string();
|
self.input = self.input[..self.input.len() - 1].to_string();
|
||||||
|
|||||||
+1
-3
@@ -5,6 +5,4 @@ pub mod calendar;
|
|||||||
pub mod clock;
|
pub mod clock;
|
||||||
pub mod date;
|
pub mod date;
|
||||||
pub mod launcher;
|
pub mod launcher;
|
||||||
|
pub mod sound;
|
||||||
#[cfg(any(feature = "alsa-widget", feature = "pulseaudio-widget"))]
|
|
||||||
pub mod audio;
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
use crate::cmd::Cmd;
|
use crate::cmd::Cmd;
|
||||||
use crate::color::Color;
|
use crate::color::Color;
|
||||||
use crate::widgets::bar_widget::{BarWidget, BarWidgetImpl};
|
use crate::widgets::bar_widget::{BarWidget, BarWidgetImpl};
|
||||||
use crate::widget::WaitContext;
|
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@@ -246,10 +245,7 @@ impl PulseAudioClient {
|
|||||||
conn.mainloop.borrow_mut().run().unwrap();
|
conn.mainloop.borrow_mut().run().unwrap();
|
||||||
});
|
});
|
||||||
|
|
||||||
let pa_writer_res = rx1.recv().unwrap();
|
if !rx1.recv().unwrap() || !rx2.recv().unwrap() {
|
||||||
let pa_reader_res = rx2.recv().unwrap();
|
|
||||||
|
|
||||||
if !pa_writer_res || !pa_reader_res {
|
|
||||||
return Err(::std::io::Error::new(
|
return Err(::std::io::Error::new(
|
||||||
::std::io::ErrorKind::Other,
|
::std::io::ErrorKind::Other,
|
||||||
"unable to start pulseaudio thread",
|
"unable to start pulseaudio thread",
|
||||||
@@ -503,7 +499,6 @@ impl PulseAudio {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BarWidgetImpl for PulseAudio {
|
impl BarWidgetImpl for PulseAudio {
|
||||||
fn wait(&mut self, _: &mut WaitContext) {}
|
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"volume"
|
"volume"
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user