mirror of
https://github.com/Zedfrigg/ironbar.git
synced 2025-04-20 03:44:23 +02:00
refactor: update gtk/glib, remove glib channels
This is a major refactor which updates GTK, GLib and GTK Layer Shell to their latest versions. GLib channels, previously used for receiving events on the GLib Main Context thread have been deprecated and a new method for running Futures on the main thread has been added instead. This commit also replaces all the deprecated code with this. As part of the above, a bug was uncovered related to creating the GLib main context inside the Tokio runtime. Spawning of Tokio tasks has been refactored to fix this.
This commit is contained in:
parent
2c2f1c1243
commit
bea442ed96
39 changed files with 426 additions and 465 deletions
134
Cargo.lock
generated
134
Cargo.lock
generated
|
@ -247,21 +247,20 @@ checksum = "2ce4f10ea3abcd6617873bae9f91d1c5332b4a778bd9ce34d0cd517474c1de82"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atk"
|
name = "atk"
|
||||||
version = "0.17.1"
|
version = "0.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6ba16453d10c712284061a05f6510f75abeb92b56ba88dfeb48c74775020cc22"
|
checksum = "b4af014b17dd80e8af9fa689b2d4a211ddba6eb583c1622f35d0cb543f6b17e4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atk-sys",
|
"atk-sys",
|
||||||
"bitflags 1.3.2",
|
|
||||||
"glib",
|
"glib",
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atk-sys"
|
name = "atk-sys"
|
||||||
version = "0.17.0"
|
version = "0.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e3bf0a7ca572fbd5762fd8f8cd65a581e06767bc1234913fe1f43e370cff6e90"
|
checksum = "251e0b7d90e33e0ba930891a505a9a35ece37b2dd37a14f3ffc306c13b980009"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"glib-sys",
|
"glib-sys",
|
||||||
"gobject-sys",
|
"gobject-sys",
|
||||||
|
@ -364,11 +363,11 @@ checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cairo-rs"
|
name = "cairo-rs"
|
||||||
version = "0.17.10"
|
version = "0.18.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ab3603c4028a5e368d09b51c8b624b9a46edcd7c3778284077a6125af73c9f0a"
|
checksum = "f33613627f0dea6a731b0605101fad59ba4f193a52c96c4687728d822605a8a1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 2.4.0",
|
||||||
"cairo-sys-rs",
|
"cairo-sys-rs",
|
||||||
"glib",
|
"glib",
|
||||||
"libc",
|
"libc",
|
||||||
|
@ -378,9 +377,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cairo-sys-rs"
|
name = "cairo-sys-rs"
|
||||||
version = "0.17.10"
|
version = "0.18.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "691d0c66b1fb4881be80a760cb8fe76ea97218312f9dfe2c9cc0f496ca279cb1"
|
checksum = "685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"glib-sys",
|
"glib-sys",
|
||||||
"libc",
|
"libc",
|
||||||
|
@ -1104,11 +1103,10 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gdk"
|
name = "gdk"
|
||||||
version = "0.17.1"
|
version = "0.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "be1df5ea52cccd7e3a0897338b5564968274b52f5fd12601e0afa44f454c74d3"
|
checksum = "f5ba081bdef3b75ebcdbfc953699ed2d7417d6bd853347a42a37d76406a33646"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
|
||||||
"cairo-rs",
|
"cairo-rs",
|
||||||
"gdk-pixbuf",
|
"gdk-pixbuf",
|
||||||
"gdk-sys",
|
"gdk-sys",
|
||||||
|
@ -1120,11 +1118,10 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gdk-pixbuf"
|
name = "gdk-pixbuf"
|
||||||
version = "0.17.10"
|
version = "0.18.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "695d6bc846438c5708b07007537b9274d883373dd30858ca881d7d71b5540717"
|
checksum = "446f32b74d22c33b7b258d4af4ffde53c2bf96ca2e29abdf1a785fe59bd6c82c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
|
||||||
"gdk-pixbuf-sys",
|
"gdk-pixbuf-sys",
|
||||||
"gio",
|
"gio",
|
||||||
"glib",
|
"glib",
|
||||||
|
@ -1134,9 +1131,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gdk-pixbuf-sys"
|
name = "gdk-pixbuf-sys"
|
||||||
version = "0.17.10"
|
version = "0.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9285ec3c113c66d7d0ab5676599176f1f42f4944ca1b581852215bf5694870cb"
|
checksum = "3f9839ea644ed9c97a34d129ad56d38a25e6756f99f3a88e15cd39c20629caf7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gio-sys",
|
"gio-sys",
|
||||||
"glib-sys",
|
"glib-sys",
|
||||||
|
@ -1147,9 +1144,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gdk-sys"
|
name = "gdk-sys"
|
||||||
version = "0.17.0"
|
version = "0.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2152de9d38bc67a17b3fe49dc0823af5bf874df59ea088c5f28f31cf103de703"
|
checksum = "31ff856cb3386dae1703a920f803abafcc580e9b5f711ca62ed1620c25b51ff2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cairo-sys-rs",
|
"cairo-sys-rs",
|
||||||
"gdk-pixbuf-sys",
|
"gdk-pixbuf-sys",
|
||||||
|
@ -1191,11 +1188,10 @@ checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gio"
|
name = "gio"
|
||||||
version = "0.17.10"
|
version = "0.18.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a6973e92937cf98689b6a054a9e56c657ed4ff76de925e36fc331a15f0c5d30a"
|
checksum = "d4fc8f532f87b79cbc51a79748f16a6828fb784be93145a322fa14d06d354c73"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-io",
|
"futures-io",
|
||||||
|
@ -1211,9 +1207,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gio-sys"
|
name = "gio-sys"
|
||||||
version = "0.17.10"
|
version = "0.18.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0ccf87c30a12c469b6d958950f6a9c09f2be20b7773f7e70d20b867fdf2628c3"
|
checksum = "37566df850baf5e4cb0dfb78af2e4b9898d817ed9263d1090a2df958c64737d2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"glib-sys",
|
"glib-sys",
|
||||||
"gobject-sys",
|
"gobject-sys",
|
||||||
|
@ -1224,11 +1220,11 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "glib"
|
name = "glib"
|
||||||
version = "0.17.10"
|
version = "0.18.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d3fad45ba8d4d2cea612b432717e834f48031cd8853c8aaf43b2c79fec8d144b"
|
checksum = "951bbd7fdc5c044ede9f05170f05a3ae9479239c3afdfe2d22d537a3add15c4e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 2.4.0",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-executor",
|
"futures-executor",
|
||||||
|
@ -1247,24 +1243,23 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "glib-macros"
|
name = "glib-macros"
|
||||||
version = "0.17.10"
|
version = "0.18.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "eca5c79337338391f1ab8058d6698125034ce8ef31b72a442437fa6c8580de26"
|
checksum = "72793962ceece3863c2965d7f10c8786323b17c7adea75a515809fa20ab799a5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
|
||||||
"heck 0.4.1",
|
"heck 0.4.1",
|
||||||
"proc-macro-crate",
|
"proc-macro-crate 2.0.1",
|
||||||
"proc-macro-error",
|
"proc-macro-error",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.32",
|
"quote 1.0.32",
|
||||||
"syn 1.0.109",
|
"syn 2.0.28",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "glib-sys"
|
name = "glib-sys"
|
||||||
version = "0.17.10"
|
version = "0.18.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d80aa6ea7bba0baac79222204aa786a6293078c210abe69ef1336911d4bdc4f0"
|
checksum = "063ce2eb6a8d0ea93d2bf8ba1957e78dbab6be1c2220dd3daca57d5a9d869898"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"system-deps",
|
"system-deps",
|
||||||
|
@ -1272,9 +1267,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gobject-sys"
|
name = "gobject-sys"
|
||||||
version = "0.17.10"
|
version = "0.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cd34c3317740a6358ec04572c1bcfd3ac0b5b6529275fae255b237b314bb8062"
|
checksum = "0850127b514d1c4a4654ead6dedadb18198999985908e6ffe4436f53c785ce44"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"glib-sys",
|
"glib-sys",
|
||||||
"libc",
|
"libc",
|
||||||
|
@ -1283,12 +1278,11 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gtk"
|
name = "gtk"
|
||||||
version = "0.17.1"
|
version = "0.18.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b6c4222ab92b08d4d0bab90ddb6185b4e575ceeea8b8cdf00b938d7b6661d966"
|
checksum = "93c4f5e0e20b60e10631a5f06da7fe3dda744b05ad0ea71fee2f47adf865890c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atk",
|
"atk",
|
||||||
"bitflags 1.3.2",
|
|
||||||
"cairo-rs",
|
"cairo-rs",
|
||||||
"field-offset",
|
"field-offset",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
|
@ -1299,16 +1293,15 @@ dependencies = [
|
||||||
"gtk-sys",
|
"gtk-sys",
|
||||||
"gtk3-macros",
|
"gtk3-macros",
|
||||||
"libc",
|
"libc",
|
||||||
"once_cell",
|
|
||||||
"pango",
|
"pango",
|
||||||
"pkg-config",
|
"pkg-config",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gtk-layer-shell"
|
name = "gtk-layer-shell"
|
||||||
version = "0.6.1"
|
version = "0.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "992f5fedb31835424a5280acd162bf348995f617d26969fde8d3dfd389b3ff5f"
|
checksum = "19fd93acba7b8ea8918fc564843a22cd1eeffe234b85a8c7d5732c611a425bb0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.4.0",
|
"bitflags 2.4.0",
|
||||||
"gdk",
|
"gdk",
|
||||||
|
@ -1321,9 +1314,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gtk-layer-shell-sys"
|
name = "gtk-layer-shell-sys"
|
||||||
version = "0.6.0"
|
version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5754bcfaadfc3529116af6ae93559b267d88647f965382153a4b8ea9372be75a"
|
checksum = "90e46fa9aa7c926630b2483cc3d47de26a51173fc2fddb65737e5d813d4be448"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gdk-sys",
|
"gdk-sys",
|
||||||
"glib-sys",
|
"glib-sys",
|
||||||
|
@ -1334,9 +1327,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gtk-sys"
|
name = "gtk-sys"
|
||||||
version = "0.17.0"
|
version = "0.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4d8eb6a4b93e5a7e6980f7348d08c1cd93d31fae07cf97f20678c5ec41de3d7e"
|
checksum = "771437bf1de2c1c0b496c11505bdf748e26066bbe942dfc8f614c9460f6d7722"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atk-sys",
|
"atk-sys",
|
||||||
"cairo-sys-rs",
|
"cairo-sys-rs",
|
||||||
|
@ -1352,16 +1345,15 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gtk3-macros"
|
name = "gtk3-macros"
|
||||||
version = "0.17.1"
|
version = "0.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3efb84d682c9a39c10bd9f24f5a4b9c15cc8c7edc45c19cb2ca2c4fc38b2d95e"
|
checksum = "c6063efb63db582968fb7df72e1ae68aa6360dcfb0a75143f34fc7d616bad75e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"proc-macro-crate 1.3.1",
|
||||||
"proc-macro-crate",
|
|
||||||
"proc-macro-error",
|
"proc-macro-error",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.32",
|
"quote 1.0.32",
|
||||||
"syn 1.0.109",
|
"syn 2.0.28",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2144,11 +2136,10 @@ checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pango"
|
name = "pango"
|
||||||
version = "0.17.10"
|
version = "0.18.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "35be456fc620e61f62dff7ff70fbd54dcbaf0a4b920c0f16de1107c47d921d48"
|
checksum = "7ca27ec1eb0457ab26f3036ea52229edbdb74dee1edd29063f5b9b010e7ebee4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
|
||||||
"gio",
|
"gio",
|
||||||
"glib",
|
"glib",
|
||||||
"libc",
|
"libc",
|
||||||
|
@ -2158,9 +2149,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pango-sys"
|
name = "pango-sys"
|
||||||
version = "0.17.10"
|
version = "0.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3da69f9f3850b0d8990d462f8c709561975e95f689c1cdf0fecdebde78b35195"
|
checksum = "436737e391a843e5933d6d9aa102cb126d501e815b83601365a948a518555dc5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"glib-sys",
|
"glib-sys",
|
||||||
"gobject-sys",
|
"gobject-sys",
|
||||||
|
@ -2314,7 +2305,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919"
|
checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"toml_edit",
|
"toml_edit 0.19.14",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro-crate"
|
||||||
|
version = "2.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "97dc5fea232fc28d2f597b37c4876b348a40e33f3b02cc975c8d006d78d94b1a"
|
||||||
|
dependencies = [
|
||||||
|
"toml_datetime",
|
||||||
|
"toml_edit 0.20.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3205,7 +3206,7 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_spanned",
|
"serde_spanned",
|
||||||
"toml_datetime",
|
"toml_datetime",
|
||||||
"toml_edit",
|
"toml_edit 0.19.14",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3230,6 +3231,17 @@ dependencies = [
|
||||||
"winnow",
|
"winnow",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_edit"
|
||||||
|
version = "0.20.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap 2.1.0",
|
||||||
|
"toml_datetime",
|
||||||
|
"winnow",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tower-service"
|
name = "tower-service"
|
||||||
version = "0.3.2"
|
version = "0.3.2"
|
||||||
|
@ -4029,7 +4041,7 @@ version = "3.14.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "41d1794a946878c0e807f55a397187c11fc7a038ba5d868e7db4f3bd7760bc9d"
|
checksum = "41d1794a946878c0e807f55a397187c11fc7a038ba5d868e7db4f3bd7760bc9d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-crate",
|
"proc-macro-crate 1.3.1",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.32",
|
"quote 1.0.32",
|
||||||
"regex",
|
"regex",
|
||||||
|
@ -4068,7 +4080,7 @@ version = "3.15.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "934d7a7dfc310d6ee06c87ffe88ef4eca7d3e37bb251dece2ef93da8f17d8ecd"
|
checksum = "934d7a7dfc310d6ee06c87ffe88ef4eca7d3e37bb251dece2ef93da8f17d8ecd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-crate",
|
"proc-macro-crate 1.3.1",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.32",
|
"quote 1.0.32",
|
||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
|
|
|
@ -63,9 +63,9 @@ workspaces = ["futures-util"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# core
|
# core
|
||||||
gtk = "0.17.0"
|
gtk = "0.18.1"
|
||||||
gtk-layer-shell = "0.6.0"
|
gtk-layer-shell = "0.8.0"
|
||||||
glib = "0.17.10"
|
glib = "0.18.4"
|
||||||
tokio = { version = "1.35.0", features = [
|
tokio = { version = "1.35.0", features = [
|
||||||
"macros",
|
"macros",
|
||||||
"rt-multi-thread",
|
"rt-multi-thread",
|
||||||
|
|
38
src/bar.rs
38
src/bar.rs
|
@ -5,9 +5,11 @@ use crate::modules::{
|
||||||
use crate::popup::Popup;
|
use crate::popup::Popup;
|
||||||
use crate::{Config, Ironbar};
|
use crate::{Config, Ironbar};
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
|
use glib::Propagation;
|
||||||
use gtk::gdk::Monitor;
|
use gtk::gdk::Monitor;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::{Application, ApplicationWindow, IconTheme, Orientation, Window, WindowType};
|
use gtk::{Application, ApplicationWindow, IconTheme, Orientation, Window, WindowType};
|
||||||
|
use gtk_layer_shell::LayerShell;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
@ -81,7 +83,7 @@ impl Bar {
|
||||||
window.connect_destroy_event(|_, _| {
|
window.connect_destroy_event(|_, _| {
|
||||||
info!("Shutting down");
|
info!("Shutting down");
|
||||||
gtk::main_quit();
|
gtk::main_quit();
|
||||||
Inhibit(false)
|
Propagation::Proceed
|
||||||
});
|
});
|
||||||
|
|
||||||
Bar {
|
Bar {
|
||||||
|
@ -161,42 +163,38 @@ impl Bar {
|
||||||
) {
|
) {
|
||||||
let position = self.position;
|
let position = self.position;
|
||||||
|
|
||||||
gtk_layer_shell::init_for_window(win);
|
win.init_layer_shell();
|
||||||
gtk_layer_shell::set_monitor(win, monitor);
|
win.set_monitor(monitor);
|
||||||
gtk_layer_shell::set_layer(win, gtk_layer_shell::Layer::Top);
|
win.set_layer(gtk_layer_shell::Layer::Top);
|
||||||
gtk_layer_shell::set_namespace(win, env!("CARGO_PKG_NAME"));
|
win.set_namespace(env!("CARGO_PKG_NAME"));
|
||||||
|
|
||||||
if exclusive_zone {
|
if exclusive_zone {
|
||||||
gtk_layer_shell::auto_exclusive_zone_enable(win);
|
win.auto_exclusive_zone_enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
gtk_layer_shell::set_margin(win, gtk_layer_shell::Edge::Top, margin.top);
|
win.set_layer_shell_margin(gtk_layer_shell::Edge::Top, margin.top);
|
||||||
gtk_layer_shell::set_margin(win, gtk_layer_shell::Edge::Bottom, margin.bottom);
|
win.set_layer_shell_margin(gtk_layer_shell::Edge::Bottom, margin.bottom);
|
||||||
gtk_layer_shell::set_margin(win, gtk_layer_shell::Edge::Left, margin.left);
|
win.set_layer_shell_margin(gtk_layer_shell::Edge::Left, margin.left);
|
||||||
gtk_layer_shell::set_margin(win, gtk_layer_shell::Edge::Right, margin.right);
|
win.set_layer_shell_margin(gtk_layer_shell::Edge::Right, margin.right);
|
||||||
|
|
||||||
let bar_orientation = position.get_orientation();
|
let bar_orientation = position.get_orientation();
|
||||||
|
|
||||||
gtk_layer_shell::set_anchor(
|
win.set_anchor(
|
||||||
win,
|
|
||||||
gtk_layer_shell::Edge::Top,
|
gtk_layer_shell::Edge::Top,
|
||||||
position == BarPosition::Top
|
position == BarPosition::Top
|
||||||
|| (bar_orientation == Orientation::Vertical && anchor_to_edges),
|
|| (bar_orientation == Orientation::Vertical && anchor_to_edges),
|
||||||
);
|
);
|
||||||
gtk_layer_shell::set_anchor(
|
win.set_anchor(
|
||||||
win,
|
|
||||||
gtk_layer_shell::Edge::Bottom,
|
gtk_layer_shell::Edge::Bottom,
|
||||||
position == BarPosition::Bottom
|
position == BarPosition::Bottom
|
||||||
|| (bar_orientation == Orientation::Vertical && anchor_to_edges),
|
|| (bar_orientation == Orientation::Vertical && anchor_to_edges),
|
||||||
);
|
);
|
||||||
gtk_layer_shell::set_anchor(
|
win.set_anchor(
|
||||||
win,
|
|
||||||
gtk_layer_shell::Edge::Left,
|
gtk_layer_shell::Edge::Left,
|
||||||
position == BarPosition::Left
|
position == BarPosition::Left
|
||||||
|| (bar_orientation == Orientation::Horizontal && anchor_to_edges),
|
|| (bar_orientation == Orientation::Horizontal && anchor_to_edges),
|
||||||
);
|
);
|
||||||
gtk_layer_shell::set_anchor(
|
win.set_anchor(
|
||||||
win,
|
|
||||||
gtk_layer_shell::Edge::Right,
|
gtk_layer_shell::Edge::Right,
|
||||||
position == BarPosition::Right
|
position == BarPosition::Right
|
||||||
|| (bar_orientation == Orientation::Horizontal && anchor_to_edges),
|
|| (bar_orientation == Orientation::Horizontal && anchor_to_edges),
|
||||||
|
@ -221,7 +219,7 @@ impl Bar {
|
||||||
win.hide();
|
win.hide();
|
||||||
hotspot_window.show();
|
hotspot_window.show();
|
||||||
});
|
});
|
||||||
Inhibit(false)
|
Propagation::Proceed
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,7 +230,7 @@ impl Bar {
|
||||||
hotspot_win.hide();
|
hotspot_win.hide();
|
||||||
win.show();
|
win.show();
|
||||||
|
|
||||||
Inhibit(false)
|
Propagation::Proceed
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,44 +0,0 @@
|
||||||
use crate::send;
|
|
||||||
use tokio::spawn;
|
|
||||||
use tokio::sync::mpsc;
|
|
||||||
|
|
||||||
/// MPSC async -> GTK sync channel.
|
|
||||||
/// The sender uses `tokio::sync::mpsc`
|
|
||||||
/// while the receiver uses `glib::MainContext::channel`.
|
|
||||||
///
|
|
||||||
/// This makes it possible to send events asynchronously
|
|
||||||
/// and receive them on the main thread,
|
|
||||||
/// allowing UI updates to be handled on the receiving end.
|
|
||||||
pub struct BridgeChannel<T> {
|
|
||||||
async_tx: mpsc::Sender<T>,
|
|
||||||
sync_rx: glib::Receiver<T>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Send + 'static> BridgeChannel<T> {
|
|
||||||
/// Creates a new channel
|
|
||||||
pub fn new() -> Self {
|
|
||||||
let (async_tx, mut async_rx) = mpsc::channel(32);
|
|
||||||
let (sync_tx, sync_rx) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
|
|
||||||
|
|
||||||
spawn(async move {
|
|
||||||
while let Some(val) = async_rx.recv().await {
|
|
||||||
send!(sync_tx, val);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Self { async_tx, sync_rx }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets a clone of the sender.
|
|
||||||
pub fn create_sender(&self) -> mpsc::Sender<T> {
|
|
||||||
self.async_tx.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Attaches a callback to the receiver.
|
|
||||||
pub fn recv<F>(self, f: F) -> glib::SourceId
|
|
||||||
where
|
|
||||||
F: FnMut(T) -> glib::Continue + 'static,
|
|
||||||
{
|
|
||||||
self.sync_rx.attach(None, f)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,10 +1,9 @@
|
||||||
use super::wayland::{self, ClipboardItem};
|
use super::wayland::{self, ClipboardItem};
|
||||||
use crate::{arc_mut, lock, try_send};
|
use crate::{arc_mut, lock, spawn, try_send};
|
||||||
use indexmap::map::Iter;
|
use indexmap::map::Iter;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use tokio::spawn;
|
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
use tracing::{debug, trace};
|
use tracing::{debug, trace};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use super::{Visibility, Workspace, WorkspaceClient, WorkspaceUpdate};
|
use super::{Visibility, Workspace, WorkspaceClient, WorkspaceUpdate};
|
||||||
use crate::{arc_mut, lock, send};
|
use crate::{arc_mut, lock, send, spawn_blocking};
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
use hyprland::data::{Workspace as HWorkspace, Workspaces};
|
use hyprland::data::{Workspace as HWorkspace, Workspaces};
|
||||||
use hyprland::dispatch::{Dispatch, DispatchType, WorkspaceIdentifierWithSpecial};
|
use hyprland::dispatch::{Dispatch, DispatchType, WorkspaceIdentifierWithSpecial};
|
||||||
|
@ -8,7 +8,6 @@ use hyprland::prelude::*;
|
||||||
use hyprland::shared::{HyprDataVec, WorkspaceType};
|
use hyprland::shared::{HyprDataVec, WorkspaceType};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use tokio::sync::broadcast::{channel, Receiver, Sender};
|
use tokio::sync::broadcast::{channel, Receiver, Sender};
|
||||||
use tokio::task::spawn_blocking;
|
|
||||||
use tracing::{debug, error, info};
|
use tracing::{debug, error, info};
|
||||||
|
|
||||||
pub struct EventClient {
|
pub struct EventClient {
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
use super::{Visibility, Workspace, WorkspaceClient, WorkspaceUpdate};
|
use super::{Visibility, Workspace, WorkspaceClient, WorkspaceUpdate};
|
||||||
use crate::{await_sync, send};
|
use crate::{await_sync, send, spawn};
|
||||||
use async_once::AsyncOnce;
|
use async_once::AsyncOnce;
|
||||||
use color_eyre::Report;
|
use color_eyre::Report;
|
||||||
use futures_util::StreamExt;
|
use futures_util::StreamExt;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use swayipc_async::{Connection, Event, EventType, Node, WorkspaceChange, WorkspaceEvent};
|
use swayipc_async::{Connection, Event, EventType, Node, WorkspaceChange, WorkspaceEvent};
|
||||||
use tokio::spawn;
|
|
||||||
use tokio::sync::broadcast::{channel, Receiver, Sender};
|
use tokio::sync::broadcast::{channel, Receiver, Sender};
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
use tracing::{info, trace};
|
use tracing::{info, trace};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use super::{
|
use super::{
|
||||||
MusicClient, PlayerState, PlayerUpdate, ProgressTick, Status, Track, TICK_INTERVAL_MS,
|
MusicClient, PlayerState, PlayerUpdate, ProgressTick, Status, Track, TICK_INTERVAL_MS,
|
||||||
};
|
};
|
||||||
use crate::{await_sync, send};
|
use crate::{await_sync, send, spawn};
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use mpd_client::client::{Connection, ConnectionEvent, Subsystem};
|
use mpd_client::client::{Connection, ConnectionEvent, Subsystem};
|
||||||
|
@ -17,7 +17,6 @@ use std::path::{Path, PathBuf};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tokio::net::{TcpStream, UnixStream};
|
use tokio::net::{TcpStream, UnixStream};
|
||||||
use tokio::spawn;
|
|
||||||
use tokio::sync::broadcast;
|
use tokio::sync::broadcast;
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
use tokio::time::sleep;
|
use tokio::time::sleep;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use super::{MusicClient, PlayerState, PlayerUpdate, Status, Track, TICK_INTERVAL_MS};
|
use super::{MusicClient, PlayerState, PlayerUpdate, Status, Track, TICK_INTERVAL_MS};
|
||||||
use crate::clients::music::ProgressTick;
|
use crate::clients::music::ProgressTick;
|
||||||
use crate::{arc_mut, lock, send};
|
use crate::{arc_mut, lock, send, spawn_blocking};
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use mpris::{DBusError, Event, Metadata, PlaybackStatus, Player, PlayerFinder};
|
use mpris::{DBusError, Event, Metadata, PlaybackStatus, Player, PlayerFinder};
|
||||||
|
@ -10,7 +10,6 @@ use std::thread::sleep;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::{cmp, string};
|
use std::{cmp, string};
|
||||||
use tokio::sync::broadcast;
|
use tokio::sync::broadcast;
|
||||||
use tokio::task::spawn_blocking;
|
|
||||||
use tracing::{debug, error, trace};
|
use tracing::{debug, error, trace};
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{arc_mut, lock, send, Ironbar};
|
use crate::{arc_mut, lock, send, spawn, Ironbar};
|
||||||
use async_once::AsyncOnce;
|
use async_once::AsyncOnce;
|
||||||
use color_eyre::Report;
|
use color_eyre::Report;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
@ -8,7 +8,6 @@ use system_tray::message::menu::TrayMenu;
|
||||||
use system_tray::message::tray::StatusNotifierItem;
|
use system_tray::message::tray::StatusNotifierItem;
|
||||||
use system_tray::message::{NotifierItemCommand, NotifierItemMessage};
|
use system_tray::message::{NotifierItemCommand, NotifierItemMessage};
|
||||||
use system_tray::StatusNotifierWatcher;
|
use system_tray::StatusNotifierWatcher;
|
||||||
use tokio::spawn;
|
|
||||||
use tokio::sync::{broadcast, mpsc};
|
use tokio::sync::{broadcast, mpsc};
|
||||||
use tracing::{debug, error, trace};
|
use tracing::{debug, error, trace};
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ use super::wlr_foreign_toplevel::manager::ToplevelManagerState;
|
||||||
use super::wlr_foreign_toplevel::ToplevelEvent;
|
use super::wlr_foreign_toplevel::ToplevelEvent;
|
||||||
use super::Environment;
|
use super::Environment;
|
||||||
use crate::error::ERR_CHANNEL_RECV;
|
use crate::error::ERR_CHANNEL_RECV;
|
||||||
use crate::send;
|
use crate::{send, spawn_blocking};
|
||||||
use cfg_if::cfg_if;
|
use cfg_if::cfg_if;
|
||||||
use color_eyre::Report;
|
use color_eyre::Report;
|
||||||
use smithay_client_toolkit::output::{OutputInfo, OutputState};
|
use smithay_client_toolkit::output::{OutputInfo, OutputState};
|
||||||
|
@ -15,7 +15,6 @@ use smithay_client_toolkit::seat::SeatState;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
use tokio::sync::broadcast;
|
use tokio::sync::broadcast;
|
||||||
use tokio::task::spawn_blocking;
|
|
||||||
use tracing::{debug, error, trace};
|
use tracing::{debug, error, trace};
|
||||||
use wayland_client::globals::registry_queue_init;
|
use wayland_client::globals::registry_queue_init;
|
||||||
use wayland_client::protocol::wl_seat::WlSeat;
|
use wayland_client::protocol::wl_seat::WlSeat;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::dynamic_value::{dynamic_string, DynamicBool};
|
use crate::dynamic_value::{dynamic_string, DynamicBool};
|
||||||
use crate::script::{Script, ScriptInput};
|
use crate::script::{Script, ScriptInput};
|
||||||
|
use glib::Propagation;
|
||||||
use gtk::gdk::ScrollDirection;
|
use gtk::gdk::ScrollDirection;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::{EventBox, Orientation, Revealer, RevealerTransitionType};
|
use gtk::{EventBox, Orientation, Revealer, RevealerTransitionType};
|
||||||
|
@ -75,7 +76,7 @@ impl CommonConfig {
|
||||||
script.run_as_oneshot(None);
|
script.run_as_oneshot(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
Inhibit(false)
|
Propagation::Proceed
|
||||||
});
|
});
|
||||||
|
|
||||||
let scroll_up_script = self.on_scroll_up.map(Script::new_polling);
|
let scroll_up_script = self.on_scroll_up.map(Script::new_polling);
|
||||||
|
@ -93,7 +94,7 @@ impl CommonConfig {
|
||||||
script.run_as_oneshot(None);
|
script.run_as_oneshot(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
Inhibit(false)
|
Propagation::Proceed
|
||||||
});
|
});
|
||||||
|
|
||||||
macro_rules! install_oneshot {
|
macro_rules! install_oneshot {
|
||||||
|
@ -101,7 +102,7 @@ impl CommonConfig {
|
||||||
$option.map(Script::new_polling).map(|script| {
|
$option.map(Script::new_polling).map(|script| {
|
||||||
container.$method(move |_, _| {
|
container.$method(move |_, _| {
|
||||||
script.run_as_oneshot(None);
|
script.run_as_oneshot(None);
|
||||||
Inhibit(false)
|
Propagation::Proceed
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
@ -114,7 +115,6 @@ impl CommonConfig {
|
||||||
let container = container.clone();
|
let container = container.clone();
|
||||||
dynamic_string(&tooltip, move |string| {
|
dynamic_string(&tooltip, move |string| {
|
||||||
container.set_tooltip_text(Some(&string));
|
container.set_tooltip_text(Some(&string));
|
||||||
Continue(true)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,7 +136,6 @@ impl CommonConfig {
|
||||||
container.show_all();
|
container.show_all();
|
||||||
}
|
}
|
||||||
revealer.set_reveal_child(success);
|
revealer.set_reveal_child(success);
|
||||||
Continue(true)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
use crate::script::Script;
|
use crate::script::Script;
|
||||||
use crate::send;
|
use crate::{glib_recv_mpsc, spawn, try_send};
|
||||||
#[cfg(feature = "ipc")]
|
#[cfg(feature = "ipc")]
|
||||||
use crate::Ironbar;
|
use crate::{send_async, Ironbar};
|
||||||
use cfg_if::cfg_if;
|
use cfg_if::cfg_if;
|
||||||
use glib::Continue;
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use tokio::spawn;
|
use tokio::sync::mpsc;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
|
@ -18,9 +17,9 @@ pub enum DynamicBool {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DynamicBool {
|
impl DynamicBool {
|
||||||
pub fn subscribe<F>(self, f: F)
|
pub fn subscribe<F>(self, mut f: F)
|
||||||
where
|
where
|
||||||
F: FnMut(bool) -> Continue + 'static,
|
F: FnMut(bool) + 'static,
|
||||||
{
|
{
|
||||||
let value = match self {
|
let value = match self {
|
||||||
Self::Unknown(input) => {
|
Self::Unknown(input) => {
|
||||||
|
@ -40,16 +39,16 @@ impl DynamicBool {
|
||||||
_ => self,
|
_ => self,
|
||||||
};
|
};
|
||||||
|
|
||||||
let (tx, rx) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
|
let (tx, mut rx) = mpsc::channel(32);
|
||||||
|
|
||||||
rx.attach(None, f);
|
glib_recv_mpsc!(rx, val => f(val));
|
||||||
|
|
||||||
spawn(async move {
|
spawn(async move {
|
||||||
match value {
|
match value {
|
||||||
DynamicBool::Script(script) => {
|
DynamicBool::Script(script) => {
|
||||||
script
|
script
|
||||||
.run(None, |_, success| {
|
.run(None, |_, success| {
|
||||||
send!(tx, success);
|
try_send!(tx, success);
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
@ -62,7 +61,7 @@ impl DynamicBool {
|
||||||
|
|
||||||
while let Ok(value) = rx.recv().await {
|
while let Ok(value) = rx.recv().await {
|
||||||
let has_value = value.map(|s| is_truthy(&s)).unwrap_or_default();
|
let has_value = value.map(|s| is_truthy(&s)).unwrap_or_default();
|
||||||
send!(tx, has_value);
|
send_async!(tx, has_value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DynamicBool::Unknown(_) => unreachable!(),
|
DynamicBool::Unknown(_) => unreachable!(),
|
||||||
|
@ -71,7 +70,10 @@ impl DynamicBool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if a string ironvar is 'truthy'
|
/// Check if a string ironvar is 'truthy',
|
||||||
|
/// i.e should be evaluated to true.
|
||||||
|
///
|
||||||
|
/// This loosely follows the common JavaScript cases.
|
||||||
#[cfg(feature = "ipc")]
|
#[cfg(feature = "ipc")]
|
||||||
fn is_truthy(string: &str) -> bool {
|
fn is_truthy(string: &str) -> bool {
|
||||||
!(string.is_empty() || string == "0" || string == "false")
|
!(string.is_empty() || string == "0" || string == "false")
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
use crate::script::{OutputStream, Script};
|
use crate::script::{OutputStream, Script};
|
||||||
#[cfg(feature = "ipc")]
|
#[cfg(feature = "ipc")]
|
||||||
use crate::Ironbar;
|
use crate::Ironbar;
|
||||||
use crate::{arc_mut, lock, send};
|
use crate::{arc_mut, glib_recv_mpsc, lock, spawn, try_send};
|
||||||
use gtk::prelude::*;
|
use tokio::sync::mpsc;
|
||||||
use tokio::spawn;
|
|
||||||
|
|
||||||
/// A segment of a dynamic string,
|
/// A segment of a dynamic string,
|
||||||
/// containing either a static string
|
/// containing either a static string
|
||||||
|
@ -24,17 +23,16 @@ enum DynamicStringSegment {
|
||||||
/// ```rs
|
/// ```rs
|
||||||
/// dynamic_string(&text, move |string| {
|
/// dynamic_string(&text, move |string| {
|
||||||
/// label.set_markup(&string);
|
/// label.set_markup(&string);
|
||||||
/// Continue(true)
|
|
||||||
/// });
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
pub fn dynamic_string<F>(input: &str, f: F)
|
pub fn dynamic_string<F>(input: &str, mut f: F)
|
||||||
where
|
where
|
||||||
F: FnMut(String) -> Continue + 'static,
|
F: FnMut(String) + 'static,
|
||||||
{
|
{
|
||||||
let tokens = parse_input(input);
|
let tokens = parse_input(input);
|
||||||
|
|
||||||
let label_parts = arc_mut!(vec![]);
|
let label_parts = arc_mut!(vec![]);
|
||||||
let (tx, rx) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
|
let (tx, mut rx) = mpsc::channel(32);
|
||||||
|
|
||||||
for (i, segment) in tokens.into_iter().enumerate() {
|
for (i, segment) in tokens.into_iter().enumerate() {
|
||||||
match segment {
|
match segment {
|
||||||
|
@ -57,7 +55,7 @@ where
|
||||||
let _: String = std::mem::replace(&mut label_parts[i], out);
|
let _: String = std::mem::replace(&mut label_parts[i], out);
|
||||||
|
|
||||||
let string = label_parts.join("");
|
let string = label_parts.join("");
|
||||||
send!(tx, string);
|
try_send!(tx, string);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
|
@ -82,7 +80,7 @@ where
|
||||||
let _: String = std::mem::replace(&mut label_parts[i], value);
|
let _: String = std::mem::replace(&mut label_parts[i], value);
|
||||||
|
|
||||||
let string = label_parts.join("");
|
let string = label_parts.join("");
|
||||||
send!(tx, string);
|
try_send!(tx, string);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -90,12 +88,12 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rx.attach(None, f);
|
glib_recv_mpsc!(rx , val => f(val));
|
||||||
|
|
||||||
// initialize
|
// initialize
|
||||||
{
|
{
|
||||||
let label_parts = lock!(label_parts).join("");
|
let label_parts = lock!(label_parts).join("");
|
||||||
send!(tx, label_parts);
|
try_send!(tx, label_parts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
use crate::desktop_file::get_desktop_icon_name;
|
use crate::desktop_file::get_desktop_icon_name;
|
||||||
|
#[cfg(feature = "http")]
|
||||||
|
use crate::{glib_recv_mpsc, send_async, spawn};
|
||||||
use cfg_if::cfg_if;
|
use cfg_if::cfg_if;
|
||||||
use color_eyre::{Help, Report, Result};
|
use color_eyre::{Help, Report, Result};
|
||||||
use gtk::cairo::Surface;
|
use gtk::cairo::Surface;
|
||||||
|
@ -7,13 +9,13 @@ use gtk::gdk_pixbuf::Pixbuf;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::{IconLookupFlags, IconTheme};
|
use gtk::{IconLookupFlags, IconTheme};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
#[cfg(feature = "http")]
|
||||||
|
use tokio::sync::mpsc;
|
||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
|
|
||||||
cfg_if!(
|
cfg_if!(
|
||||||
if #[cfg(feature = "http")] {
|
if #[cfg(feature = "http")] {
|
||||||
use crate::send;
|
|
||||||
use gtk::gio::{Cancellable, MemoryInputStream};
|
use gtk::gio::{Cancellable, MemoryInputStream};
|
||||||
use tokio::spawn;
|
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -143,18 +145,18 @@ impl<'a> ImageProvider<'a> {
|
||||||
#[cfg(feature = "http")]
|
#[cfg(feature = "http")]
|
||||||
if let ImageLocation::Remote(url) = &self.location {
|
if let ImageLocation::Remote(url) = &self.location {
|
||||||
let url = url.clone();
|
let url = url.clone();
|
||||||
let (tx, rx) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
|
let (tx, mut rx) = mpsc::channel(64);
|
||||||
|
|
||||||
spawn(async move {
|
spawn(async move {
|
||||||
let bytes = Self::get_bytes_from_http(url).await;
|
let bytes = Self::get_bytes_from_http(url).await;
|
||||||
if let Ok(bytes) = bytes {
|
if let Ok(bytes) = bytes {
|
||||||
send!(tx, bytes);
|
send_async!(tx, bytes);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
{
|
{
|
||||||
let size = self.size;
|
let size = self.size;
|
||||||
rx.attach(None, move |bytes| {
|
glib_recv_mpsc!(rx, bytes => {
|
||||||
let stream = MemoryInputStream::from_bytes(&bytes);
|
let stream = MemoryInputStream::from_bytes(&bytes);
|
||||||
|
|
||||||
let scale = image.scale_factor();
|
let scale = image.scale_factor();
|
||||||
|
@ -175,8 +177,6 @@ impl<'a> ImageProvider<'a> {
|
||||||
Err(err) => error!("{err:?}"),
|
Err(err) => error!("{err:?}"),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
Continue(false)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -3,20 +3,17 @@ use std::path::Path;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use color_eyre::{Report, Result};
|
use color_eyre::{Report, Result};
|
||||||
use glib::Continue;
|
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::Application;
|
use gtk::Application;
|
||||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||||
use tokio::net::{UnixListener, UnixStream};
|
use tokio::net::{UnixListener, UnixStream};
|
||||||
use tokio::spawn;
|
|
||||||
use tokio::sync::mpsc::{self, Receiver, Sender};
|
use tokio::sync::mpsc::{self, Receiver, Sender};
|
||||||
use tracing::{debug, error, info, warn};
|
use tracing::{debug, error, info, warn};
|
||||||
|
|
||||||
use crate::bridge_channel::BridgeChannel;
|
|
||||||
use crate::ipc::{Command, Response};
|
use crate::ipc::{Command, Response};
|
||||||
use crate::modules::PopupButton;
|
use crate::modules::PopupButton;
|
||||||
use crate::style::load_css;
|
use crate::style::load_css;
|
||||||
use crate::{read_lock, send_async, try_send, write_lock, Ironbar};
|
use crate::{glib_recv_mpsc, read_lock, send_async, spawn, try_send, write_lock, Ironbar};
|
||||||
|
|
||||||
use super::Ipc;
|
use super::Ipc;
|
||||||
|
|
||||||
|
@ -25,8 +22,7 @@ impl Ipc {
|
||||||
///
|
///
|
||||||
/// Once started, the server will begin accepting connections.
|
/// Once started, the server will begin accepting connections.
|
||||||
pub fn start(&self, application: &Application, ironbar: Rc<Ironbar>) {
|
pub fn start(&self, application: &Application, ironbar: Rc<Ironbar>) {
|
||||||
let bridge = BridgeChannel::<Command>::new();
|
let (cmd_tx, mut cmd_rx) = mpsc::channel(32);
|
||||||
let cmd_tx = bridge.create_sender();
|
|
||||||
let (res_tx, mut res_rx) = mpsc::channel(32);
|
let (res_tx, mut res_rx) = mpsc::channel(32);
|
||||||
|
|
||||||
let path = self.path.clone();
|
let path = self.path.clone();
|
||||||
|
@ -68,10 +64,9 @@ impl Ipc {
|
||||||
});
|
});
|
||||||
|
|
||||||
let application = application.clone();
|
let application = application.clone();
|
||||||
bridge.recv(move |command| {
|
glib_recv_mpsc!(cmd_rx, command => {
|
||||||
let res = Self::handle_command(command, &application, ironbar.clone());
|
let res = Self::handle_command(command, &application, &ironbar);
|
||||||
try_send!(res_tx, res);
|
try_send!(res_tx, res);
|
||||||
Continue(true)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,11 +104,7 @@ impl Ipc {
|
||||||
/// Takes an input command, runs it and returns with the appropriate response.
|
/// Takes an input command, runs it and returns with the appropriate response.
|
||||||
///
|
///
|
||||||
/// This runs on the main thread, allowing commands to interact with GTK.
|
/// This runs on the main thread, allowing commands to interact with GTK.
|
||||||
fn handle_command(
|
fn handle_command(command: Command, application: &Application, ironbar: &Ironbar) -> Response {
|
||||||
command: Command,
|
|
||||||
application: &Application,
|
|
||||||
ironbar: Rc<Ironbar>,
|
|
||||||
) -> Response {
|
|
||||||
match command {
|
match command {
|
||||||
Command::Inspect => {
|
Command::Inspect => {
|
||||||
gtk::Window::set_interactive_debugging(true);
|
gtk::Window::set_interactive_debugging(true);
|
||||||
|
|
|
@ -43,6 +43,55 @@ macro_rules! try_send {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Spawns a `GLib` future on the local thread, and calls `rx.recv()`
|
||||||
|
/// in a loop.
|
||||||
|
///
|
||||||
|
/// This allows use of `GObjects` and futures in the same context.
|
||||||
|
///
|
||||||
|
/// For use with receivers which return a `Result`.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```rs
|
||||||
|
/// let (tx, mut rx) = broadcast::channel(32);
|
||||||
|
/// glib_recv(rx, msg => println!("{msg}"));
|
||||||
|
/// ```
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! glib_recv {
|
||||||
|
($rx:expr, $val:ident => $expr:expr) => {
|
||||||
|
glib::spawn_future_local(async move {
|
||||||
|
while let Ok($val) = $rx.recv().await {
|
||||||
|
$expr
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Spawns a `GLib` future on the local thread, and calls `rx.recv()`
|
||||||
|
/// in a loop.
|
||||||
|
///
|
||||||
|
/// This allows use of `GObjects` and futures in the same context.
|
||||||
|
///
|
||||||
|
/// For use with receivers which return an `Option`,
|
||||||
|
/// such as Tokio's `mpsc` channel.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```rs
|
||||||
|
/// let (tx, mut rx) = broadcast::channel(32);
|
||||||
|
/// glib_recv_mpsc(rx, msg => println!("{msg}"));
|
||||||
|
/// ```
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! glib_recv_mpsc {
|
||||||
|
($rx:expr, $val:ident => $expr:expr) => {
|
||||||
|
glib::spawn_future_local(async move {
|
||||||
|
while let Some($val) = $rx.recv().await {
|
||||||
|
$expr
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/// Locks a `Mutex`.
|
/// Locks a `Mutex`.
|
||||||
/// Panics if the `Mutex` cannot be locked.
|
/// Panics if the `Mutex` cannot be locked.
|
||||||
///
|
///
|
||||||
|
|
64
src/main.rs
64
src/main.rs
|
@ -7,9 +7,9 @@ use std::path::PathBuf;
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||||
use std::sync::mpsc;
|
|
||||||
#[cfg(feature = "ipc")]
|
#[cfg(feature = "ipc")]
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::RwLock;
|
||||||
|
use std::sync::{mpsc, Arc};
|
||||||
|
|
||||||
use cfg_if::cfg_if;
|
use cfg_if::cfg_if;
|
||||||
#[cfg(feature = "cli")]
|
#[cfg(feature = "cli")]
|
||||||
|
@ -21,8 +21,8 @@ use glib::PropertySet;
|
||||||
use gtk::gdk::Display;
|
use gtk::gdk::Display;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::Application;
|
use gtk::Application;
|
||||||
use tokio::runtime::Handle;
|
use tokio::runtime::{Handle, Runtime};
|
||||||
use tokio::task::{block_in_place, spawn_blocking};
|
use tokio::task::{block_in_place, JoinHandle};
|
||||||
use tracing::{debug, error, info, warn};
|
use tracing::{debug, error, info, warn};
|
||||||
use universal_config::ConfigLoader;
|
use universal_config::ConfigLoader;
|
||||||
|
|
||||||
|
@ -36,7 +36,6 @@ use crate::ironvar::VariableManager;
|
||||||
use crate::style::load_css;
|
use crate::style::load_css;
|
||||||
|
|
||||||
mod bar;
|
mod bar;
|
||||||
mod bridge_channel;
|
|
||||||
#[cfg(feature = "cli")]
|
#[cfg(feature = "cli")]
|
||||||
mod cli;
|
mod cli;
|
||||||
mod clients;
|
mod clients;
|
||||||
|
@ -60,13 +59,12 @@ mod style;
|
||||||
const GTK_APP_ID: &str = "dev.jstanger.ironbar";
|
const GTK_APP_ID: &str = "dev.jstanger.ironbar";
|
||||||
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
|
|
||||||
#[tokio::main]
|
fn main() {
|
||||||
async fn main() {
|
|
||||||
let _guard = logging::install_logging();
|
let _guard = logging::install_logging();
|
||||||
|
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(feature = "cli")] {
|
if #[cfg(feature = "cli")] {
|
||||||
run_with_args().await;
|
run_with_args();
|
||||||
} else {
|
} else {
|
||||||
start_ironbar();
|
start_ironbar();
|
||||||
}
|
}
|
||||||
|
@ -74,16 +72,19 @@ async fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "cli")]
|
#[cfg(feature = "cli")]
|
||||||
async fn run_with_args() {
|
fn run_with_args() {
|
||||||
let args = cli::Args::parse();
|
let args = cli::Args::parse();
|
||||||
|
|
||||||
match args.command {
|
match args.command {
|
||||||
Some(command) => {
|
Some(command) => {
|
||||||
let ipc = ipc::Ipc::new();
|
let rt = create_runtime();
|
||||||
match ipc.send(command).await {
|
rt.block_on(async move {
|
||||||
Ok(res) => cli::handle_response(res),
|
let ipc = ipc::Ipc::new();
|
||||||
Err(err) => error!("{err:?}"),
|
match ipc.send(command).await {
|
||||||
};
|
Ok(res) => cli::handle_response(res),
|
||||||
|
Err(err) => error!("{err:?}"),
|
||||||
|
};
|
||||||
|
});
|
||||||
}
|
}
|
||||||
None => start_ironbar(),
|
None => start_ironbar(),
|
||||||
}
|
}
|
||||||
|
@ -91,6 +92,10 @@ async fn run_with_args() {
|
||||||
|
|
||||||
static COUNTER: AtomicUsize = AtomicUsize::new(1);
|
static COUNTER: AtomicUsize = AtomicUsize::new(1);
|
||||||
|
|
||||||
|
lazy_static::lazy_static! {
|
||||||
|
static ref RUNTIME: Arc<Runtime> = Arc::new(create_runtime());
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "ipc")]
|
#[cfg(feature = "ipc")]
|
||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
static ref VARIABLE_MANAGER: Arc<RwLock<VariableManager>> = arc_rw!(VariableManager::new());
|
static ref VARIABLE_MANAGER: Arc<RwLock<VariableManager>> = arc_rw!(VariableManager::new());
|
||||||
|
@ -184,6 +189,12 @@ impl Ironbar {
|
||||||
app.run_with_args(&Vec::<&str>::new());
|
app.run_with_args(&Vec::<&str>::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the current Tokio runtime.
|
||||||
|
#[must_use]
|
||||||
|
pub fn runtime() -> Arc<Runtime> {
|
||||||
|
RUNTIME.clone()
|
||||||
|
}
|
||||||
|
|
||||||
/// Gets a `usize` ID value that is unique to the entire Ironbar instance.
|
/// Gets a `usize` ID value that is unique to the entire Ironbar instance.
|
||||||
/// This is just a static `AtomicUsize` that increments every time this function is called.
|
/// This is just a static `AtomicUsize` that increments every time this function is called.
|
||||||
pub fn unique_id() -> usize {
|
pub fn unique_id() -> usize {
|
||||||
|
@ -323,6 +334,31 @@ fn create_bars(app: &Application, display: &Display, config: &Config) -> Result<
|
||||||
Ok(all_bars)
|
Ok(all_bars)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_runtime() -> Runtime {
|
||||||
|
tokio::runtime::Builder::new_multi_thread()
|
||||||
|
.enable_all()
|
||||||
|
.build()
|
||||||
|
.expect("tokio to create a valid runtime")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Calls `spawn` on the Tokio runtime.
|
||||||
|
pub fn spawn<F>(f: F) -> JoinHandle<F::Output>
|
||||||
|
where
|
||||||
|
F: Future + Send + 'static,
|
||||||
|
F::Output: Send + 'static,
|
||||||
|
{
|
||||||
|
Ironbar::runtime().spawn(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Calls `spawn_blocking` on the Tokio runtime.
|
||||||
|
pub fn spawn_blocking<F, R>(f: F) -> JoinHandle<R>
|
||||||
|
where
|
||||||
|
F: FnOnce() -> R + Send + 'static,
|
||||||
|
R: Send + 'static,
|
||||||
|
{
|
||||||
|
Ironbar::runtime().spawn_blocking(f)
|
||||||
|
}
|
||||||
|
|
||||||
/// Blocks on a `Future` until it resolves.
|
/// Blocks on a `Future` until it resolves.
|
||||||
///
|
///
|
||||||
/// This is not an `async` operation
|
/// This is not an `async` operation
|
||||||
|
|
|
@ -5,7 +5,8 @@ use crate::image::new_icon_button;
|
||||||
use crate::modules::{
|
use crate::modules::{
|
||||||
Module, ModuleInfo, ModuleParts, ModulePopup, ModuleUpdateEvent, PopupButton, WidgetContext,
|
Module, ModuleInfo, ModuleParts, ModulePopup, ModuleUpdateEvent, PopupButton, WidgetContext,
|
||||||
};
|
};
|
||||||
use crate::try_send;
|
use crate::{glib_recv, spawn, try_send};
|
||||||
|
use glib::Propagation;
|
||||||
use gtk::gdk_pixbuf::Pixbuf;
|
use gtk::gdk_pixbuf::Pixbuf;
|
||||||
use gtk::gio::{Cancellable, MemoryInputStream};
|
use gtk::gio::{Cancellable, MemoryInputStream};
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
|
@ -13,8 +14,7 @@ use gtk::{Button, EventBox, Image, Label, Orientation, RadioButton, Widget};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::spawn;
|
use tokio::sync::{broadcast, mpsc};
|
||||||
use tokio::sync::mpsc::{Receiver, Sender};
|
|
||||||
use tracing::{debug, error};
|
use tracing::{debug, error};
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
|
@ -72,8 +72,8 @@ impl Module<Button> for ClipboardModule {
|
||||||
fn spawn_controller(
|
fn spawn_controller(
|
||||||
&self,
|
&self,
|
||||||
_info: &ModuleInfo,
|
_info: &ModuleInfo,
|
||||||
tx: Sender<ModuleUpdateEvent<Self::SendMessage>>,
|
tx: mpsc::Sender<ModuleUpdateEvent<Self::SendMessage>>,
|
||||||
mut rx: Receiver<Self::ReceiveMessage>,
|
mut rx: mpsc::Receiver<Self::ReceiveMessage>,
|
||||||
) -> color_eyre::Result<()> {
|
) -> color_eyre::Result<()> {
|
||||||
let max_items = self.max_items;
|
let max_items = self.max_items;
|
||||||
|
|
||||||
|
@ -129,19 +129,14 @@ impl Module<Button> for ClipboardModule {
|
||||||
let button = new_icon_button(&self.icon, info.icon_theme, self.icon_size);
|
let button = new_icon_button(&self.icon, info.icon_theme, self.icon_size);
|
||||||
button.style_context().add_class("btn");
|
button.style_context().add_class("btn");
|
||||||
|
|
||||||
|
let tx = context.tx.clone();
|
||||||
button.connect_clicked(move |button| {
|
button.connect_clicked(move |button| {
|
||||||
try_send!(
|
try_send!(tx, ModuleUpdateEvent::TogglePopup(button.popup_id()));
|
||||||
context.tx,
|
|
||||||
ModuleUpdateEvent::TogglePopup(button.popup_id())
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// we need to bind to the receiver as the channel does not open
|
let rx = context.subscribe();
|
||||||
// until the popup is first opened.
|
|
||||||
context.widget_rx.attach(None, |_| Continue(true));
|
|
||||||
|
|
||||||
let popup = self
|
let popup = self
|
||||||
.into_popup(context.controller_tx, context.popup_rx, info)
|
.into_popup(context.controller_tx, rx, info)
|
||||||
.into_popup_parts(vec![&button]);
|
.into_popup_parts(vec![&button]);
|
||||||
|
|
||||||
Ok(ModuleParts::new(button, popup))
|
Ok(ModuleParts::new(button, popup))
|
||||||
|
@ -149,8 +144,8 @@ impl Module<Button> for ClipboardModule {
|
||||||
|
|
||||||
fn into_popup(
|
fn into_popup(
|
||||||
self,
|
self,
|
||||||
tx: Sender<Self::ReceiveMessage>,
|
tx: mpsc::Sender<Self::ReceiveMessage>,
|
||||||
rx: glib::Receiver<Self::SendMessage>,
|
mut rx: broadcast::Receiver<Self::SendMessage>,
|
||||||
_info: &ModuleInfo,
|
_info: &ModuleInfo,
|
||||||
) -> Option<gtk::Box>
|
) -> Option<gtk::Box>
|
||||||
where
|
where
|
||||||
|
@ -168,7 +163,7 @@ impl Module<Button> for ClipboardModule {
|
||||||
|
|
||||||
{
|
{
|
||||||
let hidden_option = hidden_option.clone();
|
let hidden_option = hidden_option.clone();
|
||||||
rx.attach(None, move |event| {
|
glib_recv!(rx, event => {
|
||||||
match event {
|
match event {
|
||||||
ControllerEvent::Add(id, item) => {
|
ControllerEvent::Add(id, item) => {
|
||||||
debug!("Adding new value with ID {}", id);
|
debug!("Adding new value with ID {}", id);
|
||||||
|
@ -234,7 +229,7 @@ impl Module<Button> for ClipboardModule {
|
||||||
try_send!(tx, UIEvent::Copy(id));
|
try_send!(tx, UIEvent::Copy(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
Inhibit(true)
|
Propagation::Stop
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -293,8 +288,6 @@ impl Module<Button> for ClipboardModule {
|
||||||
hidden_option.set_active(true);
|
hidden_option.set_active(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Continue(true)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,12 +2,10 @@ use std::env;
|
||||||
|
|
||||||
use chrono::{DateTime, Local, Locale};
|
use chrono::{DateTime, Local, Locale};
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
use glib::Continue;
|
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::{Align, Button, Calendar, Label, Orientation};
|
use gtk::{Align, Button, Calendar, Label, Orientation};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use tokio::spawn;
|
use tokio::sync::{broadcast, mpsc};
|
||||||
use tokio::sync::mpsc;
|
|
||||||
use tokio::time::sleep;
|
use tokio::time::sleep;
|
||||||
|
|
||||||
use crate::config::CommonConfig;
|
use crate::config::CommonConfig;
|
||||||
|
@ -15,7 +13,7 @@ use crate::gtk_helpers::IronbarGtkExt;
|
||||||
use crate::modules::{
|
use crate::modules::{
|
||||||
Module, ModuleInfo, ModuleParts, ModulePopup, ModuleUpdateEvent, PopupButton, WidgetContext,
|
Module, ModuleInfo, ModuleParts, ModulePopup, ModuleUpdateEvent, PopupButton, WidgetContext,
|
||||||
};
|
};
|
||||||
use crate::{send_async, try_send};
|
use crate::{glib_recv, send_async, spawn, try_send};
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
pub struct ClockModule {
|
pub struct ClockModule {
|
||||||
|
@ -104,24 +102,22 @@ impl Module<Button> for ClockModule {
|
||||||
label.set_angle(info.bar_position.get_angle());
|
label.set_angle(info.bar_position.get_angle());
|
||||||
button.add(&label);
|
button.add(&label);
|
||||||
|
|
||||||
|
let tx = context.tx.clone();
|
||||||
button.connect_clicked(move |button| {
|
button.connect_clicked(move |button| {
|
||||||
try_send!(
|
try_send!(tx, ModuleUpdateEvent::TogglePopup(button.popup_id()));
|
||||||
context.tx,
|
|
||||||
ModuleUpdateEvent::TogglePopup(button.popup_id())
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let format = self.format.clone();
|
let format = self.format.clone();
|
||||||
let locale = Locale::try_from(self.locale.as_str()).unwrap_or(Locale::POSIX);
|
let locale = Locale::try_from(self.locale.as_str()).unwrap_or(Locale::POSIX);
|
||||||
|
|
||||||
context.widget_rx.attach(None, move |date| {
|
let mut rx = context.subscribe();
|
||||||
|
glib_recv!(rx, date => {
|
||||||
let date_string = format!("{}", date.format_localized(&format, locale));
|
let date_string = format!("{}", date.format_localized(&format, locale));
|
||||||
label.set_label(&date_string);
|
label.set_label(&date_string);
|
||||||
Continue(true)
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let popup = self
|
let popup = self
|
||||||
.into_popup(context.controller_tx, context.popup_rx, info)
|
.into_popup(context.controller_tx.clone(), context.subscribe(), info)
|
||||||
.into_popup_parts(vec![&button]);
|
.into_popup_parts(vec![&button]);
|
||||||
|
|
||||||
Ok(ModuleParts::new(button, popup))
|
Ok(ModuleParts::new(button, popup))
|
||||||
|
@ -130,7 +126,7 @@ impl Module<Button> for ClockModule {
|
||||||
fn into_popup(
|
fn into_popup(
|
||||||
self,
|
self,
|
||||||
_tx: mpsc::Sender<Self::ReceiveMessage>,
|
_tx: mpsc::Sender<Self::ReceiveMessage>,
|
||||||
rx: glib::Receiver<Self::SendMessage>,
|
mut rx: broadcast::Receiver<Self::SendMessage>,
|
||||||
_info: &ModuleInfo,
|
_info: &ModuleInfo,
|
||||||
) -> Option<gtk::Box> {
|
) -> Option<gtk::Box> {
|
||||||
let container = gtk::Box::new(Orientation::Vertical, 0);
|
let container = gtk::Box::new(Orientation::Vertical, 0);
|
||||||
|
@ -147,10 +143,9 @@ impl Module<Button> for ClockModule {
|
||||||
let format = self.format_popup;
|
let format = self.format_popup;
|
||||||
let locale = Locale::try_from(self.locale.as_str()).unwrap_or(Locale::POSIX);
|
let locale = Locale::try_from(self.locale.as_str()).unwrap_or(Locale::POSIX);
|
||||||
|
|
||||||
rx.attach(None, move |date| {
|
glib_recv!(rx, date => {
|
||||||
let date_string = format!("{}", date.format_localized(&format, locale));
|
let date_string = format!("{}", date.format_localized(&format, locale));
|
||||||
clock.set_label(&date_string);
|
clock.set_label(&date_string);
|
||||||
Continue(true)
|
|
||||||
});
|
});
|
||||||
|
|
||||||
container.show_all();
|
container.show_all();
|
||||||
|
|
|
@ -30,7 +30,6 @@ impl CustomWidget for ButtonWidget {
|
||||||
|
|
||||||
dynamic_string(&text, move |string| {
|
dynamic_string(&text, move |string| {
|
||||||
label.set_markup(&string);
|
label.set_markup(&string);
|
||||||
Continue(true)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,8 +34,6 @@ impl CustomWidget for ImageWidget {
|
||||||
dynamic_string(&self.src, move |src| {
|
dynamic_string(&self.src, move |src| {
|
||||||
ImageProvider::parse(&src, &icon_theme, false, self.size)
|
ImageProvider::parse(&src, &icon_theme, false, self.size)
|
||||||
.map(|image| image.load_into_image(gtk_image.clone()));
|
.map(|image| image.load_into_image(gtk_image.clone()));
|
||||||
|
|
||||||
Continue(true)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,6 @@ impl CustomWidget for LabelWidget {
|
||||||
let label = label.clone();
|
let label = label.clone();
|
||||||
dynamic_string(&self.label, move |string| {
|
dynamic_string(&self.label, move |string| {
|
||||||
label.set_markup(&string);
|
label.set_markup(&string);
|
||||||
Continue(true)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,15 +16,14 @@ use crate::modules::{
|
||||||
wrap_widget, Module, ModuleInfo, ModuleParts, ModulePopup, ModuleUpdateEvent, WidgetContext,
|
wrap_widget, Module, ModuleInfo, ModuleParts, ModulePopup, ModuleUpdateEvent, WidgetContext,
|
||||||
};
|
};
|
||||||
use crate::script::Script;
|
use crate::script::Script;
|
||||||
use crate::send_async;
|
use crate::{send_async, spawn};
|
||||||
use color_eyre::{Report, Result};
|
use color_eyre::{Report, Result};
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::{Button, IconTheme, Orientation};
|
use gtk::{Button, IconTheme, Orientation};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use tokio::spawn;
|
use tokio::sync::{broadcast, mpsc};
|
||||||
use tokio::sync::mpsc::{Receiver, Sender};
|
|
||||||
use tracing::{debug, error};
|
use tracing::{debug, error};
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
|
@ -59,7 +58,7 @@ pub enum Widget {
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct CustomWidgetContext<'a> {
|
struct CustomWidgetContext<'a> {
|
||||||
tx: &'a Sender<ExecEvent>,
|
tx: &'a mpsc::Sender<ExecEvent>,
|
||||||
bar_orientation: Orientation,
|
bar_orientation: Orientation,
|
||||||
icon_theme: &'a IconTheme,
|
icon_theme: &'a IconTheme,
|
||||||
popup_buttons: Rc<RefCell<Vec<Button>>>,
|
popup_buttons: Rc<RefCell<Vec<Button>>>,
|
||||||
|
@ -159,8 +158,8 @@ impl Module<gtk::Box> for CustomModule {
|
||||||
fn spawn_controller(
|
fn spawn_controller(
|
||||||
&self,
|
&self,
|
||||||
_info: &ModuleInfo,
|
_info: &ModuleInfo,
|
||||||
tx: Sender<ModuleUpdateEvent<Self::SendMessage>>,
|
tx: mpsc::Sender<ModuleUpdateEvent<Self::SendMessage>>,
|
||||||
mut rx: Receiver<Self::ReceiveMessage>,
|
mut rx: mpsc::Receiver<Self::ReceiveMessage>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
spawn(async move {
|
spawn(async move {
|
||||||
while let Some(event) = rx.recv().await {
|
while let Some(event) = rx.recv().await {
|
||||||
|
@ -213,7 +212,7 @@ impl Module<gtk::Box> for CustomModule {
|
||||||
});
|
});
|
||||||
|
|
||||||
let popup = self
|
let popup = self
|
||||||
.into_popup(context.controller_tx, context.popup_rx, info)
|
.into_popup(context.controller_tx.clone(), context.subscribe(), info)
|
||||||
.into_popup_parts_owned(popup_buttons.take());
|
.into_popup_parts_owned(popup_buttons.take());
|
||||||
|
|
||||||
Ok(ModuleParts {
|
Ok(ModuleParts {
|
||||||
|
@ -224,8 +223,8 @@ impl Module<gtk::Box> for CustomModule {
|
||||||
|
|
||||||
fn into_popup(
|
fn into_popup(
|
||||||
self,
|
self,
|
||||||
tx: Sender<Self::ReceiveMessage>,
|
tx: mpsc::Sender<Self::ReceiveMessage>,
|
||||||
_rx: glib::Receiver<Self::SendMessage>,
|
_rx: broadcast::Receiver<Self::SendMessage>,
|
||||||
info: &ModuleInfo,
|
info: &ModuleInfo,
|
||||||
) -> Option<gtk::Box>
|
) -> Option<gtk::Box>
|
||||||
where
|
where
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::ProgressBar;
|
use gtk::ProgressBar;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use tokio::spawn;
|
use tokio::sync::mpsc;
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
|
|
||||||
use crate::dynamic_value::dynamic_string;
|
use crate::dynamic_value::dynamic_string;
|
||||||
use crate::modules::custom::set_length;
|
use crate::modules::custom::set_length;
|
||||||
use crate::script::{OutputStream, Script, ScriptInput};
|
use crate::script::{OutputStream, Script, ScriptInput};
|
||||||
use crate::{build, send};
|
use crate::{build, glib_recv_mpsc, spawn, try_send};
|
||||||
|
|
||||||
use super::{try_get_orientation, CustomWidget, CustomWidgetContext};
|
use super::{try_get_orientation, CustomWidget, CustomWidgetContext};
|
||||||
|
|
||||||
|
@ -47,13 +47,13 @@ impl CustomWidget for ProgressWidget {
|
||||||
let script = Script::from(value);
|
let script = Script::from(value);
|
||||||
let progress = progress.clone();
|
let progress = progress.clone();
|
||||||
|
|
||||||
let (tx, rx) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
|
let (tx, mut rx) = mpsc::channel(128);
|
||||||
|
|
||||||
spawn(async move {
|
spawn(async move {
|
||||||
script
|
script
|
||||||
.run(None, move |stream, _success| match stream {
|
.run(None, move |stream, _success| match stream {
|
||||||
OutputStream::Stdout(out) => match out.parse::<f64>() {
|
OutputStream::Stdout(out) => match out.parse::<f64>() {
|
||||||
Ok(value) => send!(tx, value),
|
Ok(value) => try_send!(tx, value),
|
||||||
Err(err) => error!("{err:?}"),
|
Err(err) => error!("{err:?}"),
|
||||||
},
|
},
|
||||||
OutputStream::Stderr(err) => error!("{err:?}"),
|
OutputStream::Stderr(err) => error!("{err:?}"),
|
||||||
|
@ -61,10 +61,7 @@ impl CustomWidget for ProgressWidget {
|
||||||
.await;
|
.await;
|
||||||
});
|
});
|
||||||
|
|
||||||
rx.attach(None, move |value| {
|
glib_recv_mpsc!(rx, value => progress.set_fraction(value / self.max));
|
||||||
progress.set_fraction(value / self.max);
|
|
||||||
Continue(true)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(text) = self.label {
|
if let Some(text) = self.label {
|
||||||
|
@ -73,7 +70,6 @@ impl CustomWidget for ProgressWidget {
|
||||||
|
|
||||||
dynamic_string(&text, move |string| {
|
dynamic_string(&text, move |string| {
|
||||||
progress.set_text(Some(&string));
|
progress.set_text(Some(&string));
|
||||||
Continue(true)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
|
use glib::Propagation;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::ops::Neg;
|
use std::ops::Neg;
|
||||||
|
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::Scale;
|
use gtk::Scale;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use tokio::spawn;
|
use tokio::sync::mpsc;
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
|
|
||||||
use crate::modules::custom::set_length;
|
use crate::modules::custom::set_length;
|
||||||
use crate::script::{OutputStream, Script, ScriptInput};
|
use crate::script::{OutputStream, Script, ScriptInput};
|
||||||
use crate::{build, send, try_send};
|
use crate::{build, glib_recv_mpsc, spawn, try_send};
|
||||||
|
|
||||||
use super::{try_get_orientation, CustomWidget, CustomWidgetContext, ExecEvent};
|
use super::{try_get_orientation, CustomWidget, CustomWidgetContext, ExecEvent};
|
||||||
|
|
||||||
|
@ -77,7 +78,7 @@ impl CustomWidget for SliderWidget {
|
||||||
};
|
};
|
||||||
|
|
||||||
scale.set_value(value + delta);
|
scale.set_value(value + delta);
|
||||||
Inhibit(false)
|
Propagation::Proceed
|
||||||
});
|
});
|
||||||
|
|
||||||
scale.connect_change_value(move |_, _, val| {
|
scale.connect_change_value(move |_, _, val| {
|
||||||
|
@ -97,7 +98,7 @@ impl CustomWidget for SliderWidget {
|
||||||
prev_value.set(val);
|
prev_value.set(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
Inhibit(false)
|
Propagation::Proceed
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,13 +106,13 @@ impl CustomWidget for SliderWidget {
|
||||||
let script = Script::from(value);
|
let script = Script::from(value);
|
||||||
let scale = scale.clone();
|
let scale = scale.clone();
|
||||||
|
|
||||||
let (tx, rx) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
|
let (tx, mut rx) = mpsc::channel(128);
|
||||||
|
|
||||||
spawn(async move {
|
spawn(async move {
|
||||||
script
|
script
|
||||||
.run(None, move |stream, _success| match stream {
|
.run(None, move |stream, _success| match stream {
|
||||||
OutputStream::Stdout(out) => match out.parse() {
|
OutputStream::Stdout(out) => match out.parse() {
|
||||||
Ok(value) => send!(tx, value),
|
Ok(value) => try_send!(tx, value),
|
||||||
Err(err) => error!("{err:?}"),
|
Err(err) => error!("{err:?}"),
|
||||||
},
|
},
|
||||||
OutputStream::Stderr(err) => error!("{err:?}"),
|
OutputStream::Stderr(err) => error!("{err:?}"),
|
||||||
|
@ -119,10 +120,7 @@ impl CustomWidget for SliderWidget {
|
||||||
.await;
|
.await;
|
||||||
});
|
});
|
||||||
|
|
||||||
rx.attach(None, move |value| {
|
glib_recv_mpsc!(rx, value => scale.set_value(value));
|
||||||
scale.set_value(value);
|
|
||||||
Continue(true)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
scale
|
scale
|
||||||
|
|
|
@ -3,13 +3,11 @@ use crate::config::{CommonConfig, TruncateMode};
|
||||||
use crate::gtk_helpers::IronbarGtkExt;
|
use crate::gtk_helpers::IronbarGtkExt;
|
||||||
use crate::image::ImageProvider;
|
use crate::image::ImageProvider;
|
||||||
use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext};
|
use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext};
|
||||||
use crate::{lock, send_async, try_send};
|
use crate::{glib_recv, lock, send_async, spawn, try_send};
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
use glib::Continue;
|
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::Label;
|
use gtk::Label;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use tokio::spawn;
|
|
||||||
use tokio::sync::mpsc::{Receiver, Sender};
|
use tokio::sync::mpsc::{Receiver, Sender};
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
|
@ -141,7 +139,7 @@ impl Module<gtk::Box> for FocusedModule {
|
||||||
|
|
||||||
{
|
{
|
||||||
let icon_theme = icon_theme.clone();
|
let icon_theme = icon_theme.clone();
|
||||||
context.widget_rx.attach(None, move |data| {
|
glib_recv!(context.subscribe(), data => {
|
||||||
if let Some((name, id)) = data {
|
if let Some((name, id)) = data {
|
||||||
if self.show_icon {
|
if self.show_icon {
|
||||||
match ImageProvider::parse(&id, &icon_theme, true, self.icon_size)
|
match ImageProvider::parse(&id, &icon_theme, true, self.icon_size)
|
||||||
|
@ -160,8 +158,6 @@ impl Module<gtk::Box> for FocusedModule {
|
||||||
icon.hide();
|
icon.hide();
|
||||||
label.hide();
|
label.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
Continue(true)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
use crate::config::CommonConfig;
|
use crate::config::CommonConfig;
|
||||||
use crate::dynamic_value::dynamic_string;
|
use crate::dynamic_value::dynamic_string;
|
||||||
use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext};
|
use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext};
|
||||||
use crate::try_send;
|
use crate::{glib_recv, try_send};
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
use glib::Continue;
|
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::Label;
|
use gtk::Label;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
@ -42,7 +41,6 @@ impl Module<Label> for LabelModule {
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
dynamic_string(&self.label, move |string| {
|
dynamic_string(&self.label, move |string| {
|
||||||
try_send!(tx, ModuleUpdateEvent::Update(string));
|
try_send!(tx, ModuleUpdateEvent::Update(string));
|
||||||
Continue(true)
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -58,10 +56,7 @@ impl Module<Label> for LabelModule {
|
||||||
|
|
||||||
{
|
{
|
||||||
let label = label.clone();
|
let label = label.clone();
|
||||||
context.widget_rx.attach(None, move |string| {
|
glib_recv!(context.subscribe(), string => label.set_markup(&string));
|
||||||
label.set_markup(&string);
|
|
||||||
Continue(true)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(ModuleParts {
|
Ok(ModuleParts {
|
||||||
|
|
|
@ -7,6 +7,7 @@ use crate::modules::launcher::{ItemEvent, LauncherUpdate};
|
||||||
use crate::modules::ModuleUpdateEvent;
|
use crate::modules::ModuleUpdateEvent;
|
||||||
use crate::{read_lock, try_send};
|
use crate::{read_lock, try_send};
|
||||||
use color_eyre::{Report, Result};
|
use color_eyre::{Report, Result};
|
||||||
|
use glib::Propagation;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::{Button, IconTheme};
|
use gtk::{Button, IconTheme};
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
@ -258,7 +259,7 @@ impl ItemButton {
|
||||||
try_send!(tx, ModuleUpdateEvent::ClosePopup);
|
try_send!(tx, ModuleUpdateEvent::ClosePopup);
|
||||||
}
|
}
|
||||||
|
|
||||||
Inhibit(false)
|
Propagation::Proceed
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,7 +284,7 @@ impl ItemButton {
|
||||||
try_send!(tx, ModuleUpdateEvent::ClosePopup);
|
try_send!(tx, ModuleUpdateEvent::ClosePopup);
|
||||||
}
|
}
|
||||||
|
|
||||||
Inhibit(false)
|
Propagation::Proceed
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,17 +10,15 @@ use crate::modules::launcher::item::AppearanceOptions;
|
||||||
use crate::modules::{
|
use crate::modules::{
|
||||||
Module, ModuleInfo, ModuleParts, ModulePopup, ModuleUpdateEvent, WidgetContext,
|
Module, ModuleInfo, ModuleParts, ModulePopup, ModuleUpdateEvent, WidgetContext,
|
||||||
};
|
};
|
||||||
use crate::{arc_mut, lock, send_async, try_send, write_lock};
|
use crate::{arc_mut, glib_recv, lock, send_async, spawn, try_send, write_lock};
|
||||||
use color_eyre::{Help, Report};
|
use color_eyre::{Help, Report};
|
||||||
use glib::Continue;
|
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::{Button, Orientation};
|
use gtk::{Button, Orientation};
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::spawn;
|
use tokio::sync::{broadcast, mpsc};
|
||||||
use tokio::sync::mpsc::{Receiver, Sender};
|
|
||||||
use tracing::{debug, error, trace};
|
use tracing::{debug, error, trace};
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
|
@ -92,8 +90,8 @@ impl Module<gtk::Box> for LauncherModule {
|
||||||
fn spawn_controller(
|
fn spawn_controller(
|
||||||
&self,
|
&self,
|
||||||
_info: &ModuleInfo,
|
_info: &ModuleInfo,
|
||||||
tx: Sender<ModuleUpdateEvent<Self::SendMessage>>,
|
tx: mpsc::Sender<ModuleUpdateEvent<Self::SendMessage>>,
|
||||||
mut rx: Receiver<Self::ReceiveMessage>,
|
mut rx: mpsc::Receiver<Self::ReceiveMessage>,
|
||||||
) -> crate::Result<()> {
|
) -> crate::Result<()> {
|
||||||
let items = self
|
let items = self
|
||||||
.favorites
|
.favorites
|
||||||
|
@ -338,7 +336,9 @@ impl Module<gtk::Box> for LauncherModule {
|
||||||
|
|
||||||
let mut buttons = IndexMap::<String, ItemButton>::new();
|
let mut buttons = IndexMap::<String, ItemButton>::new();
|
||||||
|
|
||||||
context.widget_rx.attach(None, move |event| {
|
let tx = context.tx.clone();
|
||||||
|
let mut rx = context.subscribe();
|
||||||
|
glib_recv!(rx, event => {
|
||||||
match event {
|
match event {
|
||||||
LauncherUpdate::AddItem(item) => {
|
LauncherUpdate::AddItem(item) => {
|
||||||
debug!("Adding item with id {}", item.app_id);
|
debug!("Adding item with id {}", item.app_id);
|
||||||
|
@ -351,7 +351,7 @@ impl Module<gtk::Box> for LauncherModule {
|
||||||
appearance_options,
|
appearance_options,
|
||||||
&icon_theme,
|
&icon_theme,
|
||||||
bar_position,
|
bar_position,
|
||||||
&context.tx,
|
&tx,
|
||||||
&controller_tx,
|
&controller_tx,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -411,13 +411,12 @@ impl Module<gtk::Box> for LauncherModule {
|
||||||
}
|
}
|
||||||
LauncherUpdate::Hover(_) => {}
|
LauncherUpdate::Hover(_) => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
Continue(true)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let rx = context.subscribe();
|
||||||
let popup = self
|
let popup = self
|
||||||
.into_popup(context.controller_tx, context.popup_rx, info)
|
.into_popup(context.controller_tx, rx, info)
|
||||||
.into_popup_parts(vec![]); // since item buttons are dynamic, they pass their geometry directly
|
.into_popup_parts(vec![]); // since item buttons are dynamic, they pass their geometry directly
|
||||||
|
|
||||||
Ok(ModuleParts {
|
Ok(ModuleParts {
|
||||||
|
@ -428,8 +427,8 @@ impl Module<gtk::Box> for LauncherModule {
|
||||||
|
|
||||||
fn into_popup(
|
fn into_popup(
|
||||||
self,
|
self,
|
||||||
controller_tx: Sender<Self::ReceiveMessage>,
|
controller_tx: mpsc::Sender<Self::ReceiveMessage>,
|
||||||
rx: glib::Receiver<Self::SendMessage>,
|
mut rx: broadcast::Receiver<Self::SendMessage>,
|
||||||
_info: &ModuleInfo,
|
_info: &ModuleInfo,
|
||||||
) -> Option<gtk::Box> {
|
) -> Option<gtk::Box> {
|
||||||
const MAX_WIDTH: i32 = 250;
|
const MAX_WIDTH: i32 = 250;
|
||||||
|
@ -445,7 +444,7 @@ impl Module<gtk::Box> for LauncherModule {
|
||||||
|
|
||||||
{
|
{
|
||||||
let container = container.clone();
|
let container = container.clone();
|
||||||
rx.attach(None, move |event| {
|
glib_recv!(rx, event => {
|
||||||
match event {
|
match event {
|
||||||
LauncherUpdate::AddItem(item) => {
|
LauncherUpdate::AddItem(item) => {
|
||||||
let app_id = item.app_id.clone();
|
let app_id = item.app_id.clone();
|
||||||
|
@ -532,8 +531,6 @@ impl Module<gtk::Box> for LauncherModule {
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
Continue(true)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
use std::fmt::Debug;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
|
@ -6,14 +7,13 @@ use glib::IsA;
|
||||||
use gtk::gdk::{EventMask, Monitor};
|
use gtk::gdk::{EventMask, Monitor};
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::{Application, Button, EventBox, IconTheme, Orientation, Revealer, Widget};
|
use gtk::{Application, Button, EventBox, IconTheme, Orientation, Revealer, Widget};
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::{broadcast, mpsc};
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
use crate::bridge_channel::BridgeChannel;
|
|
||||||
use crate::config::{BarPosition, CommonConfig, TransitionType};
|
use crate::config::{BarPosition, CommonConfig, TransitionType};
|
||||||
use crate::gtk_helpers::{IronbarGtkExt, WidgetGeometry};
|
use crate::gtk_helpers::{IronbarGtkExt, WidgetGeometry};
|
||||||
use crate::popup::Popup;
|
use crate::popup::Popup;
|
||||||
use crate::send;
|
use crate::{glib_recv_mpsc, send};
|
||||||
|
|
||||||
#[cfg(feature = "clipboard")]
|
#[cfg(feature = "clipboard")]
|
||||||
pub mod clipboard;
|
pub mod clipboard;
|
||||||
|
@ -56,8 +56,8 @@ pub struct ModuleInfo<'a> {
|
||||||
pub icon_theme: &'a IconTheme,
|
pub icon_theme: &'a IconTheme,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum ModuleUpdateEvent<T> {
|
pub enum ModuleUpdateEvent<T: Clone> {
|
||||||
/// Sends an update to the module UI.
|
/// Sends an update to the module UI.
|
||||||
Update(T),
|
Update(T),
|
||||||
/// Toggles the open state of the popup.
|
/// Toggles the open state of the popup.
|
||||||
|
@ -71,12 +71,25 @@ pub enum ModuleUpdateEvent<T> {
|
||||||
ClosePopup,
|
ClosePopup,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WidgetContext<TSend, TReceive> {
|
pub struct WidgetContext<TSend, TReceive>
|
||||||
|
where
|
||||||
|
TSend: Clone,
|
||||||
|
{
|
||||||
pub id: usize,
|
pub id: usize,
|
||||||
pub tx: mpsc::Sender<ModuleUpdateEvent<TSend>>,
|
pub tx: mpsc::Sender<ModuleUpdateEvent<TSend>>,
|
||||||
|
pub update_tx: broadcast::Sender<TSend>,
|
||||||
pub controller_tx: mpsc::Sender<TReceive>,
|
pub controller_tx: mpsc::Sender<TReceive>,
|
||||||
pub widget_rx: glib::Receiver<TSend>,
|
|
||||||
pub popup_rx: glib::Receiver<TSend>,
|
_update_rx: broadcast::Receiver<TSend>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<TSend, TReceive> WidgetContext<TSend, TReceive>
|
||||||
|
where
|
||||||
|
TSend: Clone,
|
||||||
|
{
|
||||||
|
pub fn subscribe(&self) -> broadcast::Receiver<TSend> {
|
||||||
|
self.update_tx.subscribe()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ModuleParts<W: IsA<Widget>> {
|
pub struct ModuleParts<W: IsA<Widget>> {
|
||||||
|
@ -151,18 +164,22 @@ where
|
||||||
info: &ModuleInfo,
|
info: &ModuleInfo,
|
||||||
tx: mpsc::Sender<ModuleUpdateEvent<Self::SendMessage>>,
|
tx: mpsc::Sender<ModuleUpdateEvent<Self::SendMessage>>,
|
||||||
rx: mpsc::Receiver<Self::ReceiveMessage>,
|
rx: mpsc::Receiver<Self::ReceiveMessage>,
|
||||||
) -> Result<()>;
|
) -> Result<()>
|
||||||
|
where
|
||||||
|
<Self as Module<W>>::SendMessage: Clone;
|
||||||
|
|
||||||
fn into_widget(
|
fn into_widget(
|
||||||
self,
|
self,
|
||||||
context: WidgetContext<Self::SendMessage, Self::ReceiveMessage>,
|
context: WidgetContext<Self::SendMessage, Self::ReceiveMessage>,
|
||||||
info: &ModuleInfo,
|
info: &ModuleInfo,
|
||||||
) -> Result<ModuleParts<W>>;
|
) -> Result<ModuleParts<W>>
|
||||||
|
where
|
||||||
|
<Self as Module<W>>::SendMessage: Clone;
|
||||||
|
|
||||||
fn into_popup(
|
fn into_popup(
|
||||||
self,
|
self,
|
||||||
_tx: mpsc::Sender<Self::ReceiveMessage>,
|
_tx: mpsc::Sender<Self::ReceiveMessage>,
|
||||||
_rx: glib::Receiver<Self::SendMessage>,
|
_rx: broadcast::Receiver<Self::SendMessage>,
|
||||||
_info: &ModuleInfo,
|
_info: &ModuleInfo,
|
||||||
) -> Option<gtk::Box>
|
) -> Option<gtk::Box>
|
||||||
where
|
where
|
||||||
|
@ -184,22 +201,21 @@ pub fn create_module<TModule, TWidget, TSend, TRec>(
|
||||||
where
|
where
|
||||||
TModule: Module<TWidget, SendMessage = TSend, ReceiveMessage = TRec>,
|
TModule: Module<TWidget, SendMessage = TSend, ReceiveMessage = TRec>,
|
||||||
TWidget: IsA<Widget>,
|
TWidget: IsA<Widget>,
|
||||||
TSend: Clone + Send + 'static,
|
TSend: Debug + Clone + Send + 'static,
|
||||||
{
|
{
|
||||||
let (w_tx, w_rx) = glib::MainContext::channel::<TSend>(glib::PRIORITY_DEFAULT);
|
let (ui_tx, ui_rx) = mpsc::channel::<ModuleUpdateEvent<TSend>>(64);
|
||||||
let (p_tx, p_rx) = glib::MainContext::channel::<TSend>(glib::PRIORITY_DEFAULT);
|
let (controller_tx, controller_rx) = mpsc::channel::<TRec>(64);
|
||||||
|
|
||||||
let channel = BridgeChannel::<ModuleUpdateEvent<TSend>>::new();
|
let (tx, rx) = broadcast::channel(64);
|
||||||
let (ui_tx, ui_rx) = mpsc::channel::<TRec>(16);
|
|
||||||
|
|
||||||
module.spawn_controller(info, channel.create_sender(), ui_rx)?;
|
module.spawn_controller(info, ui_tx.clone(), controller_rx)?;
|
||||||
|
|
||||||
let context = WidgetContext {
|
let context = WidgetContext {
|
||||||
id,
|
id,
|
||||||
widget_rx: w_rx,
|
tx: ui_tx,
|
||||||
popup_rx: p_rx,
|
update_tx: tx.clone(),
|
||||||
tx: channel.create_sender(),
|
controller_tx,
|
||||||
controller_tx: ui_tx,
|
_update_rx: rx,
|
||||||
};
|
};
|
||||||
|
|
||||||
let module_name = TModule::name();
|
let module_name = TModule::name();
|
||||||
|
@ -209,27 +225,16 @@ where
|
||||||
module_parts.widget.add_class("widget");
|
module_parts.widget.add_class("widget");
|
||||||
module_parts.widget.add_class(module_name);
|
module_parts.widget.add_class(module_name);
|
||||||
|
|
||||||
let has_popup = if let Some(popup_content) = module_parts.popup.clone() {
|
if let Some(popup_content) = module_parts.popup.clone() {
|
||||||
popup_content
|
popup_content
|
||||||
.container
|
.container
|
||||||
.style_context()
|
.style_context()
|
||||||
.add_class(&format!("popup-{module_name}"));
|
.add_class(&format!("popup-{module_name}"));
|
||||||
|
|
||||||
register_popup_content(popup, id, instance_name, popup_content);
|
register_popup_content(popup, id, instance_name, popup_content);
|
||||||
true
|
}
|
||||||
} else {
|
|
||||||
false
|
|
||||||
};
|
|
||||||
|
|
||||||
setup_receiver(
|
setup_receiver(tx, ui_rx, popup.clone(), module_name, id);
|
||||||
channel,
|
|
||||||
w_tx,
|
|
||||||
p_tx,
|
|
||||||
popup.clone(),
|
|
||||||
module_name,
|
|
||||||
id,
|
|
||||||
has_popup,
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(module_parts)
|
Ok(module_parts)
|
||||||
}
|
}
|
||||||
|
@ -250,28 +255,22 @@ fn register_popup_content(
|
||||||
/// Handles opening/closing popups
|
/// Handles opening/closing popups
|
||||||
/// and communicating update messages between controllers and widgets/popups.
|
/// and communicating update messages between controllers and widgets/popups.
|
||||||
fn setup_receiver<TSend>(
|
fn setup_receiver<TSend>(
|
||||||
channel: BridgeChannel<ModuleUpdateEvent<TSend>>,
|
tx: broadcast::Sender<TSend>,
|
||||||
w_tx: glib::Sender<TSend>,
|
mut rx: mpsc::Receiver<ModuleUpdateEvent<TSend>>,
|
||||||
p_tx: glib::Sender<TSend>,
|
|
||||||
popup: Rc<RefCell<Popup>>,
|
popup: Rc<RefCell<Popup>>,
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
id: usize,
|
id: usize,
|
||||||
has_popup: bool,
|
|
||||||
) where
|
) where
|
||||||
TSend: Clone + Send + 'static,
|
TSend: Debug + Clone + Send + 'static,
|
||||||
{
|
{
|
||||||
// some rare cases can cause the popup to incorrectly calculate its size on first open.
|
// some rare cases can cause the popup to incorrectly calculate its size on first open.
|
||||||
// we can fix that by just force re-rendering it on its first open.
|
// we can fix that by just force re-rendering it on its first open.
|
||||||
let mut has_popup_opened = false;
|
let mut has_popup_opened = false;
|
||||||
|
|
||||||
channel.recv(move |ev| {
|
glib_recv_mpsc!(rx, ev => {
|
||||||
match ev {
|
match ev {
|
||||||
ModuleUpdateEvent::Update(update) => {
|
ModuleUpdateEvent::Update(update) => {
|
||||||
if has_popup {
|
send!(tx, update);
|
||||||
send!(p_tx, update.clone());
|
|
||||||
}
|
|
||||||
|
|
||||||
send!(w_tx, update);
|
|
||||||
}
|
}
|
||||||
ModuleUpdateEvent::TogglePopup(button_id) => {
|
ModuleUpdateEvent::TogglePopup(button_id) => {
|
||||||
debug!("Toggling popup for {} [#{}]", name, id);
|
debug!("Toggling popup for {} [#{}]", name, id);
|
||||||
|
@ -321,8 +320,6 @@ fn setup_receiver<TSend>(
|
||||||
popup.hide();
|
popup.hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Continue(true)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,11 @@ use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
use glib::{Continue, PropertySet};
|
use glib::{Propagation, PropertySet};
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::{Button, IconTheme, Label, Orientation, Scale};
|
use gtk::{Button, IconTheme, Label, Orientation, Scale};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use tokio::spawn;
|
use tokio::sync::{broadcast, mpsc};
|
||||||
use tokio::sync::mpsc::{Receiver, Sender};
|
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
|
|
||||||
use crate::clients::music::{
|
use crate::clients::music::{
|
||||||
|
@ -21,7 +20,7 @@ use crate::modules::PopupButton;
|
||||||
use crate::modules::{
|
use crate::modules::{
|
||||||
Module, ModuleInfo, ModuleParts, ModulePopup, ModuleUpdateEvent, WidgetContext,
|
Module, ModuleInfo, ModuleParts, ModulePopup, ModuleUpdateEvent, WidgetContext,
|
||||||
};
|
};
|
||||||
use crate::{send_async, try_send};
|
use crate::{glib_recv, send_async, spawn, try_send};
|
||||||
|
|
||||||
pub use self::config::MusicModule;
|
pub use self::config::MusicModule;
|
||||||
use self::config::PlayerType;
|
use self::config::PlayerType;
|
||||||
|
@ -91,8 +90,8 @@ impl Module<Button> for MusicModule {
|
||||||
fn spawn_controller(
|
fn spawn_controller(
|
||||||
&self,
|
&self,
|
||||||
_info: &ModuleInfo,
|
_info: &ModuleInfo,
|
||||||
tx: Sender<ModuleUpdateEvent<Self::SendMessage>>,
|
tx: mpsc::Sender<ModuleUpdateEvent<Self::SendMessage>>,
|
||||||
mut rx: Receiver<Self::ReceiveMessage>,
|
mut rx: mpsc::Receiver<Self::ReceiveMessage>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let format = self.format.clone();
|
let format = self.format.clone();
|
||||||
|
|
||||||
|
@ -213,11 +212,13 @@ impl Module<Button> for MusicModule {
|
||||||
|
|
||||||
{
|
{
|
||||||
let button = button.clone();
|
let button = button.clone();
|
||||||
let tx = context.tx.clone();
|
|
||||||
|
|
||||||
context.widget_rx.attach(None, move |event| {
|
let tx = context.tx.clone();
|
||||||
|
let mut rx = context.subscribe();
|
||||||
|
|
||||||
|
glib_recv!(rx, event => {
|
||||||
let ControllerEvent::Update(mut event) = event else {
|
let ControllerEvent::Update(mut event) = event else {
|
||||||
return Continue(true);
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(event) = event.take() {
|
if let Some(event) = event.take() {
|
||||||
|
@ -248,13 +249,12 @@ impl Module<Button> for MusicModule {
|
||||||
button.hide();
|
button.hide();
|
||||||
try_send!(tx, ModuleUpdateEvent::ClosePopup);
|
try_send!(tx, ModuleUpdateEvent::ClosePopup);
|
||||||
}
|
}
|
||||||
|
|
||||||
Continue(true)
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let rx = context.subscribe();
|
||||||
let popup = self
|
let popup = self
|
||||||
.into_popup(context.controller_tx, context.popup_rx, info)
|
.into_popup(context.controller_tx, rx, info)
|
||||||
.into_popup_parts(vec![&button]);
|
.into_popup_parts(vec![&button]);
|
||||||
|
|
||||||
Ok(ModuleParts::new(button, popup))
|
Ok(ModuleParts::new(button, popup))
|
||||||
|
@ -262,8 +262,8 @@ impl Module<Button> for MusicModule {
|
||||||
|
|
||||||
fn into_popup(
|
fn into_popup(
|
||||||
self,
|
self,
|
||||||
tx: Sender<Self::ReceiveMessage>,
|
tx: mpsc::Sender<Self::ReceiveMessage>,
|
||||||
rx: glib::Receiver<Self::SendMessage>,
|
mut rx: broadcast::Receiver<Self::SendMessage>,
|
||||||
info: &ModuleInfo,
|
info: &ModuleInfo,
|
||||||
) -> Option<gtk::Box> {
|
) -> Option<gtk::Box> {
|
||||||
let icon_theme = info.icon_theme;
|
let icon_theme = info.icon_theme;
|
||||||
|
@ -355,7 +355,7 @@ impl Module<Button> for MusicModule {
|
||||||
let tx_vol = tx.clone();
|
let tx_vol = tx.clone();
|
||||||
volume_slider.connect_change_value(move |_, _, val| {
|
volume_slider.connect_change_value(move |_, _, val| {
|
||||||
try_send!(tx_vol, PlayerCommand::Volume(val as u8));
|
try_send!(tx_vol, PlayerCommand::Volume(val as u8));
|
||||||
Inhibit(false)
|
Propagation::Proceed
|
||||||
});
|
});
|
||||||
|
|
||||||
let progress_box = gtk::Box::new(Orientation::Horizontal, 5);
|
let progress_box = gtk::Box::new(Orientation::Horizontal, 5);
|
||||||
|
@ -380,7 +380,7 @@ impl Module<Button> for MusicModule {
|
||||||
let drag_lock = drag_lock.clone();
|
let drag_lock = drag_lock.clone();
|
||||||
progress.connect_button_press_event(move |_, _| {
|
progress.connect_button_press_event(move |_, _| {
|
||||||
drag_lock.set(true);
|
drag_lock.set(true);
|
||||||
Inhibit(false)
|
Propagation::Proceed
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,7 +391,7 @@ impl Module<Button> for MusicModule {
|
||||||
try_send!(tx, PlayerCommand::Seek(Duration::from_secs_f64(value)));
|
try_send!(tx, PlayerCommand::Seek(Duration::from_secs_f64(value)));
|
||||||
|
|
||||||
drag_lock.set(false);
|
drag_lock.set(false);
|
||||||
Inhibit(false)
|
Propagation::Proceed
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -402,7 +402,7 @@ impl Module<Button> for MusicModule {
|
||||||
let image_size = self.cover_image_size;
|
let image_size = self.cover_image_size;
|
||||||
|
|
||||||
let mut prev_cover = None;
|
let mut prev_cover = None;
|
||||||
rx.attach(None, move |event| {
|
glib_recv!(rx, event => {
|
||||||
match event {
|
match event {
|
||||||
ControllerEvent::Update(Some(update)) => {
|
ControllerEvent::Update(Some(update)) => {
|
||||||
// only update art when album changes
|
// only update art when album changes
|
||||||
|
@ -487,8 +487,6 @@ impl Module<Button> for MusicModule {
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
Continue(true)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
use crate::config::CommonConfig;
|
use crate::config::CommonConfig;
|
||||||
use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext};
|
use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext};
|
||||||
use crate::script::{OutputStream, Script, ScriptMode};
|
use crate::script::{OutputStream, Script, ScriptMode};
|
||||||
use crate::try_send;
|
use crate::{glib_recv, spawn, try_send};
|
||||||
use color_eyre::{Help, Report, Result};
|
use color_eyre::{Help, Report, Result};
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::Label;
|
use gtk::Label;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use tokio::spawn;
|
|
||||||
use tokio::sync::mpsc::{Receiver, Sender};
|
use tokio::sync::mpsc::{Receiver, Sender};
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
|
|
||||||
|
@ -89,10 +88,7 @@ impl Module<Label> for ScriptModule {
|
||||||
|
|
||||||
{
|
{
|
||||||
let label = label.clone();
|
let label = label.clone();
|
||||||
context.widget_rx.attach(None, move |s| {
|
glib_recv!(context.subscribe(), s => label.set_markup(s.as_str()));
|
||||||
label.set_markup(s.as_str());
|
|
||||||
Continue(true)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(ModuleParts {
|
Ok(ModuleParts {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::config::CommonConfig;
|
use crate::config::CommonConfig;
|
||||||
use crate::gtk_helpers::IronbarGtkExt;
|
use crate::gtk_helpers::IronbarGtkExt;
|
||||||
use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext};
|
use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext};
|
||||||
use crate::send_async;
|
use crate::{glib_recv, send_async, spawn};
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::Label;
|
use gtk::Label;
|
||||||
|
@ -10,7 +10,6 @@ use serde::Deserialize;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use sysinfo::{ComponentExt, CpuExt, DiskExt, NetworkExt, RefreshKind, System, SystemExt};
|
use sysinfo::{ComponentExt, CpuExt, DiskExt, NetworkExt, RefreshKind, System, SystemExt};
|
||||||
use tokio::spawn;
|
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
use tokio::sync::mpsc::{Receiver, Sender};
|
use tokio::sync::mpsc::{Receiver, Sender};
|
||||||
use tokio::time::sleep;
|
use tokio::time::sleep;
|
||||||
|
@ -205,7 +204,7 @@ impl Module<gtk::Box> for SysInfoModule {
|
||||||
|
|
||||||
{
|
{
|
||||||
let formats = self.format;
|
let formats = self.format;
|
||||||
context.widget_rx.attach(None, move |info| {
|
glib_recv!(context.subscribe(), info => {
|
||||||
for (format, label) in formats.iter().zip(labels.clone()) {
|
for (format, label) in formats.iter().zip(labels.clone()) {
|
||||||
let format_compiled = re.replace_all(format, |caps: &Captures| {
|
let format_compiled = re.replace_all(format, |caps: &Captures| {
|
||||||
info.get(&caps[1])
|
info.get(&caps[1])
|
||||||
|
@ -215,8 +214,6 @@ impl Module<gtk::Box> for SysInfoModule {
|
||||||
|
|
||||||
label.set_markup(format_compiled.as_ref());
|
label.set_markup(format_compiled.as_ref());
|
||||||
}
|
}
|
||||||
|
|
||||||
Continue(true)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
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, ModuleParts, ModuleUpdateEvent, WidgetContext};
|
use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext};
|
||||||
use crate::{await_sync, try_send};
|
use crate::{await_sync, glib_recv, spawn, try_send};
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
use glib::ffi::g_strfreev;
|
use glib::ffi::g_strfreev;
|
||||||
use glib::translate::ToGlibPtr;
|
use glib::translate::ToGlibPtr;
|
||||||
|
@ -20,7 +20,6 @@ use std::ptr;
|
||||||
use system_tray::message::menu::{MenuItem as MenuItemInfo, MenuType};
|
use system_tray::message::menu::{MenuItem as MenuItemInfo, MenuType};
|
||||||
use system_tray::message::tray::StatusNotifierItem;
|
use system_tray::message::tray::StatusNotifierItem;
|
||||||
use system_tray::message::{NotifierItemCommand, NotifierItemMessage};
|
use system_tray::message::{NotifierItemCommand, NotifierItemMessage};
|
||||||
use tokio::spawn;
|
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
use tokio::sync::mpsc::{Receiver, Sender};
|
use tokio::sync::mpsc::{Receiver, Sender};
|
||||||
|
|
||||||
|
@ -58,9 +57,9 @@ fn get_icon_theme_search_paths(icon_theme: &IconTheme) -> HashSet<String> {
|
||||||
|
|
||||||
/// Attempts to get a GTK `Image` component
|
/// Attempts to get a GTK `Image` component
|
||||||
/// for the status notifier item's icon.
|
/// for the status notifier item's icon.
|
||||||
fn get_image_from_icon_name(item: &StatusNotifierItem, icon_theme: IconTheme) -> Option<Image> {
|
fn get_image_from_icon_name(item: &StatusNotifierItem, icon_theme: &IconTheme) -> Option<Image> {
|
||||||
if let Some(path) = item.icon_theme_path.as_ref() {
|
if let Some(path) = item.icon_theme_path.as_ref() {
|
||||||
if !path.is_empty() && !get_icon_theme_search_paths(&icon_theme).contains(path) {
|
if !path.is_empty() && !get_icon_theme_search_paths(icon_theme).contains(path) {
|
||||||
icon_theme.append_search_path(path);
|
icon_theme.append_search_path(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -209,7 +208,7 @@ impl Module<MenuBar> for TrayModule {
|
||||||
let icon_theme = info.icon_theme.clone();
|
let icon_theme = info.icon_theme.clone();
|
||||||
|
|
||||||
// listen for UI updates
|
// listen for UI updates
|
||||||
context.widget_rx.attach(None, move |update| {
|
glib_recv!(context.subscribe(), update => {
|
||||||
match update {
|
match update {
|
||||||
NotifierItemMessage::Update {
|
NotifierItemMessage::Update {
|
||||||
item,
|
item,
|
||||||
|
@ -221,7 +220,7 @@ impl Module<MenuBar> for TrayModule {
|
||||||
let menu_item = MenuItem::new();
|
let menu_item = MenuItem::new();
|
||||||
menu_item.style_context().add_class("item");
|
menu_item.style_context().add_class("item");
|
||||||
|
|
||||||
get_image_from_icon_name(&item, icon_theme.clone())
|
get_image_from_icon_name(&item, &icon_theme)
|
||||||
.or_else(|| get_image_from_pixmap(&item))
|
.or_else(|| get_image_from_pixmap(&item))
|
||||||
.map_or_else(
|
.map_or_else(
|
||||||
|| {
|
|| {
|
||||||
|
@ -262,8 +261,6 @@ impl Module<MenuBar> for TrayModule {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Continue(true)
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,7 @@ use futures_lite::stream::StreamExt;
|
||||||
use gtk::{prelude::*, Button};
|
use gtk::{prelude::*, Button};
|
||||||
use gtk::{Label, Orientation};
|
use gtk::{Label, Orientation};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use tokio::spawn;
|
use tokio::sync::{broadcast, mpsc};
|
||||||
use tokio::sync::mpsc::{Receiver, Sender};
|
|
||||||
use upower_dbus::BatteryState;
|
use upower_dbus::BatteryState;
|
||||||
use zbus;
|
use zbus;
|
||||||
|
|
||||||
|
@ -16,7 +15,7 @@ use crate::modules::PopupButton;
|
||||||
use crate::modules::{
|
use crate::modules::{
|
||||||
Module, ModuleInfo, ModuleParts, ModulePopup, ModuleUpdateEvent, WidgetContext,
|
Module, ModuleInfo, ModuleParts, ModulePopup, ModuleUpdateEvent, WidgetContext,
|
||||||
};
|
};
|
||||||
use crate::{await_sync, error, send_async, try_send};
|
use crate::{await_sync, error, glib_recv, send_async, spawn, try_send};
|
||||||
|
|
||||||
const DAY: i64 = 24 * 60 * 60;
|
const DAY: i64 = 24 * 60 * 60;
|
||||||
const HOUR: i64 = 60 * 60;
|
const HOUR: i64 = 60 * 60;
|
||||||
|
@ -62,8 +61,8 @@ impl Module<gtk::Button> for UpowerModule {
|
||||||
fn spawn_controller(
|
fn spawn_controller(
|
||||||
&self,
|
&self,
|
||||||
_info: &ModuleInfo,
|
_info: &ModuleInfo,
|
||||||
tx: Sender<ModuleUpdateEvent<Self::SendMessage>>,
|
tx: mpsc::Sender<ModuleUpdateEvent<Self::SendMessage>>,
|
||||||
_rx: Receiver<Self::ReceiveMessage>,
|
_rx: mpsc::Receiver<Self::ReceiveMessage>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
spawn(async move {
|
spawn(async move {
|
||||||
// await_sync due to strange "higher-ranked lifetime error"
|
// await_sync due to strange "higher-ranked lifetime error"
|
||||||
|
@ -174,29 +173,28 @@ impl Module<gtk::Button> for UpowerModule {
|
||||||
container.add(&label);
|
container.add(&label);
|
||||||
button.add(&container);
|
button.add(&container);
|
||||||
|
|
||||||
|
let tx = context.tx.clone();
|
||||||
button.connect_clicked(move |button| {
|
button.connect_clicked(move |button| {
|
||||||
try_send!(
|
try_send!(tx, ModuleUpdateEvent::TogglePopup(button.popup_id()));
|
||||||
context.tx,
|
|
||||||
ModuleUpdateEvent::TogglePopup(button.popup_id())
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
label.set_angle(info.bar_position.get_angle());
|
label.set_angle(info.bar_position.get_angle());
|
||||||
let format = self.format.clone();
|
let format = self.format.clone();
|
||||||
|
|
||||||
context
|
let mut rx = context.subscribe();
|
||||||
.widget_rx
|
glib_recv!(rx, properties => {
|
||||||
.attach(None, move |properties: UpowerProperties| {
|
let format = format.replace("{percentage}", &properties.percentage.to_string());
|
||||||
let format = format.replace("{percentage}", &properties.percentage.to_string());
|
let icon_name = String::from("icon:") + &properties.icon_name;
|
||||||
let icon_name = String::from("icon:") + &properties.icon_name;
|
|
||||||
ImageProvider::parse(&icon_name, &icon_theme, false, self.icon_size)
|
|
||||||
.map(|provider| provider.load_into_image(icon.clone()));
|
|
||||||
label.set_markup(format.as_ref());
|
|
||||||
Continue(true)
|
|
||||||
});
|
|
||||||
|
|
||||||
|
ImageProvider::parse(&icon_name, &icon_theme, false, self.icon_size)
|
||||||
|
.map(|provider| provider.load_into_image(icon.clone()));
|
||||||
|
|
||||||
|
label.set_markup(format.as_ref());
|
||||||
|
});
|
||||||
|
|
||||||
|
let rx = context.subscribe();
|
||||||
let popup = self
|
let popup = self
|
||||||
.into_popup(context.controller_tx, context.popup_rx, info)
|
.into_popup(context.controller_tx, rx, info)
|
||||||
.into_popup_parts(vec![&button]);
|
.into_popup_parts(vec![&button]);
|
||||||
|
|
||||||
Ok(ModuleParts::new(button, popup))
|
Ok(ModuleParts::new(button, popup))
|
||||||
|
@ -204,8 +202,8 @@ impl Module<gtk::Button> for UpowerModule {
|
||||||
|
|
||||||
fn into_popup(
|
fn into_popup(
|
||||||
self,
|
self,
|
||||||
_tx: Sender<Self::ReceiveMessage>,
|
_tx: mpsc::Sender<Self::ReceiveMessage>,
|
||||||
rx: glib::Receiver<Self::SendMessage>,
|
mut rx: broadcast::Receiver<Self::SendMessage>,
|
||||||
_info: &ModuleInfo,
|
_info: &ModuleInfo,
|
||||||
) -> Option<gtk::Box>
|
) -> Option<gtk::Box>
|
||||||
where
|
where
|
||||||
|
@ -219,7 +217,7 @@ impl Module<gtk::Button> for UpowerModule {
|
||||||
label.add_class("upower-details");
|
label.add_class("upower-details");
|
||||||
container.add(&label);
|
container.add(&label);
|
||||||
|
|
||||||
rx.attach(None, move |properties| {
|
glib_recv!(rx, properties => {
|
||||||
let state = u32_to_battery_state(properties.state);
|
let state = u32_to_battery_state(properties.state);
|
||||||
let format = match state {
|
let format = match state {
|
||||||
Ok(BatteryState::Charging | BatteryState::PendingCharge) => {
|
Ok(BatteryState::Charging | BatteryState::PendingCharge) => {
|
||||||
|
@ -246,7 +244,6 @@ impl Module<gtk::Button> for UpowerModule {
|
||||||
};
|
};
|
||||||
|
|
||||||
label.set_markup(&format);
|
label.set_markup(&format);
|
||||||
Continue(true)
|
|
||||||
});
|
});
|
||||||
|
|
||||||
container.show_all();
|
container.show_all();
|
||||||
|
|
|
@ -2,14 +2,13 @@ use crate::clients::compositor::{Compositor, Visibility, Workspace, WorkspaceUpd
|
||||||
use crate::config::CommonConfig;
|
use crate::config::CommonConfig;
|
||||||
use crate::image::new_icon_button;
|
use crate::image::new_icon_button;
|
||||||
use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext};
|
use crate::modules::{Module, ModuleInfo, ModuleParts, ModuleUpdateEvent, WidgetContext};
|
||||||
use crate::{send_async, try_send};
|
use crate::{glib_recv, send_async, spawn, try_send};
|
||||||
use color_eyre::{Report, Result};
|
use color_eyre::{Report, Result};
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::{Button, IconTheme};
|
use gtk::{Button, IconTheme};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use tokio::spawn;
|
|
||||||
use tokio::sync::mpsc::{Receiver, Sender};
|
use tokio::sync::mpsc::{Receiver, Sender};
|
||||||
use tracing::trace;
|
use tracing::trace;
|
||||||
|
|
||||||
|
@ -205,7 +204,7 @@ impl Module<gtk::Box> for WorkspacesModule {
|
||||||
// since it fires for every workspace subscriber
|
// since it fires for every workspace subscriber
|
||||||
let mut has_initialized = false;
|
let mut has_initialized = false;
|
||||||
|
|
||||||
context.widget_rx.attach(None, move |event| {
|
glib_recv!(context.subscribe(), event => {
|
||||||
match event {
|
match event {
|
||||||
WorkspaceUpdate::Init(workspaces) => {
|
WorkspaceUpdate::Init(workspaces) => {
|
||||||
if !has_initialized {
|
if !has_initialized {
|
||||||
|
@ -350,8 +349,6 @@ impl Module<gtk::Box> for WorkspacesModule {
|
||||||
}
|
}
|
||||||
WorkspaceUpdate::Update(_) => {}
|
WorkspaceUpdate::Update(_) => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
Continue(true)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
44
src/popup.rs
44
src/popup.rs
|
@ -1,8 +1,10 @@
|
||||||
|
use glib::Propagation;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use gtk::gdk::Monitor;
|
use gtk::gdk::Monitor;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::{ApplicationWindow, Orientation};
|
use gtk::{ApplicationWindow, Orientation};
|
||||||
|
use gtk_layer_shell::LayerShell;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
use crate::config::BarPosition;
|
use crate::config::BarPosition;
|
||||||
|
@ -37,52 +39,38 @@ impl Popup {
|
||||||
.application(module_info.app)
|
.application(module_info.app)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
gtk_layer_shell::init_for_window(&win);
|
win.init_layer_shell();
|
||||||
gtk_layer_shell::set_monitor(&win, module_info.monitor);
|
win.set_monitor(module_info.monitor);
|
||||||
gtk_layer_shell::set_layer(&win, gtk_layer_shell::Layer::Overlay);
|
win.set_layer(gtk_layer_shell::Layer::Overlay);
|
||||||
gtk_layer_shell::set_namespace(&win, env!("CARGO_PKG_NAME"));
|
win.set_namespace(env!("CARGO_PKG_NAME"));
|
||||||
|
|
||||||
gtk_layer_shell::set_margin(
|
win.set_layer_shell_margin(
|
||||||
&win,
|
|
||||||
gtk_layer_shell::Edge::Top,
|
gtk_layer_shell::Edge::Top,
|
||||||
if pos == BarPosition::Top { gap } else { 0 },
|
if pos == BarPosition::Top { gap } else { 0 },
|
||||||
);
|
);
|
||||||
gtk_layer_shell::set_margin(
|
win.set_layer_shell_margin(
|
||||||
&win,
|
|
||||||
gtk_layer_shell::Edge::Bottom,
|
gtk_layer_shell::Edge::Bottom,
|
||||||
if pos == BarPosition::Bottom { gap } else { 0 },
|
if pos == BarPosition::Bottom { gap } else { 0 },
|
||||||
);
|
);
|
||||||
gtk_layer_shell::set_margin(
|
win.set_layer_shell_margin(
|
||||||
&win,
|
|
||||||
gtk_layer_shell::Edge::Left,
|
gtk_layer_shell::Edge::Left,
|
||||||
if pos == BarPosition::Left { gap } else { 0 },
|
if pos == BarPosition::Left { gap } else { 0 },
|
||||||
);
|
);
|
||||||
gtk_layer_shell::set_margin(
|
win.set_layer_shell_margin(
|
||||||
&win,
|
|
||||||
gtk_layer_shell::Edge::Right,
|
gtk_layer_shell::Edge::Right,
|
||||||
if pos == BarPosition::Right { gap } else { 0 },
|
if pos == BarPosition::Right { gap } else { 0 },
|
||||||
);
|
);
|
||||||
|
|
||||||
gtk_layer_shell::set_anchor(
|
win.set_anchor(
|
||||||
&win,
|
|
||||||
gtk_layer_shell::Edge::Top,
|
gtk_layer_shell::Edge::Top,
|
||||||
pos == BarPosition::Top || orientation == Orientation::Vertical,
|
pos == BarPosition::Top || orientation == Orientation::Vertical,
|
||||||
);
|
);
|
||||||
gtk_layer_shell::set_anchor(
|
win.set_anchor(gtk_layer_shell::Edge::Bottom, pos == BarPosition::Bottom);
|
||||||
&win,
|
win.set_anchor(
|
||||||
gtk_layer_shell::Edge::Bottom,
|
|
||||||
pos == BarPosition::Bottom,
|
|
||||||
);
|
|
||||||
gtk_layer_shell::set_anchor(
|
|
||||||
&win,
|
|
||||||
gtk_layer_shell::Edge::Left,
|
gtk_layer_shell::Edge::Left,
|
||||||
pos == BarPosition::Left || orientation == Orientation::Horizontal,
|
pos == BarPosition::Left || orientation == Orientation::Horizontal,
|
||||||
);
|
);
|
||||||
gtk_layer_shell::set_anchor(
|
win.set_anchor(gtk_layer_shell::Edge::Right, pos == BarPosition::Right);
|
||||||
&win,
|
|
||||||
gtk_layer_shell::Edge::Right,
|
|
||||||
pos == BarPosition::Right,
|
|
||||||
);
|
|
||||||
|
|
||||||
win.connect_leave_notify_event(move |win, ev| {
|
win.connect_leave_notify_event(move |win, ev| {
|
||||||
const THRESHOLD: f64 = 3.0;
|
const THRESHOLD: f64 = 3.0;
|
||||||
|
@ -111,7 +99,7 @@ impl Popup {
|
||||||
win.hide();
|
win.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
Inhibit(false)
|
Propagation::Proceed
|
||||||
});
|
});
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
@ -229,6 +217,6 @@ impl Popup {
|
||||||
gtk_layer_shell::Edge::Top
|
gtk_layer_shell::Edge::Top
|
||||||
};
|
};
|
||||||
|
|
||||||
gtk_layer_shell::set_margin(&self.window, edge, offset as i32);
|
self.window.set_layer_shell_margin(edge, offset as i32);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
34
src/style.rs
34
src/style.rs
|
@ -1,6 +1,5 @@
|
||||||
use crate::send;
|
use crate::{glib_recv_mpsc, spawn, try_send};
|
||||||
use color_eyre::{Help, Report};
|
use color_eyre::{Help, Report};
|
||||||
use glib::Continue;
|
|
||||||
use gtk::ffi::GTK_STYLE_PROVIDER_PRIORITY_USER;
|
use gtk::ffi::GTK_STYLE_PROVIDER_PRIORITY_USER;
|
||||||
use gtk::prelude::CssProviderExt;
|
use gtk::prelude::CssProviderExt;
|
||||||
use gtk::{gdk, gio, CssProvider, StyleContext};
|
use gtk::{gdk, gio, CssProvider, StyleContext};
|
||||||
|
@ -8,7 +7,7 @@ use notify::event::ModifyKind;
|
||||||
use notify::{recommended_watcher, Event, EventKind, RecursiveMode, Result, Watcher};
|
use notify::{recommended_watcher, Event, EventKind, RecursiveMode, Result, Watcher};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tokio::spawn;
|
use tokio::sync::mpsc;
|
||||||
use tokio::time::sleep;
|
use tokio::time::sleep;
|
||||||
use tracing::{debug, error, info};
|
use tracing::{debug, error, info};
|
||||||
|
|
||||||
|
@ -36,7 +35,7 @@ pub fn load_css(style_path: PathBuf) {
|
||||||
GTK_STYLE_PROVIDER_PRIORITY_USER as u32,
|
GTK_STYLE_PROVIDER_PRIORITY_USER as u32,
|
||||||
);
|
);
|
||||||
|
|
||||||
let (tx, rx) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
|
let (tx, mut rx) = mpsc::channel(8);
|
||||||
|
|
||||||
spawn(async move {
|
spawn(async move {
|
||||||
let style_path2 = style_path.clone();
|
let style_path2 = style_path.clone();
|
||||||
|
@ -49,7 +48,7 @@ pub fn load_css(style_path: PathBuf) {
|
||||||
.map(|p| p == &style_path2)
|
.map(|p| p == &style_path2)
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
{
|
{
|
||||||
send!(tx, style_path2.clone());
|
try_send!(tx, style_path2.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => error!("Error occurred when watching stylesheet: {:?}", e),
|
Err(e) => error!("Error occurred when watching stylesheet: {:?}", e),
|
||||||
|
@ -70,19 +69,14 @@ pub fn load_css(style_path: PathBuf) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
{
|
glib_recv_mpsc!(rx, path => {
|
||||||
rx.attach(None, move |path| {
|
info!("Reloading CSS");
|
||||||
info!("Reloading CSS");
|
if let Err(err) = provider.load_from_file(&gio::File::for_path(path)) {
|
||||||
if let Err(err) = provider
|
error!("{:?}", Report::new(err)
|
||||||
.load_from_file(&gio::File::for_path(path)) {
|
.wrap_err("Failed to load CSS")
|
||||||
error!("{:?}", Report::new(err)
|
.suggestion("Check the CSS file for errors")
|
||||||
.wrap_err("Failed to load CSS")
|
.suggestion("GTK CSS uses a subset of the full CSS spec and many properties are not available. Ensure you are not using any unsupported property.")
|
||||||
.suggestion("Check the CSS file for errors")
|
);
|
||||||
.suggestion("GTK CSS uses a subset of the full CSS spec and many properties are not available. Ensure you are not using any unsupported property.")
|
}
|
||||||
);
|
});
|
||||||
}
|
|
||||||
|
|
||||||
Continue(true)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue