mirror of
https://github.com/Zedfrigg/ironbar.git
synced 2025-07-02 03:01:04 +02:00
Merge pull request #43 from JakeStanger/refactor/general
General refactoring and tidy-up
This commit is contained in:
commit
bb81f8e583
25 changed files with 686 additions and 748 deletions
257
Cargo.lock
generated
257
Cargo.lock
generated
|
@ -71,11 +71,11 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-channel"
|
name = "async-channel"
|
||||||
version = "1.7.1"
|
version = "1.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e14485364214912d3b19cc3435dde4df66065127f05fa0d75c712f36f12c2f28"
|
checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"concurrent-queue 1.2.4",
|
"concurrent-queue",
|
||||||
"event-listener",
|
"event-listener",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
]
|
]
|
||||||
|
@ -88,7 +88,7 @@ checksum = "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-lock",
|
"async-lock",
|
||||||
"async-task",
|
"async-task",
|
||||||
"concurrent-queue 2.0.0",
|
"concurrent-queue",
|
||||||
"fastrand",
|
"fastrand",
|
||||||
"futures-lite",
|
"futures-lite",
|
||||||
"slab",
|
"slab",
|
||||||
|
@ -102,7 +102,7 @@ checksum = "8c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-lock",
|
"async-lock",
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"concurrent-queue 2.0.0",
|
"concurrent-queue",
|
||||||
"futures-lite",
|
"futures-lite",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
|
@ -153,9 +153,9 @@ checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-trait"
|
name = "async-trait"
|
||||||
version = "0.1.58"
|
version = "0.1.59"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c"
|
checksum = "31e6e93155431f3931513b243d371981bb2770112b370c82745a1d19d2f99364"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -246,12 +246,6 @@ version = "1.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c"
|
checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cache-padded"
|
|
||||||
version = "1.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cairo-rs"
|
name = "cairo-rs"
|
||||||
version = "0.16.3"
|
version = "0.16.3"
|
||||||
|
@ -279,12 +273,12 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "calloop"
|
name = "calloop"
|
||||||
version = "0.10.3"
|
version = "0.10.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5bcf530afb40e45e14440701e5e996d7fd139e84a912a4d83a8d6a0fb3e58663"
|
checksum = "19457a0da465234abd76134a5c2a910c14bd3c5558463e4396ab9a37a328e465"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"nix 0.25.0",
|
"nix 0.25.1",
|
||||||
"slotmap",
|
"slotmap",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"vec_map",
|
"vec_map",
|
||||||
|
@ -363,15 +357,6 @@ dependencies = [
|
||||||
"tracing-error",
|
"tracing-error",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "concurrent-queue"
|
|
||||||
version = "1.2.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "af4780a44ab5696ea9e28294517f1fffb421a83a25af521333c838635509db9c"
|
|
||||||
dependencies = [
|
|
||||||
"cache-padded",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "concurrent-queue"
|
name = "concurrent-queue"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
|
@ -451,9 +436,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cxx"
|
name = "cxx"
|
||||||
version = "1.0.82"
|
version = "1.0.83"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d4a41a86530d0fe7f5d9ea779916b7cadd2d4f9add748b99c2c029cbbdfaf453"
|
checksum = "bdf07d07d6531bfcdbe9b8b739b104610c6508dcc4d63b410585faf338241daf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"cxxbridge-flags",
|
"cxxbridge-flags",
|
||||||
|
@ -463,9 +448,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cxx-build"
|
name = "cxx-build"
|
||||||
version = "1.0.82"
|
version = "1.0.83"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "06416d667ff3e3ad2df1cd8cd8afae5da26cf9cec4d0825040f88b5ca659a2f0"
|
checksum = "d2eb5b96ecdc99f72657332953d4d9c50135af1bac34277801cc3937906ebd39"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"codespan-reporting",
|
"codespan-reporting",
|
||||||
|
@ -478,56 +463,21 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cxxbridge-flags"
|
name = "cxxbridge-flags"
|
||||||
version = "1.0.82"
|
version = "1.0.83"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "820a9a2af1669deeef27cb271f476ffd196a2c4b6731336011e0ba63e2c7cf71"
|
checksum = "ac040a39517fd1674e0f32177648334b0f4074625b5588a64519804ba0553b12"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cxxbridge-macro"
|
name = "cxxbridge-macro"
|
||||||
version = "1.0.82"
|
version = "1.0.83"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a08a6e2fcc370a089ad3b4aaf54db3b1b4cee38ddabce5896b33eb693275f470"
|
checksum = "1362b0ddcfc4eb0a1f57b68bd77dd99f0e826958a96abd0ae9bd092e114ffed6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "darling"
|
|
||||||
version = "0.14.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b0dd3cd20dc6b5a876612a6e5accfe7f3dd883db6d07acfbf14c128f61550dfa"
|
|
||||||
dependencies = [
|
|
||||||
"darling_core",
|
|
||||||
"darling_macro",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "darling_core"
|
|
||||||
version = "0.14.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a784d2ccaf7c98501746bf0be29b2022ba41fd62a2e622af997a03e9f972859f"
|
|
||||||
dependencies = [
|
|
||||||
"fnv",
|
|
||||||
"ident_case",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"strsim",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "darling_macro"
|
|
||||||
version = "0.14.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7618812407e9402654622dd402b0a89dff9ba93badd6540781526117b92aab7e"
|
|
||||||
dependencies = [
|
|
||||||
"darling_core",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "derivative"
|
name = "derivative"
|
||||||
version = "2.2.0"
|
version = "2.2.0"
|
||||||
|
@ -539,37 +489,6 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "derive_builder"
|
|
||||||
version = "0.11.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d07adf7be193b71cc36b193d0f5fe60b918a3a9db4dad0449f57bcfd519704a3"
|
|
||||||
dependencies = [
|
|
||||||
"derive_builder_macro",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "derive_builder_core"
|
|
||||||
version = "0.11.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1f91d4cfa921f1c05904dc3c57b4a32c38aed3340cce209f3a6fd1478babafc4"
|
|
||||||
dependencies = [
|
|
||||||
"darling",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "derive_builder_macro"
|
|
||||||
version = "0.11.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8f0314b72bed045f3a68671b3c86328386762c93f82d98c65c3cb5e5f573dd68"
|
|
||||||
dependencies = [
|
|
||||||
"derive_builder_core",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "digest"
|
name = "digest"
|
||||||
version = "0.10.6"
|
version = "0.10.6"
|
||||||
|
@ -679,9 +598,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "filetime"
|
name = "filetime"
|
||||||
version = "0.2.18"
|
version = "0.2.19"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4b9663d381d07ae25dc88dbdf27df458faa83a9b25336bcac83d5e452b5fc9d3"
|
checksum = "4e884668cd0c7480504233e951174ddc3b382f7c2666e3b7310b5c4e7b0c37f9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
|
@ -689,12 +608,6 @@ dependencies = [
|
||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fnv"
|
|
||||||
version = "1.0.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-channel"
|
name = "futures-channel"
|
||||||
version = "0.3.25"
|
version = "0.3.25"
|
||||||
|
@ -782,9 +695,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gdk"
|
name = "gdk"
|
||||||
version = "0.16.0"
|
version = "0.16.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8f0a4a7aa015962d02634258715164977eb151b48fd250dcac48fab8d312a5aa"
|
checksum = "aa9cb33da481c6c040404a11f8212d193889e9b435db2c14fd86987f630d3ce1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"cairo-rs",
|
"cairo-rs",
|
||||||
|
@ -798,9 +711,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gdk-pixbuf"
|
name = "gdk-pixbuf"
|
||||||
version = "0.16.3"
|
version = "0.16.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0ba3e42776d1466938add08211734738d5c76e863a25b7a8064c4433a74a1a26"
|
checksum = "d3094f2b8578136d1929cade4e0fff82f573521b579e96cfc24af2458431f176"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"gdk-pixbuf-sys",
|
"gdk-pixbuf-sys",
|
||||||
|
@ -901,9 +814,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "glib"
|
name = "glib"
|
||||||
version = "0.16.3"
|
version = "0.16.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "50feee2f1e73be50e6634c901bfced69a0937c5e4e4673067ade85e093fa9bd7"
|
checksum = "0cd04d150a2c63e6779f43aec7e04f5374252479b7bed5f45146d9c0e821f161"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
|
@ -959,9 +872,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gtk"
|
name = "gtk"
|
||||||
version = "0.16.1"
|
version = "0.16.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ca4ab4a5a19d45748f405d2e00201e86d351e80cc13b9d43dfb9be35033a8bd6"
|
checksum = "e4d3507d43908c866c805f74c9dd593c0ce7ba5c38e576e41846639cdcd4bee6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atk",
|
"atk",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
|
@ -1091,12 +1004,6 @@ dependencies = [
|
||||||
"cxx-build",
|
"cxx-build",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ident_case"
|
|
||||||
version = "1.0.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indenter"
|
name = "indenter"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
|
@ -1149,7 +1056,6 @@ dependencies = [
|
||||||
"async_once",
|
"async_once",
|
||||||
"chrono",
|
"chrono",
|
||||||
"color-eyre",
|
"color-eyre",
|
||||||
"derive_builder",
|
|
||||||
"dirs",
|
"dirs",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"glib",
|
"glib",
|
||||||
|
@ -1223,9 +1129,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.137"
|
version = "0.2.138"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
|
checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libcorn"
|
name = "libcorn"
|
||||||
|
@ -1374,9 +1280,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nix"
|
name = "nix"
|
||||||
version = "0.23.1"
|
version = "0.23.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6"
|
checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"cc",
|
"cc",
|
||||||
|
@ -1387,9 +1293,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nix"
|
name = "nix"
|
||||||
version = "0.24.2"
|
version = "0.24.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "195cdbc1741b8134346d515b3a56a1c94b0912758009cfd53f99ea0f57b065fc"
|
checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
|
@ -1399,9 +1305,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nix"
|
name = "nix"
|
||||||
version = "0.25.0"
|
version = "0.25.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e322c04a9e3440c327fca7b6c8a63e6890a32fa2ad689db972425f07e0d22abb"
|
checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
|
@ -1523,9 +1429,9 @@ checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pango"
|
name = "pango"
|
||||||
version = "0.16.3"
|
version = "0.16.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f6a83cd4015382dbb0f4fcf3ab7b277d4885711a62b2f2c1e6582a120094edad"
|
checksum = "cdff66b271861037b89d028656184059e03b0b6ccb36003820be19f7200b1e94"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"gio",
|
"gio",
|
||||||
|
@ -1565,9 +1471,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot_core"
|
name = "parking_lot_core"
|
||||||
version = "0.9.4"
|
version = "0.9.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0"
|
checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
|
@ -1578,9 +1484,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pest"
|
name = "pest"
|
||||||
version = "2.5.0"
|
version = "2.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5f400b0f7905bf702f9f3dc3df5a121b16c54e9e8012c082905fdf09a931861a"
|
checksum = "cc8bed3549e0f9b0a2a78bf7c0018237a2cdf085eecbbc048e52612438e4e9d0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"ucd-trie",
|
"ucd-trie",
|
||||||
|
@ -1588,9 +1494,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pest_derive"
|
name = "pest_derive"
|
||||||
version = "2.5.0"
|
version = "2.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "423c2ba011d6e27b02b482a3707c773d19aec65cc024637aec44e19652e66f63"
|
checksum = "cdc078600d06ff90d4ed238f0119d84ab5d43dbaad278b0e33a8820293b32344"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"pest",
|
"pest",
|
||||||
"pest_generator",
|
"pest_generator",
|
||||||
|
@ -1598,9 +1504,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pest_generator"
|
name = "pest_generator"
|
||||||
version = "2.5.0"
|
version = "2.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3e64e6c2c85031c02fdbd9e5c72845445ca0a724d419aa0bc068ac620c9935c1"
|
checksum = "28a1af60b1c4148bb269006a750cff8e2ea36aff34d2d96cf7be0b14d1bed23c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"pest",
|
"pest",
|
||||||
"pest_meta",
|
"pest_meta",
|
||||||
|
@ -1611,9 +1517,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pest_meta"
|
name = "pest_meta"
|
||||||
version = "2.5.0"
|
version = "2.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "57959b91f0a133f89a68be874a5c88ed689c19cd729ecdb5d762ebf16c64d662"
|
checksum = "fec8605d59fc2ae0c6c1aefc0c7c7a9769732017c0ce07f7a9cfffa7b4404f20"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"pest",
|
"pest",
|
||||||
|
@ -1640,9 +1546,9 @@ checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "polling"
|
name = "polling"
|
||||||
version = "2.5.0"
|
version = "2.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9f7d73f1eaed1ca1fb37b54dcc9b38e3b17d6c7b8ecb7abfffcac8d0351f17d4"
|
checksum = "166ca89eb77fd403230b9c156612965a81e094ec6ec3aa13663d4c8b113fa748"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
|
@ -1743,11 +1649,10 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rayon"
|
name = "rayon"
|
||||||
version = "1.6.0"
|
version = "1.6.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1e060280438193c554f654141c9ea9417886713b7acd75974c85b18a69a88e0b"
|
checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-deque",
|
|
||||||
"either",
|
"either",
|
||||||
"rayon-core",
|
"rayon-core",
|
||||||
]
|
]
|
||||||
|
@ -1881,18 +1786,18 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.147"
|
version = "1.0.149"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965"
|
checksum = "256b9932320c590e707b94576e3cc1f7c9024d0ee6612dfbcf1cb106cbe8e055"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.147"
|
version = "1.0.149"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852"
|
checksum = "b4eae9b04cbffdfd550eb462ed33bc6a1b68c935127d008b27444d08380f94e4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -2014,7 +1919,7 @@ dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"log",
|
"log",
|
||||||
"memmap2",
|
"memmap2",
|
||||||
"nix 0.24.2",
|
"nix 0.24.3",
|
||||||
"pkg-config",
|
"pkg-config",
|
||||||
"wayland-client",
|
"wayland-client",
|
||||||
"wayland-cursor",
|
"wayland-cursor",
|
||||||
|
@ -2064,12 +1969,6 @@ dependencies = [
|
||||||
"vte",
|
"vte",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "strsim"
|
|
||||||
version = "0.10.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "swayipc-async"
|
name = "swayipc-async"
|
||||||
version = "2.0.1"
|
version = "2.0.1"
|
||||||
|
@ -2097,9 +1996,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.103"
|
version = "1.0.105"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d"
|
checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -2108,9 +2007,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sysinfo"
|
name = "sysinfo"
|
||||||
version = "0.26.8"
|
version = "0.27.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "29ddf41e393a9133c81d5f0974195366bd57082deac6e0eb02ed39b8341c2bb6"
|
checksum = "0d08ba83d6dde63d053e42d7230f0dc7f8d8efeb8d30d3681580d158156461ba"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"core-foundation-sys",
|
"core-foundation-sys",
|
||||||
|
@ -2226,9 +2125,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.22.0"
|
version = "1.23.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d76ce4a75fb488c605c54bf610f221cea8b0dafb53333c1a67e8ee199dcd2ae3"
|
checksum = "eab6d665857cc6ca78d6e80303a02cea7a7851e85dfbd77cbdc09bd129f1ef46"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
@ -2240,14 +2139,14 @@ dependencies = [
|
||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
"socket2",
|
"socket2",
|
||||||
"tokio-macros",
|
"tokio-macros",
|
||||||
"winapi",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-macros"
|
name = "tokio-macros"
|
||||||
version = "1.8.0"
|
version = "1.8.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484"
|
checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -2359,9 +2258,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.15.0"
|
version = "1.16.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
|
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ucd-trie"
|
name = "ucd-trie"
|
||||||
|
@ -2540,7 +2439,7 @@ dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"downcast-rs",
|
"downcast-rs",
|
||||||
"libc",
|
"libc",
|
||||||
"nix 0.24.2",
|
"nix 0.24.3",
|
||||||
"wayland-commons",
|
"wayland-commons",
|
||||||
"wayland-scanner",
|
"wayland-scanner",
|
||||||
"wayland-sys",
|
"wayland-sys",
|
||||||
|
@ -2552,7 +2451,7 @@ version = "0.29.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8691f134d584a33a6606d9d717b95c4fa20065605f798a3f350d78dced02a902"
|
checksum = "8691f134d584a33a6606d9d717b95c4fa20065605f798a3f350d78dced02a902"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"nix 0.24.2",
|
"nix 0.24.3",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"wayland-sys",
|
"wayland-sys",
|
||||||
|
@ -2564,7 +2463,7 @@ version = "0.29.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6865c6b66f13d6257bef1cd40cbfe8ef2f150fb8ebbdb1e8e873455931377661"
|
checksum = "6865c6b66f13d6257bef1cd40cbfe8ef2f150fb8ebbdb1e8e873455931377661"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"nix 0.24.2",
|
"nix 0.24.3",
|
||||||
"wayland-client",
|
"wayland-client",
|
||||||
"xcursor",
|
"xcursor",
|
||||||
]
|
]
|
||||||
|
@ -2736,7 +2635,7 @@ dependencies = [
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"hex",
|
"hex",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"nix 0.23.1",
|
"nix 0.23.2",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"ordered-stream",
|
"ordered-stream",
|
||||||
"rand",
|
"rand",
|
||||||
|
@ -2768,9 +2667,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zbus_names"
|
name = "zbus_names"
|
||||||
version = "2.3.0"
|
version = "2.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d69bb79b44e1901ed8b217e485d0f01991aec574479b68cb03415f142bc7ae67"
|
checksum = "6c737644108627748a660d038974160e0cbb62605536091bdfa28fd7f64d43c8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"static_assertions",
|
"static_assertions",
|
||||||
|
@ -2779,9 +2678,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zvariant"
|
name = "zvariant"
|
||||||
version = "3.8.0"
|
version = "3.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5c817f416f05fcbc833902f1e6064b72b1778573978cfeac54731451ccc9e207"
|
checksum = "56f8c89c183461e11867ded456db252eae90874bc6769b7adbea464caa777e51"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"enumflags2",
|
"enumflags2",
|
||||||
|
@ -2793,9 +2692,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zvariant_derive"
|
name = "zvariant_derive"
|
||||||
version = "3.8.0"
|
version = "3.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fdd24fffd02794a76eb10109de463444064c88f5adb9e9d1a78488adc332bfef"
|
checksum = "155247a5d1ab55e335421c104ccd95d64f17cebbd02f50cdbc1c33385f9c4d81"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-crate",
|
"proc-macro-crate",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
|
|
|
@ -6,7 +6,6 @@ license = "MIT"
|
||||||
description = "Customisable GTK Layer Shell wlroots/sway bar"
|
description = "Customisable GTK Layer Shell wlroots/sway bar"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
derive_builder = "0.11.2"
|
|
||||||
gtk = "0.16.0"
|
gtk = "0.16.0"
|
||||||
gtk-layer-shell = "0.5.0"
|
gtk-layer-shell = "0.5.0"
|
||||||
glib = "0.16.2"
|
glib = "0.16.2"
|
||||||
|
@ -34,7 +33,7 @@ walkdir = "2.3.2"
|
||||||
notify = { version = "5.0.0", default-features = false }
|
notify = { version = "5.0.0", default-features = false }
|
||||||
mpd_client = "1.0.0"
|
mpd_client = "1.0.0"
|
||||||
swayipc-async = { version = "2.0.1" }
|
swayipc-async = { version = "2.0.1" }
|
||||||
sysinfo = "0.26.4"
|
sysinfo = "0.27.0"
|
||||||
wayland-client = "0.29.5"
|
wayland-client = "0.29.5"
|
||||||
wayland-protocols = { version = "0.29.5", features = ["unstable_protocols", "client"] }
|
wayland-protocols = { version = "0.29.5", features = ["unstable_protocols", "client"] }
|
||||||
smithay-client-toolkit = { version = "0.16.0", default-features = false, features = ["calloop"] }
|
smithay-client-toolkit = { version = "0.16.0", default-features = false, features = ["calloop"] }
|
502
src/bar.rs
502
src/bar.rs
|
@ -1,23 +1,15 @@
|
||||||
use crate::bridge_channel::BridgeChannel;
|
use crate::bridge_channel::BridgeChannel;
|
||||||
use crate::config::{BarPosition, ModuleConfig};
|
use crate::config::{BarPosition, CommonConfig, ModuleConfig};
|
||||||
use crate::dynamic_string::DynamicString;
|
use crate::dynamic_string::DynamicString;
|
||||||
use crate::modules::custom::ExecEvent;
|
use crate::modules::{Module, ModuleInfo, ModuleLocation, ModuleUpdateEvent, WidgetContext};
|
||||||
use crate::modules::launcher::{ItemEvent, LauncherUpdate};
|
|
||||||
use crate::modules::mpd::{PlayerCommand, SongUpdate};
|
|
||||||
use crate::modules::workspaces::WorkspaceUpdate;
|
|
||||||
use crate::modules::{Module, ModuleInfoBuilder, ModuleLocation, ModuleUpdateEvent, WidgetContext};
|
|
||||||
use crate::popup::Popup;
|
use crate::popup::Popup;
|
||||||
use crate::script::{OutputStream, Script};
|
use crate::script::{OutputStream, Script};
|
||||||
use crate::{await_sync, Config};
|
use crate::{await_sync, read_lock, send, write_lock, Config};
|
||||||
use chrono::{DateTime, Local};
|
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
use gtk::gdk::Monitor;
|
use gtk::gdk::Monitor;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::{Application, ApplicationWindow, Orientation};
|
use gtk::{Application, ApplicationWindow, EventBox, Orientation, Widget};
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
use stray::message::NotifierItemCommand;
|
|
||||||
use stray::NotifierItemMessage;
|
|
||||||
use tokio::spawn;
|
use tokio::spawn;
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
use tracing::{debug, error, info, trace};
|
use tracing::{debug, error, info, trace};
|
||||||
|
@ -49,26 +41,11 @@ pub fn create_bar(
|
||||||
}
|
}
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let start = gtk::Box::builder()
|
|
||||||
.orientation(orientation)
|
|
||||||
.spacing(0)
|
|
||||||
.name("start")
|
|
||||||
.build();
|
|
||||||
let center = gtk::Box::builder()
|
|
||||||
.orientation(orientation)
|
|
||||||
.spacing(0)
|
|
||||||
.name("center")
|
|
||||||
.build();
|
|
||||||
let end = gtk::Box::builder()
|
|
||||||
.orientation(orientation)
|
|
||||||
.spacing(0)
|
|
||||||
.name("end")
|
|
||||||
.build();
|
|
||||||
|
|
||||||
content.style_context().add_class("container");
|
content.style_context().add_class("container");
|
||||||
start.style_context().add_class("container");
|
|
||||||
center.style_context().add_class("container");
|
let start = create_container("start", orientation);
|
||||||
end.style_context().add_class("container");
|
let center = create_container("center", orientation);
|
||||||
|
let end = create_container("end", orientation);
|
||||||
|
|
||||||
content.add(&start);
|
content.add(&start);
|
||||||
content.set_center_widget(Some(¢er));
|
content.set_center_widget(Some(¢er));
|
||||||
|
@ -84,6 +61,9 @@ pub fn create_bar(
|
||||||
});
|
});
|
||||||
|
|
||||||
debug!("Showing bar");
|
debug!("Showing bar");
|
||||||
|
|
||||||
|
// show each box but do not use `show_all`.
|
||||||
|
// this ensures `show_if` option works as intended.
|
||||||
start.show();
|
start.show();
|
||||||
center.show();
|
center.show();
|
||||||
end.show();
|
end.show();
|
||||||
|
@ -93,218 +73,6 @@ pub fn create_bar(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Loads the configured modules onto a bar.
|
|
||||||
fn load_modules(
|
|
||||||
left: >k::Box,
|
|
||||||
center: >k::Box,
|
|
||||||
right: >k::Box,
|
|
||||||
app: &Application,
|
|
||||||
config: Config,
|
|
||||||
monitor: &Monitor,
|
|
||||||
output_name: &str,
|
|
||||||
) -> Result<()> {
|
|
||||||
let mut info_builder = ModuleInfoBuilder::default();
|
|
||||||
let info_builder = info_builder
|
|
||||||
.app(app)
|
|
||||||
.bar_position(config.position)
|
|
||||||
.monitor(monitor)
|
|
||||||
.output_name(output_name);
|
|
||||||
|
|
||||||
if let Some(modules) = config.start {
|
|
||||||
let info_builder = info_builder.location(ModuleLocation::Left);
|
|
||||||
|
|
||||||
add_modules(left, modules, info_builder)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(modules) = config.center {
|
|
||||||
let info_builder = info_builder.location(ModuleLocation::Center);
|
|
||||||
|
|
||||||
add_modules(center, modules, info_builder)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(modules) = config.end {
|
|
||||||
let info_builder = info_builder.location(ModuleLocation::Right);
|
|
||||||
|
|
||||||
add_modules(right, modules, info_builder)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Adds modules into a provided GTK box,
|
|
||||||
/// which should be one of its left, center or right containers.
|
|
||||||
fn add_modules(
|
|
||||||
content: >k::Box,
|
|
||||||
modules: Vec<ModuleConfig>,
|
|
||||||
info_builder: &mut ModuleInfoBuilder,
|
|
||||||
) -> Result<()> {
|
|
||||||
let base_popup_info = info_builder.module_name("").build()?;
|
|
||||||
let popup = Popup::new(&base_popup_info);
|
|
||||||
let popup = Arc::new(RwLock::new(popup));
|
|
||||||
|
|
||||||
macro_rules! add_module {
|
|
||||||
($module:expr, $id:expr, $name:literal, $send_message:ty, $receive_message:ty) => {
|
|
||||||
let info = info_builder.module_name($name).build()?;
|
|
||||||
|
|
||||||
let (w_tx, w_rx) = glib::MainContext::channel::<$send_message>(glib::PRIORITY_DEFAULT);
|
|
||||||
let (p_tx, p_rx) = glib::MainContext::channel::<$send_message>(glib::PRIORITY_DEFAULT);
|
|
||||||
|
|
||||||
let channel = BridgeChannel::<ModuleUpdateEvent<$send_message>>::new();
|
|
||||||
let (ui_tx, ui_rx) = mpsc::channel::<$receive_message>(16);
|
|
||||||
|
|
||||||
$module.spawn_controller(&info, channel.create_sender(), ui_rx)?;
|
|
||||||
|
|
||||||
let context = WidgetContext {
|
|
||||||
id: $id,
|
|
||||||
widget_rx: w_rx,
|
|
||||||
popup_rx: p_rx,
|
|
||||||
tx: channel.create_sender(),
|
|
||||||
controller_tx: ui_tx,
|
|
||||||
};
|
|
||||||
|
|
||||||
let common = $module.common.clone();
|
|
||||||
|
|
||||||
let widget = $module.into_widget(context, &info)?;
|
|
||||||
|
|
||||||
let container = gtk::EventBox::new();
|
|
||||||
container.add(&widget.widget);
|
|
||||||
|
|
||||||
content.add(&container);
|
|
||||||
widget.widget.set_widget_name(info.module_name);
|
|
||||||
|
|
||||||
if let Some(show_if) = common.show_if {
|
|
||||||
let script = Script::new_polling(show_if);
|
|
||||||
let container = container.clone();
|
|
||||||
|
|
||||||
let (tx, rx) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
|
|
||||||
|
|
||||||
spawn(async move {
|
|
||||||
script
|
|
||||||
.run(|(_, success)| {
|
|
||||||
tx.send(success)
|
|
||||||
.expect("Failed to send widget visibility toggle message");
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
});
|
|
||||||
|
|
||||||
rx.attach(None, move |success| {
|
|
||||||
if success {
|
|
||||||
container.show_all()
|
|
||||||
} else {
|
|
||||||
container.hide()
|
|
||||||
};
|
|
||||||
Continue(true)
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
container.show_all();
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(on_click) = common.on_click {
|
|
||||||
let script = Script::new_polling(on_click);
|
|
||||||
container.connect_button_press_event(move |_, _| {
|
|
||||||
trace!("Running on-click script");
|
|
||||||
match await_sync(async { script.get_output().await }) {
|
|
||||||
Ok((OutputStream::Stderr(out), _)) => error!("{out}"),
|
|
||||||
Err(err) => error!("{err:?}"),
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
Inhibit(false)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(tooltip) = common.tooltip {
|
|
||||||
DynamicString::new(&tooltip, move |string| {
|
|
||||||
container.set_tooltip_text(Some(&string));
|
|
||||||
Continue(true)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let has_popup = widget.popup.is_some();
|
|
||||||
if let Some(popup_content) = widget.popup {
|
|
||||||
popup
|
|
||||||
.write()
|
|
||||||
.expect("Failed to get write lock on popup")
|
|
||||||
.register_content($id, popup_content);
|
|
||||||
}
|
|
||||||
|
|
||||||
let popup2 = Arc::clone(&popup);
|
|
||||||
channel.recv(move |ev| {
|
|
||||||
let popup = popup2.clone();
|
|
||||||
match ev {
|
|
||||||
ModuleUpdateEvent::Update(update) => {
|
|
||||||
if has_popup {
|
|
||||||
p_tx.send(update.clone())
|
|
||||||
.expect("Failed to send update to popup");
|
|
||||||
}
|
|
||||||
|
|
||||||
w_tx.send(update).expect("Failed to send update to module");
|
|
||||||
}
|
|
||||||
ModuleUpdateEvent::TogglePopup(geometry) => {
|
|
||||||
debug!("Toggling popup for {} [#{}]", $name, $id);
|
|
||||||
let popup = popup.read().expect("Failed to get read lock on popup");
|
|
||||||
if popup.is_visible() {
|
|
||||||
popup.hide()
|
|
||||||
} else {
|
|
||||||
popup.show_content($id);
|
|
||||||
popup.show(geometry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ModuleUpdateEvent::OpenPopup(geometry) => {
|
|
||||||
debug!("Opening popup for {} [#{}]", $name, $id);
|
|
||||||
|
|
||||||
let popup = popup.read().expect("Failed to get read lock on popup");
|
|
||||||
popup.hide();
|
|
||||||
popup.show_content($id);
|
|
||||||
popup.show(geometry);
|
|
||||||
}
|
|
||||||
ModuleUpdateEvent::ClosePopup => {
|
|
||||||
debug!("Closing popup for {} [#{}]", $name, $id);
|
|
||||||
|
|
||||||
let popup = popup.read().expect("Failed to get read lock on popup");
|
|
||||||
popup.hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Continue(true)
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
for (id, config) in modules.into_iter().enumerate() {
|
|
||||||
match config {
|
|
||||||
ModuleConfig::Clock(module) => {
|
|
||||||
add_module!(module, id, "clock", DateTime<Local>, ());
|
|
||||||
}
|
|
||||||
ModuleConfig::Script(module) => {
|
|
||||||
add_module!(module, id, "script", String, ());
|
|
||||||
}
|
|
||||||
ModuleConfig::SysInfo(module) => {
|
|
||||||
add_module!(module, id, "sysinfo", HashMap<String, String>, ());
|
|
||||||
}
|
|
||||||
ModuleConfig::Focused(module) => {
|
|
||||||
add_module!(module, id, "focused", (String, String), ());
|
|
||||||
}
|
|
||||||
ModuleConfig::Workspaces(module) => {
|
|
||||||
add_module!(module, id, "workspaces", WorkspaceUpdate, String);
|
|
||||||
}
|
|
||||||
ModuleConfig::Tray(module) => {
|
|
||||||
add_module!(module, id, "tray", NotifierItemMessage, NotifierItemCommand);
|
|
||||||
}
|
|
||||||
ModuleConfig::Mpd(module) => {
|
|
||||||
add_module!(module, id, "mpd", Option<SongUpdate>, PlayerCommand);
|
|
||||||
}
|
|
||||||
ModuleConfig::Launcher(module) => {
|
|
||||||
add_module!(module, id, "launcher", LauncherUpdate, ItemEvent);
|
|
||||||
}
|
|
||||||
ModuleConfig::Custom(module) => {
|
|
||||||
add_module!(module, id, "custom", (), ExecEvent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets up GTK layer shell for a provided application window.
|
/// Sets up GTK layer shell for a provided application window.
|
||||||
fn setup_layer_shell(
|
fn setup_layer_shell(
|
||||||
win: &ApplicationWindow,
|
win: &ApplicationWindow,
|
||||||
|
@ -349,3 +117,251 @@ fn setup_layer_shell(
|
||||||
|| (bar_orientation == Orientation::Horizontal && anchor_to_edges),
|
|| (bar_orientation == Orientation::Horizontal && anchor_to_edges),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a `gtk::Box` container to place widgets inside.
|
||||||
|
fn create_container(name: &str, orientation: Orientation) -> gtk::Box {
|
||||||
|
let container = gtk::Box::builder()
|
||||||
|
.orientation(orientation)
|
||||||
|
.spacing(0)
|
||||||
|
.name(name)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
container.style_context().add_class("container");
|
||||||
|
container
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Loads the configured modules onto a bar.
|
||||||
|
fn load_modules(
|
||||||
|
left: >k::Box,
|
||||||
|
center: >k::Box,
|
||||||
|
right: >k::Box,
|
||||||
|
app: &Application,
|
||||||
|
config: Config,
|
||||||
|
monitor: &Monitor,
|
||||||
|
output_name: &str,
|
||||||
|
) -> Result<()> {
|
||||||
|
macro_rules! info {
|
||||||
|
($location:expr) => {
|
||||||
|
ModuleInfo {
|
||||||
|
app,
|
||||||
|
bar_position: config.position,
|
||||||
|
monitor,
|
||||||
|
output_name,
|
||||||
|
location: $location,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(modules) = config.start {
|
||||||
|
let info = info!(ModuleLocation::Left);
|
||||||
|
add_modules(left, modules, &info)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(modules) = config.center {
|
||||||
|
let info = info!(ModuleLocation::Center);
|
||||||
|
add_modules(center, modules, &info)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(modules) = config.end {
|
||||||
|
let info = info!(ModuleLocation::Right);
|
||||||
|
add_modules(right, modules, &info)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds modules into a provided GTK box,
|
||||||
|
/// which should be one of its left, center or right containers.
|
||||||
|
fn add_modules(content: >k::Box, modules: Vec<ModuleConfig>, info: &ModuleInfo) -> Result<()> {
|
||||||
|
let popup = Popup::new(info);
|
||||||
|
let popup = Arc::new(RwLock::new(popup));
|
||||||
|
|
||||||
|
macro_rules! add_module {
|
||||||
|
($module:expr, $id:expr) => {{
|
||||||
|
let common = $module.common.take().expect("Common config did not exist");
|
||||||
|
let widget = create_module($module, $id, &info, &Arc::clone(&popup))?;
|
||||||
|
|
||||||
|
let container = wrap_widget(&widget);
|
||||||
|
content.add(&container);
|
||||||
|
setup_module_common_options(container, common);
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
for (id, config) in modules.into_iter().enumerate() {
|
||||||
|
match config {
|
||||||
|
ModuleConfig::Clock(mut module) => add_module!(module, id),
|
||||||
|
ModuleConfig::Script(mut module) => add_module!(module, id),
|
||||||
|
ModuleConfig::SysInfo(mut module) => add_module!(module, id),
|
||||||
|
ModuleConfig::Focused(mut module) => add_module!(module, id),
|
||||||
|
ModuleConfig::Workspaces(mut module) => add_module!(module, id),
|
||||||
|
ModuleConfig::Tray(mut module) => add_module!(module, id),
|
||||||
|
ModuleConfig::Mpd(mut module) => add_module!(module, id),
|
||||||
|
ModuleConfig::Launcher(mut module) => add_module!(module, id),
|
||||||
|
ModuleConfig::Custom(mut module) => add_module!(module, id),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a module and sets it up.
|
||||||
|
/// This setup includes widget/popup content and event channels.
|
||||||
|
fn create_module<TModule, TWidget, TSend, TRec>(
|
||||||
|
module: TModule,
|
||||||
|
id: usize,
|
||||||
|
info: &ModuleInfo,
|
||||||
|
popup: &Arc<RwLock<Popup>>,
|
||||||
|
) -> Result<TWidget>
|
||||||
|
where
|
||||||
|
TModule: Module<TWidget, SendMessage = TSend, ReceiveMessage = TRec>,
|
||||||
|
TWidget: IsA<Widget>,
|
||||||
|
TSend: Clone + Send + 'static,
|
||||||
|
{
|
||||||
|
let (w_tx, w_rx) = glib::MainContext::channel::<TSend>(glib::PRIORITY_DEFAULT);
|
||||||
|
let (p_tx, p_rx) = glib::MainContext::channel::<TSend>(glib::PRIORITY_DEFAULT);
|
||||||
|
|
||||||
|
let channel = BridgeChannel::<ModuleUpdateEvent<TSend>>::new();
|
||||||
|
let (ui_tx, ui_rx) = mpsc::channel::<TRec>(16);
|
||||||
|
|
||||||
|
module.spawn_controller(info, channel.create_sender(), ui_rx)?;
|
||||||
|
|
||||||
|
let context = WidgetContext {
|
||||||
|
id,
|
||||||
|
widget_rx: w_rx,
|
||||||
|
popup_rx: p_rx,
|
||||||
|
tx: channel.create_sender(),
|
||||||
|
controller_tx: ui_tx,
|
||||||
|
};
|
||||||
|
|
||||||
|
let name = TModule::name();
|
||||||
|
|
||||||
|
let module_parts = module.into_widget(context, info)?;
|
||||||
|
module_parts.widget.set_widget_name(name);
|
||||||
|
|
||||||
|
let mut has_popup = false;
|
||||||
|
if let Some(popup_content) = module_parts.popup {
|
||||||
|
register_popup_content(popup, id, popup_content);
|
||||||
|
has_popup = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_receiver(channel, w_tx, p_tx, popup.clone(), name, id, has_popup);
|
||||||
|
|
||||||
|
Ok(module_parts.widget)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Registers the popup content with the popup.
|
||||||
|
fn register_popup_content(popup: &Arc<RwLock<Popup>>, id: usize, popup_content: gtk::Box) {
|
||||||
|
write_lock!(popup).register_content(id, popup_content);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets up the bridge channel receiver
|
||||||
|
/// to pick up events from the controller, widget or popup.
|
||||||
|
///
|
||||||
|
/// Handles opening/closing popups
|
||||||
|
/// and communicating update messages between controllers and widgets/popups.
|
||||||
|
fn setup_receiver<TSend>(
|
||||||
|
channel: BridgeChannel<ModuleUpdateEvent<TSend>>,
|
||||||
|
w_tx: glib::Sender<TSend>,
|
||||||
|
p_tx: glib::Sender<TSend>,
|
||||||
|
popup: Arc<RwLock<Popup>>,
|
||||||
|
name: &'static str,
|
||||||
|
id: usize,
|
||||||
|
has_popup: bool,
|
||||||
|
) where
|
||||||
|
TSend: Clone + Send + 'static,
|
||||||
|
{
|
||||||
|
channel.recv(move |ev| {
|
||||||
|
match ev {
|
||||||
|
ModuleUpdateEvent::Update(update) => {
|
||||||
|
if has_popup {
|
||||||
|
send!(p_tx, update.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
send!(w_tx, update);
|
||||||
|
}
|
||||||
|
ModuleUpdateEvent::TogglePopup(geometry) => {
|
||||||
|
debug!("Toggling popup for {} [#{}]", name, id);
|
||||||
|
let popup = read_lock!(popup);
|
||||||
|
if popup.is_visible() {
|
||||||
|
popup.hide();
|
||||||
|
} else {
|
||||||
|
popup.show_content(id);
|
||||||
|
popup.show(geometry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ModuleUpdateEvent::OpenPopup(geometry) => {
|
||||||
|
debug!("Opening popup for {} [#{}]", name, id);
|
||||||
|
|
||||||
|
let popup = read_lock!(popup);
|
||||||
|
popup.hide();
|
||||||
|
popup.show_content(id);
|
||||||
|
popup.show(geometry);
|
||||||
|
}
|
||||||
|
ModuleUpdateEvent::ClosePopup => {
|
||||||
|
debug!("Closing popup for {} [#{}]", name, id);
|
||||||
|
|
||||||
|
let popup = read_lock!(popup);
|
||||||
|
popup.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Continue(true)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Takes a widget and adds it into a new `gtk::EventBox`.
|
||||||
|
/// The event box container is returned.
|
||||||
|
fn wrap_widget<W: IsA<Widget>>(widget: &W) -> EventBox {
|
||||||
|
let container = EventBox::new();
|
||||||
|
container.add(widget);
|
||||||
|
container
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Configures the module's container according to the common config options.
|
||||||
|
fn setup_module_common_options(container: EventBox, common: CommonConfig) {
|
||||||
|
common.show_if.map_or_else(
|
||||||
|
|| {
|
||||||
|
container.show_all();
|
||||||
|
},
|
||||||
|
|show_if| {
|
||||||
|
let script = Script::new_polling(show_if);
|
||||||
|
let container = container.clone();
|
||||||
|
let (tx, rx) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
|
||||||
|
spawn(async move {
|
||||||
|
script
|
||||||
|
.run(|(_, success)| {
|
||||||
|
send!(tx, success);
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
});
|
||||||
|
rx.attach(None, move |success| {
|
||||||
|
if success {
|
||||||
|
container.show_all();
|
||||||
|
} else {
|
||||||
|
container.hide();
|
||||||
|
};
|
||||||
|
Continue(true)
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Some(on_click) = common.on_click {
|
||||||
|
let script = Script::new_polling(on_click);
|
||||||
|
container.connect_button_press_event(move |_, _| {
|
||||||
|
trace!("Running on-click script");
|
||||||
|
match await_sync(async { script.get_output().await }) {
|
||||||
|
Ok((OutputStream::Stderr(out), _)) => error!("{out}"),
|
||||||
|
Err(err) => error!("{err:?}"),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
Inhibit(false)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(tooltip) = common.tooltip {
|
||||||
|
DynamicString::new(&tooltip, move |string| {
|
||||||
|
container.set_tooltip_text(Some(&string));
|
||||||
|
Continue(true)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::send;
|
||||||
use tokio::spawn;
|
use tokio::spawn;
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
|
|
||||||
|
@ -21,7 +22,7 @@ impl<T: Send + 'static> BridgeChannel<T> {
|
||||||
|
|
||||||
spawn(async move {
|
spawn(async move {
|
||||||
while let Some(val) = async_rx.recv().await {
|
while let Some(val) = async_rx.recv().await {
|
||||||
sync_tx.send(val).expect("Failed to send message");
|
send!(sync_tx, val);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ use super::toplevel::{ToplevelEvent, ToplevelInfo};
|
||||||
use super::toplevel_manager::listen_for_toplevels;
|
use super::toplevel_manager::listen_for_toplevels;
|
||||||
use super::ToplevelChange;
|
use super::ToplevelChange;
|
||||||
use super::{Env, ToplevelHandler};
|
use super::{Env, ToplevelHandler};
|
||||||
|
use crate::{error as err, send, write_lock};
|
||||||
use color_eyre::Report;
|
use color_eyre::Report;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use smithay_client_toolkit::environment::Environment;
|
use smithay_client_toolkit::environment::Environment;
|
||||||
|
@ -46,19 +47,16 @@ impl WaylandClient {
|
||||||
.expect("Failed to connect to Wayland compositor");
|
.expect("Failed to connect to Wayland compositor");
|
||||||
|
|
||||||
let outputs = Self::get_outputs(&env);
|
let outputs = Self::get_outputs(&env);
|
||||||
output_tx
|
send!(output_tx, outputs);
|
||||||
.send(outputs)
|
|
||||||
.expect("Failed to send outputs out of task");
|
|
||||||
|
|
||||||
let seats = env.get_all_seats();
|
let seats = env.get_all_seats();
|
||||||
seat_tx
|
send!(
|
||||||
.send(
|
seat_tx,
|
||||||
seats
|
seats
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|seat| seat.detach())
|
.map(|seat| seat.detach())
|
||||||
.collect::<Vec<WlSeat>>(),
|
.collect::<Vec<WlSeat>>()
|
||||||
)
|
);
|
||||||
.expect("Failed to send seats out of task");
|
|
||||||
|
|
||||||
let _toplevel_manager = env.require_global::<ZwlrForeignToplevelManagerV1>();
|
let _toplevel_manager = env.require_global::<ZwlrForeignToplevelManagerV1>();
|
||||||
|
|
||||||
|
@ -66,20 +64,13 @@ impl WaylandClient {
|
||||||
trace!("Received toplevel event: {:?}", event);
|
trace!("Received toplevel event: {:?}", event);
|
||||||
|
|
||||||
if event.change == ToplevelChange::Close {
|
if event.change == ToplevelChange::Close {
|
||||||
toplevels2
|
write_lock!(toplevels2).remove(&event.toplevel.id);
|
||||||
.write()
|
|
||||||
.expect("Failed to get write lock on toplevels")
|
|
||||||
.remove(&event.toplevel.id);
|
|
||||||
} else {
|
} else {
|
||||||
toplevels2
|
write_lock!(toplevels2)
|
||||||
.write()
|
|
||||||
.expect("Failed to get write lock on toplevels")
|
|
||||||
.insert(event.toplevel.id, (event.toplevel.clone(), handle));
|
.insert(event.toplevel.id, (event.toplevel.clone(), handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
toplevel_tx2
|
send!(toplevel_tx2, event);
|
||||||
.send(event)
|
|
||||||
.expect("Failed to send toplevel event");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut event_loop =
|
let mut event_loop =
|
||||||
|
@ -99,11 +90,9 @@ impl WaylandClient {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let outputs = output_rx
|
let outputs = output_rx.await.expect(err::ERR_CHANNEL_RECV);
|
||||||
.await
|
|
||||||
.expect("Failed to receive outputs from task");
|
|
||||||
|
|
||||||
let seats = seat_rx.await.expect("Failed to receive seats from task");
|
let seats = seat_rx.await.expect(err::ERR_CHANNEL_RECV);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
outputs,
|
outputs,
|
||||||
|
|
|
@ -4,11 +4,13 @@ use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use tracing::trace;
|
use tracing::trace;
|
||||||
use wayland_client::{DispatchData, Main};
|
use wayland_client::{DispatchData, Main};
|
||||||
use wayland_protocols::wlr::unstable::foreign_toplevel::v1::client::zwlr_foreign_toplevel_handle_v1::{Event, ZwlrForeignToplevelHandleV1};
|
use wayland_protocols::wlr::unstable::foreign_toplevel::v1::client::zwlr_foreign_toplevel_handle_v1::{Event, ZwlrForeignToplevelHandleV1};
|
||||||
|
use crate::write_lock;
|
||||||
|
|
||||||
const STATE_ACTIVE: u32 = 2;
|
const STATE_ACTIVE: u32 = 2;
|
||||||
const STATE_FULLSCREEN: u32 = 3;
|
const STATE_FULLSCREEN: u32 = 3;
|
||||||
|
|
||||||
static COUNTER: AtomicUsize = AtomicUsize::new(1);
|
static COUNTER: AtomicUsize = AtomicUsize::new(1);
|
||||||
|
|
||||||
fn get_id() -> usize {
|
fn get_id() -> usize {
|
||||||
COUNTER.fetch_add(1, Ordering::Relaxed)
|
COUNTER.fetch_add(1, Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
|
@ -108,9 +110,9 @@ where
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Event::OutputEnter { output: _ } => None,
|
Event::OutputEnter { output: _ }
|
||||||
Event::OutputLeave { output: _ } => None,
|
| Event::OutputLeave { output: _ }
|
||||||
Event::Parent { parent: _ } => None,
|
| Event::Parent { parent: _ } => None,
|
||||||
Event::Done => {
|
Event::Done => {
|
||||||
if info.ready || info.app_id.is_empty() {
|
if info.ready || info.app_id.is_empty() {
|
||||||
None
|
None
|
||||||
|
@ -119,6 +121,7 @@ where
|
||||||
Some(ToplevelChange::New)
|
Some(ToplevelChange::New)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -140,9 +143,7 @@ impl Toplevel {
|
||||||
let inner = Arc::new(RwLock::new(ToplevelInfo::new()));
|
let inner = Arc::new(RwLock::new(ToplevelInfo::new()));
|
||||||
|
|
||||||
handle.quick_assign(move |_handle, event, ddata| {
|
handle.quick_assign(move |_handle, event, ddata| {
|
||||||
let mut inner = inner
|
let mut inner = write_lock!(inner);
|
||||||
.write()
|
|
||||||
.expect("Failed to get write lock on toplevel inner state");
|
|
||||||
toplevel_implem(event, &mut inner, &mut callback, ddata);
|
toplevel_implem(event, &mut inner, &mut callback, ddata);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,8 @@ impl Default for BarPosition {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BarPosition {
|
impl BarPosition {
|
||||||
|
/// Gets the orientation the bar and widgets should use
|
||||||
|
/// based on this position.
|
||||||
pub fn get_orientation(self) -> Orientation {
|
pub fn get_orientation(self) -> Orientation {
|
||||||
if self == Self::Top || self == Self::Bottom {
|
if self == Self::Top || self == Self::Bottom {
|
||||||
Orientation::Horizontal
|
Orientation::Horizontal
|
||||||
|
@ -71,6 +73,8 @@ impl BarPosition {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the angle that label text should be displayed at
|
||||||
|
/// based on this position.
|
||||||
pub const fn get_angle(self) -> f64 {
|
pub const fn get_angle(self) -> f64 {
|
||||||
match self {
|
match self {
|
||||||
Self::Top | Self::Bottom => 0.0,
|
Self::Top | Self::Bottom => 0.0,
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::script::{OutputStream, Script};
|
use crate::script::{OutputStream, Script};
|
||||||
|
use crate::{lock, send};
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
@ -10,9 +11,7 @@ enum DynamicStringSegment {
|
||||||
Dynamic(Script),
|
Dynamic(Script),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DynamicString {
|
pub struct DynamicString;
|
||||||
// pub label: gtk::Label,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DynamicString {
|
impl DynamicString {
|
||||||
pub fn new<F>(input: &str, f: F) -> Self
|
pub fn new<F>(input: &str, f: F) -> Self
|
||||||
|
@ -67,10 +66,7 @@ impl DynamicString {
|
||||||
for (i, segment) in segments.into_iter().enumerate() {
|
for (i, segment) in segments.into_iter().enumerate() {
|
||||||
match segment {
|
match segment {
|
||||||
DynamicStringSegment::Static(str) => {
|
DynamicStringSegment::Static(str) => {
|
||||||
label_parts
|
lock!(label_parts).insert(i, str);
|
||||||
.lock()
|
|
||||||
.expect("Failed to get lock on label parts")
|
|
||||||
.insert(i, str);
|
|
||||||
}
|
}
|
||||||
DynamicStringSegment::Dynamic(script) => {
|
DynamicStringSegment::Dynamic(script) => {
|
||||||
let tx = tx.clone();
|
let tx = tx.clone();
|
||||||
|
@ -80,21 +76,16 @@ impl DynamicString {
|
||||||
script
|
script
|
||||||
.run(|(out, _)| {
|
.run(|(out, _)| {
|
||||||
if let OutputStream::Stdout(out) = out {
|
if let OutputStream::Stdout(out) = out {
|
||||||
let mut label_parts = label_parts
|
let mut label_parts = lock!(label_parts);
|
||||||
.lock()
|
|
||||||
.expect("Failed to get lock on label parts");
|
|
||||||
|
|
||||||
label_parts
|
label_parts.insert(i, out);
|
||||||
// .lock()
|
|
||||||
// .expect("Failed to get lock on label parts")
|
|
||||||
.insert(i, out);
|
|
||||||
|
|
||||||
let string = label_parts
|
let string = label_parts
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(_, part)| part.as_str())
|
.map(|(_, part)| part.as_str())
|
||||||
.collect::<String>();
|
.collect::<String>();
|
||||||
|
|
||||||
tx.send(string).expect("Failed to send update");
|
send!(tx, string);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
|
@ -105,20 +96,17 @@ impl DynamicString {
|
||||||
|
|
||||||
// initialize
|
// initialize
|
||||||
{
|
{
|
||||||
let label_parts = label_parts
|
let label_parts = lock!(label_parts)
|
||||||
.lock()
|
|
||||||
.expect("Failed to get lock on label parts")
|
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(_, part)| part.as_str())
|
.map(|(_, part)| part.as_str())
|
||||||
.collect::<String>();
|
.collect::<String>();
|
||||||
|
|
||||||
tx.send(label_parts).expect("Failed to send update");
|
send!(tx, label_parts);
|
||||||
}
|
}
|
||||||
|
|
||||||
rx.attach(None, f);
|
rx.attach(None, f);
|
||||||
|
|
||||||
// Self { label }
|
Self
|
||||||
Self {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
13
src/error.rs
Normal file
13
src/error.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#[repr(i32)]
|
||||||
|
pub enum ExitCode {
|
||||||
|
GtkDisplay = 1,
|
||||||
|
CreateBars = 2,
|
||||||
|
Config = 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const ERR_OUTPUTS: &str = "GTK and Sway are reporting a different set of outputs - this is a severe bug and should never happen";
|
||||||
|
pub const ERR_MUTEX_LOCK: &str = "Failed to get lock on Mutex";
|
||||||
|
pub const ERR_READ_LOCK: &str = "Failed to get read lock";
|
||||||
|
pub const ERR_WRITE_LOCK: &str = "Failed to get write lock";
|
||||||
|
pub const ERR_CHANNEL_SEND: &str = "Failed to send message to channel";
|
||||||
|
pub const ERR_CHANNEL_RECV: &str = "Failed to receive message from channel";
|
|
@ -1,7 +1,8 @@
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
use dirs::data_dir;
|
use dirs::data_dir;
|
||||||
use std::env;
|
use std::{env, panic};
|
||||||
use strip_ansi_escapes::Writer;
|
use strip_ansi_escapes::Writer;
|
||||||
|
use tracing::error;
|
||||||
use tracing_appender::non_blocking::{NonBlocking, WorkerGuard};
|
use tracing_appender::non_blocking::{NonBlocking, WorkerGuard};
|
||||||
use tracing_error::ErrorLayer;
|
use tracing_error::ErrorLayer;
|
||||||
use tracing_subscriber::fmt::{Layer, MakeWriter};
|
use tracing_subscriber::fmt::{Layer, MakeWriter};
|
||||||
|
@ -26,11 +27,34 @@ impl<'a> MakeWriter<'a> for MakeFileWriter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn install_logging() -> Result<WorkerGuard> {
|
||||||
|
// Disable backtraces by default
|
||||||
|
if env::var("RUST_LIB_BACKTRACE").is_err() {
|
||||||
|
env::set_var("RUST_LIB_BACKTRACE", "0");
|
||||||
|
}
|
||||||
|
|
||||||
|
// keep guard in scope
|
||||||
|
// otherwise file logging drops
|
||||||
|
let guard = install_tracing()?;
|
||||||
|
|
||||||
|
let hook_builder = color_eyre::config::HookBuilder::default();
|
||||||
|
let (panic_hook, eyre_hook) = hook_builder.into_hooks();
|
||||||
|
|
||||||
|
eyre_hook.install()?;
|
||||||
|
|
||||||
|
// custom hook allows tracing_appender to capture panics
|
||||||
|
panic::set_hook(Box::new(move |panic_info| {
|
||||||
|
error!("{}", panic_hook.panic_report(panic_info));
|
||||||
|
}));
|
||||||
|
|
||||||
|
Ok(guard)
|
||||||
|
}
|
||||||
|
|
||||||
/// Installs tracing into the current application.
|
/// Installs tracing into the current application.
|
||||||
///
|
///
|
||||||
/// The returned `WorkerGuard` must remain in scope
|
/// The returned `WorkerGuard` must remain in scope
|
||||||
/// for the lifetime of the application for logging to file to work.
|
/// for the lifetime of the application for logging to file to work.
|
||||||
pub fn install_tracing() -> Result<WorkerGuard> {
|
fn install_tracing() -> Result<WorkerGuard> {
|
||||||
const DEFAULT_LOG: &str = "info";
|
const DEFAULT_LOG: &str = "info";
|
||||||
const DEFAULT_FILE_LOG: &str = "warn";
|
const DEFAULT_FILE_LOG: &str = "warn";
|
||||||
|
|
||||||
|
|
89
src/macros.rs
Normal file
89
src/macros.rs
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
/// Sends a message on an asynchronous `Sender` using `send()`
|
||||||
|
/// Panics if the message cannot be sent.
|
||||||
|
///
|
||||||
|
/// Usage:
|
||||||
|
///
|
||||||
|
/// ```rs
|
||||||
|
/// send_async!(tx, "my message");
|
||||||
|
/// ```
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! send_async {
|
||||||
|
($tx:expr, $msg:expr) => {
|
||||||
|
$tx.send($msg).await.expect($crate::error::ERR_CHANNEL_SEND)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sends a message on an synchronous `Sender` using `send()`
|
||||||
|
/// Panics if the message cannot be sent.
|
||||||
|
///
|
||||||
|
/// Usage:
|
||||||
|
///
|
||||||
|
/// ```rs
|
||||||
|
/// send!(tx, "my message");
|
||||||
|
/// ```
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! send {
|
||||||
|
($tx:expr, $msg:expr) => {
|
||||||
|
$tx.send($msg).expect($crate::error::ERR_CHANNEL_SEND)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sends a message on an synchronous `Sender` using `try_send()`
|
||||||
|
/// Panics if the message cannot be sent.
|
||||||
|
///
|
||||||
|
/// Usage:
|
||||||
|
///
|
||||||
|
/// ```rs
|
||||||
|
/// try_send!(tx, "my message");
|
||||||
|
/// ```
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! try_send {
|
||||||
|
($tx:expr, $msg:expr) => {
|
||||||
|
$tx.try_send($msg).expect($crate::error::ERR_CHANNEL_SEND)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Locks a `Mutex`.
|
||||||
|
/// Panics if the `Mutex` cannot be locked.
|
||||||
|
///
|
||||||
|
/// Usage:
|
||||||
|
///
|
||||||
|
/// ```rs
|
||||||
|
/// let mut val = lock!(my_mutex);
|
||||||
|
/// ```
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! lock {
|
||||||
|
($mutex:expr) => {
|
||||||
|
$mutex.lock().expect($crate::error::ERR_MUTEX_LOCK)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets a read lock on a `RwLock`.
|
||||||
|
/// Panics if the `RwLock` cannot be locked.
|
||||||
|
///
|
||||||
|
/// Usage:
|
||||||
|
///
|
||||||
|
/// ```rs
|
||||||
|
/// let val = read_lock!(my_rwlock);
|
||||||
|
/// ```
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! read_lock {
|
||||||
|
($rwlock:expr) => {
|
||||||
|
$rwlock.read().expect($crate::error::ERR_READ_LOCK)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets a write lock on a `RwLock`.
|
||||||
|
/// Panics if the `RwLock` cannot be locked.
|
||||||
|
///
|
||||||
|
/// Usage:
|
||||||
|
///
|
||||||
|
/// ```rs
|
||||||
|
/// let mut val = write_lock!(my_rwlock);
|
||||||
|
/// ```
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! write_lock {
|
||||||
|
($rwlock:expr) => {
|
||||||
|
$rwlock.write().expect($crate::error::ERR_WRITE_LOCK)
|
||||||
|
};
|
||||||
|
}
|
56
src/main.rs
56
src/main.rs
|
@ -3,8 +3,10 @@ mod bridge_channel;
|
||||||
mod clients;
|
mod clients;
|
||||||
mod config;
|
mod config;
|
||||||
mod dynamic_string;
|
mod dynamic_string;
|
||||||
|
mod error;
|
||||||
mod icon;
|
mod icon;
|
||||||
mod logging;
|
mod logging;
|
||||||
|
mod macros;
|
||||||
mod modules;
|
mod modules;
|
||||||
mod popup;
|
mod popup;
|
||||||
mod script;
|
mod script;
|
||||||
|
@ -19,62 +21,37 @@ use dirs::config_dir;
|
||||||
use gtk::gdk::Display;
|
use gtk::gdk::Display;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::Application;
|
use gtk::Application;
|
||||||
|
use std::env;
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
use std::{env, panic};
|
|
||||||
use tokio::runtime::Handle;
|
use tokio::runtime::Handle;
|
||||||
use tokio::task::block_in_place;
|
use tokio::task::block_in_place;
|
||||||
|
|
||||||
use crate::logging::install_tracing;
|
use crate::error::ExitCode;
|
||||||
use clients::wayland::{self, WaylandClient};
|
use clients::wayland::{self, WaylandClient};
|
||||||
use tracing::{debug, error, info};
|
use tracing::{debug, error, info};
|
||||||
|
|
||||||
|
const GTK_APP_ID: &str = "dev.jstanger.ironbar";
|
||||||
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
|
|
||||||
#[repr(i32)]
|
|
||||||
enum ErrorCode {
|
|
||||||
GtkDisplay = 1,
|
|
||||||
CreateBars = 2,
|
|
||||||
Config = 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
// Disable backtraces by default
|
let _guard = logging::install_logging();
|
||||||
if env::var("RUST_LIB_BACKTRACE").is_err() {
|
|
||||||
env::set_var("RUST_LIB_BACKTRACE", "0");
|
|
||||||
}
|
|
||||||
|
|
||||||
// keep guard in scope
|
|
||||||
// otherwise file logging drops
|
|
||||||
let _guard = install_tracing()?;
|
|
||||||
|
|
||||||
let hook_builder = color_eyre::config::HookBuilder::default();
|
|
||||||
let (panic_hook, eyre_hook) = hook_builder.into_hooks();
|
|
||||||
|
|
||||||
eyre_hook.install()?;
|
|
||||||
|
|
||||||
// custom hook allows tracing_appender to capture panics
|
|
||||||
panic::set_hook(Box::new(move |panic_info| {
|
|
||||||
error!("{}", panic_hook.panic_report(panic_info));
|
|
||||||
}));
|
|
||||||
|
|
||||||
info!("Ironbar version {}", VERSION);
|
info!("Ironbar version {}", VERSION);
|
||||||
info!("Starting application");
|
info!("Starting application");
|
||||||
|
|
||||||
let wayland_client = wayland::get_client().await;
|
let wayland_client = wayland::get_client().await;
|
||||||
|
|
||||||
let app = Application::builder()
|
let app = Application::builder().application_id(GTK_APP_ID).build();
|
||||||
.application_id("dev.jstanger.ironbar")
|
|
||||||
.build();
|
|
||||||
|
|
||||||
app.connect_activate(move |app| {
|
app.connect_activate(move |app| {
|
||||||
let display = Display::default().map_or_else(
|
let display = Display::default().map_or_else(
|
||||||
|| {
|
|| {
|
||||||
let report = Report::msg("Failed to get default GTK display");
|
let report = Report::msg("Failed to get default GTK display");
|
||||||
error!("{:?}", report);
|
error!("{:?}", report);
|
||||||
exit(ErrorCode::GtkDisplay as i32)
|
exit(ExitCode::GtkDisplay as i32)
|
||||||
},
|
},
|
||||||
|display| display,
|
|display| display,
|
||||||
);
|
);
|
||||||
|
@ -83,14 +60,14 @@ async fn main() -> Result<()> {
|
||||||
Ok(config) => config,
|
Ok(config) => config,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("{:?}", err);
|
error!("{:?}", err);
|
||||||
exit(ErrorCode::Config as i32)
|
exit(ExitCode::Config as i32)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
debug!("Loaded config file");
|
debug!("Loaded config file");
|
||||||
|
|
||||||
if let Err(err) = create_bars(app, &display, wayland_client, &config) {
|
if let Err(err) = create_bars(app, &display, wayland_client, &config) {
|
||||||
error!("{:?}", err);
|
error!("{:?}", err);
|
||||||
exit(ErrorCode::CreateBars as i32);
|
exit(ExitCode::CreateBars as i32);
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("Created bars");
|
debug!("Created bars");
|
||||||
|
@ -101,7 +78,7 @@ async fn main() -> Result<()> {
|
||||||
|| {
|
|| {
|
||||||
let report = Report::msg("Failed to locate user config dir");
|
let report = Report::msg("Failed to locate user config dir");
|
||||||
error!("{:?}", report);
|
error!("{:?}", report);
|
||||||
exit(ErrorCode::CreateBars as i32);
|
exit(ExitCode::CreateBars as i32);
|
||||||
},
|
},
|
||||||
|dir| dir.join("ironbar").join("style.css"),
|
|dir| dir.join("ironbar").join("style.css"),
|
||||||
)
|
)
|
||||||
|
@ -136,11 +113,14 @@ fn create_bars(
|
||||||
let num_monitors = display.n_monitors();
|
let num_monitors = display.n_monitors();
|
||||||
|
|
||||||
for i in 0..num_monitors {
|
for i in 0..num_monitors {
|
||||||
let monitor = display.monitor(i).ok_or_else(|| Report::msg("GTK and Sway are reporting a different set of outputs - this is a severe bug and should never happen"))?;
|
let monitor = display
|
||||||
let output = outputs.get(i as usize).ok_or_else(|| Report::msg("GTK and Sway are reporting a different set of outputs - this is a severe bug and should never happen"))?;
|
.monitor(i)
|
||||||
|
.ok_or_else(|| Report::msg(error::ERR_OUTPUTS))?;
|
||||||
|
let output = outputs
|
||||||
|
.get(i as usize)
|
||||||
|
.ok_or_else(|| Report::msg(error::ERR_OUTPUTS))?;
|
||||||
let monitor_name = &output.name;
|
let monitor_name = &output.name;
|
||||||
|
|
||||||
// TODO: Could we use an Arc<Config> or `Cow<Config>` here to avoid cloning?
|
|
||||||
config.monitors.as_ref().map_or_else(
|
config.monitors.as_ref().map_or_else(
|
||||||
|| {
|
|| {
|
||||||
info!("Creating bar on '{}'", monitor_name);
|
info!("Creating bar on '{}'", monitor_name);
|
||||||
|
@ -178,6 +158,8 @@ fn create_bars(
|
||||||
/// Do note it must be called from within a Tokio runtime still.
|
/// Do note it must be called from within a Tokio runtime still.
|
||||||
///
|
///
|
||||||
/// Use sparingly! Prefer async functions wherever possible.
|
/// Use sparingly! Prefer async functions wherever possible.
|
||||||
|
///
|
||||||
|
/// TODO: remove all instances of this once async trait funcs are stable
|
||||||
pub fn await_sync<F: Future>(f: F) -> F::Output {
|
pub fn await_sync<F: Future>(f: F) -> F::Output {
|
||||||
block_in_place(|| Handle::current().block_on(f))
|
block_in_place(|| Handle::current().block_on(f))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::config::CommonConfig;
|
use crate::config::CommonConfig;
|
||||||
use crate::modules::{Module, ModuleInfo, ModuleUpdateEvent, ModuleWidget, WidgetContext};
|
use crate::modules::{Module, ModuleInfo, ModuleUpdateEvent, ModuleWidget, WidgetContext};
|
||||||
use crate::popup::Popup;
|
use crate::popup::Popup;
|
||||||
|
use crate::{send_async, try_send};
|
||||||
use chrono::{DateTime, Local};
|
use chrono::{DateTime, Local};
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
use glib::Continue;
|
use glib::Continue;
|
||||||
|
@ -22,7 +23,7 @@ pub struct ClockModule {
|
||||||
format: String,
|
format: String,
|
||||||
|
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub common: CommonConfig,
|
pub common: Option<CommonConfig>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_format() -> String {
|
fn default_format() -> String {
|
||||||
|
@ -33,6 +34,10 @@ impl Module<Button> for ClockModule {
|
||||||
type SendMessage = DateTime<Local>;
|
type SendMessage = DateTime<Local>;
|
||||||
type ReceiveMessage = ();
|
type ReceiveMessage = ();
|
||||||
|
|
||||||
|
fn name() -> &'static str {
|
||||||
|
"clock"
|
||||||
|
}
|
||||||
|
|
||||||
fn spawn_controller(
|
fn spawn_controller(
|
||||||
&self,
|
&self,
|
||||||
_info: &ModuleInfo,
|
_info: &ModuleInfo,
|
||||||
|
@ -42,9 +47,7 @@ impl Module<Button> for ClockModule {
|
||||||
spawn(async move {
|
spawn(async move {
|
||||||
loop {
|
loop {
|
||||||
let date = Local::now();
|
let date = Local::now();
|
||||||
tx.send(ModuleUpdateEvent::Update(date))
|
send_async!(tx, ModuleUpdateEvent::Update(date));
|
||||||
.await
|
|
||||||
.expect("Failed to send date");
|
|
||||||
sleep(tokio::time::Duration::from_millis(500)).await;
|
sleep(tokio::time::Duration::from_millis(500)).await;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -64,13 +67,10 @@ impl Module<Button> for ClockModule {
|
||||||
|
|
||||||
let orientation = info.bar_position.get_orientation();
|
let orientation = info.bar_position.get_orientation();
|
||||||
button.connect_clicked(move |button| {
|
button.connect_clicked(move |button| {
|
||||||
context
|
try_send!(
|
||||||
.tx
|
context.tx,
|
||||||
.try_send(ModuleUpdateEvent::TogglePopup(Popup::button_pos(
|
ModuleUpdateEvent::TogglePopup(Popup::button_pos(button, orientation))
|
||||||
button,
|
);
|
||||||
orientation,
|
|
||||||
)))
|
|
||||||
.expect("Failed to toggle popup");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let format = self.format.clone();
|
let format = self.format.clone();
|
||||||
|
|
|
@ -3,6 +3,7 @@ use crate::dynamic_string::DynamicString;
|
||||||
use crate::modules::{Module, ModuleInfo, ModuleUpdateEvent, ModuleWidget, WidgetContext};
|
use crate::modules::{Module, ModuleInfo, ModuleUpdateEvent, ModuleWidget, WidgetContext};
|
||||||
use crate::popup::{ButtonGeometry, Popup};
|
use crate::popup::{ButtonGeometry, Popup};
|
||||||
use crate::script::Script;
|
use crate::script::Script;
|
||||||
|
use crate::{send_async, try_send};
|
||||||
use color_eyre::{Report, Result};
|
use color_eyre::{Report, Result};
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::{Button, Label, Orientation};
|
use gtk::{Button, Label, Orientation};
|
||||||
|
@ -21,7 +22,7 @@ pub struct CustomModule {
|
||||||
popup: Option<Vec<Widget>>,
|
popup: Option<Vec<Widget>>,
|
||||||
|
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub common: CommonConfig,
|
pub common: Option<CommonConfig>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to parse an `Orientation` from `String`
|
/// Attempts to parse an `Orientation` from `String`
|
||||||
|
@ -119,8 +120,6 @@ impl Widget {
|
||||||
}
|
}
|
||||||
|
|
||||||
label
|
label
|
||||||
|
|
||||||
// DynamicString::new(label, &text)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a `gtk::Button` from this widget
|
/// Creates a `gtk::Button` from this widget
|
||||||
|
@ -146,11 +145,13 @@ impl Widget {
|
||||||
|
|
||||||
if let Some(exec) = self.on_click {
|
if let Some(exec) = self.on_click {
|
||||||
button.connect_clicked(move |button| {
|
button.connect_clicked(move |button| {
|
||||||
tx.try_send(ExecEvent {
|
try_send!(
|
||||||
cmd: exec.clone(),
|
tx,
|
||||||
geometry: Popup::button_pos(button, bar_orientation),
|
ExecEvent {
|
||||||
})
|
cmd: exec.clone(),
|
||||||
.expect("Failed to send exec message");
|
geometry: Popup::button_pos(button, bar_orientation),
|
||||||
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,6 +169,10 @@ impl Module<gtk::Box> for CustomModule {
|
||||||
type SendMessage = ();
|
type SendMessage = ();
|
||||||
type ReceiveMessage = ExecEvent;
|
type ReceiveMessage = ExecEvent;
|
||||||
|
|
||||||
|
fn name() -> &'static str {
|
||||||
|
"custom"
|
||||||
|
}
|
||||||
|
|
||||||
fn spawn_controller(
|
fn spawn_controller(
|
||||||
&self,
|
&self,
|
||||||
_info: &ModuleInfo,
|
_info: &ModuleInfo,
|
||||||
|
@ -185,17 +190,11 @@ impl Module<gtk::Box> for CustomModule {
|
||||||
error!("{err:?}");
|
error!("{err:?}");
|
||||||
}
|
}
|
||||||
} else if event.cmd == "popup:toggle" {
|
} else if event.cmd == "popup:toggle" {
|
||||||
tx.send(ModuleUpdateEvent::TogglePopup(event.geometry))
|
send_async!(tx, ModuleUpdateEvent::TogglePopup(event.geometry));
|
||||||
.await
|
|
||||||
.expect("Failed to send open popup event");
|
|
||||||
} else if event.cmd == "popup:open" {
|
} else if event.cmd == "popup:open" {
|
||||||
tx.send(ModuleUpdateEvent::OpenPopup(event.geometry))
|
send_async!(tx, ModuleUpdateEvent::OpenPopup(event.geometry));
|
||||||
.await
|
|
||||||
.expect("Failed to send open popup event");
|
|
||||||
} else if event.cmd == "popup:close" {
|
} else if event.cmd == "popup:close" {
|
||||||
tx.send(ModuleUpdateEvent::ClosePopup)
|
send_async!(tx, ModuleUpdateEvent::ClosePopup);
|
||||||
.await
|
|
||||||
.expect("Failed to send open popup event");
|
|
||||||
} else {
|
} else {
|
||||||
error!("Received invalid command: '{}'", event.cmd);
|
error!("Received invalid command: '{}'", event.cmd);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::clients::wayland::{self, ToplevelChange};
|
use crate::clients::wayland::{self, ToplevelChange};
|
||||||
use crate::config::CommonConfig;
|
use crate::config::CommonConfig;
|
||||||
use crate::modules::{Module, ModuleInfo, ModuleUpdateEvent, ModuleWidget, WidgetContext};
|
use crate::modules::{Module, ModuleInfo, ModuleUpdateEvent, ModuleWidget, WidgetContext};
|
||||||
use crate::{await_sync, icon};
|
use crate::{await_sync, icon, read_lock, send_async};
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
use glib::Continue;
|
use glib::Continue;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
|
@ -26,7 +26,7 @@ pub struct FocusedModule {
|
||||||
icon_theme: Option<String>,
|
icon_theme: Option<String>,
|
||||||
|
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub common: CommonConfig,
|
pub common: Option<CommonConfig>,
|
||||||
}
|
}
|
||||||
|
|
||||||
const fn default_icon_size() -> i32 {
|
const fn default_icon_size() -> i32 {
|
||||||
|
@ -37,6 +37,10 @@ impl Module<gtk::Box> for FocusedModule {
|
||||||
type SendMessage = (String, String);
|
type SendMessage = (String, String);
|
||||||
type ReceiveMessage = ();
|
type ReceiveMessage = ();
|
||||||
|
|
||||||
|
fn name() -> &'static str {
|
||||||
|
"focused"
|
||||||
|
}
|
||||||
|
|
||||||
fn spawn_controller(
|
fn spawn_controller(
|
||||||
&self,
|
&self,
|
||||||
_info: &ModuleInfo,
|
_info: &ModuleInfo,
|
||||||
|
@ -45,16 +49,15 @@ impl Module<gtk::Box> for FocusedModule {
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let focused = await_sync(async {
|
let focused = await_sync(async {
|
||||||
let wl = wayland::get_client().await;
|
let wl = wayland::get_client().await;
|
||||||
let toplevels = wl
|
let toplevels = read_lock!(wl.toplevels);
|
||||||
.toplevels
|
|
||||||
.read()
|
|
||||||
.expect("Failed to get read lock on toplevels")
|
|
||||||
.clone();
|
|
||||||
|
|
||||||
toplevels.into_iter().find(|(_, (top, _))| top.active)
|
toplevels
|
||||||
|
.iter()
|
||||||
|
.find(|(_, (top, _))| top.active)
|
||||||
|
.map(|(_, (top, _))| top.clone())
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Some((_, (top, _))) = focused {
|
if let Some(top) = focused {
|
||||||
tx.try_send(ModuleUpdateEvent::Update((top.title.clone(), top.app_id)))?;
|
tx.try_send(ModuleUpdateEvent::Update((top.title.clone(), top.app_id)))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,12 +75,10 @@ impl Module<gtk::Box> for FocusedModule {
|
||||||
};
|
};
|
||||||
|
|
||||||
if update {
|
if update {
|
||||||
tx.send(ModuleUpdateEvent::Update((
|
send_async!(
|
||||||
event.toplevel.title,
|
tx,
|
||||||
event.toplevel.app_id,
|
ModuleUpdateEvent::Update((event.toplevel.title, event.toplevel.app_id))
|
||||||
)))
|
);
|
||||||
.await
|
|
||||||
.expect("Failed to send focus update");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,6 +4,7 @@ use crate::icon::get_icon;
|
||||||
use crate::modules::launcher::{ItemEvent, LauncherUpdate};
|
use crate::modules::launcher::{ItemEvent, LauncherUpdate};
|
||||||
use crate::modules::ModuleUpdateEvent;
|
use crate::modules::ModuleUpdateEvent;
|
||||||
use crate::popup::Popup;
|
use crate::popup::Popup;
|
||||||
|
use crate::{read_lock, try_send};
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::{Button, IconTheme, Image, Orientation};
|
use gtk::{Button, IconTheme, Image, Orientation};
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
@ -177,14 +178,12 @@ impl ItemButton {
|
||||||
let app_id = item.app_id.clone();
|
let app_id = item.app_id.clone();
|
||||||
let tx = controller_tx.clone();
|
let tx = controller_tx.clone();
|
||||||
button.connect_clicked(move |button| {
|
button.connect_clicked(move |button| {
|
||||||
// lazy check :|
|
// lazy check :| TODO: Improve this
|
||||||
let style_context = button.style_context();
|
let style_context = button.style_context();
|
||||||
if style_context.has_class("open") {
|
if style_context.has_class("open") {
|
||||||
tx.try_send(ItemEvent::FocusItem(app_id.clone()))
|
try_send!(tx, ItemEvent::FocusItem(app_id.clone()));
|
||||||
.expect("Failed to send item focus event");
|
|
||||||
} else {
|
} else {
|
||||||
tx.try_send(ItemEvent::OpenItem(app_id.clone()))
|
try_send!(tx, ItemEvent::OpenItem(app_id.clone()));
|
||||||
.expect("Failed to send item open event");
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -199,24 +198,20 @@ impl ItemButton {
|
||||||
let menu_state = menu_state.clone();
|
let menu_state = menu_state.clone();
|
||||||
|
|
||||||
button.connect_enter_notify_event(move |button, _| {
|
button.connect_enter_notify_event(move |button, _| {
|
||||||
let menu_state = menu_state
|
let menu_state = read_lock!(menu_state);
|
||||||
.read()
|
|
||||||
.expect("Failed to get read lock on item menu state");
|
|
||||||
|
|
||||||
if menu_state.num_windows > 1 {
|
if menu_state.num_windows > 1 {
|
||||||
tx.try_send(ModuleUpdateEvent::Update(LauncherUpdate::Hover(
|
try_send!(
|
||||||
app_id.clone(),
|
tx,
|
||||||
)))
|
ModuleUpdateEvent::Update(LauncherUpdate::Hover(app_id.clone(),))
|
||||||
.expect("Failed to send item open popup event");
|
);
|
||||||
|
|
||||||
tx.try_send(ModuleUpdateEvent::OpenPopup(Popup::button_pos(
|
try_send!(
|
||||||
button,
|
tx,
|
||||||
orientation,
|
ModuleUpdateEvent::OpenPopup(Popup::button_pos(button, orientation,))
|
||||||
)))
|
);
|
||||||
.expect("Failed to send item open popup event");
|
|
||||||
} else {
|
} else {
|
||||||
tx.try_send(ModuleUpdateEvent::ClosePopup)
|
try_send!(tx, ModuleUpdateEvent::ClosePopup);
|
||||||
.expect("Failed to send item close popup event");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Inhibit(false)
|
Inhibit(false)
|
||||||
|
|
|
@ -7,6 +7,7 @@ use crate::clients::wayland::{self, ToplevelChange};
|
||||||
use crate::config::CommonConfig;
|
use crate::config::CommonConfig;
|
||||||
use crate::icon::find_desktop_file;
|
use crate::icon::find_desktop_file;
|
||||||
use crate::modules::{Module, ModuleInfo, ModuleUpdateEvent, ModuleWidget, WidgetContext};
|
use crate::modules::{Module, ModuleInfo, ModuleUpdateEvent, ModuleWidget, WidgetContext};
|
||||||
|
use crate::{lock, read_lock, try_send, write_lock};
|
||||||
use color_eyre::{Help, Report};
|
use color_eyre::{Help, Report};
|
||||||
use glib::Continue;
|
use glib::Continue;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
|
@ -36,7 +37,7 @@ pub struct LauncherModule {
|
||||||
icon_theme: Option<String>,
|
icon_theme: Option<String>,
|
||||||
|
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub common: CommonConfig,
|
pub common: Option<CommonConfig>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -78,6 +79,10 @@ impl Module<gtk::Box> for LauncherModule {
|
||||||
type SendMessage = LauncherUpdate;
|
type SendMessage = LauncherUpdate;
|
||||||
type ReceiveMessage = ItemEvent;
|
type ReceiveMessage = ItemEvent;
|
||||||
|
|
||||||
|
fn name() -> &'static str {
|
||||||
|
"launcher"
|
||||||
|
}
|
||||||
|
|
||||||
fn spawn_controller(
|
fn spawn_controller(
|
||||||
&self,
|
&self,
|
||||||
_info: &ModuleInfo,
|
_info: &ModuleInfo,
|
||||||
|
@ -106,12 +111,9 @@ impl Module<gtk::Box> for LauncherModule {
|
||||||
let tx = tx.clone();
|
let tx = tx.clone();
|
||||||
spawn(async move {
|
spawn(async move {
|
||||||
let wl = wayland::get_client().await;
|
let wl = wayland::get_client().await;
|
||||||
let open_windows = wl
|
let open_windows = read_lock!(wl.toplevels);
|
||||||
.toplevels
|
|
||||||
.read()
|
|
||||||
.expect("Failed to get read lock on toplevels");
|
|
||||||
|
|
||||||
let mut items = items.lock().expect("Failed to get lock on items");
|
let mut items = lock!(items);
|
||||||
|
|
||||||
for (_, (window, _)) in open_windows.clone() {
|
for (_, (window, _)) in open_windows.clone() {
|
||||||
let item = items.get_mut(&window.app_id);
|
let item = items.get_mut(&window.app_id);
|
||||||
|
@ -153,12 +155,10 @@ impl Module<gtk::Box> for LauncherModule {
|
||||||
let window = event.toplevel;
|
let window = event.toplevel;
|
||||||
let app_id = window.app_id.clone();
|
let app_id = window.app_id.clone();
|
||||||
|
|
||||||
let items = || items.lock().expect("Failed to get lock on items");
|
|
||||||
|
|
||||||
match event.change {
|
match event.change {
|
||||||
ToplevelChange::New => {
|
ToplevelChange::New => {
|
||||||
let new_item = {
|
let new_item = {
|
||||||
let mut items = items();
|
let mut items = lock!(items);
|
||||||
let item = items.get_mut(&app_id);
|
let item = items.get_mut(&app_id);
|
||||||
match item {
|
match item {
|
||||||
None => {
|
None => {
|
||||||
|
@ -185,7 +185,7 @@ impl Module<gtk::Box> for LauncherModule {
|
||||||
}
|
}
|
||||||
ToplevelChange::Close => {
|
ToplevelChange::Close => {
|
||||||
let remove_item = {
|
let remove_item = {
|
||||||
let mut items = items();
|
let mut items = lock!(items);
|
||||||
let item = items.get_mut(&app_id);
|
let item = items.get_mut(&app_id);
|
||||||
match item {
|
match item {
|
||||||
Some(item) => {
|
Some(item) => {
|
||||||
|
@ -214,23 +214,19 @@ impl Module<gtk::Box> for LauncherModule {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
ToplevelChange::Focus(focused) => {
|
ToplevelChange::Focus(focused) => {
|
||||||
let update_title = if focused {
|
let mut update_title = false;
|
||||||
if let Some(item) = items().get_mut(&app_id) {
|
|
||||||
|
if focused {
|
||||||
|
if let Some(item) = lock!(items).get_mut(&app_id) {
|
||||||
item.set_window_focused(window.id, true);
|
item.set_window_focused(window.id, true);
|
||||||
|
|
||||||
// might be switching focus between windows of same app
|
// might be switching focus between windows of same app
|
||||||
if item.windows.len() > 1 {
|
if item.windows.len() > 1 {
|
||||||
item.set_window_name(window.id, window.title.clone());
|
item.set_window_name(window.id, window.title.clone());
|
||||||
true
|
update_title = true;
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
false
|
|
||||||
};
|
|
||||||
|
|
||||||
send_update(LauncherUpdate::Focus(app_id.clone(), focused)).await?;
|
send_update(LauncherUpdate::Focus(app_id.clone(), focused)).await?;
|
||||||
|
|
||||||
|
@ -240,7 +236,7 @@ impl Module<gtk::Box> for LauncherModule {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ToplevelChange::Title(title) => {
|
ToplevelChange::Title(title) => {
|
||||||
if let Some(item) = items().get_mut(&app_id) {
|
if let Some(item) = lock!(items).get_mut(&app_id) {
|
||||||
item.set_window_name(window.id, title.clone());
|
item.set_window_name(window.id, title.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,7 +278,7 @@ impl Module<gtk::Box> for LauncherModule {
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
let wl = wayland::get_client().await;
|
let wl = wayland::get_client().await;
|
||||||
let items = items.lock().expect("Failed to get lock on items");
|
let items = lock!(items);
|
||||||
|
|
||||||
let id = match event {
|
let id = match event {
|
||||||
ItemEvent::FocusItem(app_id) => items
|
ItemEvent::FocusItem(app_id) => items
|
||||||
|
@ -293,10 +289,7 @@ impl Module<gtk::Box> for LauncherModule {
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(id) = id {
|
if let Some(id) = id {
|
||||||
let toplevels = wl
|
let toplevels = read_lock!(wl.toplevels);
|
||||||
.toplevels
|
|
||||||
.read()
|
|
||||||
.expect("Failed to get read lock on toplevels");
|
|
||||||
let seat = wl.seats.first().expect("Failed to get Wayland seat");
|
let seat = wl.seats.first().expect("Failed to get Wayland seat");
|
||||||
if let Some((_top, handle)) = toplevels.get(&id) {
|
if let Some((_top, handle)) = toplevels.get(&id) {
|
||||||
handle.activate(seat);
|
handle.activate(seat);
|
||||||
|
@ -359,10 +352,7 @@ impl Module<gtk::Box> for LauncherModule {
|
||||||
if let Some(button) = buttons.get(&app_id) {
|
if let Some(button) = buttons.get(&app_id) {
|
||||||
button.set_open(true);
|
button.set_open(true);
|
||||||
|
|
||||||
let mut menu_state = button
|
let mut menu_state = write_lock!(button.menu_state);
|
||||||
.menu_state
|
|
||||||
.write()
|
|
||||||
.expect("Failed to get write lock on item menu state");
|
|
||||||
menu_state.num_windows += 1;
|
menu_state.num_windows += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -383,10 +373,7 @@ impl Module<gtk::Box> for LauncherModule {
|
||||||
}
|
}
|
||||||
LauncherUpdate::RemoveWindow(app_id, _) => {
|
LauncherUpdate::RemoveWindow(app_id, _) => {
|
||||||
if let Some(button) = buttons.get(&app_id) {
|
if let Some(button) = buttons.get(&app_id) {
|
||||||
let mut menu_state = button
|
let mut menu_state = write_lock!(button.menu_state);
|
||||||
.menu_state
|
|
||||||
.write()
|
|
||||||
.expect("Failed to get write lock on item menu state");
|
|
||||||
menu_state.num_windows -= 1;
|
menu_state.num_windows -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -459,8 +446,7 @@ impl Module<gtk::Box> for LauncherModule {
|
||||||
{
|
{
|
||||||
let tx = controller_tx.clone();
|
let tx = controller_tx.clone();
|
||||||
button.connect_clicked(move |button| {
|
button.connect_clicked(move |button| {
|
||||||
tx.try_send(ItemEvent::FocusWindow(win.id))
|
try_send!(tx, ItemEvent::FocusWindow(win.id));
|
||||||
.expect("Failed to send window click event");
|
|
||||||
|
|
||||||
if let Some(win) = button.window() {
|
if let Some(win) = button.window() {
|
||||||
win.hide();
|
win.hide();
|
||||||
|
@ -489,8 +475,7 @@ impl Module<gtk::Box> for LauncherModule {
|
||||||
{
|
{
|
||||||
let tx = controller_tx.clone();
|
let tx = controller_tx.clone();
|
||||||
button.connect_clicked(move |button| {
|
button.connect_clicked(move |button| {
|
||||||
tx.try_send(ItemEvent::FocusWindow(win.id))
|
try_send!(tx, ItemEvent::FocusWindow(win.id));
|
||||||
.expect("Failed to send window click event");
|
|
||||||
|
|
||||||
if let Some(win) = button.window() {
|
if let Some(win) = button.window() {
|
||||||
win.hide();
|
win.hide();
|
||||||
|
|
|
@ -17,7 +17,6 @@ pub mod workspaces;
|
||||||
use crate::config::BarPosition;
|
use crate::config::BarPosition;
|
||||||
use crate::popup::ButtonGeometry;
|
use crate::popup::ButtonGeometry;
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
use derive_builder::Builder;
|
|
||||||
use glib::IsA;
|
use glib::IsA;
|
||||||
use gtk::gdk::Monitor;
|
use gtk::gdk::Monitor;
|
||||||
use gtk::{Application, Widget};
|
use gtk::{Application, Widget};
|
||||||
|
@ -29,15 +28,12 @@ pub enum ModuleLocation {
|
||||||
Center,
|
Center,
|
||||||
Right,
|
Right,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Builder)]
|
|
||||||
pub struct ModuleInfo<'a> {
|
pub struct ModuleInfo<'a> {
|
||||||
pub app: &'a Application,
|
pub app: &'a Application,
|
||||||
pub location: ModuleLocation,
|
pub location: ModuleLocation,
|
||||||
pub bar_position: BarPosition,
|
pub bar_position: BarPosition,
|
||||||
pub monitor: &'a Monitor,
|
pub monitor: &'a Monitor,
|
||||||
pub output_name: &'a str,
|
pub output_name: &'a str,
|
||||||
pub module_name: &'a str,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -73,6 +69,8 @@ where
|
||||||
type SendMessage;
|
type SendMessage;
|
||||||
type ReceiveMessage;
|
type ReceiveMessage;
|
||||||
|
|
||||||
|
fn name() -> &'static str;
|
||||||
|
|
||||||
fn spawn_controller(
|
fn spawn_controller(
|
||||||
&self,
|
&self,
|
||||||
info: &ModuleInfo,
|
info: &ModuleInfo,
|
||||||
|
|
|
@ -2,6 +2,7 @@ use crate::clients::mpd::{get_client, get_duration, get_elapsed, MpdConnectionEr
|
||||||
use crate::config::CommonConfig;
|
use crate::config::CommonConfig;
|
||||||
use crate::modules::{Module, ModuleInfo, ModuleUpdateEvent, ModuleWidget, WidgetContext};
|
use crate::modules::{Module, ModuleInfo, ModuleUpdateEvent, ModuleWidget, WidgetContext};
|
||||||
use crate::popup::Popup;
|
use crate::popup::Popup;
|
||||||
|
use crate::try_send;
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
use dirs::{audio_dir, home_dir};
|
use dirs::{audio_dir, home_dir};
|
||||||
use glib::Continue;
|
use glib::Continue;
|
||||||
|
@ -68,7 +69,7 @@ pub struct MpdModule {
|
||||||
music_dir: PathBuf,
|
music_dir: PathBuf,
|
||||||
|
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub common: CommonConfig,
|
pub common: Option<CommonConfig>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_socket() -> String {
|
fn default_socket() -> String {
|
||||||
|
@ -128,6 +129,10 @@ impl Module<Button> for MpdModule {
|
||||||
type SendMessage = Option<SongUpdate>;
|
type SendMessage = Option<SongUpdate>;
|
||||||
type ReceiveMessage = PlayerCommand;
|
type ReceiveMessage = PlayerCommand;
|
||||||
|
|
||||||
|
fn name() -> &'static str {
|
||||||
|
"mpd"
|
||||||
|
}
|
||||||
|
|
||||||
fn spawn_controller(
|
fn spawn_controller(
|
||||||
&self,
|
&self,
|
||||||
_info: &ModuleInfo,
|
_info: &ModuleInfo,
|
||||||
|
@ -221,11 +226,10 @@ impl Module<Button> for MpdModule {
|
||||||
let tx = context.tx.clone();
|
let tx = context.tx.clone();
|
||||||
|
|
||||||
button.connect_clicked(move |button| {
|
button.connect_clicked(move |button| {
|
||||||
tx.try_send(ModuleUpdateEvent::TogglePopup(Popup::button_pos(
|
try_send!(
|
||||||
button,
|
tx,
|
||||||
orientation,
|
ModuleUpdateEvent::TogglePopup(Popup::button_pos(button, orientation,))
|
||||||
)))
|
);
|
||||||
.expect("Failed to send MPD popup open event");
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,8 +243,7 @@ impl Module<Button> for MpdModule {
|
||||||
button.show();
|
button.show();
|
||||||
} else {
|
} else {
|
||||||
button.hide();
|
button.hide();
|
||||||
tx.try_send(ModuleUpdateEvent::ClosePopup)
|
try_send!(tx, ModuleUpdateEvent::ClosePopup);
|
||||||
.expect("Failed to send close popup message");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Continue(true)
|
Continue(true)
|
||||||
|
@ -318,31 +321,22 @@ impl Module<Button> for MpdModule {
|
||||||
|
|
||||||
let tx_prev = tx.clone();
|
let tx_prev = tx.clone();
|
||||||
btn_prev.connect_clicked(move |_| {
|
btn_prev.connect_clicked(move |_| {
|
||||||
tx_prev
|
try_send!(tx_prev, PlayerCommand::Previous);
|
||||||
.try_send(PlayerCommand::Previous)
|
|
||||||
.expect("Failed to send prev track message");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let tx_toggle = tx.clone();
|
let tx_toggle = tx.clone();
|
||||||
btn_play_pause.connect_clicked(move |_| {
|
btn_play_pause.connect_clicked(move |_| {
|
||||||
tx_toggle
|
try_send!(tx_toggle, PlayerCommand::Toggle);
|
||||||
.try_send(PlayerCommand::Toggle)
|
|
||||||
.expect("Failed to send play/pause track message");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let tx_next = tx.clone();
|
let tx_next = tx.clone();
|
||||||
btn_next.connect_clicked(move |_| {
|
btn_next.connect_clicked(move |_| {
|
||||||
tx_next
|
try_send!(tx_next, PlayerCommand::Next);
|
||||||
.try_send(PlayerCommand::Next)
|
|
||||||
.expect("Failed to send next track message");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let tx_vol = tx;
|
let tx_vol = tx;
|
||||||
volume_slider.connect_change_value(move |_, _, val| {
|
volume_slider.connect_change_value(move |_, _, val| {
|
||||||
tx_vol
|
try_send!(tx_vol, PlayerCommand::Volume(val as u8));
|
||||||
.try_send(PlayerCommand::Volume(val as u8))
|
|
||||||
.expect("Failed to send volume message");
|
|
||||||
|
|
||||||
Inhibit(false)
|
Inhibit(false)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ pub struct ScriptModule {
|
||||||
interval: u64,
|
interval: u64,
|
||||||
|
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub common: CommonConfig,
|
pub common: Option<CommonConfig>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `Mode::Poll`
|
/// `Mode::Poll`
|
||||||
|
@ -48,6 +48,10 @@ impl Module<Label> for ScriptModule {
|
||||||
type SendMessage = String;
|
type SendMessage = String;
|
||||||
type ReceiveMessage = ();
|
type ReceiveMessage = ();
|
||||||
|
|
||||||
|
fn name() -> &'static str {
|
||||||
|
"script"
|
||||||
|
}
|
||||||
|
|
||||||
fn spawn_controller(
|
fn spawn_controller(
|
||||||
&self,
|
&self,
|
||||||
_info: &ModuleInfo,
|
_info: &ModuleInfo,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::config::CommonConfig;
|
use crate::config::CommonConfig;
|
||||||
use crate::modules::{Module, ModuleInfo, ModuleUpdateEvent, ModuleWidget, WidgetContext};
|
use crate::modules::{Module, ModuleInfo, ModuleUpdateEvent, ModuleWidget, WidgetContext};
|
||||||
|
use crate::send_async;
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::Label;
|
use gtk::Label;
|
||||||
|
@ -22,7 +23,7 @@ pub struct SysInfoModule {
|
||||||
interval: Interval,
|
interval: Interval,
|
||||||
|
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub common: CommonConfig,
|
pub common: Option<CommonConfig>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Copy, Clone)]
|
#[derive(Debug, Deserialize, Copy, Clone)]
|
||||||
|
@ -116,6 +117,10 @@ impl Module<gtk::Box> for SysInfoModule {
|
||||||
type SendMessage = HashMap<String, String>;
|
type SendMessage = HashMap<String, String>;
|
||||||
type ReceiveMessage = ();
|
type ReceiveMessage = ();
|
||||||
|
|
||||||
|
fn name() -> &'static str {
|
||||||
|
"sysinfo"
|
||||||
|
}
|
||||||
|
|
||||||
fn spawn_controller(
|
fn spawn_controller(
|
||||||
&self,
|
&self,
|
||||||
_info: &ModuleInfo,
|
_info: &ModuleInfo,
|
||||||
|
@ -135,83 +140,24 @@ impl Module<gtk::Box> for SysInfoModule {
|
||||||
|
|
||||||
let (refresh_tx, mut refresh_rx) = mpsc::channel(16);
|
let (refresh_tx, mut refresh_rx) = mpsc::channel(16);
|
||||||
|
|
||||||
// memory refresh
|
macro_rules! spawn_refresh {
|
||||||
{
|
($refresh_type:expr, $func:ident) => {{
|
||||||
let tx = refresh_tx.clone();
|
let tx = refresh_tx.clone();
|
||||||
spawn(async move {
|
spawn(async move {
|
||||||
loop {
|
loop {
|
||||||
tx.send(RefreshType::Memory)
|
send_async!(tx, $refresh_type);
|
||||||
.await
|
sleep(Duration::from_secs(interval.$func())).await;
|
||||||
.expect("Failed to send memory refresh");
|
}
|
||||||
sleep(Duration::from_secs(interval.memory())).await;
|
});
|
||||||
}
|
}};
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// cpu refresh
|
spawn_refresh!(RefreshType::Memory, memory);
|
||||||
{
|
spawn_refresh!(RefreshType::Cpu, cpu);
|
||||||
let tx = refresh_tx.clone();
|
spawn_refresh!(RefreshType::Temps, temps);
|
||||||
spawn(async move {
|
spawn_refresh!(RefreshType::Disks, disks);
|
||||||
loop {
|
spawn_refresh!(RefreshType::Network, networks);
|
||||||
tx.send(RefreshType::Cpu)
|
spawn_refresh!(RefreshType::System, system);
|
||||||
.await
|
|
||||||
.expect("Failed to send cpu refresh");
|
|
||||||
sleep(Duration::from_secs(interval.cpu())).await;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// temp refresh
|
|
||||||
{
|
|
||||||
let tx = refresh_tx.clone();
|
|
||||||
spawn(async move {
|
|
||||||
loop {
|
|
||||||
tx.send(RefreshType::Temps)
|
|
||||||
.await
|
|
||||||
.expect("Failed to send temperature refresh");
|
|
||||||
sleep(Duration::from_secs(interval.temps())).await;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// disk refresh
|
|
||||||
{
|
|
||||||
let tx = refresh_tx.clone();
|
|
||||||
spawn(async move {
|
|
||||||
loop {
|
|
||||||
tx.send(RefreshType::Disks)
|
|
||||||
.await
|
|
||||||
.expect("Failed to send disk refresh");
|
|
||||||
sleep(Duration::from_secs(interval.disks())).await;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// network refresh
|
|
||||||
{
|
|
||||||
let tx = refresh_tx.clone();
|
|
||||||
spawn(async move {
|
|
||||||
loop {
|
|
||||||
tx.send(RefreshType::Network)
|
|
||||||
.await
|
|
||||||
.expect("Failed to send network refresh");
|
|
||||||
sleep(Duration::from_secs(interval.networks())).await;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// system refresh
|
|
||||||
{
|
|
||||||
let tx = refresh_tx;
|
|
||||||
spawn(async move {
|
|
||||||
loop {
|
|
||||||
tx.send(RefreshType::System)
|
|
||||||
.await
|
|
||||||
.expect("Failed to send system refresh");
|
|
||||||
sleep(Duration::from_secs(interval.system())).await;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
spawn(async move {
|
spawn(async move {
|
||||||
let mut format_info = HashMap::new();
|
let mut format_info = HashMap::new();
|
||||||
|
@ -228,9 +174,7 @@ impl Module<gtk::Box> for SysInfoModule {
|
||||||
RefreshType::System => refresh_system_tokens(&mut format_info, &sys),
|
RefreshType::System => refresh_system_tokens(&mut format_info, &sys),
|
||||||
};
|
};
|
||||||
|
|
||||||
tx.send(ModuleUpdateEvent::Update(format_info.clone()))
|
send_async!(tx, ModuleUpdateEvent::Update(format_info.clone()));
|
||||||
.await
|
|
||||||
.expect("Failed to send system info map");
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::await_sync;
|
|
||||||
use crate::clients::system_tray::get_tray_event_client;
|
use crate::clients::system_tray::get_tray_event_client;
|
||||||
use crate::config::CommonConfig;
|
use crate::config::CommonConfig;
|
||||||
use crate::modules::{Module, ModuleInfo, ModuleUpdateEvent, ModuleWidget, WidgetContext};
|
use crate::modules::{Module, ModuleInfo, ModuleUpdateEvent, ModuleWidget, WidgetContext};
|
||||||
|
use crate::{await_sync, try_send};
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::{IconLookupFlags, IconTheme, Image, Menu, MenuBar, MenuItem, SeparatorMenuItem};
|
use gtk::{IconLookupFlags, IconTheme, Image, Menu, MenuBar, MenuItem, SeparatorMenuItem};
|
||||||
|
@ -17,7 +17,7 @@ use tokio::sync::mpsc::{Receiver, Sender};
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
pub struct TrayModule {
|
pub struct TrayModule {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub common: CommonConfig,
|
pub common: Option<CommonConfig>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a GTK `Image` component
|
/// Gets a GTK `Image` component
|
||||||
|
@ -70,12 +70,14 @@ fn get_menu_items(
|
||||||
{
|
{
|
||||||
let tx = tx.clone();
|
let tx = tx.clone();
|
||||||
item.connect_activate(move |_item| {
|
item.connect_activate(move |_item| {
|
||||||
tx.try_send(NotifierItemCommand::MenuItemClicked {
|
try_send!(
|
||||||
submenu_id: info.id,
|
tx,
|
||||||
menu_path: path.clone(),
|
NotifierItemCommand::MenuItemClicked {
|
||||||
notifier_address: id.clone(),
|
submenu_id: info.id,
|
||||||
})
|
menu_path: path.clone(),
|
||||||
.expect("Failed to send menu item clicked event");
|
notifier_address: id.clone(),
|
||||||
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,6 +94,10 @@ impl Module<MenuBar> for TrayModule {
|
||||||
type SendMessage = NotifierItemMessage;
|
type SendMessage = NotifierItemMessage;
|
||||||
type ReceiveMessage = NotifierItemCommand;
|
type ReceiveMessage = NotifierItemCommand;
|
||||||
|
|
||||||
|
fn name() -> &'static str {
|
||||||
|
"tray"
|
||||||
|
}
|
||||||
|
|
||||||
fn spawn_controller(
|
fn spawn_controller(
|
||||||
&self,
|
&self,
|
||||||
_info: &ModuleInfo,
|
_info: &ModuleInfo,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::await_sync;
|
|
||||||
use crate::clients::sway::{get_client, get_sub_client};
|
use crate::clients::sway::{get_client, get_sub_client};
|
||||||
use crate::config::CommonConfig;
|
use crate::config::CommonConfig;
|
||||||
use crate::modules::{Module, ModuleInfo, ModuleUpdateEvent, ModuleWidget, WidgetContext};
|
use crate::modules::{Module, ModuleInfo, ModuleUpdateEvent, ModuleWidget, WidgetContext};
|
||||||
|
use crate::{await_sync, send_async, try_send};
|
||||||
use color_eyre::{Report, Result};
|
use color_eyre::{Report, Result};
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::Button;
|
use gtk::Button;
|
||||||
|
@ -22,7 +22,7 @@ pub struct WorkspacesModule {
|
||||||
all_monitors: bool,
|
all_monitors: bool,
|
||||||
|
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub common: CommonConfig,
|
pub common: Option<CommonConfig>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -53,8 +53,7 @@ fn create_button(
|
||||||
let tx = tx.clone();
|
let tx = tx.clone();
|
||||||
let name = name.to_string();
|
let name = name.to_string();
|
||||||
button.connect_clicked(move |_item| {
|
button.connect_clicked(move |_item| {
|
||||||
tx.try_send(name.clone())
|
try_send!(tx, name.clone());
|
||||||
.expect("Failed to send workspace click event");
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,6 +64,10 @@ impl Module<gtk::Box> for WorkspacesModule {
|
||||||
type SendMessage = WorkspaceUpdate;
|
type SendMessage = WorkspaceUpdate;
|
||||||
type ReceiveMessage = String;
|
type ReceiveMessage = String;
|
||||||
|
|
||||||
|
fn name() -> &'static str {
|
||||||
|
"workspaces"
|
||||||
|
}
|
||||||
|
|
||||||
fn spawn_controller(
|
fn spawn_controller(
|
||||||
&self,
|
&self,
|
||||||
info: &ModuleInfo,
|
info: &ModuleInfo,
|
||||||
|
@ -90,8 +93,10 @@ impl Module<gtk::Box> for WorkspacesModule {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
tx.try_send(ModuleUpdateEvent::Update(WorkspaceUpdate::Init(workspaces)))
|
try_send!(
|
||||||
.expect("Failed to send initial workspace list");
|
tx,
|
||||||
|
ModuleUpdateEvent::Update(WorkspaceUpdate::Init(workspaces))
|
||||||
|
);
|
||||||
|
|
||||||
// Subscribe & send events
|
// Subscribe & send events
|
||||||
spawn(async move {
|
spawn(async move {
|
||||||
|
@ -103,9 +108,10 @@ impl Module<gtk::Box> for WorkspacesModule {
|
||||||
trace!("Set up Sway workspace subscription");
|
trace!("Set up Sway workspace subscription");
|
||||||
|
|
||||||
while let Ok(payload) = srx.recv().await {
|
while let Ok(payload) = srx.recv().await {
|
||||||
tx.send(ModuleUpdateEvent::Update(WorkspaceUpdate::Update(payload)))
|
send_async!(
|
||||||
.await
|
tx,
|
||||||
.expect("Failed to send workspace update");
|
ModuleUpdateEvent::Update(WorkspaceUpdate::Update(payload))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::send_async;
|
||||||
use color_eyre::eyre::WrapErr;
|
use color_eyre::eyre::WrapErr;
|
||||||
use color_eyre::{Report, Result};
|
use color_eyre::{Report, Result};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
@ -129,12 +130,12 @@ impl From<&str> for Script {
|
||||||
.iter()
|
.iter()
|
||||||
.take_while(|c| c.is_ascii_digit())
|
.take_while(|c| c.is_ascii_digit())
|
||||||
.collect::<String>();
|
.collect::<String>();
|
||||||
(
|
|
||||||
ScriptInputToken::Interval(
|
let interval = interval_str.parse::<u64>().unwrap_or_else(|_| {
|
||||||
interval_str.parse::<u64>().expect("Invalid interval"),
|
warn!("Received invalid interval in script string. Falling back to default `5000ms`.");
|
||||||
),
|
5000
|
||||||
interval_str.len(),
|
});
|
||||||
)
|
(ScriptInputToken::Interval(interval), interval_str.len())
|
||||||
}
|
}
|
||||||
// watching or polling
|
// watching or polling
|
||||||
'w' | 'p' => {
|
'w' | 'p' => {
|
||||||
|
@ -262,10 +263,10 @@ impl Script {
|
||||||
select! {
|
select! {
|
||||||
_ = handle.wait() => break,
|
_ = handle.wait() => break,
|
||||||
Ok(Some(line)) = stdout_lines.next_line() => {
|
Ok(Some(line)) = stdout_lines.next_line() => {
|
||||||
tx.send(OutputStream::Stdout(line)).await.expect("Failed to send stdout");
|
send_async!(tx, OutputStream::Stdout(line));
|
||||||
}
|
}
|
||||||
Ok(Some(line)) = stderr_lines.next_line() => {
|
Ok(Some(line)) = stderr_lines.next_line() => {
|
||||||
tx.send(OutputStream::Stderr(line)).await.expect("Failed to send stderr");
|
send_async!(tx, OutputStream::Stderr(line));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::send;
|
||||||
use color_eyre::{Help, Report};
|
use color_eyre::{Help, Report};
|
||||||
use glib::Continue;
|
use glib::Continue;
|
||||||
use gtk::prelude::CssProviderExt;
|
use gtk::prelude::CssProviderExt;
|
||||||
|
@ -37,8 +38,7 @@ pub fn load_css(style_path: PathBuf) {
|
||||||
Ok(event) if event.kind == EventKind::Modify(ModifyKind::Data(DataChange::Any)) => {
|
Ok(event) if event.kind == EventKind::Modify(ModifyKind::Data(DataChange::Any)) => {
|
||||||
debug!("{event:?}");
|
debug!("{event:?}");
|
||||||
if let Some(path) = event.paths.first() {
|
if let Some(path) = event.paths.first() {
|
||||||
tx.send(path.clone())
|
send!(tx, path.clone());
|
||||||
.expect("Failed to send style changed message");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => error!("Error occurred when watching stylesheet: {:?}", e),
|
Err(e) => error!("Error occurred when watching stylesheet: {:?}", e),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue