public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
From: "Gonçalo Negrier Duarte" <gonegrier.duarte@gmail.com>
To: gentoo-commits@lists.gentoo.org
Subject: [gentoo-commits] repo/proj/guru:dev commit in: gui-apps/eww/, gui-apps/eww/files/
Date: Thu,  5 Sep 2024 19:50:02 +0000 (UTC)	[thread overview]
Message-ID: <1725565717.606d347cbf9250ce0587a78fc8bf90d172ebea3b.gonegrier.duarte@gentoo> (raw)

commit:     606d347cbf9250ce0587a78fc8bf90d172ebea3b
Author:     Gonçalo Negrier Duarte <gonegrier.duarte <AT> gmail <DOT> com>
AuthorDate: Thu Sep  5 19:48:37 2024 +0000
Commit:     Gonçalo Negrier Duarte <gonegrier.duarte <AT> gmail <DOT> com>
CommitDate: Thu Sep  5 19:48:37 2024 +0000
URL:        https://gitweb.gentoo.org/repo/proj/guru.git/commit/?id=606d347c

gui-apps/eww: update all crates based on latest master (8661abf)

* cleanup 9999 ebuild

Closes: https://bugs.gentoo.org/939086
Closes: https://bugs.gentoo.org/938830
Signed-off-by: Gonçalo Negrier Duarte <gonegrier.duarte <AT> gmail.com>

 gui-apps/eww/eww-0.6.0-r1.ebuild                 |  436 ++
 gui-apps/eww/eww-0.6.0.ebuild                    |  454 --
 gui-apps/eww/eww-9999.ebuild                     |  369 --
 gui-apps/eww/files/eww-0.6.0-fix-version.patch   |   35 -
 gui-apps/eww/files/eww-0.6.0-update-crates.patch | 6019 ++++++++++++++++++++++
 5 files changed, 6455 insertions(+), 858 deletions(-)

diff --git a/gui-apps/eww/eww-0.6.0-r1.ebuild b/gui-apps/eww/eww-0.6.0-r1.ebuild
new file mode 100644
index 000000000..fa16e66d8
--- /dev/null
+++ b/gui-apps/eww/eww-0.6.0-r1.ebuild
@@ -0,0 +1,436 @@
+# Copyright 2022-2024 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=8
+
+CRATES="
+        addr2line@0.22.0
+        adler@1.0.2
+        ahash@0.8.11
+        aho-corasick@1.1.3
+        allocator-api2@0.2.18
+        android-tzdata@0.1.1
+        android_system_properties@0.1.5
+        anstream@0.6.15
+        anstyle-parse@0.2.5
+        anstyle-query@1.1.1
+        anstyle-wincon@3.0.4
+        anstyle@1.0.8
+        anyhow@1.0.86
+        ascii-canvas@3.0.0
+        async-broadcast@0.7.1
+        async-channel@2.3.1
+        async-io@2.3.4
+        async-lock@3.4.0
+        async-process@2.2.4
+        async-recursion@1.1.1
+        async-signal@0.2.10
+        async-task@4.7.1
+        async-trait@0.1.81
+        atk-sys@0.18.0
+        atk@0.18.0
+        atomic-waker@1.1.2
+        autocfg@1.3.0
+        backtrace@0.3.73
+        base64@0.22.1
+        bincode@1.3.3
+        bit-set@0.5.3
+        bit-vec@0.6.3
+        bitflags@1.3.2
+        bitflags@2.6.0
+        block-buffer@0.10.4
+        blocking@1.6.1
+        bumpalo@3.16.0
+        byteorder@1.5.0
+        bytes@1.7.1
+        cached@0.53.1
+        cached_proc_macro@0.23.0
+        cached_proc_macro_types@0.1.1
+        cairo-rs@0.18.5
+        cairo-sys-rs@0.18.2
+        cc@1.1.14
+        cfg-expr@0.15.8
+        cfg-expr@0.16.0
+        cfg-if@1.0.0
+        cfg_aliases@0.2.1
+        chrono-tz-build@0.3.0
+        chrono-tz@0.9.0
+        chrono@0.4.38
+        chumsky@0.9.3
+        clap@4.5.16
+        clap_builder@4.5.15
+        clap_complete@4.5.23
+        clap_derive@4.5.13
+        clap_lex@0.7.2
+        codemap@0.1.3
+        codespan-reporting@0.11.1
+        colorchoice@1.0.2
+        concurrent-queue@2.5.0
+        console@0.15.8
+        core-foundation-sys@0.8.7
+        cpufeatures@0.2.13
+        crossbeam-channel@0.5.13
+        crossbeam-deque@0.8.5
+        crossbeam-epoch@0.9.18
+        crossbeam-utils@0.8.20
+        crunchy@0.2.2
+        crypto-common@0.1.6
+        darling@0.20.10
+        darling_core@0.20.10
+        darling_macro@0.20.10
+        dbusmenu-glib-sys@0.1.0
+        dbusmenu-glib@0.1.0
+        dbusmenu-gtk3-sys@0.1.0
+        dbusmenu-gtk3@0.1.0
+        derive_more-impl@1.0.0
+        derive_more@1.0.0
+        diff@0.1.13
+        digest@0.10.7
+        dirs-next@2.0.0
+        dirs-sys-next@0.1.2
+        dyn-clone@1.0.17
+        either@1.13.0
+        ena@0.14.3
+        encode_unicode@0.3.6
+        endi@1.1.0
+        enumflags2@0.7.10
+        enumflags2_derive@0.7.10
+        env_logger@0.10.2
+        equivalent@1.0.1
+        errno@0.3.9
+        event-listener-strategy@0.5.2
+        event-listener@5.3.1
+        extend@1.2.0
+        fastrand@2.1.1
+        field-offset@0.3.6
+        filetime@0.2.24
+        fixedbitset@0.4.2
+        fnv@1.0.7
+        fsevent-sys@4.1.0
+        futures-channel@0.3.30
+        futures-core@0.3.30
+        futures-executor@0.3.30
+        futures-io@0.3.30
+        futures-lite@2.3.0
+        futures-macro@0.3.30
+        futures-sink@0.3.30
+        futures-task@0.3.30
+        futures-util@0.3.30
+        futures@0.3.30
+        gdk-pixbuf-sys@0.18.0
+        gdk-pixbuf@0.18.5
+        gdk-sys@0.18.0
+        gdk@0.18.0
+        gdkx11-sys@0.18.0
+        gdkx11@0.18.0
+        generic-array@0.14.7
+        gethostname@0.4.3
+        getrandom@0.2.15
+        gimli@0.29.0
+        gio-sys@0.18.1
+        gio@0.18.4
+        glib-macros@0.18.5
+        glib-sys@0.18.1
+        glib@0.18.5
+        gobject-sys@0.18.0
+        grass@0.13.4
+        grass_compiler@0.13.4
+        gtk-layer-shell-sys@0.7.1
+        gtk-layer-shell@0.8.1
+        gtk-sys@0.18.0
+        gtk3-macros@0.18.0
+        gtk@0.18.1
+        hashbrown@0.14.5
+        heck@0.4.1
+        heck@0.5.0
+        hermit-abi@0.3.9
+        hermit-abi@0.4.0
+        hex@0.4.3
+        hifijson@0.2.2
+        humantime@2.1.0
+        iana-time-zone-haiku@0.1.2
+        iana-time-zone@0.1.60
+        ident_case@1.0.1
+        indexmap@2.4.0
+        inotify-sys@0.1.5
+        inotify@0.9.6
+        insta@1.39.0
+        is-terminal@0.4.13
+        is_terminal_polyfill@1.70.1
+        itertools@0.11.0
+        itertools@0.13.0
+        itoa@1.0.11
+        jaq-core@1.5.1
+        jaq-interpret@1.5.0
+        jaq-parse@1.0.3
+        jaq-std@1.6.0
+        jaq-syn@1.6.0
+        js-sys@0.3.70
+        kqueue-sys@1.0.4
+        kqueue@1.0.8
+        lalrpop-util@0.20.2
+        lalrpop@0.20.2
+        lasso@0.7.3
+        lazy_static@1.5.0
+        libc@0.2.158
+        libm@0.2.8
+        libredox@0.1.3
+        linked-hash-map@0.5.6
+        linux-raw-sys@0.4.14
+        lock_api@0.4.12
+        log@0.4.22
+        maplit@1.0.2
+        memchr@2.7.4
+        memoffset@0.9.1
+        miniz_oxide@0.7.4
+        mio@0.8.11
+        mio@1.0.2
+        new_debug_unreachable@1.0.6
+        nix@0.29.0
+        notify@6.1.1
+        ntapi@0.4.1
+        num-traits@0.2.19
+        object@0.36.3
+        once_cell@1.19.0
+        ordered-stream@0.2.0
+        pango-sys@0.18.0
+        pango@0.18.3
+        parking@2.2.0
+        parking_lot@0.12.3
+        parking_lot_core@0.9.10
+        parse-zoneinfo@0.3.1
+        petgraph@0.6.5
+        phf@0.11.2
+        phf_codegen@0.11.2
+        phf_generator@0.11.2
+        phf_macros@0.11.2
+        phf_shared@0.10.0
+        phf_shared@0.11.2
+        pico-args@0.5.0
+        pin-project-lite@0.2.14
+        pin-utils@0.1.0
+        piper@0.2.4
+        pkg-config@0.3.30
+        polling@3.7.3
+        ppv-lite86@0.2.20
+        precomputed-hash@0.1.1
+        pretty_assertions@1.4.0
+        pretty_env_logger@0.5.0
+        proc-macro-crate@1.3.1
+        proc-macro-crate@2.0.0
+        proc-macro-crate@3.1.0
+        proc-macro-error-attr@1.0.4
+        proc-macro-error@1.0.4
+        proc-macro2@1.0.86
+        pure-rust-locales@0.8.1
+        quote@1.0.37
+        rand@0.8.5
+        rand_chacha@0.3.1
+        rand_core@0.6.4
+        rayon-core@1.12.1
+        rayon@1.10.0
+        redox_syscall@0.5.3
+        redox_users@0.4.6
+        ref-cast-impl@1.0.23
+        ref-cast@1.0.23
+        regex-automata@0.4.7
+        regex-syntax@0.8.4
+        regex@1.10.6
+        rustc-demangle@0.1.24
+        rustc_version@0.4.0
+        rustix@0.38.34
+        rustversion@1.0.17
+        ryu@1.0.18
+        same-file@1.0.6
+        scopeguard@1.2.0
+        semver@1.0.23
+        serde@1.0.209
+        serde_derive@1.0.209
+        serde_json@1.0.127
+        serde_repr@0.1.19
+        serde_spanned@0.6.7
+        sha1@0.10.6
+        shlex@1.3.0
+        signal-hook-registry@1.4.2
+        similar@2.6.0
+        simple-signal@1.1.1
+        siphasher@0.3.11
+        slab@0.4.9
+        smallvec@1.13.2
+        smart-default@0.7.1
+        socket2@0.5.7
+        static_assertions@1.1.0
+        string_cache@0.8.7
+        strsim@0.11.1
+        strum@0.26.3
+        strum_macros@0.26.4
+        syn@1.0.109
+        syn@2.0.76
+        sysinfo@0.31.3
+        system-deps@6.2.2
+        system-deps@7.0.2
+        target-lexicon@0.12.16
+        tempfile@3.12.0
+        term@0.7.0
+        termcolor@1.4.1
+        thiserror-impl@1.0.63
+        thiserror@1.0.63
+        tiny-keccak@2.0.2
+        tokio-macros@2.4.0
+        tokio-util@0.7.11
+        tokio@1.39.3
+        toml@0.8.19
+        toml_datetime@0.6.8
+        toml_edit@0.19.15
+        toml_edit@0.20.7
+        toml_edit@0.21.1
+        toml_edit@0.22.20
+        tracing-attributes@0.1.27
+        tracing-core@0.1.32
+        tracing@0.1.40
+        typenum@1.17.0
+        uds_windows@1.1.0
+        unescape@0.1.0
+        unicode-ident@1.0.12
+        unicode-width@0.1.13
+        unicode-xid@0.2.5
+        urlencoding@2.1.3
+        utf8parse@0.2.2
+        version-compare@0.2.0
+        version_check@0.9.5
+        wait-timeout@0.2.0
+        walkdir@2.5.0
+        wasi@0.11.0+wasi-snapshot-preview1
+        wasm-bindgen-backend@0.2.93
+        wasm-bindgen-macro-support@0.2.93
+        wasm-bindgen-macro@0.2.93
+        wasm-bindgen-shared@0.2.93
+        wasm-bindgen@0.2.93
+        web-time@1.1.0
+        winapi-i686-pc-windows-gnu@0.4.0
+        winapi-util@0.1.9
+        winapi-x86_64-pc-windows-gnu@0.4.0
+        winapi@0.3.9
+        windows-core@0.52.0
+        windows-core@0.57.0
+        windows-implement@0.57.0
+        windows-interface@0.57.0
+        windows-result@0.1.2
+        windows-sys@0.48.0
+        windows-sys@0.52.0
+        windows-sys@0.59.0
+        windows-targets@0.48.5
+        windows-targets@0.52.6
+        windows@0.57.0
+        windows_aarch64_gnullvm@0.48.5
+        windows_aarch64_gnullvm@0.52.6
+        windows_aarch64_msvc@0.48.5
+        windows_aarch64_msvc@0.52.6
+        windows_i686_gnu@0.48.5
+        windows_i686_gnu@0.52.6
+        windows_i686_gnullvm@0.52.6
+        windows_i686_msvc@0.48.5
+        windows_i686_msvc@0.52.6
+        windows_x86_64_gnu@0.48.5
+        windows_x86_64_gnu@0.52.6
+        windows_x86_64_gnullvm@0.48.5
+        windows_x86_64_gnullvm@0.52.6
+        windows_x86_64_msvc@0.48.5
+        windows_x86_64_msvc@0.52.6
+        winnow@0.5.40
+        winnow@0.6.18
+        x11@2.21.0
+        x11rb-protocol@0.13.1
+        x11rb@0.13.1
+        xdg-home@1.3.0
+        yansi@0.5.1
+        zbus@4.4.0
+        zbus_macros@4.4.0
+        zbus_names@3.0.0
+        zerocopy-derive@0.7.35
+        zerocopy@0.7.35
+        zvariant@4.2.0
+        zvariant_derive@4.2.0
+        zvariant_utils@2.1.0
+"
+
+inherit cargo shell-completion
+
+DESCRIPTION="Elkowars Wacky Widgets is a standalone widget system made in Rust"
+HOMEPAGE="https://elkowar.github.io/eww/"
+SRC_URI="https://git.sr.ht/~antecrescent/gentoo-files/blob/main/gui-apps/eww/${P}-shellcomp.tar.xz"
+
+if [[ "${PV}" == 9999 ]]; then
+	inherit git-r3
+	EGIT_REPO_URI="https://github.com/elkowar/eww.git"
+else
+	SRC_URI+="
+		https://github.com/elkowar/eww/archive/v${PV}.tar.gz -> ${P}.tar.gz
+		${CARGO_CRATE_URIS}
+	"
+	KEYWORDS="~amd64"
+
+	PATCHES="${FILESDIR}/eww-0.6.0-update-crates.patch"
+fi
+
+LICENSE="MIT"
+# Dependent crate licenses
+LICENSE+="
+	Apache-2.0 Apache-2.0-with-LLVM-exceptions BSD CC0-1.0 ISC LGPL-3
+	Unicode-DFS-2016
+"
+SLOT="0"
+IUSE="X wayland"
+REQUIRED_USE="|| ( X wayland )"
+
+RDEPEND="
+	dev-libs/glib:2
+	dev-libs/libdbusmenu[gtk3]
+	x11-libs/cairo[glib]
+	x11-libs/gdk-pixbuf:2
+	x11-libs/gtk+:3[X?,wayland?]
+	x11-libs/pango
+	wayland? ( gui-libs/gtk-layer-shell )
+"
+# transitively hard-depend on xorg-proto due to gdk-3.0.pc
+DEPEND="${RDEPEND}
+	x11-base/xorg-proto
+"
+BDEPEND="
+	virtual/pkgconfig
+	>=virtual/rust-1.74.0
+"
+
+QA_FLAGS_IGNORED="usr/bin/.*"
+
+src_unpack() {
+	if [[ "${PV}" == 9999 ]]; then
+		git-r3_src_unpack
+		cargo_live_src_unpack
+		unpack ${P}-shellcomp.tar.xz
+	else
+		cargo_src_unpack
+	fi
+}
+
+src_configure() {
+	local myfeatures=(
+		$(usev X x11)
+		$(usev wayland wayland)
+	)
+	cargo_src_configure --no-default-features
+}
+
+src_install() {
+	dobashcomp "${WORKDIR}"/eww
+	dofishcomp "${WORKDIR}"/eww.fish
+	dozshcomp "${WORKDIR}"/_eww
+
+	dodoc README.md CHANGELOG.md
+	cargo_src_install --path crates/eww
+}
+
+pkg_postinst() {
+	elog "Eww wont run without a config file (usually in ~/.config/eww)."
+	elog "For example configs visit https://github.com/elkowar/eww#examples"
+}

diff --git a/gui-apps/eww/eww-0.6.0.ebuild b/gui-apps/eww/eww-0.6.0.ebuild
deleted file mode 100644
index 45364f718..000000000
--- a/gui-apps/eww/eww-0.6.0.ebuild
+++ /dev/null
@@ -1,454 +0,0 @@
-# Copyright 2022-2024 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=8
-
-CRATES="
-	addr2line@0.20.0
-	adler@1.0.2
-	ahash@0.7.6
-	ahash@0.8.9
-	aho-corasick@1.0.4
-	allocator-api2@0.2.16
-	android-tzdata@0.1.1
-	android_system_properties@0.1.5
-	anstream@0.6.12
-	anstyle-parse@0.2.1
-	anstyle-query@1.0.0
-	anstyle-wincon@3.0.2
-	anstyle@1.0.1
-	anyhow@1.0.80
-	ascii-canvas@3.0.0
-	async-broadcast@0.5.1
-	async-channel@1.9.0
-	async-io@1.13.0
-	async-lock@2.8.0
-	async-process@1.7.0
-	async-recursion@1.0.4
-	async-task@4.4.0
-	async-trait@0.1.73
-	atk-sys@0.17.0
-	atk@0.17.1
-	atomic-waker@1.1.1
-	autocfg@1.1.0
-	backtrace@0.3.68
-	base64@0.21.7
-	bincode@1.3.3
-	bit-set@0.5.3
-	bit-vec@0.6.3
-	bitflags@1.3.2
-	bitflags@2.4.0
-	block-buffer@0.10.4
-	blocking@1.3.1
-	bumpalo@3.13.0
-	byteorder@1.4.3
-	bytes@1.4.0
-	cached@0.48.1
-	cached_proc_macro@0.19.1
-	cached_proc_macro_types@0.1.1
-	cairo-rs@0.17.10
-	cairo-sys-rs@0.17.10
-	cc@1.0.82
-	cfg-expr@0.15.4
-	cfg-if@1.0.0
-	chrono-tz-build@0.2.0
-	chrono-tz@0.8.3
-	chrono@0.4.26
-	chumsky@0.9.3
-	clap@4.5.1
-	clap_builder@4.5.1
-	clap_complete@4.5.1
-	clap_derive@4.5.0
-	clap_lex@0.7.0
-	codemap@0.1.3
-	codespan-reporting@0.11.1
-	colorchoice@1.0.0
-	concurrent-queue@2.2.0
-	console@0.15.7
-	convert_case@0.4.0
-	core-foundation-sys@0.8.4
-	cpufeatures@0.2.9
-	crossbeam-channel@0.5.8
-	crossbeam-deque@0.8.3
-	crossbeam-epoch@0.9.15
-	crossbeam-utils@0.8.16
-	crunchy@0.2.2
-	crypto-common@0.1.6
-	darling@0.14.4
-	darling_core@0.14.4
-	darling_macro@0.14.4
-	dbusmenu-glib-sys@0.1.0
-	dbusmenu-glib@0.1.0
-	dbusmenu-gtk3-sys@0.1.0
-	dbusmenu-gtk3@0.1.0
-	deranged@0.3.11
-	derivative@2.2.0
-	derive_more@0.99.17
-	diff@0.1.13
-	digest@0.10.7
-	dirs-next@2.0.0
-	dirs-sys-next@0.1.2
-	dyn-clone@1.0.12
-	either@1.9.0
-	ena@0.14.2
-	encode_unicode@0.3.6
-	enumflags2@0.7.7
-	enumflags2_derive@0.7.7
-	env_logger@0.10.0
-	equivalent@1.0.1
-	errno-dragonfly@0.1.2
-	errno@0.3.2
-	event-listener@2.5.3
-	extend@1.2.0
-	fastrand@1.9.0
-	fastrand@2.0.0
-	field-offset@0.3.6
-	filetime@0.2.22
-	fixedbitset@0.4.2
-	fnv@1.0.7
-	fsevent-sys@4.1.0
-	futures-channel@0.3.28
-	futures-core@0.3.28
-	futures-executor@0.3.28
-	futures-io@0.3.28
-	futures-lite@1.13.0
-	futures-macro@0.3.28
-	futures-sink@0.3.28
-	futures-task@0.3.28
-	futures-util@0.3.28
-	futures@0.3.28
-	gdk-pixbuf-sys@0.17.10
-	gdk-pixbuf@0.17.10
-	gdk-sys@0.17.0
-	gdk@0.17.1
-	gdkx11-sys@0.17.0
-	gdkx11@0.17.0
-	generic-array@0.14.7
-	gethostname@0.2.3
-	getrandom@0.2.10
-	gimli@0.27.3
-	gio-sys@0.17.10
-	gio@0.17.10
-	glib-macros@0.17.10
-	glib-sys@0.17.10
-	glib@0.17.10
-	gobject-sys@0.17.10
-	grass@0.13.1
-	grass_compiler@0.13.0
-	gtk-layer-shell-sys@0.6.0
-	gtk-layer-shell@0.6.1
-	gtk-sys@0.17.0
-	gtk3-macros@0.17.1
-	gtk@0.17.1
-	hashbrown@0.11.2
-	hashbrown@0.12.3
-	hashbrown@0.14.3
-	heck@0.4.1
-	hermit-abi@0.3.2
-	hex@0.4.3
-	hifijson@0.2.0
-	humantime@2.1.0
-	iana-time-zone-haiku@0.1.2
-	iana-time-zone@0.1.57
-	ident_case@1.0.1
-	indexmap@1.9.3
-	indexmap@2.0.0
-	inotify-sys@0.1.5
-	inotify@0.9.6
-	insta@1.31.0
-	instant@0.1.12
-	io-lifetimes@1.0.11
-	is-terminal@0.4.9
-	itertools@0.10.5
-	itertools@0.12.1
-	itoa@1.0.9
-	jaq-core@1.2.1
-	jaq-interpret@1.2.1
-	jaq-parse@1.0.2
-	jaq-std@1.2.1
-	jaq-syn@1.1.0
-	js-sys@0.3.64
-	kqueue-sys@1.0.4
-	kqueue@1.0.8
-	lalrpop-util@0.20.0
-	lalrpop@0.20.0
-	lasso@0.6.0
-	lazy_static@1.4.0
-	libc@0.2.153
-	libm@0.2.8
-	linked-hash-map@0.5.6
-	linux-raw-sys@0.3.8
-	linux-raw-sys@0.4.5
-	lock_api@0.4.10
-	log@0.4.20
-	maplit@1.0.2
-	memchr@2.7.1
-	memoffset@0.6.5
-	memoffset@0.7.1
-	memoffset@0.9.0
-	miniz_oxide@0.7.1
-	mio@0.8.10
-	new_debug_unreachable@1.0.4
-	nix@0.25.1
-	nix@0.26.2
-	nix@0.27.1
-	notify@6.1.1
-	ntapi@0.4.1
-	num-conv@0.1.0
-	num-traits@0.2.16
-	num_cpus@1.16.0
-	object@0.31.1
-	once_cell@1.19.0
-	ordered-stream@0.2.0
-	pango-sys@0.17.10
-	pango@0.17.10
-	parking@2.1.0
-	parking_lot@0.12.1
-	parking_lot_core@0.9.8
-	parse-zoneinfo@0.3.0
-	petgraph@0.6.3
-	phf@0.10.1
-	phf@0.11.2
-	phf_codegen@0.11.2
-	phf_generator@0.10.0
-	phf_generator@0.11.2
-	phf_macros@0.10.0
-	phf_shared@0.10.0
-	phf_shared@0.11.2
-	pico-args@0.5.0
-	pin-project-lite@0.2.12
-	pin-utils@0.1.0
-	pkg-config@0.3.27
-	polling@2.8.0
-	powerfmt@0.2.0
-	ppv-lite86@0.2.17
-	precomputed-hash@0.1.1
-	pretty_assertions@1.4.0
-	pretty_env_logger@0.5.0
-	proc-macro-crate@1.3.1
-	proc-macro-error-attr@1.0.4
-	proc-macro-error@1.0.4
-	proc-macro-hack@0.5.20+deprecated
-	proc-macro2@1.0.78
-	quote@1.0.35
-	rand@0.8.5
-	rand_chacha@0.3.1
-	rand_core@0.6.4
-	rayon-core@1.12.1
-	rayon@1.8.1
-	redox_syscall@0.2.16
-	redox_syscall@0.3.5
-	redox_users@0.4.3
-	ref-cast-impl@1.0.22
-	ref-cast@1.0.22
-	regex-automata@0.4.5
-	regex-syntax@0.7.4
-	regex-syntax@0.8.2
-	regex@1.10.3
-	rustc-demangle@0.1.23
-	rustc_version@0.4.0
-	rustix@0.37.23
-	rustix@0.38.8
-	rustversion@1.0.14
-	ryu@1.0.15
-	same-file@1.0.6
-	scopeguard@1.2.0
-	semver@1.0.18
-	serde@1.0.197
-	serde_derive@1.0.197
-	serde_json@1.0.105
-	serde_repr@0.1.16
-	serde_spanned@0.6.3
-	sha1@0.10.5
-	signal-hook-registry@1.4.1
-	signal-hook@0.3.17
-	similar@2.2.1
-	simple-signal@1.1.1
-	siphasher@0.3.10
-	slab@0.4.8
-	smallvec@1.11.0
-	smart-default@0.7.1
-	socket2@0.4.9
-	socket2@0.5.6
-	static_assertions@1.1.0
-	string_cache@0.8.7
-	strsim@0.10.0
-	strsim@0.11.0
-	strum@0.26.1
-	strum_macros@0.26.1
-	syn@1.0.109
-	syn@2.0.50
-	sysinfo@0.30.5
-	system-deps@6.1.1
-	target-lexicon@0.12.11
-	tempfile@3.8.0
-	term@0.7.0
-	termcolor@1.2.0
-	thiserror-impl@1.0.46
-	thiserror@1.0.46
-	time-core@0.1.2
-	time-macros@0.2.17
-	time@0.1.45
-	time@0.3.34
-	tiny-keccak@2.0.2
-	tokio-macros@2.2.0
-	tokio-util@0.7.8
-	tokio@1.36.0
-	toml@0.7.6
-	toml_datetime@0.6.3
-	toml_edit@0.19.14
-	tracing-attributes@0.1.26
-	tracing-core@0.1.31
-	tracing@0.1.37
-	typenum@1.16.0
-	uds_windows@1.0.2
-	unescape@0.1.0
-	unicode-ident@1.0.11
-	unicode-width@0.1.10
-	unicode-xid@0.2.4
-	urlencoding@2.1.3
-	utf8parse@0.2.1
-	version-compare@0.1.1
-	version_check@0.9.4
-	wait-timeout@0.2.0
-	waker-fn@1.1.0
-	walkdir@2.3.3
-	wasi@0.10.0+wasi-snapshot-preview1
-	wasi@0.11.0+wasi-snapshot-preview1
-	wasm-bindgen-backend@0.2.87
-	wasm-bindgen-macro-support@0.2.87
-	wasm-bindgen-macro@0.2.87
-	wasm-bindgen-shared@0.2.87
-	wasm-bindgen@0.2.87
-	winapi-i686-pc-windows-gnu@0.4.0
-	winapi-util@0.1.5
-	winapi-wsapoll@0.1.1
-	winapi-x86_64-pc-windows-gnu@0.4.0
-	winapi@0.3.9
-	windows-core@0.52.0
-	windows-sys@0.45.0
-	windows-sys@0.48.0
-	windows-sys@0.52.0
-	windows-targets@0.42.2
-	windows-targets@0.48.2
-	windows-targets@0.52.3
-	windows@0.48.0
-	windows@0.52.0
-	windows_aarch64_gnullvm@0.42.2
-	windows_aarch64_gnullvm@0.48.2
-	windows_aarch64_gnullvm@0.52.3
-	windows_aarch64_msvc@0.42.2
-	windows_aarch64_msvc@0.48.2
-	windows_aarch64_msvc@0.52.3
-	windows_i686_gnu@0.42.2
-	windows_i686_gnu@0.48.2
-	windows_i686_gnu@0.52.3
-	windows_i686_msvc@0.42.2
-	windows_i686_msvc@0.48.2
-	windows_i686_msvc@0.52.3
-	windows_x86_64_gnu@0.42.2
-	windows_x86_64_gnu@0.48.2
-	windows_x86_64_gnu@0.52.3
-	windows_x86_64_gnullvm@0.42.2
-	windows_x86_64_gnullvm@0.48.2
-	windows_x86_64_gnullvm@0.52.3
-	windows_x86_64_msvc@0.42.2
-	windows_x86_64_msvc@0.48.2
-	windows_x86_64_msvc@0.52.3
-	winnow@0.5.11
-	x11@2.21.0
-	x11rb-protocol@0.11.1
-	x11rb@0.11.1
-	xdg-home@1.0.0
-	yaml-rust@0.4.5
-	yansi@0.5.1
-	zbus@3.14.1
-	zbus_macros@3.14.1
-	zbus_names@2.6.0
-	zerocopy-derive@0.7.32
-	zerocopy@0.7.32
-	zvariant@3.15.0
-	zvariant_derive@3.15.0
-	zvariant_utils@1.0.1
-"
-
-inherit cargo shell-completion
-
-DESCRIPTION="Elkowars Wacky Widgets is a standalone widget system made in Rust"
-HOMEPAGE="https://elkowar.github.io/eww/"
-SRC_URI="https://git.sr.ht/~antecrescent/gentoo-files/blob/main/gui-apps/eww/${P}-shellcomp.tar.xz"
-
-if [[ "${PV}" == 9999 ]]; then
-	inherit git-r3
-	EGIT_REPO_URI="https://github.com/elkowar/eww.git"
-else
-	SRC_URI+="
-		https://github.com/elkowar/eww/archive/v${PV}.tar.gz -> ${P}.tar.gz
-		${CARGO_CRATE_URIS}
-	"
-	KEYWORDS="~amd64"
-
-	PATCHES="${FILESDIR}/eww-0.6.0-fix-version.patch"
-fi
-
-LICENSE="MIT"
-# Dependent crate licenses
-LICENSE+="
-	Apache-2.0 Apache-2.0-with-LLVM-exceptions BSD CC0-1.0 ISC LGPL-3
-	Unicode-DFS-2016
-"
-SLOT="0"
-IUSE="X wayland"
-REQUIRED_USE="|| ( X wayland )"
-
-RDEPEND="
-	dev-libs/glib:2
-	dev-libs/libdbusmenu[gtk3]
-	x11-libs/cairo[glib]
-	x11-libs/gdk-pixbuf:2
-	x11-libs/gtk+:3[X?,wayland?]
-	x11-libs/pango
-	wayland? ( gui-libs/gtk-layer-shell )
-"
-# transitively hard-depend on xorg-proto due to gdk-3.0.pc
-DEPEND="${RDEPEND}
-	x11-base/xorg-proto
-"
-BDEPEND="
-	virtual/pkgconfig
-	>=virtual/rust-1.74.0
-"
-
-QA_FLAGS_IGNORED="usr/bin/.*"
-
-src_unpack() {
-	if [[ "${PV}" == 9999 ]]; then
-		git-r3_src_unpack
-		cargo_live_src_unpack
-		unpack ${P}-shellcomp.tar.xz
-	else
-		cargo_src_unpack
-	fi
-}
-
-src_configure() {
-	local myfeatures=(
-		$(usev X x11)
-		$(usev wayland wayland)
-	)
-	cargo_src_configure --no-default-features
-}
-
-src_install() {
-	dobashcomp "${WORKDIR}"/eww
-	dofishcomp "${WORKDIR}"/eww.fish
-	dozshcomp "${WORKDIR}"/_eww
-
-	dodoc README.md CHANGELOG.md
-	cargo_src_install --path crates/eww
-}
-
-pkg_postinst() {
-	elog "Eww wont run without a config file (usually in ~/.config/eww)."
-	elog "For example configs visit https://github.com/elkowar/eww#examples"
-}

diff --git a/gui-apps/eww/eww-9999.ebuild b/gui-apps/eww/eww-9999.ebuild
index 00c4650dc..ed4d039a9 100644
--- a/gui-apps/eww/eww-9999.ebuild
+++ b/gui-apps/eww/eww-9999.ebuild
@@ -3,375 +3,6 @@
 
 EAPI=8
 
-CRATES="
-	addr2line@0.20.0
-	adler@1.0.2
-	ahash@0.7.8
-	ahash@0.8.9
-	aho-corasick@1.0.4
-	allocator-api2@0.2.16
-	android-tzdata@0.1.1
-	android_system_properties@0.1.5
-	anstream@0.6.12
-	anstyle-parse@0.2.1
-	anstyle-query@1.0.0
-	anstyle-wincon@3.0.2
-	anstyle@1.0.1
-	anyhow@1.0.80
-	ascii-canvas@3.0.0
-	async-broadcast@0.5.1
-	async-channel@1.9.0
-	async-io@1.13.0
-	async-lock@2.8.0
-	async-process@1.7.0
-	async-recursion@1.0.4
-	async-task@4.4.0
-	async-trait@0.1.73
-	atk-sys@0.17.0
-	atk@0.17.1
-	atomic-waker@1.1.1
-	autocfg@1.1.0
-	backtrace@0.3.68
-	base64@0.21.7
-	bincode@1.3.3
-	bit-set@0.5.3
-	bit-vec@0.6.3
-	bitflags@1.3.2
-	bitflags@2.4.0
-	block-buffer@0.10.4
-	blocking@1.3.1
-	bumpalo@3.13.0
-	byteorder@1.4.3
-	bytes@1.4.0
-	cached@0.48.1
-	cached_proc_macro@0.19.1
-	cached_proc_macro_types@0.1.1
-	cairo-rs@0.17.10
-	cairo-sys-rs@0.17.10
-	cc@1.0.82
-	cfg-expr@0.15.4
-	cfg-if@1.0.0
-	chrono-tz-build@0.2.0
-	chrono-tz@0.8.3
-	chrono@0.4.26
-	chumsky@0.9.3
-	clap@4.5.1
-	clap_builder@4.5.1
-	clap_complete@4.5.1
-	clap_derive@4.5.0
-	clap_lex@0.7.0
-	codemap@0.1.3
-	codespan-reporting@0.11.1
-	colorchoice@1.0.0
-	concurrent-queue@2.2.0
-	console@0.15.7
-	convert_case@0.4.0
-	core-foundation-sys@0.8.4
-	cpufeatures@0.2.9
-	crossbeam-channel@0.5.8
-	crossbeam-deque@0.8.3
-	crossbeam-epoch@0.9.15
-	crossbeam-utils@0.8.16
-	crunchy@0.2.2
-	crypto-common@0.1.6
-	darling@0.14.4
-	darling_core@0.14.4
-	darling_macro@0.14.4
-	dbusmenu-glib-sys@0.1.0
-	dbusmenu-glib@0.1.0
-	dbusmenu-gtk3-sys@0.1.0
-	dbusmenu-gtk3@0.1.0
-	deranged@0.3.11
-	derivative@2.2.0
-	derive_more@0.99.17
-	diff@0.1.13
-	digest@0.10.7
-	dirs-next@2.0.0
-	dirs-sys-next@0.1.2
-	dyn-clone@1.0.12
-	either@1.9.0
-	ena@0.14.2
-	encode_unicode@0.3.6
-	enumflags2@0.7.7
-	enumflags2_derive@0.7.7
-	env_logger@0.10.0
-	equivalent@1.0.1
-	errno-dragonfly@0.1.2
-	errno@0.3.2
-	event-listener@2.5.3
-	extend@1.2.0
-	fastrand@1.9.0
-	fastrand@2.0.0
-	field-offset@0.3.6
-	filetime@0.2.22
-	fixedbitset@0.4.2
-	fnv@1.0.7
-	fsevent-sys@4.1.0
-	futures-channel@0.3.28
-	futures-core@0.3.28
-	futures-executor@0.3.28
-	futures-io@0.3.28
-	futures-lite@1.13.0
-	futures-macro@0.3.28
-	futures-sink@0.3.28
-	futures-task@0.3.28
-	futures-util@0.3.28
-	futures@0.3.28
-	gdk-pixbuf-sys@0.17.10
-	gdk-pixbuf@0.17.10
-	gdk-sys@0.17.0
-	gdk@0.17.1
-	gdkx11-sys@0.17.0
-	gdkx11@0.17.0
-	generic-array@0.14.7
-	gethostname@0.2.3
-	getrandom@0.2.10
-	gimli@0.27.3
-	gio-sys@0.17.10
-	gio@0.17.10
-	glib-macros@0.17.10
-	glib-sys@0.17.10
-	glib@0.17.10
-	gobject-sys@0.17.10
-	grass@0.13.1
-	grass_compiler@0.13.0
-	gtk-layer-shell-sys@0.6.0
-	gtk-layer-shell@0.6.1
-	gtk-sys@0.17.0
-	gtk3-macros@0.17.1
-	gtk@0.17.1
-	hashbrown@0.11.2
-	hashbrown@0.12.3
-	hashbrown@0.14.3
-	heck@0.4.1
-	hermit-abi@0.3.2
-	hex@0.4.3
-	hifijson@0.2.0
-	humantime@2.1.0
-	iana-time-zone-haiku@0.1.2
-	iana-time-zone@0.1.57
-	ident_case@1.0.1
-	indexmap@1.9.3
-	indexmap@2.0.0
-	inotify-sys@0.1.5
-	inotify@0.9.6
-	insta@1.31.0
-	instant@0.1.12
-	io-lifetimes@1.0.11
-	is-terminal@0.4.9
-	itertools@0.10.5
-	itertools@0.12.1
-	itoa@1.0.9
-	jaq-core@1.2.1
-	jaq-interpret@1.2.1
-	jaq-parse@1.0.2
-	jaq-std@1.2.1
-	jaq-syn@1.1.0
-	js-sys@0.3.64
-	kqueue-sys@1.0.4
-	kqueue@1.0.8
-	lalrpop-util@0.20.0
-	lalrpop@0.20.0
-	lasso@0.6.0
-	lazy_static@1.4.0
-	libc@0.2.153
-	libm@0.2.8
-	linked-hash-map@0.5.6
-	linux-raw-sys@0.3.8
-	linux-raw-sys@0.4.5
-	lock_api@0.4.10
-	log@0.4.20
-	maplit@1.0.2
-	memchr@2.7.1
-	memoffset@0.6.5
-	memoffset@0.7.1
-	memoffset@0.9.0
-	miniz_oxide@0.7.1
-	mio@0.8.10
-	new_debug_unreachable@1.0.4
-	nix@0.25.1
-	nix@0.26.2
-	nix@0.27.1
-	notify@6.1.1
-	ntapi@0.4.1
-	num-conv@0.1.0
-	num-traits@0.2.16
-	num_cpus@1.16.0
-	object@0.31.1
-	once_cell@1.19.0
-	ordered-stream@0.2.0
-	pango-sys@0.17.10
-	pango@0.17.10
-	parking@2.1.0
-	parking_lot@0.12.1
-	parking_lot_core@0.9.8
-	parse-zoneinfo@0.3.0
-	petgraph@0.6.3
-	phf@0.10.1
-	phf@0.11.2
-	phf_codegen@0.11.2
-	phf_generator@0.10.0
-	phf_generator@0.11.2
-	phf_macros@0.10.0
-	phf_shared@0.10.0
-	phf_shared@0.11.2
-	pico-args@0.5.0
-	pin-project-lite@0.2.12
-	pin-utils@0.1.0
-	pkg-config@0.3.27
-	polling@2.8.0
-	powerfmt@0.2.0
-	ppv-lite86@0.2.17
-	precomputed-hash@0.1.1
-	pretty_assertions@1.4.0
-	pretty_env_logger@0.5.0
-	proc-macro-crate@1.3.1
-	proc-macro-error-attr@1.0.4
-	proc-macro-error@1.0.4
-	proc-macro-hack@0.5.20+deprecated
-	proc-macro2@1.0.78
-	quote@1.0.35
-	rand@0.8.5
-	rand_chacha@0.3.1
-	rand_core@0.6.4
-	rayon-core@1.12.1
-	rayon@1.8.1
-	redox_syscall@0.2.16
-	redox_syscall@0.3.5
-	redox_users@0.4.3
-	ref-cast-impl@1.0.22
-	ref-cast@1.0.22
-	regex-automata@0.4.5
-	regex-syntax@0.7.4
-	regex-syntax@0.8.2
-	regex@1.10.3
-	rustc-demangle@0.1.23
-	rustc_version@0.4.0
-	rustix@0.37.23
-	rustix@0.38.8
-	rustversion@1.0.14
-	ryu@1.0.15
-	same-file@1.0.6
-	scopeguard@1.2.0
-	semver@1.0.18
-	serde@1.0.197
-	serde_derive@1.0.197
-	serde_json@1.0.105
-	serde_repr@0.1.16
-	serde_spanned@0.6.3
-	sha1@0.10.5
-	signal-hook-registry@1.4.1
-	signal-hook@0.3.17
-	similar@2.2.1
-	simple-signal@1.1.1
-	siphasher@0.3.10
-	slab@0.4.8
-	smallvec@1.11.0
-	smart-default@0.7.1
-	socket2@0.4.9
-	socket2@0.5.6
-	static_assertions@1.1.0
-	string_cache@0.8.7
-	strsim@0.10.0
-	strsim@0.11.0
-	strum@0.26.1
-	strum_macros@0.26.1
-	syn@1.0.109
-	syn@2.0.50
-	sysinfo@0.30.5
-	system-deps@6.1.1
-	target-lexicon@0.12.11
-	tempfile@3.8.0
-	term@0.7.0
-	termcolor@1.2.0
-	thiserror-impl@1.0.46
-	thiserror@1.0.46
-	time-core@0.1.2
-	time-macros@0.2.17
-	time@0.1.45
-	time@0.3.34
-	tiny-keccak@2.0.2
-	tokio-macros@2.2.0
-	tokio-util@0.7.8
-	tokio@1.36.0
-	toml@0.7.6
-	toml_datetime@0.6.3
-	toml_edit@0.19.14
-	tracing-attributes@0.1.26
-	tracing-core@0.1.31
-	tracing@0.1.37
-	typenum@1.16.0
-	uds_windows@1.0.2
-	unescape@0.1.0
-	unicode-ident@1.0.11
-	unicode-width@0.1.10
-	unicode-xid@0.2.4
-	urlencoding@2.1.3
-	utf8parse@0.2.1
-	version-compare@0.1.1
-	version_check@0.9.4
-	wait-timeout@0.2.0
-	waker-fn@1.1.0
-	walkdir@2.3.3
-	wasi@0.10.0+wasi-snapshot-preview1
-	wasi@0.11.0+wasi-snapshot-preview1
-	wasm-bindgen-backend@0.2.87
-	wasm-bindgen-macro-support@0.2.87
-	wasm-bindgen-macro@0.2.87
-	wasm-bindgen-shared@0.2.87
-	wasm-bindgen@0.2.87
-	winapi-i686-pc-windows-gnu@0.4.0
-	winapi-util@0.1.5
-	winapi-wsapoll@0.1.1
-	winapi-x86_64-pc-windows-gnu@0.4.0
-	winapi@0.3.9
-	windows-core@0.52.0
-	windows-sys@0.45.0
-	windows-sys@0.48.0
-	windows-sys@0.52.0
-	windows-targets@0.42.2
-	windows-targets@0.48.2
-	windows-targets@0.52.3
-	windows@0.48.0
-	windows@0.52.0
-	windows_aarch64_gnullvm@0.42.2
-	windows_aarch64_gnullvm@0.48.2
-	windows_aarch64_gnullvm@0.52.3
-	windows_aarch64_msvc@0.42.2
-	windows_aarch64_msvc@0.48.2
-	windows_aarch64_msvc@0.52.3
-	windows_i686_gnu@0.42.2
-	windows_i686_gnu@0.48.2
-	windows_i686_gnu@0.52.3
-	windows_i686_msvc@0.42.2
-	windows_i686_msvc@0.48.2
-	windows_i686_msvc@0.52.3
-	windows_x86_64_gnu@0.42.2
-	windows_x86_64_gnu@0.48.2
-	windows_x86_64_gnu@0.52.3
-	windows_x86_64_gnullvm@0.42.2
-	windows_x86_64_gnullvm@0.48.2
-	windows_x86_64_gnullvm@0.52.3
-	windows_x86_64_msvc@0.42.2
-	windows_x86_64_msvc@0.48.2
-	windows_x86_64_msvc@0.52.3
-	winnow@0.5.11
-	x11@2.21.0
-	x11rb-protocol@0.11.1
-	x11rb@0.11.1
-	xdg-home@1.0.0
-	yaml-rust@0.4.5
-	yansi@0.5.1
-	zbus@3.14.1
-	zbus_macros@3.14.1
-	zbus_names@2.6.0
-	zerocopy-derive@0.7.32
-	zerocopy@0.7.32
-	zvariant@3.15.0
-	zvariant_derive@3.15.0
-	zvariant_utils@1.0.1
-"
-
 inherit cargo shell-completion
 
 DESCRIPTION="Elkowars Wacky Widgets is a standalone widget system made in Rust"

diff --git a/gui-apps/eww/files/eww-0.6.0-fix-version.patch b/gui-apps/eww/files/eww-0.6.0-fix-version.patch
deleted file mode 100644
index 6c46ee0e3..000000000
--- a/gui-apps/eww/files/eww-0.6.0-fix-version.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-From 8397744f403c87ab39523b4bf9e0216ad444f1bb Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?W=C3=B6lfchen?= <w-lfchen@posteo.net>
-Date: Sun, 21 Apr 2024 20:04:50 +0000
-Subject: [PATCH] fix: bump cargo version (#1080)
-
----
- Cargo.lock            | 2 +-
- crates/eww/Cargo.toml | 2 +-
- 2 files changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/Cargo.lock b/Cargo.lock
-index a3f59426..5d94bd4b 100644
---- a/Cargo.lock
-+++ b/Cargo.lock
-@@ -920,7 +920,7 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
- 
- [[package]]
- name = "eww"
--version = "0.5.0"
-+version = "0.6.0"
- dependencies = [
-  "anyhow",
-  "bincode",
-diff --git a/crates/eww/Cargo.toml b/crates/eww/Cargo.toml
-index a5b62d9e..f916499c 100644
---- a/crates/eww/Cargo.toml
-+++ b/crates/eww/Cargo.toml
-@@ -1,6 +1,6 @@
- [package]
- name = "eww"
--version = "0.5.0"
-+version = "0.6.0"
- authors = ["elkowar <5300871+elkowar@users.noreply.github.com>"]
- description = "Widgets for everyone!"
- license = "MIT"

diff --git a/gui-apps/eww/files/eww-0.6.0-update-crates.patch b/gui-apps/eww/files/eww-0.6.0-update-crates.patch
new file mode 100644
index 000000000..d54657f86
--- /dev/null
+++ b/gui-apps/eww/files/eww-0.6.0-update-crates.patch
@@ -0,0 +1,6019 @@
+From bd00136f54421596842dc8515836fe85dff02938 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Gon=C3=A7alo=20Negrier=20Duarte?=
+ <gonegrier.duarte@gmail.com>
+Date: Thu, 5 Sep 2024 20:39:57 +0100
+Subject: [PATCH 1/1] eww-0.6.0-update-crates
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Gonçalo Negrier Duarte <gonegrier.duarte@gmail.com>
+---
+ Cargo.lock                                    | 1934 ++++++++---------
+ Cargo.toml                                    |   56 +-
+ crates/eww/Cargo.toml                         |   35 +-
+ crates/eww/src/app.rs                         |   33 +-
+ crates/eww/src/config/inbuilt.rs              |    4 +-
+ crates/eww/src/config/system_stats.rs         |   47 +-
+ crates/eww/src/display_backend.rs             |   43 +-
+ crates/eww/src/geometry.rs                    |    4 +-
+ crates/eww/src/main.rs                        |   23 +-
+ crates/eww/src/server.rs                      |   17 +-
+ crates/eww/src/widgets/build_widget.rs        |    2 +-
+ .../eww/src/widgets/circular_progressbar.rs   |    9 +-
+ crates/eww/src/widgets/graph.rs               |   47 +-
+ crates/eww/src/widgets/systray.rs             |   33 +-
+ crates/eww/src/widgets/transform.rs           |   37 +-
+ crates/eww/src/widgets/widget_definitions.rs  |  170 +-
+ crates/eww/src/widgets/window.rs              |    3 +-
+ crates/eww/src/window_arguments.rs            |    4 +-
+ crates/eww/src/window_initiator.rs            |    2 -
+ crates/eww_shared_util/Cargo.toml             |    1 +
+ crates/eww_shared_util/src/lib.rs             |    2 +
+ crates/eww_shared_util/src/locale.rs          |   14 +
+ crates/eww_shared_util/src/wrappers.rs        |   10 +-
+ crates/notifier_host/Cargo.toml               |    5 +-
+ crates/notifier_host/src/host.rs              |    4 +-
+ crates/notifier_host/src/icon.rs              |   10 +-
+ crates/notifier_host/src/item.rs              |    6 +-
+ .../src/proxy/dbus_status_notifier_item.rs    |   69 +-
+ .../src/proxy/dbus_status_notifier_watcher.rs |   35 +-
+ crates/notifier_host/src/proxy/mod.rs         |   12 +-
+ crates/notifier_host/src/watcher.rs           |   20 +-
+ crates/simplexpr/Cargo.toml                   |    6 +-
+ crates/simplexpr/src/eval.rs                  |   26 +-
+ crates/yuck/src/parser/ast_iterator.rs        |    2 +-
+ crates/yuck/src/value/coords.rs               |   14 +-
+ 35 files changed, 1416 insertions(+), 1323 deletions(-)
+ create mode 100644 crates/eww_shared_util/src/locale.rs
+
+diff --git a/Cargo.lock b/Cargo.lock
+index 8baf72e..6b5b3c9 100644
+--- a/Cargo.lock
++++ b/Cargo.lock
+@@ -4,9 +4,9 @@ version = 3
+ 
+ [[package]]
+ name = "addr2line"
+-version = "0.20.0"
++version = "0.22.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3"
++checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678"
+ dependencies = [
+  "gimli",
+ ]
+@@ -19,20 +19,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+ 
+ [[package]]
+ name = "ahash"
+-version = "0.7.6"
++version = "0.8.11"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
+-dependencies = [
+- "getrandom",
+- "once_cell",
+- "version_check",
+-]
+-
+-[[package]]
+-name = "ahash"
+-version = "0.8.9"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "d713b3834d76b85304d4d525563c1276e2e30dc97cc67bfb4585a4a29fc2c89f"
++checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
+ dependencies = [
+  "cfg-if",
+  "getrandom",
+@@ -43,18 +32,18 @@ dependencies = [
+ 
+ [[package]]
+ name = "aho-corasick"
+-version = "1.0.4"
++version = "1.1.3"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "6748e8def348ed4d14996fa801f4122cd763fff530258cdc03f64b25f89d3a5a"
++checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
+ dependencies = [
+  "memchr",
+ ]
+ 
+ [[package]]
+ name = "allocator-api2"
+-version = "0.2.16"
++version = "0.2.18"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
++checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
+ 
+ [[package]]
+ name = "android-tzdata"
+@@ -73,47 +62,48 @@ dependencies = [
+ 
+ [[package]]
+ name = "anstream"
+-version = "0.6.12"
++version = "0.6.15"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "96b09b5178381e0874812a9b157f7fe84982617e48f71f4e3235482775e5b540"
++checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526"
+ dependencies = [
+  "anstyle",
+  "anstyle-parse",
+  "anstyle-query",
+  "anstyle-wincon",
+  "colorchoice",
++ "is_terminal_polyfill",
+  "utf8parse",
+ ]
+ 
+ [[package]]
+ name = "anstyle"
+-version = "1.0.1"
++version = "1.0.8"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd"
++checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1"
+ 
+ [[package]]
+ name = "anstyle-parse"
+-version = "0.2.1"
++version = "0.2.5"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333"
++checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb"
+ dependencies = [
+  "utf8parse",
+ ]
+ 
+ [[package]]
+ name = "anstyle-query"
+-version = "1.0.0"
++version = "1.1.1"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
++checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
+ dependencies = [
+- "windows-sys 0.48.0",
++ "windows-sys 0.52.0",
+ ]
+ 
+ [[package]]
+ name = "anstyle-wincon"
+-version = "3.0.2"
++version = "3.0.4"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
++checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8"
+ dependencies = [
+  "anstyle",
+  "windows-sys 0.52.0",
+@@ -121,9 +111,9 @@ dependencies = [
+ 
+ [[package]]
+ name = "anyhow"
+-version = "1.0.80"
++version = "1.0.86"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1"
++checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
+ 
+ [[package]]
+ name = "ascii-canvas"
+@@ -136,141 +126,164 @@ dependencies = [
+ 
+ [[package]]
+ name = "async-broadcast"
+-version = "0.5.1"
++version = "0.7.1"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "7c48ccdbf6ca6b121e0f586cbc0e73ae440e56c67c30fa0873b4e110d9c26d2b"
++checksum = "20cd0e2e25ea8e5f7e9df04578dc6cf5c83577fd09b1a46aaf5c85e1c33f2a7e"
+ dependencies = [
+  "event-listener",
++ "event-listener-strategy",
+  "futures-core",
++ "pin-project-lite",
+ ]
+ 
+ [[package]]
+ name = "async-channel"
+-version = "1.9.0"
++version = "2.3.1"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35"
++checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a"
+ dependencies = [
+  "concurrent-queue",
+- "event-listener",
++ "event-listener-strategy",
+  "futures-core",
++ "pin-project-lite",
+ ]
+ 
+ [[package]]
+ name = "async-io"
+-version = "1.13.0"
++version = "2.3.4"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af"
++checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8"
+ dependencies = [
+  "async-lock",
+- "autocfg",
+  "cfg-if",
+  "concurrent-queue",
++ "futures-io",
+  "futures-lite",
+- "log",
+  "parking",
+  "polling",
+- "rustix 0.37.23",
++ "rustix",
+  "slab",
+- "socket2 0.4.9",
+- "waker-fn",
++ "tracing",
++ "windows-sys 0.59.0",
+ ]
+ 
+ [[package]]
+ name = "async-lock"
+-version = "2.8.0"
++version = "3.4.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b"
++checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18"
+ dependencies = [
+  "event-listener",
++ "event-listener-strategy",
++ "pin-project-lite",
+ ]
+ 
+ [[package]]
+ name = "async-process"
+-version = "1.7.0"
++version = "2.2.4"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "7a9d28b1d97e08915212e2e45310d47854eafa69600756fc735fb788f75199c9"
++checksum = "a8a07789659a4d385b79b18b9127fc27e1a59e1e89117c78c5ea3b806f016374"
+ dependencies = [
++ "async-channel",
+  "async-io",
+  "async-lock",
+- "autocfg",
++ "async-signal",
++ "async-task",
+  "blocking",
+  "cfg-if",
+  "event-listener",
+  "futures-lite",
+- "rustix 0.37.23",
+- "signal-hook",
+- "windows-sys 0.48.0",
++ "rustix",
++ "tracing",
++ "windows-sys 0.59.0",
+ ]
+ 
+ [[package]]
+ name = "async-recursion"
+-version = "1.0.4"
++version = "1.1.1"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "0e97ce7de6cf12de5d7226c73f5ba9811622f4db3a5b91b55c53e987e5f91cba"
++checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
+ dependencies = [
+  "proc-macro2",
+  "quote",
+- "syn 2.0.50",
++ "syn 2.0.76",
++]
++
++[[package]]
++name = "async-signal"
++version = "0.2.10"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3"
++dependencies = [
++ "async-io",
++ "async-lock",
++ "atomic-waker",
++ "cfg-if",
++ "futures-core",
++ "futures-io",
++ "rustix",
++ "signal-hook-registry",
++ "slab",
++ "windows-sys 0.59.0",
+ ]
+ 
+ [[package]]
+ name = "async-task"
+-version = "4.4.0"
++version = "4.7.1"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae"
++checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de"
+ 
+ [[package]]
+ name = "async-trait"
+-version = "0.1.73"
++version = "0.1.81"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0"
++checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107"
+ dependencies = [
+  "proc-macro2",
+  "quote",
+- "syn 2.0.50",
++ "syn 2.0.76",
+ ]
+ 
+ [[package]]
+ name = "atk"
+-version = "0.17.1"
++version = "0.18.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "6ba16453d10c712284061a05f6510f75abeb92b56ba88dfeb48c74775020cc22"
++checksum = "b4af014b17dd80e8af9fa689b2d4a211ddba6eb583c1622f35d0cb543f6b17e4"
+ dependencies = [
+  "atk-sys",
+- "bitflags 1.3.2",
+  "glib",
+  "libc",
+ ]
+ 
+ [[package]]
+ name = "atk-sys"
+-version = "0.17.0"
++version = "0.18.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "e3bf0a7ca572fbd5762fd8f8cd65a581e06767bc1234913fe1f43e370cff6e90"
++checksum = "251e0b7d90e33e0ba930891a505a9a35ece37b2dd37a14f3ffc306c13b980009"
+ dependencies = [
+  "glib-sys",
+  "gobject-sys",
+  "libc",
+- "system-deps",
++ "system-deps 6.2.2",
+ ]
+ 
+ [[package]]
+ name = "atomic-waker"
+-version = "1.1.1"
++version = "1.1.2"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3"
++checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
+ 
+ [[package]]
+ name = "autocfg"
+-version = "1.1.0"
++version = "1.3.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
++checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
+ 
+ [[package]]
+ name = "backtrace"
+-version = "0.3.68"
++version = "0.3.73"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12"
++checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a"
+ dependencies = [
+  "addr2line",
+  "cc",
+@@ -283,9 +296,9 @@ dependencies = [
+ 
+ [[package]]
+ name = "base64"
+-version = "0.21.7"
++version = "0.22.1"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
++checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
+ 
+ [[package]]
+ name = "bincode"
+@@ -319,9 +332,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+ 
+ [[package]]
+ name = "bitflags"
+-version = "2.4.0"
++version = "2.6.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
++checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
+ 
+ [[package]]
+ name = "block-buffer"
+@@ -334,62 +347,60 @@ dependencies = [
+ 
+ [[package]]
+ name = "blocking"
+-version = "1.3.1"
++version = "1.6.1"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "77231a1c8f801696fc0123ec6150ce92cffb8e164a02afb9c8ddee0e9b65ad65"
++checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea"
+ dependencies = [
+  "async-channel",
+- "async-lock",
+  "async-task",
+- "atomic-waker",
+- "fastrand 1.9.0",
++ "futures-io",
+  "futures-lite",
+- "log",
++ "piper",
+ ]
+ 
+ [[package]]
+ name = "bumpalo"
+-version = "3.13.0"
++version = "3.16.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
++checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
+ 
+ [[package]]
+ name = "byteorder"
+-version = "1.4.3"
++version = "1.5.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
++checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
+ 
+ [[package]]
+ name = "bytes"
+-version = "1.4.0"
++version = "1.7.1"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
++checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50"
+ 
+ [[package]]
+ name = "cached"
+-version = "0.48.1"
++version = "0.53.1"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "355face540df58778b96814c48abb3c2ed67c4878a8087ab1819c1fedeec505f"
++checksum = "b4d73155ae6b28cf5de4cfc29aeb02b8a1c6dab883cb015d15cd514e42766846"
+ dependencies = [
+- "ahash 0.8.9",
++ "ahash",
+  "cached_proc_macro",
+  "cached_proc_macro_types",
+- "hashbrown 0.14.3",
+- "instant",
++ "hashbrown",
+  "once_cell",
+  "thiserror",
++ "web-time",
+ ]
+ 
+ [[package]]
+ name = "cached_proc_macro"
+-version = "0.19.1"
++version = "0.23.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "9d52f526f7cbc875b296856ca8c964a9f6290556922c303a8a3883e3c676e6a1"
++checksum = "2f42a145ed2d10dce2191e1dcf30cfccfea9026660e143662ba5eec4017d5daa"
+ dependencies = [
+  "darling",
+  "proc-macro2",
+  "quote",
+- "syn 1.0.109",
++ "syn 2.0.76",
+ ]
+ 
+ [[package]]
+@@ -400,11 +411,11 @@ checksum = "ade8366b8bd5ba243f0a58f036cc0ca8a2f069cff1a2351ef1cac6b083e16fc0"
+ 
+ [[package]]
+ name = "cairo-rs"
+-version = "0.17.10"
++version = "0.18.5"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "ab3603c4028a5e368d09b51c8b624b9a46edcd7c3778284077a6125af73c9f0a"
++checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2"
+ dependencies = [
+- "bitflags 1.3.2",
++ "bitflags 2.6.0",
+  "cairo-sys-rs",
+  "glib",
+  "libc",
+@@ -414,29 +425,39 @@ dependencies = [
+ 
+ [[package]]
+ name = "cairo-sys-rs"
+-version = "0.17.10"
++version = "0.18.2"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "691d0c66b1fb4881be80a760cb8fe76ea97218312f9dfe2c9cc0f496ca279cb1"
++checksum = "685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51"
+ dependencies = [
+  "glib-sys",
+  "libc",
+- "system-deps",
++ "system-deps 6.2.2",
+ ]
+ 
+ [[package]]
+ name = "cc"
+-version = "1.0.82"
++version = "1.1.14"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01"
++checksum = "50d2eb3cd3d1bf4529e31c215ee6f93ec5a3d536d9f578f93d9d33ee19562932"
+ dependencies = [
+- "libc",
++ "shlex",
+ ]
+ 
+ [[package]]
+ name = "cfg-expr"
+-version = "0.15.4"
++version = "0.15.8"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "b40ccee03b5175c18cde8f37e7d2a33bcef6f8ec8f7cc0d81090d1bb380949c9"
++checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02"
++dependencies = [
++ "smallvec",
++ "target-lexicon",
++]
++
++[[package]]
++name = "cfg-expr"
++version = "0.16.0"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "345c78335be0624ed29012dc10c49102196c6882c12dde65d9f35b02da2aada8"
+ dependencies = [
+  "smallvec",
+  "target-lexicon",
+@@ -448,40 +469,46 @@ version = "1.0.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+ 
++[[package]]
++name = "cfg_aliases"
++version = "0.2.1"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
++
+ [[package]]
+ name = "chrono"
+-version = "0.4.26"
++version = "0.4.38"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5"
++checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
+ dependencies = [
+  "android-tzdata",
+  "iana-time-zone",
+  "js-sys",
+  "num-traits",
+- "time 0.1.45",
++ "pure-rust-locales",
+  "wasm-bindgen",
+- "winapi",
++ "windows-targets 0.52.6",
+ ]
+ 
+ [[package]]
+ name = "chrono-tz"
+-version = "0.8.3"
++version = "0.9.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "f1369bc6b9e9a7dfdae2055f6ec151fe9c554a9d23d357c0237cee2e25eaabb7"
++checksum = "93698b29de5e97ad0ae26447b344c482a7284c737d9ddc5f9e52b74a336671bb"
+ dependencies = [
+  "chrono",
+  "chrono-tz-build",
+- "phf 0.11.2",
++ "phf",
+ ]
+ 
+ [[package]]
+ name = "chrono-tz-build"
+-version = "0.2.0"
++version = "0.3.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "e2f5ebdc942f57ed96d560a6d1a459bae5851102a25d5bf89dc04ae453e31ecf"
++checksum = "0c088aee841df9c3041febbb73934cfc39708749bf96dc827e3359cd39ef11b1"
+ dependencies = [
+  "parse-zoneinfo",
+- "phf 0.11.2",
++ "phf",
+  "phf_codegen",
+ ]
+ 
+@@ -491,14 +518,14 @@ version = "0.9.3"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+ checksum = "8eebd66744a15ded14960ab4ccdbfb51ad3b81f51f3f04a80adac98c985396c9"
+ dependencies = [
+- "hashbrown 0.14.3",
++ "hashbrown",
+ ]
+ 
+ [[package]]
+ name = "clap"
+-version = "4.5.1"
++version = "4.5.16"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da"
++checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019"
+ dependencies = [
+  "clap_builder",
+  "clap_derive",
+@@ -506,42 +533,42 @@ dependencies = [
+ 
+ [[package]]
+ name = "clap_builder"
+-version = "4.5.1"
++version = "4.5.15"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb"
++checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6"
+ dependencies = [
+  "anstream",
+  "anstyle",
+  "clap_lex",
+- "strsim 0.11.0",
++ "strsim",
+ ]
+ 
+ [[package]]
+ name = "clap_complete"
+-version = "4.5.1"
++version = "4.5.23"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "885e4d7d5af40bfb99ae6f9433e292feac98d452dcb3ec3d25dfe7552b77da8c"
++checksum = "531d7959c5bbb6e266cecdd0f20213639c3a5c3e4d615f97db87661745f781ff"
+ dependencies = [
+  "clap",
+ ]
+ 
+ [[package]]
+ name = "clap_derive"
+-version = "4.5.0"
++version = "4.5.13"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47"
++checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0"
+ dependencies = [
+- "heck",
++ "heck 0.5.0",
+  "proc-macro2",
+  "quote",
+- "syn 2.0.50",
++ "syn 2.0.76",
+ ]
+ 
+ [[package]]
+ name = "clap_lex"
+-version = "0.7.0"
++version = "0.7.2"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
++checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
+ 
+ [[package]]
+ name = "codemap"
+@@ -561,94 +588,79 @@ dependencies = [
+ 
+ [[package]]
+ name = "colorchoice"
+-version = "1.0.0"
++version = "1.0.2"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
++checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
+ 
+ [[package]]
+ name = "concurrent-queue"
+-version = "2.2.0"
++version = "2.5.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c"
++checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
+ dependencies = [
+  "crossbeam-utils",
+ ]
+ 
+ [[package]]
+ name = "console"
+-version = "0.15.7"
++version = "0.15.8"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8"
++checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb"
+ dependencies = [
+  "encode_unicode",
+  "lazy_static",
+  "libc",
+- "windows-sys 0.45.0",
++ "windows-sys 0.52.0",
+ ]
+ 
+-[[package]]
+-name = "convert_case"
+-version = "0.4.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
+-
+ [[package]]
+ name = "core-foundation-sys"
+-version = "0.8.4"
++version = "0.8.7"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
++checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
+ 
+ [[package]]
+ name = "cpufeatures"
+-version = "0.2.9"
++version = "0.2.13"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1"
++checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad"
+ dependencies = [
+  "libc",
+ ]
+ 
+ [[package]]
+ name = "crossbeam-channel"
+-version = "0.5.8"
++version = "0.5.13"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
++checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2"
+ dependencies = [
+- "cfg-if",
+  "crossbeam-utils",
+ ]
+ 
+ [[package]]
+ name = "crossbeam-deque"
+-version = "0.8.3"
++version = "0.8.5"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
++checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
+ dependencies = [
+- "cfg-if",
+  "crossbeam-epoch",
+  "crossbeam-utils",
+ ]
+ 
+ [[package]]
+ name = "crossbeam-epoch"
+-version = "0.9.15"
++version = "0.9.18"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
++checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
+ dependencies = [
+- "autocfg",
+- "cfg-if",
+  "crossbeam-utils",
+- "memoffset 0.9.0",
+- "scopeguard",
+ ]
+ 
+ [[package]]
+ name = "crossbeam-utils"
+-version = "0.8.16"
++version = "0.8.20"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
+-dependencies = [
+- "cfg-if",
+-]
++checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
+ 
+ [[package]]
+ name = "crunchy"
+@@ -668,9 +680,9 @@ dependencies = [
+ 
+ [[package]]
+ name = "darling"
+-version = "0.14.4"
++version = "0.20.10"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850"
++checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
+ dependencies = [
+  "darling_core",
+  "darling_macro",
+@@ -678,27 +690,27 @@ dependencies = [
+ 
+ [[package]]
+ name = "darling_core"
+-version = "0.14.4"
++version = "0.20.10"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0"
++checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5"
+ dependencies = [
+  "fnv",
+  "ident_case",
+  "proc-macro2",
+  "quote",
+- "strsim 0.10.0",
+- "syn 1.0.109",
++ "strsim",
++ "syn 2.0.76",
+ ]
+ 
+ [[package]]
+ name = "darling_macro"
+-version = "0.14.4"
++version = "0.20.10"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e"
++checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
+ dependencies = [
+  "darling_core",
+  "quote",
+- "syn 1.0.109",
++ "syn 2.0.76",
+ ]
+ 
+ [[package]]
+@@ -721,7 +733,7 @@ dependencies = [
+  "glib-sys",
+  "gobject-sys",
+  "libc",
+- "system-deps",
++ "system-deps 6.2.2",
+ ]
+ 
+ [[package]]
+@@ -751,40 +763,28 @@ dependencies = [
+  "gobject-sys",
+  "gtk-sys",
+  "libc",
+- "system-deps",
+-]
+-
+-[[package]]
+-name = "deranged"
+-version = "0.3.11"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
+-dependencies = [
+- "powerfmt",
++ "system-deps 6.2.2",
+ ]
+ 
+ [[package]]
+-name = "derivative"
+-version = "2.2.0"
++name = "derive_more"
++version = "1.0.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
++checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05"
+ dependencies = [
+- "proc-macro2",
+- "quote",
+- "syn 1.0.109",
++ "derive_more-impl",
+ ]
+ 
+ [[package]]
+-name = "derive_more"
+-version = "0.99.17"
++name = "derive_more-impl"
++version = "1.0.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
++checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22"
+ dependencies = [
+- "convert_case",
+  "proc-macro2",
+  "quote",
+- "rustc_version",
+- "syn 1.0.109",
++ "syn 2.0.76",
++ "unicode-xid",
+ ]
+ 
+ [[package]]
+@@ -826,21 +826,21 @@ dependencies = [
+ 
+ [[package]]
+ name = "dyn-clone"
+-version = "1.0.12"
++version = "1.0.17"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "304e6508efa593091e97a9abbc10f90aa7ca635b6d2784feff3c89d41dd12272"
++checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125"
+ 
+ [[package]]
+ name = "either"
+-version = "1.9.0"
++version = "1.13.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
++checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
+ 
+ [[package]]
+ name = "ena"
+-version = "0.14.2"
++version = "0.14.3"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "c533630cf40e9caa44bd91aadc88a75d75a4c3a12b4cfde353cbed41daa1e1f1"
++checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5"
+ dependencies = [
+  "log",
+ ]
+@@ -851,11 +851,17 @@ version = "0.3.6"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
+ 
++[[package]]
++name = "endi"
++version = "1.1.0"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf"
++
+ [[package]]
+ name = "enumflags2"
+-version = "0.7.7"
++version = "0.7.10"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "c041f5090df68b32bcd905365fd51769c8b9d553fe87fde0b683534f10c01bd2"
++checksum = "d232db7f5956f3f14313dc2f87985c58bd2c695ce124c8cdd984e08e15ac133d"
+ dependencies = [
+  "enumflags2_derive",
+  "serde",
+@@ -863,20 +869,20 @@ dependencies = [
+ 
+ [[package]]
+ name = "enumflags2_derive"
+-version = "0.7.7"
++version = "0.7.10"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "5e9a1f9f7d83e59740248a6e14ecf93929ade55027844dfcea78beafccc15745"
++checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8"
+ dependencies = [
+  "proc-macro2",
+  "quote",
+- "syn 2.0.50",
++ "syn 2.0.76",
+ ]
+ 
+ [[package]]
+ name = "env_logger"
+-version = "0.10.0"
++version = "0.10.2"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0"
++checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580"
+ dependencies = [
+  "humantime",
+  "is-terminal",
+@@ -893,39 +899,41 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
+ 
+ [[package]]
+ name = "errno"
+-version = "0.3.2"
++version = "0.3.9"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f"
++checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
+ dependencies = [
+- "errno-dragonfly",
+  "libc",
+- "windows-sys 0.48.0",
++ "windows-sys 0.52.0",
+ ]
+ 
+ [[package]]
+-name = "errno-dragonfly"
+-version = "0.1.2"
++name = "event-listener"
++version = "5.3.1"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
++checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba"
+ dependencies = [
+- "cc",
+- "libc",
++ "concurrent-queue",
++ "parking",
++ "pin-project-lite",
+ ]
+ 
+ [[package]]
+-name = "event-listener"
+-version = "2.5.3"
++name = "event-listener-strategy"
++version = "0.5.2"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
++checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1"
++dependencies = [
++ "event-listener",
++ "pin-project-lite",
++]
+ 
+ [[package]]
+ name = "eww"
+-version = "0.5.0"
++version = "0.6.0"
+ dependencies = [
+  "anyhow",
+  "bincode",
+- "cairo-rs",
+- "cairo-sys-rs",
+  "chrono",
+  "clap",
+  "clap_complete",
+@@ -934,24 +942,20 @@ dependencies = [
+  "eww_shared_util",
+  "extend",
+  "futures",
+- "gdk",
+- "gdk-pixbuf",
++ "gdk-sys",
+  "gdkx11",
+- "glib",
+- "glib-macros",
+  "grass",
+  "gtk",
+  "gtk-layer-shell",
+- "itertools 0.12.1",
++ "itertools 0.13.0",
+  "libc",
+  "log",
+  "maplit",
+- "nix 0.27.1",
++ "nix",
+  "notifier_host",
+  "notify",
+  "once_cell",
+  "ordered-stream",
+- "pango",
+  "pretty_env_logger",
+  "regex",
+  "serde",
+@@ -972,6 +976,7 @@ dependencies = [
+ name = "eww_shared_util"
+ version = "0.1.0"
+ dependencies = [
++ "chrono",
+  "derive_more",
+  "ref-cast",
+  "serde",
+@@ -985,23 +990,14 @@ checksum = "311a6d2f1f9d60bff73d2c78a0af97ed27f79672f15c238192a5bbb64db56d00"
+ dependencies = [
+  "proc-macro2",
+  "quote",
+- "syn 2.0.50",
+-]
+-
+-[[package]]
+-name = "fastrand"
+-version = "1.9.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
+-dependencies = [
+- "instant",
++ "syn 2.0.76",
+ ]
+ 
+ [[package]]
+ name = "fastrand"
+-version = "2.0.0"
++version = "2.1.1"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764"
++checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6"
+ 
+ [[package]]
+ name = "field-offset"
+@@ -1009,20 +1005,20 @@ version = "0.3.6"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+ checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f"
+ dependencies = [
+- "memoffset 0.9.0",
++ "memoffset",
+  "rustc_version",
+ ]
+ 
+ [[package]]
+ name = "filetime"
+-version = "0.2.22"
++version = "0.2.24"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0"
++checksum = "bf401df4a4e3872c4fe8151134cf483738e74b67fc934d6532c882b3d24a4550"
+ dependencies = [
+  "cfg-if",
+  "libc",
+- "redox_syscall 0.3.5",
+- "windows-sys 0.48.0",
++ "libredox",
++ "windows-sys 0.59.0",
+ ]
+ 
+ [[package]]
+@@ -1048,9 +1044,9 @@ dependencies = [
+ 
+ [[package]]
+ name = "futures"
+-version = "0.3.28"
++version = "0.3.30"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40"
++checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
+ dependencies = [
+  "futures-channel",
+  "futures-core",
+@@ -1063,9 +1059,9 @@ dependencies = [
+ 
+ [[package]]
+ name = "futures-channel"
+-version = "0.3.28"
++version = "0.3.30"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2"
++checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
+ dependencies = [
+  "futures-core",
+  "futures-sink",
+@@ -1073,15 +1069,15 @@ dependencies = [
+ 
+ [[package]]
+ name = "futures-core"
+-version = "0.3.28"
++version = "0.3.30"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
++checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
+ 
+ [[package]]
+ name = "futures-executor"
+-version = "0.3.28"
++version = "0.3.30"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0"
++checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d"
+ dependencies = [
+  "futures-core",
+  "futures-task",
+@@ -1090,53 +1086,51 @@ dependencies = [
+ 
+ [[package]]
+ name = "futures-io"
+-version = "0.3.28"
++version = "0.3.30"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964"
++checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
+ 
+ [[package]]
+ name = "futures-lite"
+-version = "1.13.0"
++version = "2.3.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce"
++checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5"
+ dependencies = [
+- "fastrand 1.9.0",
++ "fastrand",
+  "futures-core",
+  "futures-io",
+- "memchr",
+  "parking",
+  "pin-project-lite",
+- "waker-fn",
+ ]
+ 
+ [[package]]
+ name = "futures-macro"
+-version = "0.3.28"
++version = "0.3.30"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
++checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
+ dependencies = [
+  "proc-macro2",
+  "quote",
+- "syn 2.0.50",
++ "syn 2.0.76",
+ ]
+ 
+ [[package]]
+ name = "futures-sink"
+-version = "0.3.28"
++version = "0.3.30"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e"
++checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
+ 
+ [[package]]
+ name = "futures-task"
+-version = "0.3.28"
++version = "0.3.30"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65"
++checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
+ 
+ [[package]]
+ name = "futures-util"
+-version = "0.3.28"
++version = "0.3.30"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
++checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
+ dependencies = [
+  "futures-channel",
+  "futures-core",
+@@ -1152,11 +1146,10 @@ dependencies = [
+ 
+ [[package]]
+ name = "gdk"
+-version = "0.17.1"
++version = "0.18.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "be1df5ea52cccd7e3a0897338b5564968274b52f5fd12601e0afa44f454c74d3"
++checksum = "f5ba081bdef3b75ebcdbfc953699ed2d7417d6bd853347a42a37d76406a33646"
+ dependencies = [
+- "bitflags 1.3.2",
+  "cairo-rs",
+  "gdk-pixbuf",
+  "gdk-sys",
+@@ -1168,11 +1161,10 @@ dependencies = [
+ 
+ [[package]]
+ name = "gdk-pixbuf"
+-version = "0.17.10"
++version = "0.18.5"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "695d6bc846438c5708b07007537b9274d883373dd30858ca881d7d71b5540717"
++checksum = "50e1f5f1b0bfb830d6ccc8066d18db35c487b1b2b1e8589b5dfe9f07e8defaec"
+ dependencies = [
+- "bitflags 1.3.2",
+  "gdk-pixbuf-sys",
+  "gio",
+  "glib",
+@@ -1182,22 +1174,22 @@ dependencies = [
+ 
+ [[package]]
+ name = "gdk-pixbuf-sys"
+-version = "0.17.10"
++version = "0.18.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "9285ec3c113c66d7d0ab5676599176f1f42f4944ca1b581852215bf5694870cb"
++checksum = "3f9839ea644ed9c97a34d129ad56d38a25e6756f99f3a88e15cd39c20629caf7"
+ dependencies = [
+  "gio-sys",
+  "glib-sys",
+  "gobject-sys",
+  "libc",
+- "system-deps",
++ "system-deps 6.2.2",
+ ]
+ 
+ [[package]]
+ name = "gdk-sys"
+-version = "0.17.0"
++version = "0.18.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "2152de9d38bc67a17b3fe49dc0823af5bf874df59ea088c5f28f31cf103de703"
++checksum = "31ff856cb3386dae1703a920f803abafcc580e9b5f711ca62ed1620c25b51ff2"
+ dependencies = [
+  "cairo-sys-rs",
+  "gdk-pixbuf-sys",
+@@ -1207,14 +1199,14 @@ dependencies = [
+  "libc",
+  "pango-sys",
+  "pkg-config",
+- "system-deps",
++ "system-deps 6.2.2",
+ ]
+ 
+ [[package]]
+ name = "gdkx11"
+-version = "0.17.0"
++version = "0.18.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "08f9efc60ffeede8e3816d1e4ca54b62107c31b6560f967cd84583c8b23acccf"
++checksum = "db2ea8a4909d530f79921290389cbd7c34cb9d623bfe970eaae65ca5f9cd9cce"
+ dependencies = [
+  "gdk",
+  "gdkx11-sys",
+@@ -1226,14 +1218,14 @@ dependencies = [
+ 
+ [[package]]
+ name = "gdkx11-sys"
+-version = "0.17.0"
++version = "0.18.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "6aaa174c09165bb416717bf5cf3132a3dc617a069b09000ac0eae1b921a00740"
++checksum = "fee8f00f4ee46cad2939b8990f5c70c94ff882c3028f3cc5abf950fa4ab53043"
+ dependencies = [
+  "gdk-sys",
+  "glib-sys",
+  "libc",
+- "system-deps",
++ "system-deps 6.2.2",
+  "x11",
+ ]
+ 
+@@ -1249,38 +1241,39 @@ dependencies = [
+ 
+ [[package]]
+ name = "gethostname"
+-version = "0.2.3"
++version = "0.4.3"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "c1ebd34e35c46e00bb73e81363248d627782724609fe1b6396f553f68fe3862e"
++checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818"
+ dependencies = [
+  "libc",
+- "winapi",
++ "windows-targets 0.48.5",
+ ]
+ 
+ [[package]]
+ name = "getrandom"
+-version = "0.2.10"
++version = "0.2.15"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
++checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
+ dependencies = [
+  "cfg-if",
++ "js-sys",
+  "libc",
+- "wasi 0.11.0+wasi-snapshot-preview1",
++ "wasi",
++ "wasm-bindgen",
+ ]
+ 
+ [[package]]
+ name = "gimli"
+-version = "0.27.3"
++version = "0.29.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e"
++checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
+ 
+ [[package]]
+ name = "gio"
+-version = "0.17.10"
++version = "0.18.4"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "a6973e92937cf98689b6a054a9e56c657ed4ff76de925e36fc331a15f0c5d30a"
++checksum = "d4fc8f532f87b79cbc51a79748f16a6828fb784be93145a322fa14d06d354c73"
+ dependencies = [
+- "bitflags 1.3.2",
+  "futures-channel",
+  "futures-core",
+  "futures-io",
+@@ -1296,24 +1289,24 @@ dependencies = [
+ 
+ [[package]]
+ name = "gio-sys"
+-version = "0.17.10"
++version = "0.18.1"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "0ccf87c30a12c469b6d958950f6a9c09f2be20b7773f7e70d20b867fdf2628c3"
++checksum = "37566df850baf5e4cb0dfb78af2e4b9898d817ed9263d1090a2df958c64737d2"
+ dependencies = [
+  "glib-sys",
+  "gobject-sys",
+  "libc",
+- "system-deps",
++ "system-deps 6.2.2",
+  "winapi",
+ ]
+ 
+ [[package]]
+ name = "glib"
+-version = "0.17.10"
++version = "0.18.5"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "d3fad45ba8d4d2cea612b432717e834f48031cd8853c8aaf43b2c79fec8d144b"
++checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5"
+ dependencies = [
+- "bitflags 1.3.2",
++ "bitflags 2.6.0",
+  "futures-channel",
+  "futures-core",
+  "futures-executor",
+@@ -1332,70 +1325,71 @@ dependencies = [
+ 
+ [[package]]
+ name = "glib-macros"
+-version = "0.17.10"
++version = "0.18.5"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "eca5c79337338391f1ab8058d6698125034ce8ef31b72a442437fa6c8580de26"
++checksum = "0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc"
+ dependencies = [
+- "anyhow",
+- "heck",
+- "proc-macro-crate",
++ "heck 0.4.1",
++ "proc-macro-crate 2.0.0",
+  "proc-macro-error",
+  "proc-macro2",
+  "quote",
+- "syn 1.0.109",
++ "syn 2.0.76",
+ ]
+ 
+ [[package]]
+ name = "glib-sys"
+-version = "0.17.10"
++version = "0.18.1"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "d80aa6ea7bba0baac79222204aa786a6293078c210abe69ef1336911d4bdc4f0"
++checksum = "063ce2eb6a8d0ea93d2bf8ba1957e78dbab6be1c2220dd3daca57d5a9d869898"
+ dependencies = [
+  "libc",
+- "system-deps",
++ "system-deps 6.2.2",
+ ]
+ 
+ [[package]]
+ name = "gobject-sys"
+-version = "0.17.10"
++version = "0.18.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "cd34c3317740a6358ec04572c1bcfd3ac0b5b6529275fae255b237b314bb8062"
++checksum = "0850127b514d1c4a4654ead6dedadb18198999985908e6ffe4436f53c785ce44"
+ dependencies = [
+  "glib-sys",
+  "libc",
+- "system-deps",
++ "system-deps 6.2.2",
+ ]
+ 
+ [[package]]
+ name = "grass"
+-version = "0.13.1"
++version = "0.13.4"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "7746cd9bf09f9bb7d98638774a70642000356f543898d9a352cd043f82744528"
++checksum = "f7a68216437ef68f0738e48d6c7bb9e6e6a92237e001b03d838314b068f33c94"
+ dependencies = [
++ "clap",
++ "getrandom",
+  "grass_compiler",
+ ]
+ 
+ [[package]]
+ name = "grass_compiler"
+-version = "0.13.0"
++version = "0.13.4"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "187adfc0b34289c7f8f3819453ce9da3177c3d73f40ac74bb17faba578813d45"
++checksum = "2d9e3df7f0222ce5184154973d247c591d9aadc28ce7a73c6cd31100c9facff6"
+ dependencies = [
+  "codemap",
+- "indexmap 1.9.3",
++ "indexmap",
+  "lasso",
+  "once_cell",
+- "phf 0.10.1",
++ "phf",
++ "rand",
+ ]
+ 
+ [[package]]
+ name = "gtk"
+-version = "0.17.1"
++version = "0.18.1"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "b6c4222ab92b08d4d0bab90ddb6185b4e575ceeea8b8cdf00b938d7b6661d966"
++checksum = "93c4f5e0e20b60e10631a5f06da7fe3dda744b05ad0ea71fee2f47adf865890c"
+ dependencies = [
+  "atk",
+- "bitflags 1.3.2",
+  "cairo-rs",
+  "field-offset",
+  "futures-channel",
+@@ -1406,18 +1400,17 @@ dependencies = [
+  "gtk-sys",
+  "gtk3-macros",
+  "libc",
+- "once_cell",
+  "pango",
+  "pkg-config",
+ ]
+ 
+ [[package]]
+ name = "gtk-layer-shell"
+-version = "0.6.1"
++version = "0.8.1"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "992f5fedb31835424a5280acd162bf348995f617d26969fde8d3dfd389b3ff5f"
++checksum = "adb41643070b55cdda5a4a10a338520cff4345395e342b754c02f341e4107383"
+ dependencies = [
+- "bitflags 2.4.0",
++ "bitflags 2.6.0",
+  "gdk",
+  "glib",
+  "glib-sys",
+@@ -1428,22 +1421,22 @@ dependencies = [
+ 
+ [[package]]
+ name = "gtk-layer-shell-sys"
+-version = "0.6.0"
++version = "0.7.1"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "5754bcfaadfc3529116af6ae93559b267d88647f965382153a4b8ea9372be75a"
++checksum = "b9aa75cbb5bf5195d8be239b189f2a36cbea223777188c50f0bce124e291fe34"
+ dependencies = [
+  "gdk-sys",
+  "glib-sys",
+  "gtk-sys",
+  "libc",
+- "system-deps",
++ "system-deps 7.0.2",
+ ]
+ 
+ [[package]]
+ name = "gtk-sys"
+-version = "0.17.0"
++version = "0.18.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "4d8eb6a4b93e5a7e6980f7348d08c1cd93d31fae07cf97f20678c5ec41de3d7e"
++checksum = "771437bf1de2c1c0b496c11505bdf748e26066bbe942dfc8f614c9460f6d7722"
+ dependencies = [
+  "atk-sys",
+  "cairo-sys-rs",
+@@ -1454,59 +1447,55 @@ dependencies = [
+  "gobject-sys",
+  "libc",
+  "pango-sys",
+- "system-deps",
++ "system-deps 6.2.2",
+ ]
+ 
+ [[package]]
+ name = "gtk3-macros"
+-version = "0.17.1"
++version = "0.18.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "3efb84d682c9a39c10bd9f24f5a4b9c15cc8c7edc45c19cb2ca2c4fc38b2d95e"
++checksum = "c6063efb63db582968fb7df72e1ae68aa6360dcfb0a75143f34fc7d616bad75e"
+ dependencies = [
+- "anyhow",
+- "proc-macro-crate",
++ "proc-macro-crate 1.3.1",
+  "proc-macro-error",
+  "proc-macro2",
+  "quote",
+- "syn 1.0.109",
++ "syn 2.0.76",
+ ]
+ 
+ [[package]]
+ name = "hashbrown"
+-version = "0.11.2"
++version = "0.14.5"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
++checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
+ dependencies = [
+- "ahash 0.7.6",
++ "ahash",
++ "allocator-api2",
+ ]
+ 
+ [[package]]
+-name = "hashbrown"
+-version = "0.12.3"
++name = "heck"
++version = "0.4.1"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
++checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+ 
+ [[package]]
+-name = "hashbrown"
+-version = "0.14.3"
++name = "heck"
++version = "0.5.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
+-dependencies = [
+- "ahash 0.8.9",
+- "allocator-api2",
+-]
++checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+ 
+ [[package]]
+-name = "heck"
+-version = "0.4.1"
++name = "hermit-abi"
++version = "0.3.9"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
++checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
+ 
+ [[package]]
+ name = "hermit-abi"
+-version = "0.3.2"
++version = "0.4.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
++checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
+ 
+ [[package]]
+ name = "hex"
+@@ -1516,9 +1505,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+ 
+ [[package]]
+ name = "hifijson"
+-version = "0.2.0"
++version = "0.2.2"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "85ef6b41c333e6dd2a4aaa59125a19b633cd17e7aaf372b2260809777bcdef4a"
++checksum = "9958ab3ce3170c061a27679916bd9b969eceeb5e8b120438e6751d0987655c42"
+ 
+ [[package]]
+ name = "humantime"
+@@ -1528,16 +1517,16 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
+ 
+ [[package]]
+ name = "iana-time-zone"
+-version = "0.1.57"
++version = "0.1.60"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613"
++checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
+ dependencies = [
+  "android_system_properties",
+  "core-foundation-sys",
+  "iana-time-zone-haiku",
+  "js-sys",
+  "wasm-bindgen",
+- "windows 0.48.0",
++ "windows-core 0.52.0",
+ ]
+ 
+ [[package]]
+@@ -1557,22 +1546,12 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
+ 
+ [[package]]
+ name = "indexmap"
+-version = "1.9.3"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
+-dependencies = [
+- "autocfg",
+- "hashbrown 0.12.3",
+-]
+-
+-[[package]]
+-name = "indexmap"
+-version = "2.0.0"
++version = "2.4.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
++checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c"
+ dependencies = [
+  "equivalent",
+- "hashbrown 0.14.3",
++ "hashbrown",
+ ]
+ 
+ [[package]]
+@@ -1597,99 +1576,84 @@ dependencies = [
+ 
+ [[package]]
+ name = "insta"
+-version = "1.31.0"
++version = "1.39.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "a0770b0a3d4c70567f0d58331f3088b0e4c4f56c9b8d764efe654b4a5d46de3a"
++checksum = "810ae6042d48e2c9e9215043563a58a80b877bc863228a74cf10c49d4620a6f5"
+ dependencies = [
+  "console",
+  "lazy_static",
+  "linked-hash-map",
+  "similar",
+- "yaml-rust",
+ ]
+ 
+ [[package]]
+-name = "instant"
+-version = "0.1.12"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
+-dependencies = [
+- "cfg-if",
+-]
+-
+-[[package]]
+-name = "io-lifetimes"
+-version = "1.0.11"
++name = "is-terminal"
++version = "0.4.13"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
++checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b"
+ dependencies = [
+- "hermit-abi",
++ "hermit-abi 0.4.0",
+  "libc",
+- "windows-sys 0.48.0",
++ "windows-sys 0.52.0",
+ ]
+ 
+ [[package]]
+-name = "is-terminal"
+-version = "0.4.9"
++name = "is_terminal_polyfill"
++version = "1.70.1"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
+-dependencies = [
+- "hermit-abi",
+- "rustix 0.38.8",
+- "windows-sys 0.48.0",
+-]
++checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
+ 
+ [[package]]
+ name = "itertools"
+-version = "0.10.5"
++version = "0.11.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
++checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57"
+ dependencies = [
+  "either",
+ ]
+ 
+ [[package]]
+ name = "itertools"
+-version = "0.12.1"
++version = "0.13.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
++checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
+ dependencies = [
+  "either",
+ ]
+ 
+ [[package]]
+ name = "itoa"
+-version = "1.0.9"
++version = "1.0.11"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
++checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
+ 
+ [[package]]
+ name = "jaq-core"
+-version = "1.2.1"
++version = "1.5.1"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "03d6a5713b8f33675abfac79d1db0022a3f28764b2a6b96a185c199ad8dab86d"
++checksum = "d6fda09ee08c84c81293fdf811d9ebaa87b327557b5391f290c926d728c2ddd4"
+ dependencies = [
+  "aho-corasick",
+  "base64",
++ "chrono",
+  "hifijson",
+  "jaq-interpret",
+  "libm",
+  "log",
+  "regex",
+- "time 0.3.34",
+  "urlencoding",
+ ]
+ 
+ [[package]]
+ name = "jaq-interpret"
+-version = "1.2.1"
++version = "1.5.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "f569e38e5fc677db8dfda89ee0b4c25b3f53e811b16434fd14bdc5b43fc362ac"
++checksum = "2fe95ec3c24af3fd9f3dd1091593f5e49b003a66c496a8aa39d764d0a06ae17b"
+ dependencies = [
+- "ahash 0.8.9",
++ "ahash",
+  "dyn-clone",
+  "hifijson",
+- "indexmap 2.0.0",
++ "indexmap",
+  "jaq-syn",
+  "once_cell",
+  "serde_json",
+@@ -1697,9 +1661,9 @@ dependencies = [
+ 
+ [[package]]
+ name = "jaq-parse"
+-version = "1.0.2"
++version = "1.0.3"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "ef6f8beb9f9922546419e774e24199e8a968f54c63a5a2323c8f3ef3321ace14"
++checksum = "0346d7d3146cdda8acd929581f3d6626a332356c74d5c95aeaffaac2eb6dee82"
+ dependencies = [
+  "chumsky",
+  "jaq-syn",
+@@ -1707,29 +1671,27 @@ dependencies = [
+ 
+ [[package]]
+ name = "jaq-std"
+-version = "1.2.1"
++version = "1.6.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "5d7871c59297cbfdd18f6f1bbbafaad24e97fd555ee1e2a1be7a40a5a20f551a"
++checksum = "bfbaa55578fd3b70433b594a370741e0c364e4afff92cc0099623fce87311bc1"
+ dependencies = [
+- "bincode",
+- "jaq-parse",
+  "jaq-syn",
+ ]
+ 
+ [[package]]
+ name = "jaq-syn"
+-version = "1.1.0"
++version = "1.6.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "a4d60101fb791b20c982731d848ed6e7d25363656497647c2093b68bd88398d6"
++checksum = "1ba44fe4428c71304604261ecbae047ee9cfb60c4f1a6bd222ebbb31726d3948"
+ dependencies = [
+  "serde",
+ ]
+ 
+ [[package]]
+ name = "js-sys"
+-version = "0.3.64"
++version = "0.3.70"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a"
++checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a"
+ dependencies = [
+  "wasm-bindgen",
+ ]
+@@ -1756,56 +1718,55 @@ dependencies = [
+ 
+ [[package]]
+ name = "lalrpop"
+-version = "0.20.0"
++version = "0.20.2"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "da4081d44f4611b66c6dd725e6de3169f9f63905421e8626fcb86b6a898998b8"
++checksum = "55cb077ad656299f160924eb2912aa147d7339ea7d69e1b5517326fdcec3c1ca"
+ dependencies = [
+  "ascii-canvas",
+  "bit-set",
+- "diff",
+  "ena",
+- "is-terminal",
+- "itertools 0.10.5",
++ "itertools 0.11.0",
+  "lalrpop-util",
+  "petgraph",
+  "pico-args",
+  "regex",
+- "regex-syntax 0.7.4",
++ "regex-syntax",
+  "string_cache",
+  "term",
+  "tiny-keccak",
+  "unicode-xid",
++ "walkdir",
+ ]
+ 
+ [[package]]
+ name = "lalrpop-util"
+-version = "0.20.0"
++version = "0.20.2"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "3f35c735096c0293d313e8f2a641627472b83d01b937177fe76e5e2708d31e0d"
++checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553"
+ dependencies = [
+- "regex",
++ "regex-automata",
+ ]
+ 
+ [[package]]
+ name = "lasso"
+-version = "0.6.0"
++version = "0.7.3"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "aeb7b21a526375c5ca55f1a6dfd4e1fad9fa4edd750f530252a718a44b2608f0"
++checksum = "6e14eda50a3494b3bf7b9ce51c52434a761e383d7238ce1dd5dcec2fbc13e9fb"
+ dependencies = [
+- "hashbrown 0.11.2",
++ "hashbrown",
+ ]
+ 
+ [[package]]
+ name = "lazy_static"
+-version = "1.4.0"
++version = "1.5.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
++checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
+ 
+ [[package]]
+ name = "libc"
+-version = "0.2.153"
++version = "0.2.158"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
++checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
+ 
+ [[package]]
+ name = "libm"
+@@ -1813,6 +1774,17 @@ version = "0.2.8"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+ checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
+ 
++[[package]]
++name = "libredox"
++version = "0.1.3"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
++dependencies = [
++ "bitflags 2.6.0",
++ "libc",
++ "redox_syscall",
++]
++
+ [[package]]
+ name = "linked-hash-map"
+ version = "0.5.6"
+@@ -1821,21 +1793,15 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
+ 
+ [[package]]
+ name = "linux-raw-sys"
+-version = "0.3.8"
++version = "0.4.14"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
++checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
+ 
+ [[package]]
+-name = "linux-raw-sys"
+-version = "0.4.5"
++name = "lock_api"
++version = "0.4.12"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503"
+-
+-[[package]]
+-name = "lock_api"
+-version = "0.4.10"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
++checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
+ dependencies = [
+  "autocfg",
+  "scopeguard",
+@@ -1843,9 +1809,9 @@ dependencies = [
+ 
+ [[package]]
+ name = "log"
+-version = "0.4.20"
++version = "0.4.22"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
++checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
+ 
+ [[package]]
+ name = "maplit"
+@@ -1855,99 +1821,69 @@ checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
+ 
+ [[package]]
+ name = "memchr"
+-version = "2.7.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
+-
+-[[package]]
+-name = "memoffset"
+-version = "0.6.5"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
+-dependencies = [
+- "autocfg",
+-]
+-
+-[[package]]
+-name = "memoffset"
+-version = "0.7.1"
++version = "2.7.4"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
+-dependencies = [
+- "autocfg",
+-]
++checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
+ 
+ [[package]]
+ name = "memoffset"
+-version = "0.9.0"
++version = "0.9.1"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
++checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
+ dependencies = [
+  "autocfg",
+ ]
+ 
+ [[package]]
+ name = "miniz_oxide"
+-version = "0.7.1"
++version = "0.7.4"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
++checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
+ dependencies = [
+  "adler",
+ ]
+ 
+ [[package]]
+ name = "mio"
+-version = "0.8.10"
++version = "0.8.11"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09"
++checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
+ dependencies = [
+  "libc",
+  "log",
+- "wasi 0.11.0+wasi-snapshot-preview1",
++ "wasi",
+  "windows-sys 0.48.0",
+ ]
+ 
+ [[package]]
+-name = "new_debug_unreachable"
+-version = "1.0.4"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
+-
+-[[package]]
+-name = "nix"
+-version = "0.25.1"
++name = "mio"
++version = "1.0.2"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4"
++checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec"
+ dependencies = [
+- "autocfg",
+- "bitflags 1.3.2",
+- "cfg-if",
++ "hermit-abi 0.3.9",
+  "libc",
+- "memoffset 0.6.5",
++ "wasi",
++ "windows-sys 0.52.0",
+ ]
+ 
+ [[package]]
+-name = "nix"
+-version = "0.26.2"
++name = "new_debug_unreachable"
++version = "1.0.6"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a"
+-dependencies = [
+- "bitflags 1.3.2",
+- "cfg-if",
+- "libc",
+- "memoffset 0.7.1",
+- "static_assertions",
+-]
++checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
+ 
+ [[package]]
+ name = "nix"
+-version = "0.27.1"
++version = "0.29.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"
++checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
+ dependencies = [
+- "bitflags 2.4.0",
++ "bitflags 2.6.0",
+  "cfg-if",
++ "cfg_aliases",
+  "libc",
++ "memoffset",
+ ]
+ 
+ [[package]]
+@@ -1955,7 +1891,6 @@ name = "notifier_host"
+ version = "0.1.0"
+ dependencies = [
+  "dbusmenu-gtk3",
+- "gdk",
+  "gtk",
+  "log",
+  "thiserror",
+@@ -1969,7 +1904,7 @@ version = "6.1.1"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+ checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d"
+ dependencies = [
+- "bitflags 2.4.0",
++ "bitflags 2.6.0",
+  "crossbeam-channel",
+  "filetime",
+  "fsevent-sys",
+@@ -1977,7 +1912,7 @@ dependencies = [
+  "kqueue",
+  "libc",
+  "log",
+- "mio",
++ "mio 0.8.11",
+  "walkdir",
+  "windows-sys 0.48.0",
+ ]
+@@ -1991,36 +1926,20 @@ dependencies = [
+  "winapi",
+ ]
+ 
+-[[package]]
+-name = "num-conv"
+-version = "0.1.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
+-
+ [[package]]
+ name = "num-traits"
+-version = "0.2.16"
++version = "0.2.19"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
++checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
+ dependencies = [
+  "autocfg",
+ ]
+ 
+-[[package]]
+-name = "num_cpus"
+-version = "1.16.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
+-dependencies = [
+- "hermit-abi",
+- "libc",
+-]
+-
+ [[package]]
+ name = "object"
+-version = "0.31.1"
++version = "0.36.3"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1"
++checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9"
+ dependencies = [
+  "memchr",
+ ]
+@@ -2043,11 +1962,10 @@ dependencies = [
+ 
+ [[package]]
+ name = "pango"
+-version = "0.17.10"
++version = "0.18.3"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "35be456fc620e61f62dff7ff70fbd54dcbaf0a4b920c0f16de1107c47d921d48"
++checksum = "7ca27ec1eb0457ab26f3036ea52229edbdb74dee1edd29063f5b9b010e7ebee4"
+ dependencies = [
+- "bitflags 1.3.2",
+  "gio",
+  "glib",
+  "libc",
+@@ -2057,27 +1975,27 @@ dependencies = [
+ 
+ [[package]]
+ name = "pango-sys"
+-version = "0.17.10"
++version = "0.18.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "3da69f9f3850b0d8990d462f8c709561975e95f689c1cdf0fecdebde78b35195"
++checksum = "436737e391a843e5933d6d9aa102cb126d501e815b83601365a948a518555dc5"
+ dependencies = [
+  "glib-sys",
+  "gobject-sys",
+  "libc",
+- "system-deps",
++ "system-deps 6.2.2",
+ ]
+ 
+ [[package]]
+ name = "parking"
+-version = "2.1.0"
++version = "2.2.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e"
++checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae"
+ 
+ [[package]]
+ name = "parking_lot"
+-version = "0.12.1"
++version = "0.12.3"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
++checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
+ dependencies = [
+  "lock_api",
+  "parking_lot_core",
+@@ -2085,45 +2003,34 @@ dependencies = [
+ 
+ [[package]]
+ name = "parking_lot_core"
+-version = "0.9.8"
++version = "0.9.10"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"
++checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
+ dependencies = [
+  "cfg-if",
+  "libc",
+- "redox_syscall 0.3.5",
++ "redox_syscall",
+  "smallvec",
+- "windows-targets 0.48.2",
++ "windows-targets 0.52.6",
+ ]
+ 
+ [[package]]
+ name = "parse-zoneinfo"
+-version = "0.3.0"
++version = "0.3.1"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41"
++checksum = "1f2a05b18d44e2957b88f96ba460715e295bc1d7510468a2f3d3b44535d26c24"
+ dependencies = [
+  "regex",
+ ]
+ 
+ [[package]]
+ name = "petgraph"
+-version = "0.6.3"
++version = "0.6.5"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4"
++checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db"
+ dependencies = [
+  "fixedbitset",
+- "indexmap 1.9.3",
+-]
+-
+-[[package]]
+-name = "phf"
+-version = "0.10.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259"
+-dependencies = [
+- "phf_macros",
+- "phf_shared 0.10.0",
+- "proc-macro-hack",
++ "indexmap",
+ ]
+ 
+ [[package]]
+@@ -2132,6 +2039,7 @@ version = "0.11.2"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+ checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
+ dependencies = [
++ "phf_macros",
+  "phf_shared 0.11.2",
+ ]
+ 
+@@ -2141,20 +2049,10 @@ version = "0.11.2"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+ checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a"
+ dependencies = [
+- "phf_generator 0.11.2",
++ "phf_generator",
+  "phf_shared 0.11.2",
+ ]
+ 
+-[[package]]
+-name = "phf_generator"
+-version = "0.10.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6"
+-dependencies = [
+- "phf_shared 0.10.0",
+- "rand",
+-]
+-
+ [[package]]
+ name = "phf_generator"
+ version = "0.11.2"
+@@ -2167,16 +2065,15 @@ dependencies = [
+ 
+ [[package]]
+ name = "phf_macros"
+-version = "0.10.0"
++version = "0.11.2"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0"
++checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b"
+ dependencies = [
+- "phf_generator 0.10.0",
+- "phf_shared 0.10.0",
+- "proc-macro-hack",
++ "phf_generator",
++ "phf_shared 0.11.2",
+  "proc-macro2",
+  "quote",
+- "syn 1.0.109",
++ "syn 2.0.76",
+ ]
+ 
+ [[package]]
+@@ -2205,9 +2102,9 @@ checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315"
+ 
+ [[package]]
+ name = "pin-project-lite"
+-version = "0.2.12"
++version = "0.2.14"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "12cc1b0bf1727a77a54b6654e7b5f1af8604923edc8b81885f8ec92f9e3f0a05"
++checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
+ 
+ [[package]]
+ name = "pin-utils"
+@@ -2215,39 +2112,46 @@ version = "0.1.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+ 
++[[package]]
++name = "piper"
++version = "0.2.4"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066"
++dependencies = [
++ "atomic-waker",
++ "fastrand",
++ "futures-io",
++]
++
+ [[package]]
+ name = "pkg-config"
+-version = "0.3.27"
++version = "0.3.30"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
++checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
+ 
+ [[package]]
+ name = "polling"
+-version = "2.8.0"
++version = "3.7.3"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce"
++checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511"
+ dependencies = [
+- "autocfg",
+- "bitflags 1.3.2",
+  "cfg-if",
+  "concurrent-queue",
+- "libc",
+- "log",
++ "hermit-abi 0.4.0",
+  "pin-project-lite",
+- "windows-sys 0.48.0",
++ "rustix",
++ "tracing",
++ "windows-sys 0.59.0",
+ ]
+ 
+-[[package]]
+-name = "powerfmt"
+-version = "0.2.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
+-
+ [[package]]
+ name = "ppv-lite86"
+-version = "0.2.17"
++version = "0.2.20"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
++checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
++dependencies = [
++ "zerocopy",
++]
+ 
+ [[package]]
+ name = "precomputed-hash"
+@@ -2282,7 +2186,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
+ checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919"
+ dependencies = [
+  "once_cell",
+- "toml_edit",
++ "toml_edit 0.19.15",
++]
++
++[[package]]
++name = "proc-macro-crate"
++version = "2.0.0"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8"
++dependencies = [
++ "toml_edit 0.20.7",
++]
++
++[[package]]
++name = "proc-macro-crate"
++version = "3.1.0"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284"
++dependencies = [
++ "toml_edit 0.21.1",
+ ]
+ 
+ [[package]]
+@@ -2309,26 +2231,26 @@ dependencies = [
+  "version_check",
+ ]
+ 
+-[[package]]
+-name = "proc-macro-hack"
+-version = "0.5.20+deprecated"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
+-
+ [[package]]
+ name = "proc-macro2"
+-version = "1.0.78"
++version = "1.0.86"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
++checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
+ dependencies = [
+  "unicode-ident",
+ ]
+ 
++[[package]]
++name = "pure-rust-locales"
++version = "0.8.1"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "1190fd18ae6ce9e137184f207593877e70f39b015040156b1e05081cdfe3733a"
++
+ [[package]]
+ name = "quote"
+-version = "1.0.35"
++version = "1.0.37"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
++checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
+ dependencies = [
+  "proc-macro2",
+ ]
+@@ -2365,9 +2287,9 @@ dependencies = [
+ 
+ [[package]]
+ name = "rayon"
+-version = "1.8.1"
++version = "1.10.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051"
++checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
+ dependencies = [
+  "either",
+  "rayon-core",
+@@ -2385,93 +2307,78 @@ dependencies = [
+ 
+ [[package]]
+ name = "redox_syscall"
+-version = "0.2.16"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
+-dependencies = [
+- "bitflags 1.3.2",
+-]
+-
+-[[package]]
+-name = "redox_syscall"
+-version = "0.3.5"
++version = "0.5.3"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
++checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4"
+ dependencies = [
+- "bitflags 1.3.2",
++ "bitflags 2.6.0",
+ ]
+ 
+ [[package]]
+ name = "redox_users"
+-version = "0.4.3"
++version = "0.4.6"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
++checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43"
+ dependencies = [
+  "getrandom",
+- "redox_syscall 0.2.16",
++ "libredox",
+  "thiserror",
+ ]
+ 
+ [[package]]
+ name = "ref-cast"
+-version = "1.0.22"
++version = "1.0.23"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "c4846d4c50d1721b1a3bef8af76924eef20d5e723647333798c1b519b3a9473f"
++checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931"
+ dependencies = [
+  "ref-cast-impl",
+ ]
+ 
+ [[package]]
+ name = "ref-cast-impl"
+-version = "1.0.22"
++version = "1.0.23"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "5fddb4f8d99b0a2ebafc65a87a69a7b9875e4b1ae1f00db265d300ef7f28bccc"
++checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6"
+ dependencies = [
+  "proc-macro2",
+  "quote",
+- "syn 2.0.50",
++ "syn 2.0.76",
+ ]
+ 
+ [[package]]
+ name = "regex"
+-version = "1.10.3"
++version = "1.10.6"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15"
++checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619"
+ dependencies = [
+  "aho-corasick",
+  "memchr",
+  "regex-automata",
+- "regex-syntax 0.8.2",
++ "regex-syntax",
+ ]
+ 
+ [[package]]
+ name = "regex-automata"
+-version = "0.4.5"
++version = "0.4.7"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd"
++checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
+ dependencies = [
+  "aho-corasick",
+  "memchr",
+- "regex-syntax 0.8.2",
++ "regex-syntax",
+ ]
+ 
+ [[package]]
+ name = "regex-syntax"
+-version = "0.7.4"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2"
+-
+-[[package]]
+-name = "regex-syntax"
+-version = "0.8.2"
++version = "0.8.4"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
++checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
+ 
+ [[package]]
+ name = "rustc-demangle"
+-version = "0.1.23"
++version = "0.1.24"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
++checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
+ 
+ [[package]]
+ name = "rustc_version"
+@@ -2484,42 +2391,28 @@ dependencies = [
+ 
+ [[package]]
+ name = "rustix"
+-version = "0.37.23"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06"
+-dependencies = [
+- "bitflags 1.3.2",
+- "errno",
+- "io-lifetimes",
+- "libc",
+- "linux-raw-sys 0.3.8",
+- "windows-sys 0.48.0",
+-]
+-
+-[[package]]
+-name = "rustix"
+-version = "0.38.8"
++version = "0.38.34"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f"
++checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
+ dependencies = [
+- "bitflags 2.4.0",
++ "bitflags 2.6.0",
+  "errno",
+  "libc",
+- "linux-raw-sys 0.4.5",
+- "windows-sys 0.48.0",
++ "linux-raw-sys",
++ "windows-sys 0.52.0",
+ ]
+ 
+ [[package]]
+ name = "rustversion"
+-version = "1.0.14"
++version = "1.0.17"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
++checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
+ 
+ [[package]]
+ name = "ryu"
+-version = "1.0.15"
++version = "1.0.18"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
++checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
+ 
+ [[package]]
+ name = "same-file"
+@@ -2538,66 +2431,67 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+ 
+ [[package]]
+ name = "semver"
+-version = "1.0.18"
++version = "1.0.23"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918"
++checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
+ 
+ [[package]]
+ name = "serde"
+-version = "1.0.197"
++version = "1.0.209"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
++checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09"
+ dependencies = [
+  "serde_derive",
+ ]
+ 
+ [[package]]
+ name = "serde_derive"
+-version = "1.0.197"
++version = "1.0.209"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
++checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170"
+ dependencies = [
+  "proc-macro2",
+  "quote",
+- "syn 2.0.50",
++ "syn 2.0.76",
+ ]
+ 
+ [[package]]
+ name = "serde_json"
+-version = "1.0.105"
++version = "1.0.127"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360"
++checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad"
+ dependencies = [
+  "itoa",
++ "memchr",
+  "ryu",
+  "serde",
+ ]
+ 
+ [[package]]
+ name = "serde_repr"
+-version = "0.1.16"
++version = "0.1.19"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00"
++checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
+ dependencies = [
+  "proc-macro2",
+  "quote",
+- "syn 2.0.50",
++ "syn 2.0.76",
+ ]
+ 
+ [[package]]
+ name = "serde_spanned"
+-version = "0.6.3"
++version = "0.6.7"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186"
++checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d"
+ dependencies = [
+  "serde",
+ ]
+ 
+ [[package]]
+ name = "sha1"
+-version = "0.10.5"
++version = "0.10.6"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3"
++checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
+ dependencies = [
+  "cfg-if",
+  "cpufeatures",
+@@ -2605,29 +2499,25 @@ dependencies = [
+ ]
+ 
+ [[package]]
+-name = "signal-hook"
+-version = "0.3.17"
++name = "shlex"
++version = "1.3.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801"
+-dependencies = [
+- "libc",
+- "signal-hook-registry",
+-]
++checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+ 
+ [[package]]
+ name = "signal-hook-registry"
+-version = "1.4.1"
++version = "1.4.2"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
++checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
+ dependencies = [
+  "libc",
+ ]
+ 
+ [[package]]
+ name = "similar"
+-version = "2.2.1"
++version = "2.6.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf"
++checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e"
+ 
+ [[package]]
+ name = "simple-signal"
+@@ -2648,7 +2538,7 @@ dependencies = [
+  "chrono-tz",
+  "eww_shared_util",
+  "insta",
+- "itertools 0.12.1",
++ "itertools 0.13.0",
+  "jaq-core",
+  "jaq-interpret",
+  "jaq-parse",
+@@ -2661,31 +2551,31 @@ dependencies = [
+  "serde",
+  "serde_json",
+  "static_assertions",
+- "strsim 0.11.0",
++ "strsim",
+  "strum",
+  "thiserror",
+ ]
+ 
+ [[package]]
+ name = "siphasher"
+-version = "0.3.10"
++version = "0.3.11"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de"
++checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
+ 
+ [[package]]
+ name = "slab"
+-version = "0.4.8"
++version = "0.4.9"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d"
++checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
+ dependencies = [
+  "autocfg",
+ ]
+ 
+ [[package]]
+ name = "smallvec"
+-version = "1.11.0"
++version = "1.13.2"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
++checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
+ 
+ [[package]]
+ name = "smart-default"
+@@ -2695,24 +2585,14 @@ checksum = "0eb01866308440fc64d6c44d9e86c5cc17adfe33c4d6eed55da9145044d0ffc1"
+ dependencies = [
+  "proc-macro2",
+  "quote",
+- "syn 2.0.50",
++ "syn 2.0.76",
+ ]
+ 
+ [[package]]
+ name = "socket2"
+-version = "0.4.9"
++version = "0.5.7"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"
+-dependencies = [
+- "libc",
+- "winapi",
+-]
+-
+-[[package]]
+-name = "socket2"
+-version = "0.5.6"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871"
++checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c"
+ dependencies = [
+  "libc",
+  "windows-sys 0.52.0",
+@@ -2739,36 +2619,30 @@ dependencies = [
+ 
+ [[package]]
+ name = "strsim"
+-version = "0.10.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
+-
+-[[package]]
+-name = "strsim"
+-version = "0.11.0"
++version = "0.11.1"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01"
++checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
+ 
+ [[package]]
+ name = "strum"
+-version = "0.26.1"
++version = "0.26.3"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "723b93e8addf9aa965ebe2d11da6d7540fa2283fcea14b3371ff055f7ba13f5f"
++checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
+ dependencies = [
+  "strum_macros",
+ ]
+ 
+ [[package]]
+ name = "strum_macros"
+-version = "0.26.1"
++version = "0.26.4"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "7a3417fc93d76740d974a01654a09777cb500428cc874ca9f45edfe0c4d4cd18"
++checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be"
+ dependencies = [
+- "heck",
++ "heck 0.5.0",
+  "proc-macro2",
+  "quote",
+  "rustversion",
+- "syn 2.0.50",
++ "syn 2.0.76",
+ ]
+ 
+ [[package]]
+@@ -2778,15 +2652,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
+ checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+ dependencies = [
+  "proc-macro2",
+- "quote",
+  "unicode-ident",
+ ]
+ 
+ [[package]]
+ name = "syn"
+-version = "2.0.50"
++version = "2.0.76"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb"
++checksum = "578e081a14e0cefc3279b0472138c513f37b41a08d5a3cca9b6e4e8ceb6cd525"
+ dependencies = [
+  "proc-macro2",
+  "quote",
+@@ -2795,27 +2668,39 @@ dependencies = [
+ 
+ [[package]]
+ name = "sysinfo"
+-version = "0.30.5"
++version = "0.31.3"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "1fb4f3438c8f6389c864e61221cbc97e9bca98b4daf39a5beb7bea660f528bb2"
++checksum = "2b92e0bdf838cbc1c4c9ba14f9c97a7ec6cdcd1ae66b10e1e42775a25553f45d"
+ dependencies = [
+- "cfg-if",
+  "core-foundation-sys",
+  "libc",
++ "memchr",
+  "ntapi",
+- "once_cell",
+  "rayon",
+- "windows 0.52.0",
++ "windows",
+ ]
+ 
+ [[package]]
+ name = "system-deps"
+-version = "6.1.1"
++version = "6.2.2"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349"
++dependencies = [
++ "cfg-expr 0.15.8",
++ "heck 0.5.0",
++ "pkg-config",
++ "toml",
++ "version-compare",
++]
++
++[[package]]
++name = "system-deps"
++version = "7.0.2"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "30c2de8a4d8f4b823d634affc9cd2a74ec98c53a756f317e529a48046cbf71f3"
++checksum = "070a0a5e7da2d24be457809c4b3baa57a835fd2829ad8b86f9a049052fe71031"
+ dependencies = [
+- "cfg-expr",
+- "heck",
++ "cfg-expr 0.16.0",
++ "heck 0.5.0",
+  "pkg-config",
+  "toml",
+  "version-compare",
+@@ -2823,21 +2708,21 @@ dependencies = [
+ 
+ [[package]]
+ name = "target-lexicon"
+-version = "0.12.11"
++version = "0.12.16"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "9d0e916b1148c8e263850e1ebcbd046f333e0683c724876bb0da63ea4373dc8a"
++checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
+ 
+ [[package]]
+ name = "tempfile"
+-version = "3.8.0"
++version = "3.12.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef"
++checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64"
+ dependencies = [
+  "cfg-if",
+- "fastrand 2.0.0",
+- "redox_syscall 0.3.5",
+- "rustix 0.38.8",
+- "windows-sys 0.48.0",
++ "fastrand",
++ "once_cell",
++ "rustix",
++ "windows-sys 0.59.0",
+ ]
+ 
+ [[package]]
+@@ -2853,73 +2738,31 @@ dependencies = [
+ 
+ [[package]]
+ name = "termcolor"
+-version = "1.2.0"
++version = "1.4.1"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
++checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
+ dependencies = [
+  "winapi-util",
+ ]
+ 
+ [[package]]
+ name = "thiserror"
+-version = "1.0.46"
++version = "1.0.63"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "d9207952ae1a003f42d3d5e892dac3c6ba42aa6ac0c79a6a91a2b5cb4253e75c"
++checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724"
+ dependencies = [
+  "thiserror-impl",
+ ]
+ 
+ [[package]]
+ name = "thiserror-impl"
+-version = "1.0.46"
++version = "1.0.63"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "f1728216d3244de4f14f14f8c15c79be1a7c67867d28d69b719690e2a19fb445"
++checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
+ dependencies = [
+  "proc-macro2",
+  "quote",
+- "syn 2.0.50",
+-]
+-
+-[[package]]
+-name = "time"
+-version = "0.1.45"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
+-dependencies = [
+- "libc",
+- "wasi 0.10.0+wasi-snapshot-preview1",
+- "winapi",
+-]
+-
+-[[package]]
+-name = "time"
+-version = "0.3.34"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749"
+-dependencies = [
+- "deranged",
+- "itoa",
+- "num-conv",
+- "powerfmt",
+- "serde",
+- "time-core",
+- "time-macros",
+-]
+-
+-[[package]]
+-name = "time-core"
+-version = "0.1.2"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
+-
+-[[package]]
+-name = "time-macros"
+-version = "0.2.17"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774"
+-dependencies = [
+- "num-conv",
+- "time-core",
++ "syn 2.0.76",
+ ]
+ 
+ [[package]]
+@@ -2933,40 +2776,39 @@ dependencies = [
+ 
+ [[package]]
+ name = "tokio"
+-version = "1.36.0"
++version = "1.39.3"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931"
++checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5"
+ dependencies = [
+  "backtrace",
+  "bytes",
+  "libc",
+- "mio",
+- "num_cpus",
++ "mio 1.0.2",
+  "parking_lot",
+  "pin-project-lite",
+  "signal-hook-registry",
+- "socket2 0.5.6",
++ "socket2",
+  "tokio-macros",
+  "tracing",
+- "windows-sys 0.48.0",
++ "windows-sys 0.52.0",
+ ]
+ 
+ [[package]]
+ name = "tokio-macros"
+-version = "2.2.0"
++version = "2.4.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
++checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
+ dependencies = [
+  "proc-macro2",
+  "quote",
+- "syn 2.0.50",
++ "syn 2.0.76",
+ ]
+ 
+ [[package]]
+ name = "tokio-util"
+-version = "0.7.8"
++version = "0.7.11"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d"
++checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1"
+ dependencies = [
+  "bytes",
+  "futures-core",
+@@ -2977,45 +2819,77 @@ dependencies = [
+ 
+ [[package]]
+ name = "toml"
+-version = "0.7.6"
++version = "0.8.19"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542"
++checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e"
+ dependencies = [
+  "serde",
+  "serde_spanned",
+  "toml_datetime",
+- "toml_edit",
++ "toml_edit 0.22.20",
+ ]
+ 
+ [[package]]
+ name = "toml_datetime"
+-version = "0.6.3"
++version = "0.6.8"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b"
++checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
+ dependencies = [
+  "serde",
+ ]
+ 
+ [[package]]
+ name = "toml_edit"
+-version = "0.19.14"
++version = "0.19.15"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a"
++checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
+ dependencies = [
+- "indexmap 2.0.0",
++ "indexmap",
++ "toml_datetime",
++ "winnow 0.5.40",
++]
++
++[[package]]
++name = "toml_edit"
++version = "0.20.7"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81"
++dependencies = [
++ "indexmap",
++ "toml_datetime",
++ "winnow 0.5.40",
++]
++
++[[package]]
++name = "toml_edit"
++version = "0.21.1"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1"
++dependencies = [
++ "indexmap",
++ "toml_datetime",
++ "winnow 0.5.40",
++]
++
++[[package]]
++name = "toml_edit"
++version = "0.22.20"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d"
++dependencies = [
++ "indexmap",
+  "serde",
+  "serde_spanned",
+  "toml_datetime",
+- "winnow",
++ "winnow 0.6.18",
+ ]
+ 
+ [[package]]
+ name = "tracing"
+-version = "0.1.37"
++version = "0.1.40"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
++checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
+ dependencies = [
+- "cfg-if",
+  "pin-project-lite",
+  "tracing-attributes",
+  "tracing-core",
+@@ -3023,36 +2897,37 @@ dependencies = [
+ 
+ [[package]]
+ name = "tracing-attributes"
+-version = "0.1.26"
++version = "0.1.27"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
++checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
+ dependencies = [
+  "proc-macro2",
+  "quote",
+- "syn 2.0.50",
++ "syn 2.0.76",
+ ]
+ 
+ [[package]]
+ name = "tracing-core"
+-version = "0.1.31"
++version = "0.1.32"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a"
++checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
+ dependencies = [
+  "once_cell",
+ ]
+ 
+ [[package]]
+ name = "typenum"
+-version = "1.16.0"
++version = "1.17.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
++checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
+ 
+ [[package]]
+ name = "uds_windows"
+-version = "1.0.2"
++version = "1.1.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "ce65604324d3cce9b966701489fbd0cf318cb1f7bd9dd07ac9a4ee6fb791930d"
++checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9"
+ dependencies = [
++ "memoffset",
+  "tempfile",
+  "winapi",
+ ]
+@@ -3065,21 +2940,21 @@ checksum = "ccb97dac3243214f8d8507998906ca3e2e0b900bf9bf4870477f125b82e68f6e"
+ 
+ [[package]]
+ name = "unicode-ident"
+-version = "1.0.11"
++version = "1.0.12"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
++checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
+ 
+ [[package]]
+ name = "unicode-width"
+-version = "0.1.10"
++version = "0.1.13"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
++checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d"
+ 
+ [[package]]
+ name = "unicode-xid"
+-version = "0.2.4"
++version = "0.2.5"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
++checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a"
+ 
+ [[package]]
+ name = "urlencoding"
+@@ -3089,21 +2964,21 @@ checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
+ 
+ [[package]]
+ name = "utf8parse"
+-version = "0.2.1"
++version = "0.2.2"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
++checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
+ 
+ [[package]]
+ name = "version-compare"
+-version = "0.1.1"
++version = "0.2.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29"
++checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b"
+ 
+ [[package]]
+ name = "version_check"
+-version = "0.9.4"
++version = "0.9.5"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
++checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
+ 
+ [[package]]
+ name = "wait-timeout"
+@@ -3114,28 +2989,16 @@ dependencies = [
+  "libc",
+ ]
+ 
+-[[package]]
+-name = "waker-fn"
+-version = "1.1.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
+-
+ [[package]]
+ name = "walkdir"
+-version = "2.3.3"
++version = "2.5.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698"
++checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
+ dependencies = [
+  "same-file",
+  "winapi-util",
+ ]
+ 
+-[[package]]
+-name = "wasi"
+-version = "0.10.0+wasi-snapshot-preview1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
+-
+ [[package]]
+ name = "wasi"
+ version = "0.11.0+wasi-snapshot-preview1"
+@@ -3144,34 +3007,35 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+ 
+ [[package]]
+ name = "wasm-bindgen"
+-version = "0.2.87"
++version = "0.2.93"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342"
++checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5"
+ dependencies = [
+  "cfg-if",
++ "once_cell",
+  "wasm-bindgen-macro",
+ ]
+ 
+ [[package]]
+ name = "wasm-bindgen-backend"
+-version = "0.2.87"
++version = "0.2.93"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd"
++checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b"
+ dependencies = [
+  "bumpalo",
+  "log",
+  "once_cell",
+  "proc-macro2",
+  "quote",
+- "syn 2.0.50",
++ "syn 2.0.76",
+  "wasm-bindgen-shared",
+ ]
+ 
+ [[package]]
+ name = "wasm-bindgen-macro"
+-version = "0.2.87"
++version = "0.2.93"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d"
++checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf"
+ dependencies = [
+  "quote",
+  "wasm-bindgen-macro-support",
+@@ -3179,22 +3043,32 @@ dependencies = [
+ 
+ [[package]]
+ name = "wasm-bindgen-macro-support"
+-version = "0.2.87"
++version = "0.2.93"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
++checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836"
+ dependencies = [
+  "proc-macro2",
+  "quote",
+- "syn 2.0.50",
++ "syn 2.0.76",
+  "wasm-bindgen-backend",
+  "wasm-bindgen-shared",
+ ]
+ 
+ [[package]]
+ name = "wasm-bindgen-shared"
+-version = "0.2.87"
++version = "0.2.93"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
++checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484"
++
++[[package]]
++name = "web-time"
++version = "1.1.0"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb"
++dependencies = [
++ "js-sys",
++ "wasm-bindgen",
++]
+ 
+ [[package]]
+ name = "winapi"
+@@ -3214,20 +3088,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+ 
+ [[package]]
+ name = "winapi-util"
+-version = "0.1.5"
++version = "0.1.9"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
++checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
+ dependencies = [
+- "winapi",
+-]
+-
+-[[package]]
+-name = "winapi-wsapoll"
+-version = "0.1.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "44c17110f57155602a80dca10be03852116403c9ff3cd25b079d666f2aa3df6e"
+-dependencies = [
+- "winapi",
++ "windows-sys 0.48.0",
+ ]
+ 
+ [[package]]
+@@ -3238,39 +3103,64 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+ 
+ [[package]]
+ name = "windows"
+-version = "0.48.0"
++version = "0.57.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
++checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143"
+ dependencies = [
+- "windows-targets 0.48.2",
++ "windows-core 0.57.0",
++ "windows-targets 0.52.6",
+ ]
+ 
+ [[package]]
+-name = "windows"
++name = "windows-core"
+ version = "0.52.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
++checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
+ dependencies = [
+- "windows-core",
+- "windows-targets 0.52.3",
++ "windows-targets 0.52.6",
+ ]
+ 
+ [[package]]
+ name = "windows-core"
+-version = "0.52.0"
++version = "0.57.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
++checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d"
+ dependencies = [
+- "windows-targets 0.52.3",
++ "windows-implement",
++ "windows-interface",
++ "windows-result",
++ "windows-targets 0.52.6",
+ ]
+ 
+ [[package]]
+-name = "windows-sys"
+-version = "0.45.0"
++name = "windows-implement"
++version = "0.57.0"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7"
++dependencies = [
++ "proc-macro2",
++ "quote",
++ "syn 2.0.76",
++]
++
++[[package]]
++name = "windows-interface"
++version = "0.57.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
++checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7"
+ dependencies = [
+- "windows-targets 0.42.2",
++ "proc-macro2",
++ "quote",
++ "syn 2.0.76",
++]
++
++[[package]]
++name = "windows-result"
++version = "0.1.2"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8"
++dependencies = [
++ "windows-targets 0.52.6",
+ ]
+ 
+ [[package]]
+@@ -3279,7 +3169,7 @@ version = "0.48.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+ checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+ dependencies = [
+- "windows-targets 0.48.2",
++ "windows-targets 0.48.5",
+ ]
+ 
+ [[package]]
+@@ -3288,185 +3178,153 @@ version = "0.52.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+ checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+ dependencies = [
+- "windows-targets 0.52.3",
++ "windows-targets 0.52.6",
+ ]
+ 
+ [[package]]
+-name = "windows-targets"
+-version = "0.42.2"
++name = "windows-sys"
++version = "0.59.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
++checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
+ dependencies = [
+- "windows_aarch64_gnullvm 0.42.2",
+- "windows_aarch64_msvc 0.42.2",
+- "windows_i686_gnu 0.42.2",
+- "windows_i686_msvc 0.42.2",
+- "windows_x86_64_gnu 0.42.2",
+- "windows_x86_64_gnullvm 0.42.2",
+- "windows_x86_64_msvc 0.42.2",
++ "windows-targets 0.52.6",
+ ]
+ 
+ [[package]]
+ name = "windows-targets"
+-version = "0.48.2"
++version = "0.48.5"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "d1eeca1c172a285ee6c2c84c341ccea837e7c01b12fbb2d0fe3c9e550ce49ec8"
++checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
+ dependencies = [
+- "windows_aarch64_gnullvm 0.48.2",
+- "windows_aarch64_msvc 0.48.2",
+- "windows_i686_gnu 0.48.2",
+- "windows_i686_msvc 0.48.2",
+- "windows_x86_64_gnu 0.48.2",
+- "windows_x86_64_gnullvm 0.48.2",
+- "windows_x86_64_msvc 0.48.2",
++ "windows_aarch64_gnullvm 0.48.5",
++ "windows_aarch64_msvc 0.48.5",
++ "windows_i686_gnu 0.48.5",
++ "windows_i686_msvc 0.48.5",
++ "windows_x86_64_gnu 0.48.5",
++ "windows_x86_64_gnullvm 0.48.5",
++ "windows_x86_64_msvc 0.48.5",
+ ]
+ 
+ [[package]]
+ name = "windows-targets"
+-version = "0.52.3"
++version = "0.52.6"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "d380ba1dc7187569a8a9e91ed34b8ccfc33123bbacb8c0aed2d1ad7f3ef2dc5f"
++checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
+ dependencies = [
+- "windows_aarch64_gnullvm 0.52.3",
+- "windows_aarch64_msvc 0.52.3",
+- "windows_i686_gnu 0.52.3",
+- "windows_i686_msvc 0.52.3",
+- "windows_x86_64_gnu 0.52.3",
+- "windows_x86_64_gnullvm 0.52.3",
+- "windows_x86_64_msvc 0.52.3",
++ "windows_aarch64_gnullvm 0.52.6",
++ "windows_aarch64_msvc 0.52.6",
++ "windows_i686_gnu 0.52.6",
++ "windows_i686_gnullvm",
++ "windows_i686_msvc 0.52.6",
++ "windows_x86_64_gnu 0.52.6",
++ "windows_x86_64_gnullvm 0.52.6",
++ "windows_x86_64_msvc 0.52.6",
+ ]
+ 
+ [[package]]
+ name = "windows_aarch64_gnullvm"
+-version = "0.42.2"
++version = "0.48.5"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
++checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
+ 
+ [[package]]
+ name = "windows_aarch64_gnullvm"
+-version = "0.48.2"
++version = "0.52.6"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "b10d0c968ba7f6166195e13d593af609ec2e3d24f916f081690695cf5eaffb2f"
+-
+-[[package]]
+-name = "windows_aarch64_gnullvm"
+-version = "0.52.3"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "68e5dcfb9413f53afd9c8f86e56a7b4d86d9a2fa26090ea2dc9e40fba56c6ec6"
+-
+-[[package]]
+-name = "windows_aarch64_msvc"
+-version = "0.42.2"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
++checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
+ 
+ [[package]]
+ name = "windows_aarch64_msvc"
+-version = "0.48.2"
++version = "0.48.5"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "571d8d4e62f26d4932099a9efe89660e8bd5087775a2ab5cdd8b747b811f1058"
++checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
+ 
+ [[package]]
+ name = "windows_aarch64_msvc"
+-version = "0.52.3"
++version = "0.52.6"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "8dab469ebbc45798319e69eebf92308e541ce46760b49b18c6b3fe5e8965b30f"
++checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
+ 
+ [[package]]
+ name = "windows_i686_gnu"
+-version = "0.42.2"
++version = "0.48.5"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
++checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
+ 
+ [[package]]
+ name = "windows_i686_gnu"
+-version = "0.48.2"
++version = "0.52.6"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "2229ad223e178db5fbbc8bd8d3835e51e566b8474bfca58d2e6150c48bb723cd"
++checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+ 
+ [[package]]
+-name = "windows_i686_gnu"
+-version = "0.52.3"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "2a4e9b6a7cac734a8b4138a4e1044eac3404d8326b6c0f939276560687a033fb"
+-
+-[[package]]
+-name = "windows_i686_msvc"
+-version = "0.42.2"
++name = "windows_i686_gnullvm"
++version = "0.52.6"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
++checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
+ 
+ [[package]]
+ name = "windows_i686_msvc"
+-version = "0.48.2"
++version = "0.48.5"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "600956e2d840c194eedfc5d18f8242bc2e17c7775b6684488af3a9fff6fe3287"
++checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
+ 
+ [[package]]
+ name = "windows_i686_msvc"
+-version = "0.52.3"
++version = "0.52.6"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "28b0ec9c422ca95ff34a78755cfa6ad4a51371da2a5ace67500cf7ca5f232c58"
++checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+ 
+ [[package]]
+ name = "windows_x86_64_gnu"
+-version = "0.42.2"
++version = "0.48.5"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
++checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
+ 
+ [[package]]
+ name = "windows_x86_64_gnu"
+-version = "0.48.2"
++version = "0.52.6"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "ea99ff3f8b49fb7a8e0d305e5aec485bd068c2ba691b6e277d29eaeac945868a"
+-
+-[[package]]
+-name = "windows_x86_64_gnu"
+-version = "0.52.3"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "704131571ba93e89d7cd43482277d6632589b18ecf4468f591fbae0a8b101614"
+-
+-[[package]]
+-name = "windows_x86_64_gnullvm"
+-version = "0.42.2"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
++checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
+ 
+ [[package]]
+ name = "windows_x86_64_gnullvm"
+-version = "0.48.2"
++version = "0.48.5"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "8f1a05a1ece9a7a0d5a7ccf30ba2c33e3a61a30e042ffd247567d1de1d94120d"
++checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
+ 
+ [[package]]
+ name = "windows_x86_64_gnullvm"
+-version = "0.52.3"
++version = "0.52.6"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "42079295511643151e98d61c38c0acc444e52dd42ab456f7ccfd5152e8ecf21c"
++checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+ 
+ [[package]]
+ name = "windows_x86_64_msvc"
+-version = "0.42.2"
++version = "0.48.5"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
++checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
+ 
+ [[package]]
+ name = "windows_x86_64_msvc"
+-version = "0.48.2"
++version = "0.52.6"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "d419259aba16b663966e29e6d7c6ecfa0bb8425818bb96f6f1f3c3eb71a6e7b9"
++checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+ 
+ [[package]]
+-name = "windows_x86_64_msvc"
+-version = "0.52.3"
++name = "winnow"
++version = "0.5.40"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "0770833d60a970638e989b3fa9fd2bb1aaadcf88963d1659fd7d9990196ed2d6"
++checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876"
++dependencies = [
++ "memchr",
++]
+ 
+ [[package]]
+ name = "winnow"
+-version = "0.5.11"
++version = "0.6.18"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "1e461589e194280efaa97236b73623445efa195aa633fd7004f39805707a9d53"
++checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f"
+ dependencies = [
+  "memchr",
+ ]
+@@ -3483,43 +3341,29 @@ dependencies = [
+ 
+ [[package]]
+ name = "x11rb"
+-version = "0.11.1"
++version = "0.13.1"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "cdf3c79412dd91bae7a7366b8ad1565a85e35dd049affc3a6a2c549e97419617"
++checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12"
+ dependencies = [
+  "gethostname",
+- "nix 0.25.1",
+- "winapi",
+- "winapi-wsapoll",
++ "rustix",
+  "x11rb-protocol",
+ ]
+ 
+ [[package]]
+ name = "x11rb-protocol"
+-version = "0.11.1"
++version = "0.13.1"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "e0b1513b141123073ce54d5bb1d33f801f17508fbd61e02060b1214e96d39c56"
+-dependencies = [
+- "nix 0.25.1",
+-]
++checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d"
+ 
+ [[package]]
+ name = "xdg-home"
+-version = "1.0.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "2769203cd13a0c6015d515be729c526d041e9cf2c0cc478d57faee85f40c6dcd"
+-dependencies = [
+- "nix 0.26.2",
+- "winapi",
+-]
+-
+-[[package]]
+-name = "yaml-rust"
+-version = "0.4.5"
++version = "1.3.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
++checksum = "ec1cdab258fb55c0da61328dc52c8764709b249011b2cad0454c72f0bf10a1f6"
+ dependencies = [
+- "linked-hash-map",
++ "libc",
++ "windows-sys 0.59.0",
+ ]
+ 
+ [[package]]
+@@ -3537,7 +3381,7 @@ dependencies = [
+  "derive_more",
+  "eww_shared_util",
+  "insta",
+- "itertools 0.12.1",
++ "itertools 0.13.0",
+  "lalrpop",
+  "lalrpop-util",
+  "maplit",
+@@ -3554,24 +3398,21 @@ dependencies = [
+ 
+ [[package]]
+ name = "zbus"
+-version = "3.14.1"
++version = "4.4.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "31de390a2d872e4cd04edd71b425e29853f786dc99317ed72d73d6fcf5ebb948"
++checksum = "bb97012beadd29e654708a0fdb4c84bc046f537aecfde2c3ee0a9e4b4d48c725"
+ dependencies = [
+  "async-broadcast",
+  "async-process",
+  "async-recursion",
+  "async-trait",
+- "byteorder",
+- "derivative",
+  "enumflags2",
+  "event-listener",
+  "futures-core",
+  "futures-sink",
+  "futures-util",
+  "hex",
+- "nix 0.26.2",
+- "once_cell",
++ "nix",
+  "ordered-stream",
+  "rand",
+  "serde",
+@@ -3581,7 +3422,7 @@ dependencies = [
+  "tokio",
+  "tracing",
+  "uds_windows",
+- "winapi",
++ "windows-sys 0.52.0",
+  "xdg-home",
+  "zbus_macros",
+  "zbus_names",
+@@ -3590,23 +3431,22 @@ dependencies = [
+ 
+ [[package]]
+ name = "zbus_macros"
+-version = "3.14.1"
++version = "4.4.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "41d1794a946878c0e807f55a397187c11fc7a038ba5d868e7db4f3bd7760bc9d"
++checksum = "267db9407081e90bbfa46d841d3cbc60f59c0351838c4bc65199ecd79ab1983e"
+ dependencies = [
+- "proc-macro-crate",
++ "proc-macro-crate 3.1.0",
+  "proc-macro2",
+  "quote",
+- "regex",
+- "syn 1.0.109",
++ "syn 2.0.76",
+  "zvariant_utils",
+ ]
+ 
+ [[package]]
+ name = "zbus_names"
+-version = "2.6.0"
++version = "3.0.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "fb80bb776dbda6e23d705cf0123c3b95df99c4ebeaec6c2599d4a5419902b4a9"
++checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c"
+ dependencies = [
+  "serde",
+  "static_assertions",
+@@ -3615,33 +3455,33 @@ dependencies = [
+ 
+ [[package]]
+ name = "zerocopy"
+-version = "0.7.32"
++version = "0.7.35"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
++checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
+ dependencies = [
++ "byteorder",
+  "zerocopy-derive",
+ ]
+ 
+ [[package]]
+ name = "zerocopy-derive"
+-version = "0.7.32"
++version = "0.7.35"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
++checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
+ dependencies = [
+  "proc-macro2",
+  "quote",
+- "syn 2.0.50",
++ "syn 2.0.76",
+ ]
+ 
+ [[package]]
+ name = "zvariant"
+-version = "3.15.0"
++version = "4.2.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "44b291bee0d960c53170780af148dca5fa260a63cdd24f1962fa82e03e53338c"
++checksum = "2084290ab9a1c471c38fc524945837734fbf124487e105daec2bb57fd48c81fe"
+ dependencies = [
+- "byteorder",
++ "endi",
+  "enumflags2",
+- "libc",
+  "serde",
+  "static_assertions",
+  "zvariant_derive",
+@@ -3649,24 +3489,24 @@ dependencies = [
+ 
+ [[package]]
+ name = "zvariant_derive"
+-version = "3.15.0"
++version = "4.2.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "934d7a7dfc310d6ee06c87ffe88ef4eca7d3e37bb251dece2ef93da8f17d8ecd"
++checksum = "73e2ba546bda683a90652bac4a279bc146adad1386f25379cf73200d2002c449"
+ dependencies = [
+- "proc-macro-crate",
++ "proc-macro-crate 3.1.0",
+  "proc-macro2",
+  "quote",
+- "syn 1.0.109",
++ "syn 2.0.76",
+  "zvariant_utils",
+ ]
+ 
+ [[package]]
+ name = "zvariant_utils"
+-version = "1.0.1"
++version = "2.1.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "7234f0d811589db492d16893e3f21e8e2fd282e6d01b0cddee310322062cc200"
++checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340"
+ dependencies = [
+  "proc-macro2",
+  "quote",
+- "syn 1.0.109",
++ "syn 2.0.76",
+ ]
+diff --git a/Cargo.toml b/Cargo.toml
+index c886a87..b457ed4 100644
+--- a/Cargo.toml
++++ b/Cargo.toml
+@@ -6,53 +6,61 @@ resolver = "2"
+ 
+ simplexpr = { version = "0.1.0", path = "crates/simplexpr" }
+ eww_shared_util = { version = "0.1.0", path = "crates/eww_shared_util" }
+-yuck = { version = "0.1.0", path = "crates/yuck", default-features = false}
++yuck = { version = "0.1.0", path = "crates/yuck", default-features = false }
+ notifier_host = { version = "0.1.0", path = "crates/notifier_host" }
+ 
+-anyhow = "1.0.79"
++anyhow = "1.0.86"
+ bincode = "1.3.3"
+-cached = "0.48.0"
+-chrono = "0.4.26"
+-chrono-tz = "0.8.2"
+-clap = {version = "4.5.1", features = ["derive"] }
+-clap_complete = "4.5.1"
++cached = "0.53.1"
++chrono = "0.4.38"
++chrono-tz = "0.9.0"
++clap = { version = "4.5.1", features = ["derive"] }
++clap_complete = "4.5.12"
+ codespan-reporting = "0.11"
+-derive_more = "0.99"
++derive_more = { version = "1", features = [
++    "as_ref",
++    "debug",
++    "display",
++    "from",
++    "from_str",
++] }
+ extend = "1.2"
+-futures = "0.3.28"
+-grass = {version = "0.13.1", default-features = false}
++futures = "0.3.30"
++grass = "0.13.4"
++gtk = "0.18.1"
+ insta = "1.7"
+-itertools = "0.12.1"
+-jaq-core = "1.2.1"
+-jaq-parse = "1.0.2"
+-jaq-std = {version = "1.2.1", features = ["bincode"]}
+-jaq-interpret = "1.2.1"
+-jaq-syn = "1.1.0"
+-lalrpop = { version = "0.20.0", features = ["unicode"] }
+-lalrpop-util = { version = "0.20.0", features = ["unicode"] }
++itertools = "0.13.0"
++jaq-core = "1.5.1"
++jaq-parse = "1.0.3"
++jaq-std = "1.6.0"
++jaq-interpret = "1.5.0"
++jaq-syn = "1.6.0"
++lalrpop = { version = "0.20.2", features = ["unicode"] }
++lalrpop-util = { version = "0.20.2", features = ["unicode"] }
+ libc = "0.2"
+ log = "0.4"
+ maplit = "1"
+-nix = "0.27.1"
++nix = "0.29.0"
+ notify = "6.1.1"
+ once_cell = "1.19"
+ pretty_assertions = "1.4.0"
+ pretty_env_logger = "0.5.0"
+ ref-cast = "1.0.22"
+-regex = "1.10.3"
++regex = "1.10.5"
+ serde_json = "1.0"
+-serde = {version = "1.0", features = ["derive"]}
++serde = { version = "1.0", features = ["derive"] }
+ simple-signal = "1.1"
+ smart-default = "0.7.1"
+ static_assertions = "1.1.0"
+ strsim = "0.11"
+ strum = { version = "0.26", features = ["derive"] }
+-sysinfo = "0.30.5"
++sysinfo = "0.31.2"
+ thiserror = "1.0"
+-tokio-util = "0.7.8"
+-tokio = { version = "1.36.0", features = ["full"] }
++tokio-util = "0.7.11"
++tokio = { version = "1.39.2", features = ["full"] }
+ unescape = "0.1"
+ wait-timeout = "0.2"
++zbus = { version = "4.4.0", default-features = false, features = ["tokio"] }
+ 
+ [profile.dev]
+ split-debuginfo = "unpacked"
+diff --git a/crates/eww/Cargo.toml b/crates/eww/Cargo.toml
+index a5b62d9..d934c45 100644
+--- a/crates/eww/Cargo.toml
++++ b/crates/eww/Cargo.toml
+@@ -1,6 +1,6 @@
+ [package]
+ name = "eww"
+-version = "0.5.0"
++version = "0.6.0"
+ authors = ["elkowar <5300871+elkowar@users.noreply.github.com>"]
+ description = "Widgets for everyone!"
+ license = "MIT"
+@@ -9,7 +9,6 @@ homepage = "https://github.com/elkowar/eww"
+ edition = "2021"
+ 
+ 
+-
+ [features]
+ default = ["x11", "wayland"]
+ x11 = ["gdkx11", "x11rb"]
+@@ -21,34 +20,25 @@ eww_shared_util.workspace = true
+ yuck.workspace = true
+ notifier_host.workspace = true
+ 
+-gtk = "0.17.1"
+-gdk = "0.17.1"
+-pango = "0.17.1"
+-glib = "0.17.8"
+-glib-macros = "0.17.8"
+-
+-cairo-rs = "0.17"
+-cairo-sys-rs = "0.17"
+-
+-gdk-pixbuf = "0.17"
++gtk-layer-shell = { version = "0.8.1", optional = true }
++gdkx11 = { version = "0.18", optional = true }
++x11rb = { version = "0.13.1", features = ["randr"], optional = true }
++gdk-sys = "0.18.0"
+ 
+-gtk-layer-shell = { version = "0.6.1", optional = true }
+-gdkx11 = { version = "0.17", optional = true }
+-x11rb = { version = "0.11.1", features = ["randr"], optional = true }
+-
+-zbus = { version = "3.7.0", default-features = false, features = ["tokio"] }
+ ordered-stream = "0.2.0"
+ 
+-anyhow.workspace  = true
++
++grass.workspace = true
++anyhow.workspace = true
+ bincode.workspace = true
+ chrono.workspace = true
+-clap = {workspace = true, features = ["derive"] }
++clap = { workspace = true, features = ["derive"] }
+ clap_complete.workspace = true
+ codespan-reporting.workspace = true
+ derive_more.workspace = true
+ extend.workspace = true
+ futures.workspace = true
+-grass = {workspace = true, default-features = false}
++gtk.workspace = true
+ itertools.workspace = true
+ libc.workspace = true
+ log.workspace = true
+@@ -59,10 +49,11 @@ once_cell.workspace = true
+ pretty_env_logger.workspace = true
+ regex.workspace = true
+ serde_json.workspace = true
+-serde = {workspace = true, features = ["derive"]}
++serde = { workspace = true, features = ["derive"] }
+ simple-signal.workspace = true
+-sysinfo = { workspace = true, features = ["linux-netdevs"] }
++sysinfo = { workspace = true }
+ tokio-util.workspace = true
+ tokio = { workspace = true, features = ["full"] }
+ unescape.workspace = true
+ wait-timeout.workspace = true
++zbus = { workspace = true, default-features = false, features = ["tokio"] }
+diff --git a/crates/eww/src/app.rs b/crates/eww/src/app.rs
+index 41b3364..2da4ab2 100644
+--- a/crates/eww/src/app.rs
++++ b/crates/eww/src/app.rs
+@@ -1,5 +1,4 @@
+ use crate::{
+-    config,
+     daemon_response::DaemonResponseSender,
+     display_backend::DisplayBackend,
+     error_handling_ctx,
+@@ -17,12 +16,14 @@ use codespan_reporting::files::Files;
+ use eww_shared_util::{Span, VarName};
+ use gdk::Monitor;
+ use glib::ObjectExt;
++use gtk::{gdk, glib};
+ use itertools::Itertools;
+ use once_cell::sync::Lazy;
+ use simplexpr::{dynval::DynVal, SimplExpr};
+ use std::{
+     cell::RefCell,
+     collections::{HashMap, HashSet},
++    marker::PhantomData,
+     rc::Rc,
+ };
+ use tokio::sync::mpsc::UnboundedSender;
+@@ -87,10 +88,6 @@ pub enum DaemonCommand {
+ /// An opened window.
+ #[derive(Debug)]
+ pub struct EwwWindow {
+-    /// Every window has an id, uniquely identifying it.
+-    /// If no specific ID was specified whilst starting the window,
+-    /// this will be the same as the window name.
+-    pub instance_id: String,
+     pub name: String,
+     pub scope_index: ScopeIndex,
+     pub gtk_window: Window,
+@@ -111,11 +108,13 @@ impl EwwWindow {
+     }
+ }
+ 
+-pub struct App<B> {
+-    pub display_backend: B,
++pub struct App<B: DisplayBackend> {
+     pub scope_graph: Rc<RefCell<ScopeGraph>>,
+     pub eww_config: config::EwwConfig,
+-    /// Map of all currently open windows by their IDs
++    /// Map of all currently open windows to their unique IDs
++    /// If no specific ID was specified whilst starting the window,
++    /// it will be the same as the window name.
++    /// Therefore, only one window of a given name can exist when not using IDs.
+     pub open_windows: HashMap<String, EwwWindow>,
+     pub instance_id_to_args: HashMap<String, WindowArguments>,
+     /// Window names that are supposed to be open, but failed.
+@@ -131,9 +130,10 @@ pub struct App<B> {
+     pub window_close_timer_abort_senders: HashMap<String, futures::channel::oneshot::Sender<()>>,
+ 
+     pub paths: EwwPaths,
++    pub phantom: PhantomData<B>,
+ }
+ 
+-impl<B> std::fmt::Debug for App<B> {
++impl<B: DisplayBackend> std::fmt::Debug for App<B> {
+     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+         f.debug_struct("App")
+             .field("scope_graph", &*self.scope_graph.borrow())
+@@ -572,7 +572,6 @@ fn initialize_window<B: DisplayBackend>(
+     window.show_all();
+ 
+     Ok(EwwWindow {
+-        instance_id: window_init.id.clone(),
+         name: window_init.name.clone(),
+         gtk_window: window,
+         scope_index: window_scope,
+@@ -626,6 +625,18 @@ fn get_gdk_monitor(identifier: Option<MonitorIdentifier>) -> Result<Monitor> {
+     Ok(monitor)
+ }
+ 
++/// Get the name of monitor plug for given monitor number
++/// workaround gdk not providing this information on wayland in regular calls
++/// gdk_screen_get_monitor_plug_name is deprecated but works fine for that case
++fn get_monitor_plug_name(display: &gdk::Display, monitor_num: i32) -> Option<&str> {
++    unsafe {
++        use glib::translate::ToGlibPtr;
++        let plug_name_pointer = gdk_sys::gdk_screen_get_monitor_plug_name(display.default_screen().to_glib_none().0, monitor_num);
++        use std::ffi::CStr;
++        CStr::from_ptr(plug_name_pointer).to_str().ok()
++    }
++}
++
+ /// Returns the [Monitor][gdk::Monitor] structure corresponding to the identifer.
+ /// Outside of x11, only [MonitorIdentifier::Numeric] is supported
+ pub fn get_monitor_from_display(display: &gdk::Display, identifier: &MonitorIdentifier) -> Option<gdk::Monitor> {
+@@ -643,7 +654,7 @@ pub fn get_monitor_from_display(display: &gdk::Display, identifier: &MonitorIden
+         MonitorIdentifier::Name(name) => {
+             for m in 0..display.n_monitors() {
+                 if let Some(model) = display.monitor(m).and_then(|x| x.model()) {
+-                    if model == *name {
++                    if model == *name || Some(name.as_str()) == get_monitor_plug_name(display, m) {
+                         return display.monitor(m);
+                     }
+                 }
+diff --git a/crates/eww/src/config/inbuilt.rs b/crates/eww/src/config/inbuilt.rs
+index 13cf1e6..ba29939 100644
+--- a/crates/eww/src/config/inbuilt.rs
++++ b/crates/eww/src/config/inbuilt.rs
+@@ -34,7 +34,7 @@ define_builtin_vars! {
+     // @prop { <name>: temperature }
+     "EWW_TEMPS" [2] => || Ok(DynVal::from(get_temperatures())),
+ 
+-    // @desc EWW_RAM - Information on ram and swap usage in kB.
++    // @desc EWW_RAM - Information on ram and swap usage in bytes.
+     // @prop { total_mem, free_mem, total_swap, free_swap, available_mem, used_mem, used_mem_perc }
+     "EWW_RAM" [2] => || Ok(DynVal::from(get_ram())),
+ 
+@@ -42,7 +42,7 @@ define_builtin_vars! {
+     // @prop { <mount_point>: { name, total, free, used, used_perc } }
+     "EWW_DISK" [2] => || Ok(DynVal::from(get_disks())),
+ 
+-    // @desc EWW_BATTERY - Battery capacity in procent of the main battery
++    // @desc EWW_BATTERY - Battery capacity in percent of the main battery
+     // @prop { <name>: { capacity, status } }
+     "EWW_BATTERY" [2] => || Ok(DynVal::from(
+         match get_battery_capacity() {
+diff --git a/crates/eww/src/config/system_stats.rs b/crates/eww/src/config/system_stats.rs
+index 995d7ad..787b3de 100644
+--- a/crates/eww/src/config/system_stats.rs
++++ b/crates/eww/src/config/system_stats.rs
+@@ -202,8 +202,54 @@ pub fn get_battery_capacity() -> Result<String> {
+     Ok(serde_json::to_string(&(Data { batteries, total_avg: (current / total) * 100_f64 })).unwrap())
+ }
+ 
++#[cfg(any(target_os = "netbsd", target_os = "freebsd", target_os = "openbsd"))]
++pub fn get_battery_capacity() -> Result<String> {
++    let batteries = String::from_utf8(
++        // I have only tested `apm` on FreeBSD, but it *should* work on all of the listed targets,
++        // based on what I can tell from their online man pages.
++        std::process::Command::new("apm")
++            .output()
++            .context("\nError while getting the battery values on bsd, with `apm`: ")?
++            .stdout,
++    )?;
++
++    // `apm` output should look something like this:
++    // $ apm
++    // ...
++    // Remaining battery life: 87%
++    // Remaining battery time: unknown
++    // Number of batteries: 1
++    // Battery 0
++    //         Battery Status: charging
++    //         Remaining battery life: 87%
++    //         Remaining battery time: unknown
++    // ...
++    // last 4 lines are repeated for each battery.
++    // see also:
++    // https://www.freebsd.org/cgi/man.cgi?query=apm&manpath=FreeBSD+13.1-RELEASE+and+Ports
++    // https://man.openbsd.org/amd64/apm.8
++    // https://man.netbsd.org/apm.8
++    let mut json = String::from('{');
++    let re_total = regex!(r"(?m)^Remaining battery life: (\d+)%");
++    let re_single = regex!(r"(?sm)^Battery (\d+):.*?Status: (\w+).*?(\d+)%");
++    for bat in re_single.captures_iter(&batteries) {
++        json.push_str(&format!(
++            r#""BAT{}": {{ "status": "{}", "capacity": {} }}, "#,
++            bat.get(1).unwrap().as_str(),
++            bat.get(2).unwrap().as_str(),
++            bat.get(3).unwrap().as_str(),
++        ))
++    }
++
++    json.push_str(&format!(r#""total_avg": {}}}"#, re_total.captures(&batteries).unwrap().get(1).unwrap().as_str()));
++    Ok(json)
++}
++
+ #[cfg(not(target_os = "macos"))]
+ #[cfg(not(target_os = "linux"))]
++#[cfg(not(target_os = "netbsd"))]
++#[cfg(not(target_os = "freebsd"))]
++#[cfg(not(target_os = "openbsd"))]
+ pub fn get_battery_capacity() -> Result<String> {
+     Err(anyhow::anyhow!("Eww doesn't support your OS for getting the battery capacity"))
+ }
+@@ -212,7 +258,6 @@ pub fn net() -> String {
+     let (ref mut last_refresh, ref mut networks) = &mut *NETWORKS.lock().unwrap();
+ 
+     networks.refresh_list();
+-    networks.refresh();
+     let elapsed = last_refresh.next_refresh();
+ 
+     networks
+diff --git a/crates/eww/src/display_backend.rs b/crates/eww/src/display_backend.rs
+index d416166..fe80dcb 100644
+--- a/crates/eww/src/display_backend.rs
++++ b/crates/eww/src/display_backend.rs
+@@ -1,5 +1,7 @@
+ use crate::{widgets::window::Window, window_initiator::WindowInitiator};
+ 
++use gtk::gdk;
++
+ #[cfg(feature = "wayland")]
+ pub use platform_wayland::WaylandBackend;
+ 
+@@ -8,6 +10,7 @@ pub use platform_x11::{set_xprops, X11Backend};
+ 
+ pub trait DisplayBackend: Send + Sync + 'static {
+     const IS_X11: bool;
++    const IS_WAYLAND: bool;
+ 
+     fn initialize_window(window_init: &WindowInitiator, monitor: gdk::Rectangle, x: i32, y: i32) -> Option<Window>;
+ }
+@@ -16,6 +19,7 @@ pub struct NoBackend;
+ 
+ impl DisplayBackend for NoBackend {
+     const IS_X11: bool = false;
++    const IS_WAYLAND: bool = false;
+ 
+     fn initialize_window(_window_init: &WindowInitiator, _monitor: gdk::Rectangle, x: i32, y: i32) -> Option<Window> {
+         Some(Window::new(gtk::WindowType::Toplevel, x, y))
+@@ -25,7 +29,9 @@ impl DisplayBackend for NoBackend {
+ #[cfg(feature = "wayland")]
+ mod platform_wayland {
+     use crate::{widgets::window::Window, window_initiator::WindowInitiator};
++    use gtk::gdk;
+     use gtk::prelude::*;
++    use gtk_layer_shell::LayerShell;
+     use yuck::config::{window_definition::WindowStacking, window_geometry::AnchorAlignment};
+ 
+     use super::DisplayBackend;
+@@ -34,16 +40,17 @@ mod platform_wayland {
+ 
+     impl DisplayBackend for WaylandBackend {
+         const IS_X11: bool = false;
++        const IS_WAYLAND: bool = true;
+ 
+         fn initialize_window(window_init: &WindowInitiator, monitor: gdk::Rectangle, x: i32, y: i32) -> Option<Window> {
+             let window = Window::new(gtk::WindowType::Toplevel, x, y);
+             // Initialising a layer shell surface
+-            gtk_layer_shell::init_for_window(&window);
++            window.init_layer_shell();
+             // Sets the monitor where the surface is shown
+             if let Some(ident) = window_init.monitor.clone() {
+                 let display = gdk::Display::default().expect("could not get default display");
+                 if let Some(monitor) = crate::app::get_monitor_from_display(&display, &ident) {
+-                    gtk_layer_shell::set_monitor(&window, &monitor);
++                    window.set_monitor(&monitor);
+                 } else {
+                     return None;
+                 }
+@@ -52,18 +59,18 @@ mod platform_wayland {
+ 
+             // Sets the layer where the layer shell surface will spawn
+             match window_init.stacking {
+-                WindowStacking::Foreground => gtk_layer_shell::set_layer(&window, gtk_layer_shell::Layer::Top),
+-                WindowStacking::Background => gtk_layer_shell::set_layer(&window, gtk_layer_shell::Layer::Background),
+-                WindowStacking::Bottom => gtk_layer_shell::set_layer(&window, gtk_layer_shell::Layer::Bottom),
+-                WindowStacking::Overlay => gtk_layer_shell::set_layer(&window, gtk_layer_shell::Layer::Overlay),
++                WindowStacking::Foreground => window.set_layer(gtk_layer_shell::Layer::Top),
++                WindowStacking::Background => window.set_layer(gtk_layer_shell::Layer::Background),
++                WindowStacking::Bottom => window.set_layer(gtk_layer_shell::Layer::Bottom),
++                WindowStacking::Overlay => window.set_layer(gtk_layer_shell::Layer::Overlay),
+             }
+ 
+             if let Some(namespace) = &window_init.backend_options.wayland.namespace {
+-                gtk_layer_shell::set_namespace(&window, namespace);
++                window.set_namespace(namespace);
+             }
+ 
+             // Sets the keyboard interactivity
+-            gtk_layer_shell::set_keyboard_interactivity(&window, window_init.backend_options.wayland.focusable);
++            window.set_keyboard_interactivity(window_init.backend_options.wayland.focusable);
+ 
+             if let Some(geometry) = window_init.geometry {
+                 // Positioning surface
+@@ -83,27 +90,27 @@ mod platform_wayland {
+                     AnchorAlignment::END => bottom = true,
+                 }
+ 
+-                gtk_layer_shell::set_anchor(&window, gtk_layer_shell::Edge::Left, left);
+-                gtk_layer_shell::set_anchor(&window, gtk_layer_shell::Edge::Right, right);
+-                gtk_layer_shell::set_anchor(&window, gtk_layer_shell::Edge::Top, top);
+-                gtk_layer_shell::set_anchor(&window, gtk_layer_shell::Edge::Bottom, bottom);
++                window.set_anchor(gtk_layer_shell::Edge::Left, left);
++                window.set_anchor(gtk_layer_shell::Edge::Right, right);
++                window.set_anchor(gtk_layer_shell::Edge::Top, top);
++                window.set_anchor(gtk_layer_shell::Edge::Bottom, bottom);
+ 
+                 let xoffset = geometry.offset.x.pixels_relative_to(monitor.width());
+                 let yoffset = geometry.offset.y.pixels_relative_to(monitor.height());
+ 
+                 if left {
+-                    gtk_layer_shell::set_margin(&window, gtk_layer_shell::Edge::Left, xoffset);
++                    window.set_layer_shell_margin(gtk_layer_shell::Edge::Left, xoffset);
+                 } else {
+-                    gtk_layer_shell::set_margin(&window, gtk_layer_shell::Edge::Right, xoffset);
++                    window.set_layer_shell_margin(gtk_layer_shell::Edge::Right, xoffset);
+                 }
+                 if bottom {
+-                    gtk_layer_shell::set_margin(&window, gtk_layer_shell::Edge::Bottom, yoffset);
++                    window.set_layer_shell_margin(gtk_layer_shell::Edge::Bottom, yoffset);
+                 } else {
+-                    gtk_layer_shell::set_margin(&window, gtk_layer_shell::Edge::Top, yoffset);
++                    window.set_layer_shell_margin(gtk_layer_shell::Edge::Top, yoffset);
+                 }
+             }
+             if window_init.backend_options.wayland.exclusive {
+-                gtk_layer_shell::auto_exclusive_zone_enable(&window);
++                window.auto_exclusive_zone_enable();
+             }
+             Some(window)
+         }
+@@ -115,6 +122,7 @@ mod platform_x11 {
+     use crate::{widgets::window::Window, window_initiator::WindowInitiator};
+     use anyhow::{Context, Result};
+     use gdk::Monitor;
++    use gtk::gdk;
+     use gtk::{self, prelude::*};
+     use x11rb::protocol::xproto::ConnectionExt;
+ 
+@@ -134,6 +142,7 @@ mod platform_x11 {
+     pub struct X11Backend;
+     impl DisplayBackend for X11Backend {
+         const IS_X11: bool = true;
++        const IS_WAYLAND: bool = false;
+ 
+         fn initialize_window(window_init: &WindowInitiator, _monitor: gdk::Rectangle, x: i32, y: i32) -> Option<Window> {
+             let window_type =
+diff --git a/crates/eww/src/geometry.rs b/crates/eww/src/geometry.rs
+index bde5180..efe6352 100644
+--- a/crates/eww/src/geometry.rs
++++ b/crates/eww/src/geometry.rs
+@@ -1,7 +1,7 @@
+-use derive_more::*;
++use derive_more::{Debug, *};
+ 
+ #[derive(Debug, Copy, Clone, Eq, PartialEq, Display)]
+-#[display(fmt = ".x*.y:.width*.height")]
++#[display(".x*.y:.width*.height")]
+ pub struct Rect {
+     pub x: i32,
+     pub y: i32,
+diff --git a/crates/eww/src/main.rs b/crates/eww/src/main.rs
+index 0db2b97..853a8fb 100644
+--- a/crates/eww/src/main.rs
++++ b/crates/eww/src/main.rs
+@@ -53,28 +53,31 @@ fn main() {
+         return;
+     }
+ 
++    let detected_wayland = detect_wayland();
+     #[allow(unused)]
+-    let use_wayland = opts.force_wayland || detect_wayland();
++    let use_wayland = opts.force_wayland || detected_wayland;
+     #[cfg(all(feature = "wayland", feature = "x11"))]
+     let result = if use_wayland {
+-        run(opts, eww_binary_name, display_backend::WaylandBackend)
++        log::debug!("Running on wayland. force_wayland={}, detected_wayland={}", opts.force_wayland, detected_wayland);
++        run::<display_backend::WaylandBackend>(opts, eww_binary_name)
+     } else {
+-        run(opts, eww_binary_name, display_backend::X11Backend)
++        log::debug!("Running on X11. force_wayland={}, detected_wayland={}", opts.force_wayland, detected_wayland);
++        run::<display_backend::X11Backend>(opts, eww_binary_name)
+     };
+ 
+     #[cfg(all(not(feature = "wayland"), feature = "x11"))]
+     let result = {
+         if use_wayland {
+-            log::warn!("Eww compiled without wayland support. falling back to X11, eventhough wayland was requested.");
++            log::warn!("Eww compiled without wayland support. Falling back to X11, eventhough wayland was requested.");
+         }
+-        run(opts, eww_binary_name, display_backend::X11Backend)
++        run::<display_backend::X11Backend>(opts, eww_binary_name)
+     };
+ 
+     #[cfg(all(feature = "wayland", not(feature = "x11")))]
+-    let result = run(opts, eww_binary_name, display_backend::WaylandBackend);
++    let result = run::<display_backend::WaylandBackend>(opts, eww_binary_name);
+ 
+     #[cfg(not(any(feature = "wayland", feature = "x11")))]
+-    let result = run(opts, eww_binary_name, display_backend::NoBackend);
++    let result = run::<display_backend::NoBackend>(opts, eww_binary_name);
+ 
+     if let Err(err) = result {
+         error_handling_ctx::print_error(err);
+@@ -88,7 +91,7 @@ fn detect_wayland() -> bool {
+     session_type.contains("wayland") || (!wayland_display.is_empty() && !session_type.contains("x11"))
+ }
+ 
+-fn run<B: DisplayBackend>(opts: opts::Opt, eww_binary_name: String, display_backend: B) -> Result<()> {
++fn run<B: DisplayBackend>(opts: opts::Opt, eww_binary_name: String) -> Result<()> {
+     let paths = opts
+         .config_path
+         .map(EwwPaths::from_config_dir)
+@@ -128,7 +131,7 @@ fn run<B: DisplayBackend>(opts: opts::Opt, eww_binary_name: String, display_back
+             if !opts.show_logs {
+                 println!("Run `{} logs` to see any errors while editing your configuration.", eww_binary_name);
+             }
+-            let fork_result = server::initialize_server(paths.clone(), None, display_backend, !opts.no_daemonize)?;
++            let fork_result = server::initialize_server::<B>(paths.clone(), None, !opts.no_daemonize)?;
+             opts.no_daemonize || fork_result == ForkResult::Parent
+         }
+ 
+@@ -160,7 +163,7 @@ fn run<B: DisplayBackend>(opts: opts::Opt, eww_binary_name: String, display_back
+ 
+                     let (command, response_recv) = action.into_daemon_command();
+                     // start the daemon and give it the command
+-                    let fork_result = server::initialize_server(paths.clone(), Some(command), display_backend, true)?;
++                    let fork_result = server::initialize_server::<B>(paths.clone(), Some(command), true)?;
+                     let is_parent = fork_result == ForkResult::Parent;
+                     if let (Some(recv), true) = (response_recv, is_parent) {
+                         listen_for_daemon_response(recv);
+diff --git a/crates/eww/src/server.rs b/crates/eww/src/server.rs
+index 50b24b2..8e22d3f 100644
+--- a/crates/eww/src/server.rs
++++ b/crates/eww/src/server.rs
+@@ -1,5 +1,5 @@
+ use crate::{
+-    app::{self, DaemonCommand},
++    app::{self, App, DaemonCommand},
+     config, daemon_response,
+     display_backend::DisplayBackend,
+     error_handling_ctx, ipc_server, script_var_handler,
+@@ -12,6 +12,7 @@ use std::{
+     cell::RefCell,
+     collections::{HashMap, HashSet},
+     io::Write,
++    marker::PhantomData,
+     os::unix::io::AsRawFd,
+     path::Path,
+     rc::Rc,
+@@ -22,7 +23,6 @@ use tokio::sync::mpsc::*;
+ pub fn initialize_server<B: DisplayBackend>(
+     paths: EwwPaths,
+     action: Option<DaemonCommand>,
+-    display_backend: B,
+     should_daemonize: bool,
+ ) -> Result<ForkResult> {
+     let (ui_send, mut ui_recv) = tokio::sync::mpsc::unbounded_channel();
+@@ -57,7 +57,7 @@ pub fn initialize_server<B: DisplayBackend>(
+ ┏━━━━━━━━━━━━━━━━━━━━━━━┓
+ ┃Initializing eww daemon┃
+ ┗━━━━━━━━━━━━━━━━━━━━━━━┛
+-    "#
++"#
+     );
+ 
+     simple_signal::set_handler(&[simple_signal::Signal::Int, simple_signal::Signal::Term], move |_| {
+@@ -68,6 +68,9 @@ pub fn initialize_server<B: DisplayBackend>(
+         }
+     });
+ 
++    if B::IS_WAYLAND {
++        std::env::set_var("GDK_BACKEND", "wayland")
++    }
+     gtk::init()?;
+ 
+     log::debug!("Initializing script var handler");
+@@ -75,8 +78,7 @@ pub fn initialize_server<B: DisplayBackend>(
+ 
+     let (scope_graph_evt_send, mut scope_graph_evt_recv) = tokio::sync::mpsc::unbounded_channel();
+ 
+-    let mut app = app::App {
+-        display_backend,
++    let mut app: App<B> = app::App {
+         scope_graph: Rc::new(RefCell::new(ScopeGraph::from_global_vars(
+             eww_config.generate_initial_state()?,
+             scope_graph_evt_send,
+@@ -90,9 +92,10 @@ pub fn initialize_server<B: DisplayBackend>(
+         app_evt_send: ui_send.clone(),
+         window_close_timer_abort_senders: HashMap::new(),
+         paths,
++        phantom: PhantomData,
+     };
+ 
+-    if let Some(screen) = gdk::Screen::default() {
++    if let Some(screen) = gtk::gdk::Screen::default() {
+         gtk::StyleContext::add_provider_for_screen(&screen, &app.css_provider, gtk::STYLE_PROVIDER_PRIORITY_APPLICATION);
+     }
+ 
+@@ -105,7 +108,7 @@ pub fn initialize_server<B: DisplayBackend>(
+     // initialize all the handlers and tasks running asyncronously
+     let tokio_handle = init_async_part(app.paths.clone(), ui_send);
+ 
+-    glib::MainContext::default().spawn_local(async move {
++    gtk::glib::MainContext::default().spawn_local(async move {
+         // if an action was given to the daemon initially, execute it first.
+         if let Some(action) = action {
+             app.handle_command(action);
+diff --git a/crates/eww/src/widgets/build_widget.rs b/crates/eww/src/widgets/build_widget.rs
+index c3a1899..23e76ee 100644
+--- a/crates/eww/src/widgets/build_widget.rs
++++ b/crates/eww/src/widgets/build_widget.rs
+@@ -1,8 +1,8 @@
+ use anyhow::{Context, Result};
+ use codespan_reporting::diagnostic::Severity;
+ use eww_shared_util::{AttrName, Spanned};
+-use gdk::prelude::Cast;
+ use gtk::{
++    gdk::prelude::Cast,
+     prelude::{BoxExt, ContainerExt, WidgetExt},
+     Orientation,
+ };
+diff --git a/crates/eww/src/widgets/circular_progressbar.rs b/crates/eww/src/widgets/circular_progressbar.rs
+index 76861af..9e1baf6 100644
+--- a/crates/eww/src/widgets/circular_progressbar.rs
++++ b/crates/eww/src/widgets/circular_progressbar.rs
+@@ -1,7 +1,6 @@
+ use anyhow::{anyhow, Result};
+-use glib::{object_subclass, prelude::*, wrapper};
+-use glib_macros::Properties;
+-use gtk::{prelude::*, subclass::prelude::*};
++use gtk::glib::{self, object_subclass, prelude::*, wrapper, Properties};
++use gtk::{cairo, gdk, prelude::*, subclass::prelude::*};
+ use std::cell::RefCell;
+ 
+ use crate::error_handling_ctx;
+@@ -154,7 +153,7 @@ impl WidgetImpl for CircProgPriv {
+         self.preferred_height()
+     }
+ 
+-    fn draw(&self, cr: &cairo::Context) -> Inhibit {
++    fn draw(&self, cr: &cairo::Context) -> glib::Propagation {
+         let res: Result<()> = (|| {
+             let value = *self.value.borrow();
+             let start_at = *self.start_at.borrow();
+@@ -226,7 +225,7 @@ impl WidgetImpl for CircProgPriv {
+             error_handling_ctx::print_error(error)
+         };
+ 
+-        gtk::Inhibit(false)
++        glib::Propagation::Proceed
+     }
+ }
+ 
+diff --git a/crates/eww/src/widgets/graph.rs b/crates/eww/src/widgets/graph.rs
+index a3a7713..0d5f46f 100644
+--- a/crates/eww/src/widgets/graph.rs
++++ b/crates/eww/src/widgets/graph.rs
+@@ -2,9 +2,8 @@ use std::{cell::RefCell, collections::VecDeque};
+ // https://www.figuiere.net/technotes/notes/tn002/
+ // https://github.com/gtk-rs/examples/blob/master/src/bin/listbox_model.rs
+ use anyhow::{anyhow, Result};
+-use glib::{object_subclass, wrapper};
+-use glib_macros::Properties;
+-use gtk::{prelude::*, subclass::prelude::*};
++use gtk::glib::{self, object_subclass, wrapper, Properties};
++use gtk::{cairo, gdk, prelude::*, subclass::prelude::*};
+ 
+ use crate::error_handling_ctx;
+ 
+@@ -39,6 +38,13 @@ pub struct GraphPriv {
+     #[property(get, set, nick = "Time Range", blurb = "The Time Range", minimum = 0u64, maximum = u64::MAX, default = 10u64)]
+     time_range: RefCell<u64>,
+ 
++    #[property(get, set, nick = "Flip X", blurb = "Flip the x axis", default = true)]
++    flip_x: RefCell<bool>,
++    #[property(get, set, nick = "Flip Y", blurb = "Flip the y axis", default = true)]
++    flip_y: RefCell<bool>,
++    #[property(get, set, nick = "Vertical", blurb = "Exchange the x and y axes", default = false)]
++    vertical: RefCell<bool>,
++
+     history: RefCell<VecDeque<(std::time::Instant, f64)>>,
+     extra_point: RefCell<Option<(std::time::Instant, f64)>>,
+     last_updated_at: RefCell<std::time::Instant>,
+@@ -54,6 +60,9 @@ impl Default for GraphPriv {
+             max: RefCell::new(100.0),
+             dynamic: RefCell::new(true),
+             time_range: RefCell::new(10),
++            flip_x: RefCell::new(true),
++            flip_y: RefCell::new(true),
++            vertical: RefCell::new(false),
+             history: RefCell::new(VecDeque::new()),
+             extra_point: RefCell::new(None),
+             last_updated_at: RefCell::new(std::time::Instant::now()),
+@@ -78,6 +87,16 @@ impl GraphPriv {
+         }
+         history.push_back(v);
+     }
++    /**
++     * Receives normalized (0-1) coordinates `x` and `y` and convert them to the
++     * point on the widget.
++     */
++    fn value_to_point(&self, width: f64, height: f64, x: f64, y: f64) -> (f64, f64) {
++        let x = if *self.flip_x.borrow() { 1.0 - x } else { x };
++        let y = if *self.flip_y.borrow() { 1.0 - y } else { y };
++        let (x, y) = if *self.vertical.borrow() { (y, x) } else { (x, y) };
++        (width * x, height * y)
++    }
+ }
+ 
+ impl ObjectImpl for GraphPriv {
+@@ -111,6 +130,15 @@ impl ObjectImpl for GraphPriv {
+             "line-style" => {
+                 self.line_style.replace(value.get().unwrap());
+             }
++            "flip-x" => {
++                self.flip_x.replace(value.get().unwrap());
++            }
++            "flip-y" => {
++                self.flip_y.replace(value.get().unwrap());
++            }
++            "vertical" => {
++                self.vertical.replace(value.get().unwrap());
++            }
+             x => panic!("Tried to set inexistant property of Graph: {}", x,),
+         }
+     }
+@@ -170,7 +198,7 @@ impl WidgetImpl for GraphPriv {
+         (width, width)
+     }
+ 
+-    fn draw(&self, cr: &cairo::Context) -> Inhibit {
++    fn draw(&self, cr: &cairo::Context) -> glib::Propagation {
+         let res: Result<()> = (|| {
+             let history = &*self.history.borrow();
+             let extra_point = *self.extra_point.borrow();
+@@ -215,18 +243,15 @@ impl WidgetImpl for GraphPriv {
+                     .iter()
+                     .map(|(instant, value)| {
+                         let t = last_updated_at.duration_since(*instant).as_millis() as f64;
+-                        let x = width * (1.0 - (t / time_range));
+-                        let y = height * (1.0 - ((value - min) / value_range));
+-                        (x, y)
++                        self.value_to_point(width, height, t / time_range, (value - min) / value_range)
+                     })
+                     .collect::<VecDeque<(f64, f64)>>();
+ 
+                 // Aad an extra point outside of the graph to extend the line to the left
+                 if let Some((instant, value)) = extra_point {
+                     let t = last_updated_at.duration_since(instant).as_millis() as f64;
+-                    let x = -width * ((t - time_range) / time_range);
+-                    let y = height * (1.0 - ((value - min) / value_range));
+-                    points.push_front((x, y));
++                    let (x, y) = self.value_to_point(width, height, (t - time_range) / time_range, (value - min) / value_range);
++                    points.push_front(if *self.vertical.borrow() { (x, -y) } else { (-x, y) });
+                 }
+                 points
+             };
+@@ -276,7 +301,7 @@ impl WidgetImpl for GraphPriv {
+             error_handling_ctx::print_error(error)
+         };
+ 
+-        gtk::Inhibit(false)
++        glib::Propagation::Proceed
+     }
+ }
+ 
+diff --git a/crates/eww/src/widgets/systray.rs b/crates/eww/src/widgets/systray.rs
+index feab47e..bfd0aa8 100644
+--- a/crates/eww/src/widgets/systray.rs
++++ b/crates/eww/src/widgets/systray.rs
+@@ -1,7 +1,11 @@
+ use crate::widgets::window::Window;
+ use futures::StreamExt;
+-use gtk::{cairo::Surface, gdk::ffi::gdk_cairo_surface_create_from_pixbuf, prelude::*};
+-use notifier_host;
++use gtk::{
++    cairo::Surface,
++    gdk::{self, ffi::gdk_cairo_surface_create_from_pixbuf, NotifyType},
++    glib,
++    prelude::*,
++};
+ use std::{cell::RefCell, future::Future, rc::Rc};
+ 
+ // DBus state shared between systray instances, to avoid creating too many connections etc.
+@@ -105,6 +109,7 @@ impl notifier_host::Host for Tray {
+     fn remove_item(&mut self, id: &str) {
+         if let Some(item) = self.items.get(id) {
+             self.container.remove(&item.widget);
++            self.items.remove(id);
+         } else {
+             log::warn!("Tried to remove nonexistent item {:?} from systray", id);
+         }
+@@ -130,11 +135,27 @@ impl Drop for Item {
+ 
+ impl Item {
+     fn new(id: String, item: notifier_host::Item, icon_size: tokio::sync::watch::Receiver<i32>) -> Self {
+-        let widget = gtk::EventBox::new();
+-        let out_widget = widget.clone(); // copy so we can return it
++        let gtk_widget = gtk::EventBox::new();
++
++        // Support :hover selector
++        gtk_widget.connect_enter_notify_event(|gtk_widget, evt| {
++            if evt.detail() != NotifyType::Inferior {
++                gtk_widget.clone().set_state_flags(gtk::StateFlags::PRELIGHT, false);
++            }
++            glib::Propagation::Proceed
++        });
++
++        gtk_widget.connect_leave_notify_event(|gtk_widget, evt| {
++            if evt.detail() != NotifyType::Inferior {
++                gtk_widget.clone().unset_state_flags(gtk::StateFlags::PRELIGHT);
++            }
++            glib::Propagation::Proceed
++        });
++
++        let out_widget = gtk_widget.clone(); // copy so we can return it
+ 
+         let task = glib::MainContext::default().spawn_local(async move {
+-            if let Err(e) = Item::maintain(widget.clone(), item, icon_size).await {
++            if let Err(e) = Item::maintain(gtk_widget.clone(), item, icon_size).await {
+                 log::error!("error for systray item {}: {}", id, e);
+             }
+         });
+@@ -213,7 +234,7 @@ impl Item {
+             if let Err(result) = result {
+                 log::error!("failed to handle mouse click {}: {}", evt.button(), result);
+             }
+-            gtk::Inhibit(true)
++            glib::Propagation::Stop
+         }));
+ 
+         // updates
+diff --git a/crates/eww/src/widgets/transform.rs b/crates/eww/src/widgets/transform.rs
+index faa9aa4..5e184b6 100644
+--- a/crates/eww/src/widgets/transform.rs
++++ b/crates/eww/src/widgets/transform.rs
+@@ -1,6 +1,5 @@
+ use anyhow::{anyhow, Result};
+-use glib::{object_subclass, wrapper};
+-use glib_macros::Properties;
++use gtk::glib::{self, object_subclass, wrapper, Properties};
+ use gtk::{prelude::*, subclass::prelude::*};
+ use std::{cell::RefCell, str::FromStr};
+ use yuck::value::NumWithUnit;
+@@ -18,6 +17,12 @@ pub struct TransformPriv {
+     #[property(get, set, nick = "Rotate", blurb = "The Rotation", minimum = f64::MIN, maximum = f64::MAX, default = 0f64)]
+     rotate: RefCell<f64>,
+ 
++    #[property(get, set, nick = "Transform-Origin X", blurb = "X coordinate (%/px) for the Transform-Origin", default = None)]
++    transform_origin_x: RefCell<Option<String>>,
++
++    #[property(get, set, nick = "Transform-Origin Y", blurb = "Y coordinate (%/px) for the Transform-Origin", default = None)]
++    transform_origin_y: RefCell<Option<String>>,
++
+     #[property(get, set, nick = "Translate x", blurb = "The X Translation", default = None)]
+     translate_x: RefCell<Option<String>>,
+ 
+@@ -38,6 +43,8 @@ impl Default for TransformPriv {
+     fn default() -> Self {
+         TransformPriv {
+             rotate: RefCell::new(0.0),
++            transform_origin_x: RefCell::new(None),
++            transform_origin_y: RefCell::new(None),
+             translate_x: RefCell::new(None),
+             translate_y: RefCell::new(None),
+             scale_x: RefCell::new(None),
+@@ -58,6 +65,14 @@ impl ObjectImpl for TransformPriv {
+                 self.rotate.replace(value.get().unwrap());
+                 self.obj().queue_draw(); // Queue a draw call with the updated value
+             }
++            "transform-origin-x" => {
++                self.transform_origin_x.replace(value.get().unwrap());
++                self.obj().queue_draw(); // Queue a draw call with the updated value
++            }
++            "transform-origin-y" => {
++                self.transform_origin_y.replace(value.get().unwrap());
++                self.obj().queue_draw(); // Queue a draw call with the updated value
++            }
+             "translate-x" => {
+                 self.translate_x.replace(value.get().unwrap());
+                 self.obj().queue_draw(); // Queue a draw call with the updated value
+@@ -121,7 +136,7 @@ impl ContainerImpl for TransformPriv {
+ 
+ impl BinImpl for TransformPriv {}
+ impl WidgetImpl for TransformPriv {
+-    fn draw(&self, cr: &cairo::Context) -> Inhibit {
++    fn draw(&self, cr: &gtk::cairo::Context) -> glib::Propagation {
+         let res: Result<()> = (|| {
+             let rotate = *self.rotate.borrow();
+             let total_width = self.obj().allocated_width() as f64;
+@@ -129,6 +144,15 @@ impl WidgetImpl for TransformPriv {
+ 
+             cr.save()?;
+ 
++            let transform_origin_x = match &*self.transform_origin_x.borrow() {
++                Some(rcx) => NumWithUnit::from_str(rcx)?.pixels_relative_to(total_width as i32) as f64,
++                None => 0.0,
++            };
++            let transform_origin_y = match &*self.transform_origin_y.borrow() {
++                Some(rcy) => NumWithUnit::from_str(rcy)?.pixels_relative_to(total_height as i32) as f64,
++                None => 0.0,
++            };
++
+             let translate_x = match &*self.translate_x.borrow() {
+                 Some(tx) => NumWithUnit::from_str(tx)?.pixels_relative_to(total_width as i32) as f64,
+                 None => 0.0,
+@@ -149,9 +173,10 @@ impl WidgetImpl for TransformPriv {
+                 None => 1.0,
+             };
+ 
+-            cr.scale(scale_x, scale_y);
++            cr.translate(transform_origin_x, transform_origin_y);
+             cr.rotate(perc_to_rad(rotate));
+-            cr.translate(translate_x, translate_y);
++            cr.translate(translate_x - transform_origin_x, translate_y - transform_origin_y);
++            cr.scale(scale_x, scale_y);
+ 
+             // Children widget
+             if let Some(child) = &*self.content.borrow() {
+@@ -166,7 +191,7 @@ impl WidgetImpl for TransformPriv {
+             error_handling_ctx::print_error(error)
+         };
+ 
+-        gtk::Inhibit(false)
++        glib::Propagation::Proceed
+     }
+ }
+ 
+diff --git a/crates/eww/src/widgets/widget_definitions.rs b/crates/eww/src/widgets/widget_definitions.rs
+index 696a5bf..0fb88f1 100644
+--- a/crates/eww/src/widgets/widget_definitions.rs
++++ b/crates/eww/src/widgets/widget_definitions.rs
+@@ -8,10 +8,11 @@ use crate::{
+ use anyhow::{anyhow, Context, Result};
+ use codespan_reporting::diagnostic::Severity;
+ use eww_shared_util::Spanned;
+-use gdk::{ModifierType, NotifyType};
+ 
++use gdk::{ModifierType, NotifyType};
+ use glib::translate::FromGlib;
+ use gtk::{self, glib, prelude::*, DestDefaults, TargetEntry, TargetList};
++use gtk::{gdk, pango};
+ use itertools::Itertools;
+ use once_cell::sync::Lazy;
+ 
+@@ -208,10 +209,10 @@ pub(super) fn resolve_widget_attrs(bargs: &mut BuilderArgs, gtk_widget: &gtk::Wi
+         prop(visible: as_bool = true) {
+             if visible { gtk_widget.show(); } else { gtk_widget.hide(); }
+         },
+-        // @prop style - inline css style applied to the widget
++        // @prop style - inline scss style applied to the widget
+         prop(style: as_string) {
+             gtk_widget.reset_style();
+-            css_provider.load_from_data(format!("* {{ {} }}", style).as_bytes())?;
++            css_provider.load_from_data(grass::from_string(format!("* {{ {} }}", style), &grass::Options::default())?.as_bytes())?;
+             gtk_widget.style_context().add_provider(&css_provider, gtk::STYLE_PROVIDER_PRIORITY_APPLICATION)
+         },
+         // @prop css - scss code applied to the widget, i.e.: `button {color: red;}`
+@@ -232,11 +233,11 @@ pub(super) fn resolve_range_attrs(bargs: &mut BuilderArgs, gtk_widget: &gtk::Ran
+     let is_being_dragged = Rc::new(RefCell::new(false));
+     gtk_widget.connect_button_press_event(glib::clone!(@strong is_being_dragged => move |_, _| {
+         *is_being_dragged.borrow_mut() = true;
+-        gtk::Inhibit(false)
++        glib::Propagation::Proceed
+     }));
+     gtk_widget.connect_button_release_event(glib::clone!(@strong is_being_dragged => move |_, _| {
+         *is_being_dragged.borrow_mut() = false;
+-        gtk::Inhibit(false)
++        glib::Propagation::Proceed
+     }));
+ 
+     // We keep track of the last value that has been set via gtk_widget.set_value (by a change in the value property).
+@@ -314,12 +315,46 @@ const WIDGET_NAME_EXPANDER: &str = "expander";
+ /// @desc A widget that can expand and collapse, showing/hiding it's children.
+ fn build_gtk_expander(bargs: &mut BuilderArgs) -> Result<gtk::Expander> {
+     let gtk_widget = gtk::Expander::new(None);
++
++    match bargs.widget_use.children.len().cmp(&1) {
++        Ordering::Less => {
++            return Err(DiagError(gen_diagnostic!("expander must contain exactly one element", bargs.widget_use.span)).into());
++        }
++        Ordering::Greater => {
++            let (_, additional_children) = bargs.widget_use.children.split_at(1);
++            // we know that there is more than one child, so unwrapping on first and last here is fine.
++            let first_span = additional_children.first().unwrap().span();
++            let last_span = additional_children.last().unwrap().span();
++            return Err(DiagError(gen_diagnostic!(
++                "expander must contain exactly one element, but got more",
++                first_span.to(last_span)
++            ))
++            .into());
++        }
++        Ordering::Equal => {
++            let mut children = bargs.widget_use.children.iter().map(|child| {
++                build_gtk_widget(
++                    bargs.scope_graph,
++                    bargs.widget_defs.clone(),
++                    bargs.calling_scope,
++                    child.clone(),
++                    bargs.custom_widget_invocation.clone(),
++                )
++            });
++            // we have exactly one child, we can unwrap
++            let child = children.next().unwrap()?;
++            gtk_widget.add(&child);
++            child.show();
++        }
++    }
++
+     def_widget!(bargs, _g, gtk_widget, {
+         // @prop name - name of the expander
+-        prop(name: as_string) {gtk_widget.set_label(Some(&name));},
++        prop(name: as_string) { gtk_widget.set_label(Some(&name)); },
+         // @prop expanded - sets if the tree is expanded
+         prop(expanded: as_bool) { gtk_widget.set_expanded(expanded); }
+     });
++
+     Ok(gtk_widget)
+ }
+ 
+@@ -507,7 +542,7 @@ fn build_gtk_button(bargs: &mut BuilderArgs) -> Result<gtk::Button> {
+                     3 => run_command(timeout, &onrightclick, &[] as &[&str]),
+                     _ => {},
+                 }
+-                gtk::Inhibit(false)
++                glib::Propagation::Proceed
+             }));
+         }
+ 
+@@ -536,12 +571,35 @@ fn build_gtk_image(bargs: &mut BuilderArgs) -> Result<gtk::Image> {
+         // @prop path - path to the image file
+         // @prop image-width - width of the image
+         // @prop image-height - height of the image
+-        prop(path: as_string, image_width: as_i32 = -1, image_height: as_i32 = -1) {
++        // @prop preserve-aspect-ratio - whether to keep the aspect ratio when resizing an image. Default: true, false doesn't work for all image types
++        // @prop fill-svg - sets the color of svg images
++        prop(path: as_string, image_width: as_i32 = -1, image_height: as_i32 = -1, preserve_aspect_ratio: as_bool = true, fill_svg: as_string = "") {
++            if !path.ends_with(".svg") && !fill_svg.is_empty() {
++                log::warn!("Fill attribute ignored, file is not an svg image");
++            }
++
+             if path.ends_with(".gif") {
+                 let pixbuf_animation = gtk::gdk_pixbuf::PixbufAnimation::from_file(std::path::PathBuf::from(path))?;
+                 gtk_widget.set_from_animation(&pixbuf_animation);
+             } else {
+-                let pixbuf = gtk::gdk_pixbuf::Pixbuf::from_file_at_size(std::path::PathBuf::from(path), image_width, image_height)?;
++                let pixbuf;
++                // populate the pixel buffer
++                if path.ends_with(".svg") && !fill_svg.is_empty() {
++                    let svg_data = std::fs::read_to_string(std::path::PathBuf::from(path.clone()))?;
++                    // The fastest way to add/change fill color
++                    let svg_data = if svg_data.contains("fill=") {
++                        let reg = regex::Regex::new(r#"fill="[^"]*""#)?;
++                        reg.replace(&svg_data, &format!("fill=\"{}\"", fill_svg))
++                    } else {
++                        let reg = regex::Regex::new(r"<svg")?;
++                        reg.replace(&svg_data, &format!("<svg fill=\"{}\"", fill_svg))
++                    };
++                    let stream = gtk::gio::MemoryInputStream::from_bytes(&gtk::glib::Bytes::from(svg_data.as_bytes()));
++                    pixbuf = gtk::gdk_pixbuf::Pixbuf::from_stream_at_scale(&stream, image_width, image_height, preserve_aspect_ratio, None::<&gtk::gio::Cancellable>)?;
++                    stream.close(None::<&gtk::gio::Cancellable>)?;
++                } else {
++                    pixbuf = gtk::gdk_pixbuf::Pixbuf::from_file_at_scale(std::path::PathBuf::from(path), image_width, image_height, preserve_aspect_ratio)?;
++                }
+                 gtk_widget.set_from_pixbuf(Some(&pixbuf));
+             }
+         },
+@@ -729,25 +787,25 @@ fn build_gtk_event_box(bargs: &mut BuilderArgs) -> Result<gtk::EventBox> {
+         if evt.detail() != NotifyType::Inferior {
+             gtk_widget.clone().set_state_flags(gtk::StateFlags::PRELIGHT, false);
+         }
+-        gtk::Inhibit(false)
++        glib::Propagation::Proceed
+     });
+ 
+     gtk_widget.connect_leave_notify_event(|gtk_widget, evt| {
+         if evt.detail() != NotifyType::Inferior {
+             gtk_widget.clone().unset_state_flags(gtk::StateFlags::PRELIGHT);
+         }
+-        gtk::Inhibit(false)
++        glib::Propagation::Proceed
+     });
+ 
+     // Support :active selector
+     gtk_widget.connect_button_press_event(|gtk_widget, _| {
+         gtk_widget.clone().set_state_flags(gtk::StateFlags::ACTIVE, false);
+-        gtk::Inhibit(false)
++        glib::Propagation::Proceed
+     });
+ 
+     gtk_widget.connect_button_release_event(|gtk_widget, _| {
+         gtk_widget.clone().unset_state_flags(gtk::StateFlags::ACTIVE);
+-        gtk::Inhibit(false)
++        glib::Propagation::Proceed
+     });
+ 
+     def_widget!(bargs, _g, gtk_widget, {
+@@ -761,7 +819,7 @@ fn build_gtk_event_box(bargs: &mut BuilderArgs) -> Result<gtk::EventBox> {
+                 if delta != 0f64 { // Ignore the first event https://bugzilla.gnome.org/show_bug.cgi?id=675959
+                     run_command(timeout, &onscroll, &[if delta < 0f64 { "up" } else { "down" }]);
+                 }
+-                gtk::Inhibit(false)
++                glib::Propagation::Proceed
+             }));
+         },
+         // @prop timeout - timeout of the command. Default: "200ms"
+@@ -772,7 +830,7 @@ fn build_gtk_event_box(bargs: &mut BuilderArgs) -> Result<gtk::EventBox> {
+                 if evt.detail() != NotifyType::Inferior {
+                     run_command(timeout, &onhover, &[evt.position().0, evt.position().1]);
+                 }
+-                gtk::Inhibit(false)
++                glib::Propagation::Proceed
+             }));
+         },
+         // @prop timeout - timeout of the command. Default: "200ms"
+@@ -783,7 +841,7 @@ fn build_gtk_event_box(bargs: &mut BuilderArgs) -> Result<gtk::EventBox> {
+                 if evt.detail() != NotifyType::Inferior {
+                     run_command(timeout, &onhoverlost, &[evt.position().0, evt.position().1]);
+                 }
+-                gtk::Inhibit(false)
++                glib::Propagation::Proceed
+             }));
+         },
+         // @prop cursor - Cursor to show while hovering (see [gtk3-cursors](https://docs.gtk.org/gdk3/ctor.Cursor.new_from_name.html) for possible names)
+@@ -799,7 +857,7 @@ fn build_gtk_event_box(bargs: &mut BuilderArgs) -> Result<gtk::EventBox> {
+                         gdk_window.set_cursor(gdk::Cursor::from_name(&display, &cursor).as_ref());
+                     }
+                 }
+-                gtk::Inhibit(false)
++                glib::Propagation::Proceed
+             }));
+             connect_signal_handler!(gtk_widget, gtk_widget.connect_leave_notify_event(move |widget, _evt| {
+                 if _evt.detail() != NotifyType::Inferior {
+@@ -808,7 +866,7 @@ fn build_gtk_event_box(bargs: &mut BuilderArgs) -> Result<gtk::EventBox> {
+                         gdk_window.set_cursor(None);
+                     }
+                 }
+-                gtk::Inhibit(false)
++                glib::Propagation::Proceed
+             }));
+         },
+         // @prop timeout - timeout of the command. Default: "200ms"
+@@ -878,7 +936,7 @@ fn build_gtk_event_box(bargs: &mut BuilderArgs) -> Result<gtk::EventBox> {
+                     3 => run_command(timeout, &onrightclick, &[] as &[&str]),
+                     _ => {},
+                 }
+-                gtk::Inhibit(false)
++                glib::Propagation::Proceed
+             }));
+         }
+     });
+@@ -894,11 +952,12 @@ fn build_gtk_label(bargs: &mut BuilderArgs) -> Result<gtk::Label> {
+ 
+     def_widget!(bargs, _g, gtk_widget, {
+         // @prop text - the text to display
++        // @prop truncate - whether to truncate text (or pango markup). If `show-truncated` is `false`, or if `limit-width` has a value, this property has no effect and truncation is enabled.
+         // @prop limit-width - maximum count of characters to display
+         // @prop truncate-left - whether to truncate on the left side
+         // @prop show-truncated - show whether the text was truncated. Disabling it will also disable dynamic truncation (the labels won't be truncated more than `limit-width`, even if there is not enough space for them), and will completly disable truncation on pango markup.
+         // @prop unindent - whether to remove leading spaces
+-        prop(text: as_string, limit_width: as_i32 = i32::MAX, truncate_left: as_bool = false, show_truncated: as_bool = true, unindent: as_bool = true) {
++        prop(text: as_string, truncate: as_bool = false, limit_width: as_i32 = i32::MAX, truncate_left: as_bool = false, show_truncated: as_bool = true, unindent: as_bool = true) {
+             let text = if show_truncated {
+                 // gtk does weird thing if we set max_width_chars to i32::MAX
+                 if limit_width == i32::MAX {
+@@ -906,10 +965,14 @@ fn build_gtk_label(bargs: &mut BuilderArgs) -> Result<gtk::Label> {
+                 } else {
+                     gtk_widget.set_max_width_chars(limit_width);
+                 }
+-                if truncate_left {
+-                    gtk_widget.set_ellipsize(pango::EllipsizeMode::Start);
++                if truncate || limit_width != i32::MAX {
++                    if truncate_left {
++                        gtk_widget.set_ellipsize(pango::EllipsizeMode::Start);
++                    } else {
++                        gtk_widget.set_ellipsize(pango::EllipsizeMode::End);
++                    }
+                 } else {
+-                    gtk_widget.set_ellipsize(pango::EllipsizeMode::End);
++                    gtk_widget.set_ellipsize(pango::EllipsizeMode::None);
+                 }
+ 
+                 text
+@@ -918,7 +981,7 @@ fn build_gtk_label(bargs: &mut BuilderArgs) -> Result<gtk::Label> {
+ 
+                 let limit_width = limit_width as usize;
+                 let char_count = text.chars().count();
+-                if char_count > limit_width && !show_truncated {
++                if char_count > limit_width {
+                     if truncate_left {
+                         text.chars().skip(char_count - limit_width).collect()
+                     } else {
+@@ -934,11 +997,12 @@ fn build_gtk_label(bargs: &mut BuilderArgs) -> Result<gtk::Label> {
+             gtk_widget.set_text(&text);
+         },
+         // @prop markup - Pango markup to display
++        // @prop truncate - whether to truncate text (or pango markup). If `show-truncated` is `false`, or if `limit-width` has a value, this property has no effect and truncation is enabled.
+         // @prop limit-width - maximum count of characters to display
+         // @prop truncate-left - whether to truncate on the left side
+         // @prop show-truncated - show whether the text was truncatedd. Disabling it will also disable dynamic truncation (the labels won't be truncated more than `limit-width`, even if there is not enough space for them), and will completly disable truncation on pango markup.
+-        prop(markup: as_string, limit_width: as_i32 = i32::MAX, truncate_left: as_bool = false, show_truncated: as_bool = true) {
+-            if show_truncated {
++        prop(markup: as_string, truncate: as_bool = false, limit_width: as_i32 = i32::MAX, truncate_left: as_bool = false, show_truncated: as_bool = true) {
++            if (truncate || limit_width != i32::MAX) && show_truncated {
+                 // gtk does weird thing if we set max_width_chars to i32::MAX
+                 if limit_width == i32::MAX {
+                     gtk_widget.set_max_width_chars(-1);
+@@ -1082,6 +1146,27 @@ const WIDGET_NAME_STACK: &str = "stack";
+ /// @desc A widget that displays one of its children at a time
+ fn build_gtk_stack(bargs: &mut BuilderArgs) -> Result<gtk::Stack> {
+     let gtk_widget = gtk::Stack::new();
++
++    if bargs.widget_use.children.is_empty() {
++        return Err(DiagError(gen_diagnostic!("stack must contain at least one element", bargs.widget_use.span)).into());
++    }
++
++    let children = bargs.widget_use.children.iter().map(|child| {
++        build_gtk_widget(
++            bargs.scope_graph,
++            bargs.widget_defs.clone(),
++            bargs.calling_scope,
++            child.clone(),
++            bargs.custom_widget_invocation.clone(),
++        )
++    });
++
++    for (i, child) in children.enumerate() {
++        let child = child?;
++        gtk_widget.add_named(&child, &i.to_string());
++        child.show();
++    }
++
+     def_widget!(bargs, _g, gtk_widget, {
+         // @prop selected - index of child which should be shown
+         prop(selected: as_i32) { gtk_widget.set_visible_child_name(&selected.to_string()); },
+@@ -1091,28 +1176,7 @@ fn build_gtk_stack(bargs: &mut BuilderArgs) -> Result<gtk::Stack> {
+         prop(same_size: as_bool = false) { gtk_widget.set_homogeneous(same_size); }
+     });
+ 
+-    match bargs.widget_use.children.len().cmp(&1) {
+-        Ordering::Less => {
+-            Err(DiagError(gen_diagnostic!("stack must contain at least one element", bargs.widget_use.span)).into())
+-        }
+-        Ordering::Greater | Ordering::Equal => {
+-            let children = bargs.widget_use.children.iter().map(|child| {
+-                build_gtk_widget(
+-                    bargs.scope_graph,
+-                    bargs.widget_defs.clone(),
+-                    bargs.calling_scope,
+-                    child.clone(),
+-                    bargs.custom_widget_invocation.clone(),
+-                )
+-            });
+-            for (i, child) in children.enumerate() {
+-                let child = child?;
+-                gtk_widget.add_named(&child, &i.to_string());
+-                child.show();
+-            }
+-            Ok(gtk_widget)
+-        }
+-    }
++    Ok(gtk_widget)
+ }
+ 
+ const WIDGET_NAME_TRANSFORM: &str = "transform";
+@@ -1124,6 +1188,10 @@ fn build_transform(bargs: &mut BuilderArgs) -> Result<Transform> {
+     def_widget!(bargs, _g, w, {
+         // @prop rotate - the percentage to rotate
+         prop(rotate: as_f64) { w.set_property("rotate", rotate); },
++        // @prop transform-origin-x - x coordinate of origin of transformation (px or %)
++        prop(transform_origin_x: as_string) { w.set_property("transform-origin-x", transform_origin_x) },
++        // @prop transform-origin-y - y coordinate of origin of transformation (px or %)
++        prop(transform_origin_y: as_string) { w.set_property("transform-origin-y", transform_origin_y) },
+         // @prop translate-x - the amount to translate in the x direction (px or %)
+         prop(translate_x: as_string) { w.set_property("translate-x", translate_x); },
+         // @prop translate-y - the amount to translate in the y direction (px or %)
+@@ -1182,6 +1250,12 @@ fn build_graph(bargs: &mut BuilderArgs) -> Result<super::graph::Graph> {
+         // @prop line-style - changes the look of the edges in the graph. Values: "miter" (default), "round",
+         // "bevel"
+         prop(line_style: as_string) { w.set_property("line-style", line_style); },
++        // @prop flip-x - whether the x axis should go from high to low
++        prop(flip_x: as_bool) { w.set_property("flip-x", flip_x); },
++        // @prop flip-y - whether the y axis should go from high to low
++        prop(flip_y: as_bool) { w.set_property("flip-y", flip_y); },
++        // @prop vertical - if set to true, the x and y axes will be exchanged
++        prop(vertical: as_bool) { w.set_property("vertical", vertical); },
+     });
+     Ok(w)
+ }
+diff --git a/crates/eww/src/widgets/window.rs b/crates/eww/src/widgets/window.rs
+index 4e6c0dc..1a7b861 100644
+--- a/crates/eww/src/widgets/window.rs
++++ b/crates/eww/src/widgets/window.rs
+@@ -1,5 +1,4 @@
+-use glib::{object_subclass, wrapper};
+-use glib_macros::Properties;
++use gtk::glib::{self, object_subclass, wrapper, Properties};
+ use gtk::{prelude::*, subclass::prelude::*};
+ use std::cell::RefCell;
+ 
+diff --git a/crates/eww/src/window_arguments.rs b/crates/eww/src/window_arguments.rs
+index 44681e9..5a07979 100644
+--- a/crates/eww/src/window_arguments.rs
++++ b/crates/eww/src/window_arguments.rs
+@@ -59,10 +59,10 @@ impl WindowArguments {
+ 
+         // Ensure that the arguments passed to the window that are already interpreted by eww (id, screen)
+         // are set to the correct values
+-        if expected_args.contains(&"id".to_string()) {
++        if expected_args.contains(&String::from("id")) {
+             local_variables.insert(VarName::from("id"), DynVal::from(self.instance_id.clone()));
+         }
+-        if self.monitor.is_some() && expected_args.contains(&"screen".to_string()) {
++        if self.monitor.is_some() && expected_args.contains(&String::from("screen")) {
+             let mon_dyn = DynVal::from(&self.monitor.clone().unwrap());
+             local_variables.insert(VarName::from("screen"), mon_dyn);
+         }
+diff --git a/crates/eww/src/window_initiator.rs b/crates/eww/src/window_initiator.rs
+index cb2cda0..f2dc559 100644
+--- a/crates/eww/src/window_initiator.rs
++++ b/crates/eww/src/window_initiator.rs
+@@ -17,7 +17,6 @@ use crate::window_arguments::WindowArguments;
+ pub struct WindowInitiator {
+     pub backend_options: BackendWindowOptions,
+     pub geometry: Option<WindowGeometry>,
+-    pub id: String,
+     pub local_variables: HashMap<VarName, DynVal>,
+     pub monitor: Option<MonitorIdentifier>,
+     pub name: String,
+@@ -37,7 +36,6 @@ impl WindowInitiator {
+         Ok(WindowInitiator {
+             backend_options: window_def.backend_options.eval(&vars)?,
+             geometry,
+-            id: args.instance_id.clone(),
+             monitor,
+             name: window_def.name.clone(),
+             resizable: window_def.eval_resizable(&vars)?,
+diff --git a/crates/eww_shared_util/Cargo.toml b/crates/eww_shared_util/Cargo.toml
+index 24a9108..45d26dc 100644
+--- a/crates/eww_shared_util/Cargo.toml
++++ b/crates/eww_shared_util/Cargo.toml
+@@ -12,3 +12,4 @@ homepage = "https://github.com/elkowar/eww"
+ serde.workspace = true
+ derive_more.workspace = true
+ ref-cast.workspace = true
++chrono = { workspace = true, features = ["unstable-locales"] }
+diff --git a/crates/eww_shared_util/src/lib.rs b/crates/eww_shared_util/src/lib.rs
+index 299f994..7161120 100644
+--- a/crates/eww_shared_util/src/lib.rs
++++ b/crates/eww_shared_util/src/lib.rs
+@@ -1,6 +1,8 @@
++pub mod locale;
+ pub mod span;
+ pub mod wrappers;
+ 
++pub use locale::*;
+ pub use span::*;
+ pub use wrappers::*;
+ 
+diff --git a/crates/eww_shared_util/src/locale.rs b/crates/eww_shared_util/src/locale.rs
+new file mode 100644
+index 0000000..028e84b
+--- /dev/null
++++ b/crates/eww_shared_util/src/locale.rs
+@@ -0,0 +1,14 @@
++use chrono::Locale;
++use std::env::var;
++
++/// Returns the `Locale` enum based on the `LC_TIME` environment variable.
++/// If the environment variable is not defined or is malformed use the POSIX locale.
++pub fn get_locale() -> Locale {
++    let locale_string: String =
++        var("LC_TIME").map_or_else(|_| "C".to_string(), |v| v.split(".").next().unwrap_or("C").to_string());
++
++    match (&*locale_string).try_into() {
++        Ok(x) => x,
++        Err(_) => Locale::POSIX,
++    }
++}
+diff --git a/crates/eww_shared_util/src/wrappers.rs b/crates/eww_shared_util/src/wrappers.rs
+index ef07c79..c9beb80 100644
+--- a/crates/eww_shared_util/src/wrappers.rs
++++ b/crates/eww_shared_util/src/wrappers.rs
+@@ -1,11 +1,11 @@
+-use derive_more::*;
++use derive_more::{Debug, *};
+ use ref_cast::RefCast;
+ use serde::{Deserialize, Serialize};
+ 
+ /// The name of a variable
+ #[repr(transparent)]
+-#[derive(Clone, Hash, PartialEq, Eq, Serialize, Deserialize, AsRef, From, FromStr, Display, DebugCustom, RefCast)]
+-#[debug(fmt = "VarName({})", .0)]
++#[derive(Clone, Hash, PartialEq, Eq, Serialize, Deserialize, AsRef, From, FromStr, Display, Debug, RefCast)]
++#[debug("VarName({})", _0)]
+ pub struct VarName(pub String);
+ 
+ impl std::borrow::Borrow<str> for VarName {
+@@ -34,8 +34,8 @@ impl From<AttrName> for VarName {
+ 
+ /// The name of an attribute
+ #[repr(transparent)]
+-#[derive(Clone, Hash, PartialEq, Eq, Serialize, Deserialize, AsRef, From, FromStr, Display, DebugCustom, RefCast)]
+-#[debug(fmt="AttrName({})", .0)]
++#[derive(Clone, Hash, PartialEq, Eq, Serialize, Deserialize, AsRef, From, FromStr, Display, Debug, RefCast)]
++#[debug("AttrName({})", _0)]
+ pub struct AttrName(pub String);
+ 
+ impl AttrName {
+diff --git a/crates/notifier_host/Cargo.toml b/crates/notifier_host/Cargo.toml
+index 10a7d6c..c4fd64f 100644
+--- a/crates/notifier_host/Cargo.toml
++++ b/crates/notifier_host/Cargo.toml
+@@ -9,11 +9,10 @@ repository = "https://github.com/elkowar/eww"
+ homepage = "https://github.com/elkowar/eww"
+ 
+ [dependencies]
+-gtk = "0.17.1"
+-gdk = "0.17.1"
+-zbus = { version = "3.7.0", default-features = false, features = ["tokio"] }
+ dbusmenu-gtk3 = "0.1.0"
+ 
++gtk.workspace = true
+ log.workspace = true
+ thiserror.workspace = true
+ tokio = { workspace = true, features = ["full"] }
++zbus = { workspace = true, default-features = false, features = ["tokio"] }
+diff --git a/crates/notifier_host/src/host.rs b/crates/notifier_host/src/host.rs
+index b937395..723322e 100644
+--- a/crates/notifier_host/src/host.rs
++++ b/crates/notifier_host/src/host.rs
+@@ -88,7 +88,7 @@ pub async fn run_host(host: &mut dyn Host, snw: &proxy::StatusNotifierWatcherPro
+ 
+     // initial items first
+     for svc in try_!(snw.registered_status_notifier_items().await) {
+-        match Item::from_address(snw.connection(), &svc).await {
++        match Item::from_address(snw.inner().connection(), &svc).await {
+             Ok(item) => {
+                 item_names.insert(svc.to_owned());
+                 host.add_item(&svc, item);
+@@ -110,7 +110,7 @@ pub async fn run_host(host: &mut dyn Host, snw: &proxy::StatusNotifierWatcherPro
+                 if item_names.contains(svc) {
+                     log::info!("Got duplicate new item: {:?}", svc);
+                 } else {
+-                    match Item::from_address(snw.connection(), svc).await {
++                    match Item::from_address(snw.inner().connection(), svc).await {
+                         Ok(item) => {
+                             item_names.insert(svc.to_owned());
+                             host.add_item(svc, item);
+diff --git a/crates/notifier_host/src/icon.rs b/crates/notifier_host/src/icon.rs
+index 45057e4..ad6fdb1 100644
+--- a/crates/notifier_host/src/icon.rs
++++ b/crates/notifier_host/src/icon.rs
+@@ -105,7 +105,7 @@ fn icon_from_name(
+ ) -> std::result::Result<gtk::gdk_pixbuf::Pixbuf, IconError> {
+     let theme = if let Some(path) = theme_path {
+         let theme = gtk::IconTheme::new();
+-        theme.prepend_search_path(&path);
++        theme.prepend_search_path(path);
+         theme
+     } else {
+         gtk::IconTheme::default().expect("Could not get default gtk theme")
+@@ -136,7 +136,7 @@ pub async fn load_icon_from_sni(
+     let icon_from_name: std::result::Result<gtk::gdk_pixbuf::Pixbuf, IconError> = (async {
+         // fetch icon name
+         let icon_name = sni.icon_name().await;
+-        log::debug!("dbus: {} icon_name -> {:?}", sni.destination(), icon_name);
++        log::debug!("dbus: {} icon_name -> {:?}", sni.inner().destination(), icon_name);
+         let icon_name = match icon_name {
+             Ok(s) if s.is_empty() => return Err(IconError::NotAvailable),
+             Ok(s) => s,
+@@ -152,7 +152,7 @@ pub async fn load_icon_from_sni(
+ 
+         // otherwise, fetch icon theme and lookup using icon_from_name
+         let icon_theme_path = sni.icon_theme_path().await;
+-        log::debug!("dbus: {} icon_theme_path -> {:?}", sni.destination(), icon_theme_path);
++        log::debug!("dbus: {} icon_theme_path -> {:?}", sni.inner().destination(), icon_theme_path);
+         let icon_theme_path = match icon_theme_path {
+             Ok(p) if p.is_empty() => None,
+             Ok(p) => Some(p),
+@@ -179,7 +179,7 @@ pub async fn load_icon_from_sni(
+     match icon_from_name {
+         Ok(p) => return Some(p),           // got an icon!
+         Err(IconError::NotAvailable) => {} // this error is expected, don't log
+-        Err(e) => log::warn!("failed to get icon by name for {}: {}", sni.destination(), e),
++        Err(e) => log::warn!("failed to get icon by name for {}: {}", sni.inner().destination(), e),
+     };
+ 
+     // Can't get it from name + theme, try the pixmap
+@@ -199,7 +199,7 @@ pub async fn load_icon_from_sni(
+     match icon_from_pixmaps {
+         Ok(p) => return Some(p),
+         Err(IconError::NotAvailable) => {}
+-        Err(e) => log::warn!("failed to get icon pixmap for {}: {}", sni.destination(), e),
++        Err(e) => log::warn!("failed to get icon pixmap for {}: {}", sni.inner().destination(), e),
+     };
+ 
+     // Tray didn't provide a valid icon so use the default fallback one.
+diff --git a/crates/notifier_host/src/item.rs b/crates/notifier_host/src/item.rs
+index 70317eb..ad63f34 100644
+--- a/crates/notifier_host/src/item.rs
++++ b/crates/notifier_host/src/item.rs
+@@ -82,15 +82,15 @@ impl Item {
+     }
+ 
+     pub async fn set_menu(&mut self, widget: &gtk::EventBox) -> zbus::Result<()> {
+-        let menu = dbusmenu_gtk3::Menu::new(self.sni.destination(), &self.sni.menu().await?);
++        let menu = dbusmenu_gtk3::Menu::new(self.sni.inner().destination(), &self.sni.menu().await?);
+         menu.set_attach_widget(Some(widget));
+         self.gtk_menu = Some(menu);
+         Ok(())
+     }
+ 
+-    pub async fn popup_menu(&self, event: &gdk::EventButton, x: i32, y: i32) -> zbus::Result<()> {
++    pub async fn popup_menu(&self, event: &gtk::gdk::EventButton, x: i32, y: i32) -> zbus::Result<()> {
+         if let Some(menu) = &self.gtk_menu {
+-            menu.popup_at_pointer(event.downcast_ref::<gdk::Event>());
++            menu.popup_at_pointer(event.downcast_ref::<gtk::gdk::Event>());
+             Ok(())
+         } else {
+             self.sni.context_menu(x, y).await
+diff --git a/crates/notifier_host/src/proxy/dbus_status_notifier_item.rs b/crates/notifier_host/src/proxy/dbus_status_notifier_item.rs
+index 5c57b2a..051f180 100644
+--- a/crates/notifier_host/src/proxy/dbus_status_notifier_item.rs
++++ b/crates/notifier_host/src/proxy/dbus_status_notifier_item.rs
+@@ -1,20 +1,18 @@
+-//! # DBus interface proxy for: `org.kde.StatusNotifierItem`
++//! # D-Bus interface proxy for: `org.kde.StatusNotifierItem`
+ //!
+-//! This code was generated by `zbus-xmlgen` `3.1.0` from DBus introspection data.
+-//! Source: `dbus-status-notifier-item.xml`.
++//! This code was generated by `zbus-xmlgen` `4.1.0` from D-Bus introspection data.
++//! Source: `dbus_status_notifier_item.xml`.
+ //!
+ //! You may prefer to adapt it, instead of using it verbatim.
+ //!
+-//! More information can be found in the
+-//! [Writing a client proxy](https://dbus.pages.freedesktop.org/zbus/client.html)
+-//! section of the zbus documentation.
+-
+-// suppress warning from generated code
+-#![allow(clippy::type_complexity)]
+-
+-use zbus::dbus_proxy;
+-
+-#[dbus_proxy(interface = "org.kde.StatusNotifierItem", assume_defaults = true)]
++//! More information can be found in the [Writing a client proxy] section of the zbus
++//! documentation.
++//!
++//!
++//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html
++//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces,
++use zbus::proxy;
++#[proxy(interface = "org.kde.StatusNotifierItem", assume_defaults = true)]
+ trait StatusNotifierItem {
+     /// Activate method
+     fn activate(&self, x: i32, y: i32) -> zbus::Result<()>;
+@@ -29,86 +27,87 @@ trait StatusNotifierItem {
+     fn secondary_activate(&self, x: i32, y: i32) -> zbus::Result<()>;
+ 
+     /// NewAttentionIcon signal
+-    #[dbus_proxy(signal)]
++    #[zbus(signal)]
+     fn new_attention_icon(&self) -> zbus::Result<()>;
+ 
+     /// NewIcon signal
+-    #[dbus_proxy(signal)]
++    #[zbus(signal)]
+     fn new_icon(&self) -> zbus::Result<()>;
+ 
+     /// NewOverlayIcon signal
+-    #[dbus_proxy(signal)]
++    #[zbus(signal)]
+     fn new_overlay_icon(&self) -> zbus::Result<()>;
+ 
+     /// NewStatus signal
+-    #[dbus_proxy(signal)]
++    #[zbus(signal)]
+     fn new_status(&self, status: &str) -> zbus::Result<()>;
+ 
+     /// NewTitle signal
+-    #[dbus_proxy(signal)]
++    #[zbus(signal)]
+     fn new_title(&self) -> zbus::Result<()>;
+ 
+     /// NewToolTip signal
+-    #[dbus_proxy(signal)]
++    #[zbus(signal)]
+     fn new_tool_tip(&self) -> zbus::Result<()>;
+ 
+     /// AttentionIconName property
+-    #[dbus_proxy(property)]
++    #[zbus(property)]
+     fn attention_icon_name(&self) -> zbus::Result<String>;
+ 
+     /// AttentionIconPixmap property
+-    #[dbus_proxy(property)]
++    #[zbus(property)]
+     fn attention_icon_pixmap(&self) -> zbus::Result<Vec<(i32, i32, Vec<u8>)>>;
+ 
+     /// AttentionMovieName property
+-    #[dbus_proxy(property)]
++    #[zbus(property)]
+     fn attention_movie_name(&self) -> zbus::Result<String>;
+ 
+     /// Category property
+-    #[dbus_proxy(property)]
++    #[zbus(property)]
+     fn category(&self) -> zbus::Result<String>;
+ 
+     /// IconName property
+-    #[dbus_proxy(property(emits_changed_signal = "false"))]
++    #[zbus(property)]
+     fn icon_name(&self) -> zbus::Result<String>;
+ 
+     /// IconPixmap property
+-    #[dbus_proxy(property(emits_changed_signal = "false"))]
++    #[zbus(property)]
+     fn icon_pixmap(&self) -> zbus::Result<Vec<(i32, i32, Vec<u8>)>>;
+ 
+     /// IconThemePath property
+-    #[dbus_proxy(property)]
++    #[zbus(property)]
+     fn icon_theme_path(&self) -> zbus::Result<String>;
+ 
+     /// Id property
+-    #[dbus_proxy(property)]
++    #[zbus(property)]
+     fn id(&self) -> zbus::Result<String>;
+ 
+     /// ItemIsMenu property
+-    #[dbus_proxy(property)]
++    #[zbus(property)]
+     fn item_is_menu(&self) -> zbus::Result<bool>;
+ 
+     /// Menu property
+-    #[dbus_proxy(property)]
++    #[zbus(property)]
+     fn menu(&self) -> zbus::Result<zbus::zvariant::OwnedObjectPath>;
+ 
+     /// OverlayIconName property
+-    #[dbus_proxy(property)]
++    #[zbus(property)]
+     fn overlay_icon_name(&self) -> zbus::Result<String>;
+ 
+     /// OverlayIconPixmap property
+-    #[dbus_proxy(property)]
++    #[zbus(property)]
+     fn overlay_icon_pixmap(&self) -> zbus::Result<Vec<(i32, i32, Vec<u8>)>>;
+ 
+     /// Status property
+-    #[dbus_proxy(property)]
++    #[zbus(property)]
+     fn status(&self) -> zbus::Result<String>;
+ 
+     /// Title property
+-    #[dbus_proxy(property)]
++    #[zbus(property)]
+     fn title(&self) -> zbus::Result<String>;
+ 
+     /// ToolTip property
+-    #[dbus_proxy(property)]
+-    fn tool_tip(&self) -> zbus::Result<(String, Vec<(i32, i32, Vec<u8>)>)>;
++    #[zbus(property)]
++    #[allow(clippy::type_complexity)]
++    fn tool_tip(&self) -> zbus::Result<(String, Vec<(i32, i32, Vec<u8>)>, String, String)>;
+ }
+diff --git a/crates/notifier_host/src/proxy/dbus_status_notifier_watcher.rs b/crates/notifier_host/src/proxy/dbus_status_notifier_watcher.rs
+index 9ac2eaa..4ffb98f 100644
+--- a/crates/notifier_host/src/proxy/dbus_status_notifier_watcher.rs
++++ b/crates/notifier_host/src/proxy/dbus_status_notifier_watcher.rs
+@@ -1,17 +1,18 @@
+-//! # DBus interface proxy for: `org.kde.StatusNotifierWatcher`
++//! # D-Bus interface proxy for: `org.kde.StatusNotifierWatcher`
+ //!
+-//! This code was generated by `zbus-xmlgen` `3.1.0` from DBus introspection data.
+-//! Source: `dbus-status-notifier-watcher.xml`.
++//! This code was generated by `zbus-xmlgen` `4.1.0` from D-Bus introspection data.
++//! Source: `dbus_status_notifier_watcher.xml`.
+ //!
+ //! You may prefer to adapt it, instead of using it verbatim.
+ //!
+-//! More information can be found in the
+-//! [Writing a client proxy](https://dbus.pages.freedesktop.org/zbus/client.html)
+-//! section of the zbus documentation.
+-
+-use zbus::dbus_proxy;
+-
+-#[dbus_proxy(
++//! More information can be found in the [Writing a client proxy] section of the zbus
++//! documentation.
++//!
++//!
++//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html
++//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces,
++use zbus::proxy;
++#[proxy(
+     default_service = "org.kde.StatusNotifierWatcher",
+     interface = "org.kde.StatusNotifierWatcher",
+     default_path = "/StatusNotifierWatcher"
+@@ -24,30 +25,30 @@ trait StatusNotifierWatcher {
+     fn register_status_notifier_item(&self, service: &str) -> zbus::Result<()>;
+ 
+     /// StatusNotifierHostRegistered signal
+-    #[dbus_proxy(signal)]
++    #[zbus(signal)]
+     fn status_notifier_host_registered(&self) -> zbus::Result<()>;
+ 
+     /// StatusNotifierHostUnregistered signal
+-    #[dbus_proxy(signal)]
++    #[zbus(signal)]
+     fn status_notifier_host_unregistered(&self) -> zbus::Result<()>;
+ 
+     /// StatusNotifierItemRegistered signal
+-    #[dbus_proxy(signal)]
++    #[zbus(signal)]
+     fn status_notifier_item_registered(&self, service: &str) -> zbus::Result<()>;
+ 
+     /// StatusNotifierItemUnregistered signal
+-    #[dbus_proxy(signal)]
++    #[zbus(signal)]
+     fn status_notifier_item_unregistered(&self, service: &str) -> zbus::Result<()>;
+ 
+     /// IsStatusNotifierHostRegistered property
+-    #[dbus_proxy(property)]
++    #[zbus(property)]
+     fn is_status_notifier_host_registered(&self) -> zbus::Result<bool>;
+ 
+     /// ProtocolVersion property
+-    #[dbus_proxy(property)]
++    #[zbus(property)]
+     fn protocol_version(&self) -> zbus::Result<i32>;
+ 
+     /// RegisteredStatusNotifierItems property
+-    #[dbus_proxy(property)]
++    #[zbus(property)]
+     fn registered_status_notifier_items(&self) -> zbus::Result<Vec<String>>;
+ }
+diff --git a/crates/notifier_host/src/proxy/mod.rs b/crates/notifier_host/src/proxy/mod.rs
+index 8c8e9df..deb98d4 100644
+--- a/crates/notifier_host/src/proxy/mod.rs
++++ b/crates/notifier_host/src/proxy/mod.rs
+@@ -2,9 +2,15 @@
+ //!
+ //! The interface XML files were taken from
+ //! [Waybar](https://github.com/Alexays/Waybar/tree/master/protocol), and the proxies were
+-//! generated with [zbus-xmlgen](https://docs.rs/crate/zbus_xmlgen/latest) by running `zbus-xmlgen
+-//! dbus_status_notifier_item.xml` and `zbus-xmlgen dbus_status_notifier_watcher.xml`. At the
+-//! moment, `dbus_menu.xml` isn't used.
++//! generated with [zbus-xmlgen](https://docs.rs/crate/zbus_xmlgen/latest) by running
++//! `zbus-xmlgen file crates/notifier_host/src/proxy/dbus_status_notifier_item.xml` and
++//! `zbus-xmlgen file crates/notifier_host/src/proxy/dbus_status_notifier_watcher.xml`.
++//!
++//! Note that the `dbus_status_notifier_watcher.rs` file has been slightly adjusted, the
++//! default arguments to the [proxy](https://docs.rs/zbus/4.4.0/zbus/attr.proxy.html)
++//! macro need some adjusting.
++//!
++//! At the moment, `dbus_menu.xml` isn't used.
+ //!
+ //! For more information, see ["Writing a client proxy" in the zbus
+ //! tutorial](https://dbus2.github.io/zbus/).
+diff --git a/crates/notifier_host/src/watcher.rs b/crates/notifier_host/src/watcher.rs
+index a0e7c13..677e378 100644
+--- a/crates/notifier_host/src/watcher.rs
++++ b/crates/notifier_host/src/watcher.rs
+@@ -1,5 +1,5 @@
+ use crate::names;
+-use zbus::{dbus_interface, export::ordered_stream::OrderedStreamExt, Interface};
++use zbus::{export::ordered_stream::OrderedStreamExt, interface, Interface};
+ 
+ /// An instance of [`org.kde.StatusNotifierWatcher`]. It only tracks what tray items and trays
+ /// exist, and doesn't have any logic for displaying items (for that, see [`Host`][`crate::Host`]).
+@@ -23,7 +23,7 @@ pub struct Watcher {
+ ///
+ /// Methods and properties correspond to methods and properties on the DBus service that can be
+ /// used by others, while signals are events that we generate that other services listen to.
+-#[dbus_interface(name = "org.kde.StatusNotifierWatcher")]
++#[interface(name = "org.kde.StatusNotifierWatcher")]
+ impl Watcher {
+     /// RegisterStatusNotifierHost method
+     async fn register_status_notifier_host(
+@@ -89,15 +89,15 @@ impl Watcher {
+     }
+ 
+     /// StatusNotifierHostRegistered signal.
+-    #[dbus_interface(signal)]
++    #[zbus(signal)]
+     async fn status_notifier_host_registered(ctxt: &zbus::SignalContext<'_>) -> zbus::Result<()>;
+ 
+     /// StatusNotifierHostUnregistered signal
+-    #[dbus_interface(signal)]
++    #[zbus(signal)]
+     async fn status_notifier_host_unregistered(ctxt: &zbus::SignalContext<'_>) -> zbus::Result<()>;
+ 
+     /// IsStatusNotifierHostRegistered property
+-    #[dbus_interface(property)]
++    #[zbus(property)]
+     async fn is_status_notifier_host_registered(&self) -> bool {
+         let hosts = self.hosts.lock().unwrap(); // unwrap: mutex poisoning is okay
+         !hosts.is_empty()
+@@ -159,15 +159,15 @@ impl Watcher {
+     }
+ 
+     /// StatusNotifierItemRegistered signal
+-    #[dbus_interface(signal)]
++    #[zbus(signal)]
+     async fn status_notifier_item_registered(ctxt: &zbus::SignalContext<'_>, service: &str) -> zbus::Result<()>;
+ 
+     /// StatusNotifierItemUnregistered signal
+-    #[dbus_interface(signal)]
++    #[zbus(signal)]
+     async fn status_notifier_item_unregistered(ctxt: &zbus::SignalContext<'_>, service: &str) -> zbus::Result<()>;
+ 
+     /// RegisteredStatusNotifierItems property
+-    #[dbus_interface(property)]
++    #[zbus(property)]
+     async fn registered_status_notifier_items(&self) -> Vec<String> {
+         let items = self.items.lock().unwrap(); // unwrap: mutex poisoning is okay
+         items.iter().cloned().collect()
+@@ -176,7 +176,7 @@ impl Watcher {
+     // ------------------------------------------------------------------------
+ 
+     /// ProtocolVersion property
+-    #[dbus_interface(property)]
++    #[zbus(property)]
+     fn protocol_version(&self) -> i32 {
+         0
+     }
+@@ -244,7 +244,7 @@ async fn parse_service<'a>(
+ ) -> zbus::fdo::Result<(zbus::names::UniqueName<'static>, &'a str)> {
+     if service.starts_with('/') {
+         // they sent us just the object path
+-        if let Some(sender) = hdr.sender()? {
++        if let Some(sender) = hdr.sender() {
+             Ok((sender.to_owned(), service))
+         } else {
+             log::warn!("unknown sender");
+diff --git a/crates/simplexpr/Cargo.toml b/crates/simplexpr/Cargo.toml
+index 420c04d..2b94ae9 100644
+--- a/crates/simplexpr/Cargo.toml
++++ b/crates/simplexpr/Cargo.toml
+@@ -16,18 +16,18 @@ eww_shared_util.workspace = true
+ 
+ cached.workspace = true
+ chrono-tz.workspace = true
+-chrono.workspace = true
++chrono = { workspace = true, features = ["unstable-locales"] }
+ itertools.workspace = true
+ jaq-core.workspace = true
+ jaq-parse.workspace = true
+-jaq-std = {workspace = true, features = ["bincode"]}
++jaq-std.workspace = true
+ jaq-interpret.workspace = true
+ jaq-syn.workspace = true
+ lalrpop-util.workspace = true
+ once_cell.workspace = true
+ regex.workspace = true
+ serde_json.workspace = true
+-serde = {workspace = true, features = ["derive"]}
++serde = { workspace = true, features = ["derive"] }
+ static_assertions.workspace = true
+ strsim.workspace = true
+ strum = { workspace = true, features = ["derive"] }
+diff --git a/crates/simplexpr/src/eval.rs b/crates/simplexpr/src/eval.rs
+index cad180d..6325782 100644
+--- a/crates/simplexpr/src/eval.rs
++++ b/crates/simplexpr/src/eval.rs
+@@ -7,7 +7,7 @@ use crate::{
+     ast::{AccessType, BinOp, SimplExpr, UnaryOp},
+     dynval::{ConversionError, DynVal},
+ };
+-use eww_shared_util::{Span, Spanned, VarName};
++use eww_shared_util::{get_locale, Span, Spanned, VarName};
+ use std::{
+     collections::HashMap,
+     convert::{Infallible, TryFrom, TryInto},
+@@ -328,6 +328,22 @@ fn call_expr_function(name: &str, args: Vec<DynVal>) -> Result<DynVal, EvalError
+             }
+             _ => Err(EvalError::WrongArgCount(name.to_string())),
+         },
++        "min" => match args.as_slice() {
++            [a, b] => {
++                let a = a.as_f64()?;
++                let b = b.as_f64()?;
++                Ok(DynVal::from(f64::min(a, b)))
++            }
++            _ => Err(EvalError::WrongArgCount(name.to_string())),
++        },
++        "max" => match args.as_slice() {
++            [a, b] => {
++                let a = a.as_f64()?;
++                let b = b.as_f64()?;
++                Ok(DynVal::from(f64::max(a, b)))
++            }
++            _ => Err(EvalError::WrongArgCount(name.to_string())),
++        },
+         "sin" => match args.as_slice() {
+             [num] => {
+                 let num = num.as_f64()?;
+@@ -451,12 +467,16 @@ fn call_expr_function(name: &str, args: Vec<DynVal>) -> Result<DynVal, EvalError
+                 };
+ 
+                 Ok(DynVal::from(match timezone.timestamp_opt(timestamp.as_i64()?, 0) {
+-                    LocalResult::Single(t) | LocalResult::Ambiguous(t, _) => t.format(&format.as_string()?).to_string(),
++                    LocalResult::Single(t) | LocalResult::Ambiguous(t, _) => {
++                        t.format_localized(&format.as_string()?, get_locale()).to_string()
++                    }
+                     LocalResult::None => return Err(EvalError::ChronoError("Invalid UNIX timestamp".to_string())),
+                 }))
+             }
+             [timestamp, format] => Ok(DynVal::from(match Local.timestamp_opt(timestamp.as_i64()?, 0) {
+-                LocalResult::Single(t) | LocalResult::Ambiguous(t, _) => t.format(&format.as_string()?).to_string(),
++                LocalResult::Single(t) | LocalResult::Ambiguous(t, _) => {
++                    t.format_localized(&format.as_string()?, get_locale()).to_string()
++                }
+                 LocalResult::None => return Err(EvalError::ChronoError("Invalid UNIX timestamp".to_string())),
+             })),
+             _ => Err(EvalError::WrongArgCount(name.to_string())),
+diff --git a/crates/yuck/src/parser/ast_iterator.rs b/crates/yuck/src/parser/ast_iterator.rs
+index 603fdca..4cb6c2f 100644
+--- a/crates/yuck/src/parser/ast_iterator.rs
++++ b/crates/yuck/src/parser/ast_iterator.rs
+@@ -90,7 +90,7 @@ impl<I: Iterator<Item = Ast>> AstIterator<I> {
+         parse_key_values(self, true)
+     }
+ 
+-    pub fn put_back(&mut self, ast: Ast) {
++    pub fn put_back(&mut self, ast: Ast) -> Option<Ast> {
+         self.remaining_span.0 = ast.span().0;
+         self.iter.put_back(ast)
+     }
+diff --git a/crates/yuck/src/value/coords.rs b/crates/yuck/src/value/coords.rs
+index f500dff..4c999db 100644
+--- a/crates/yuck/src/value/coords.rs
++++ b/crates/yuck/src/value/coords.rs
+@@ -1,4 +1,4 @@
+-use derive_more::*;
++use derive_more::{Debug, *};
+ use once_cell::sync::Lazy;
+ use serde::{Deserialize, Serialize};
+ use smart_default::SmartDefault;
+@@ -14,13 +14,13 @@ pub enum Error {
+     MalformedCoords,
+ }
+ 
+-#[derive(Clone, Copy, PartialEq, Deserialize, Serialize, Display, DebugCustom, SmartDefault)]
++#[derive(Clone, Copy, PartialEq, Deserialize, Serialize, Display, Debug, SmartDefault)]
+ pub enum NumWithUnit {
+-    #[display(fmt = "{}%", .0)]
+-    #[debug(fmt = "{}%", .0)]
++    #[display("{}%", _0)]
++    #[debug("{}%", _0)]
+     Percent(f32),
+-    #[display(fmt = "{}px", .0)]
+-    #[debug(fmt = "{}px", .0)]
++    #[display("{}px", _0)]
++    #[debug("{}px", _0)]
+     #[default]
+     Pixels(i32),
+ }
+@@ -58,7 +58,7 @@ impl FromStr for NumWithUnit {
+ }
+ 
+ #[derive(Clone, Copy, PartialEq, Deserialize, Serialize, Display, Default)]
+-#[display(fmt = "{}*{}", x, y)]
++#[display("{}*{}", x, y)]
+ pub struct Coords {
+     pub x: NumWithUnit,
+     pub y: NumWithUnit,
+-- 
+2.46.0
+


             reply	other threads:[~2024-09-05 19:50 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-09-05 19:50 Gonçalo Negrier Duarte [this message]
  -- strict thread matches above, loose matches on Subject: below --
2024-05-08 17:56 [gentoo-commits] repo/proj/guru:dev commit in: gui-apps/eww/, gui-apps/eww/files/ Lucio Sauer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1725565717.606d347cbf9250ce0587a78fc8bf90d172ebea3b.gonegrier.duarte@gentoo \
    --to=gonegrier.duarte@gmail.com \
    --cc=gentoo-commits@lists.gentoo.org \
    --cc=gentoo-dev@lists.gentoo.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox