diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..fa8302a --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,108 @@ +name: CI + +on: + push: + branches: ["master", "main"] + pull_request: + branches: ["master", "main"] + +env: + CARGO_TERM_COLOR: always + +jobs: + build-ubuntu: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - features: "default" + args: "" + - features: "networking" + args: "--features networking" + - features: "no-default-features" + args: "--no-default-features" + steps: + - uses: actions/checkout@v4 + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install -y \ + llvm clang libclang-dev \ + pkg-config \ + libglib2.0-dev libcairo2-dev libpango1.0-dev libatk1.0-dev \ + libpam0g-dev \ + libwayland-dev libxkbcommon-dev + - name: Build (${{ matrix.features }}) + run: cargo build --verbose ${{ matrix.args }} + - name: Run tests + run: cargo test --verbose + + build-debian: + runs-on: ubuntu-latest + container: debian:stable-slim + steps: + - uses: actions/checkout@v4 + - name: Install system dependencies + run: | + apt-get update + apt-get install -y \ + llvm clang libclang-dev \ + pkg-config \ + libglib2.0-dev libcairo2-dev libpango1.0-dev libatk1.0-dev \ + libpam0g-dev \ + libwayland-dev libxkbcommon-dev \ + cargo rustc + - name: Build + run: cargo build --verbose + + build-fedora: + runs-on: ubuntu-latest + container: fedora:latest + steps: + - uses: actions/checkout@v4 + - name: Install system dependencies + run: | + dnf install -y \ + llvm clang libclang-devel \ + pkg-config \ + glib2-devel cairo-devel pango-devel atk-devel \ + pam-devel \ + wayland-devel libxkbcommon-devel \ + cargo rust + - name: Build + run: cargo build --verbose + + build-arch: + runs-on: ubuntu-latest + container: archlinux:latest + steps: + - uses: actions/checkout@v4 + - name: Install system dependencies + run: | + pacman -Sy --noconfirm \ + llvm clang pkgconf \ + glib2 cairo pango atk \ + pam \ + wayland libxkbcommon \ + rust cargo + - name: Build + run: cargo build --verbose + + build-opensuse: + runs-on: ubuntu-latest + container: opensuse/tumbleweed:latest + steps: + - uses: actions/checkout@v4 + - name: Install system dependencies + run: | + zypper install -y \ + llvm clang \ + pkg-config \ + glib2-devel cairo-devel pango-devel atk-devel \ + pam-devel \ + wayland-devel libxkbcommon-devel \ + rust cargo + - name: Build + run: cargo build --verbose + diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..336730c --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,156 @@ +name: Release + +on: + push: + tags: + - 'v*' + workflow_dispatch: + +jobs: + build-ubuntu: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - variant: "default" + args: "--no-default-features" + - variant: "networking" + args: "--features networking" + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install -y \ + llvm clang libclang-dev \ + pkg-config \ + libglib2.0-dev libcairo2-dev libpango1.0-dev libatk1.0-dev \ + libpam0g-dev \ + libwayland-dev libxkbcommon-dev + + - name: Build ${{ matrix.variant }} + run: cargo build --release ${{ matrix.args }} + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: rustlock-${{ matrix.variant }}-ubuntu + path: target/release/rustlock + + build-debian: + runs-on: ubuntu-latest + container: debian:stable-slim + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install system dependencies + run: | + apt-get update + apt-get install -y \ + llvm clang libclang-dev \ + pkg-config \ + libglib2.0-dev libcairo2-dev libpango1.0-dev libatk1.0-dev \ + libpam0g-dev \ + libwayland-dev libxkbcommon-dev \ + cargo rust + + - name: Build + run: cargo build --release + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: rustlock-default-debian + path: target/release/rustlock + + build-fedora: + runs-on: ubuntu-latest + container: fedora:latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install system dependencies + run: | + dnf install -y \ + llvm clang libclang-devel \ + pkg-config \ + glib2-devel cairo-devel pango-devel atk-devel \ + pam-devel \ + wayland-devel libxkbcommon-devel \ + rust cargo + + - name: Build + run: cargo build --release + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: rustlock-default-fedora + path: target/release/rustlock + + build-arch: + runs-on: ubuntu-latest + container: archlinux:latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install system dependencies + run: | + pacman -Sy --noconfirm \ + llvm clang pkgconf \ + glib2 cairo pango atk \ + pam \ + wayland libxkbcommon \ + rust cargo + + - name: Build + run: cargo build --release + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: rustlock-default-arch + path: target/release/rustlock + + release: + runs-on: ubuntu-latest + needs: [build-ubuntu, build-debian, build-fedora, build-arch] + permissions: + contents: write + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: artifacts + + - name: Determine tag + id: tag + run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT + + - name: Create Release + uses: softprops/action-gh-release@v1 + with: + tag_name: ${{ github.ref_name }} + name: RustLock v${{ steps.tag.outputs.VERSION }} + draft: true + prerelease: ${{ contains(github.ref_name, 'alpha') || contains(github.ref_name, 'beta') }} + files: | + artifacts/rustlock-default-ubuntu/rustlock + artifacts/rustlock-networking-ubuntu/rustlock + artifacts/rustlock-default-debian/rustlock + artifacts/rustlock-default-fedora/rustlock + artifacts/rustlock-default-arch/rustlock + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/Cargo.lock b/Cargo.lock index 8199cb8..b5afd79 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,24 +17,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "aligned" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee4508988c62edf04abd8d92897fca0c2995d907ce1dfeaf369dac3716a40685" -dependencies = [ - "as-slice", -] - -[[package]] -name = "aligned-vec" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" -dependencies = [ - "equator", -] - [[package]] name = "android_system_properties" version = "0.1.5" @@ -52,7 +34,6 @@ checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" dependencies = [ "anstyle", "anstyle-parse", - "anstyle-query", "anstyle-wincon", "colorchoice", "is_terminal_polyfill", @@ -61,9 +42,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anstyle-parse" @@ -74,15 +55,6 @@ dependencies = [ "utf8parse", ] -[[package]] -name = "anstyle-query" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" -dependencies = [ - "windows-sys 0.61.2", -] - [[package]] name = "anstyle-wincon" version = "3.0.11" @@ -101,37 +73,180 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] -name = "arbitrary" -version = "1.4.2" +name = "async-broadcast" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" +checksum = "7c48ccdbf6ca6b121e0f586cbc0e73ae440e56c67c30fa0873b4e110d9c26d2b" +dependencies = [ + "event-listener 2.5.3", + "futures-core", +] [[package]] -name = "arg_enum_proc_macro" -version = "0.3.4" +name = "async-channel" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand 2.3.0", + "futures-lite 2.6.1", + "pin-project-lite", + "slab", +] + +[[package]] +name = "async-fs" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06" +dependencies = [ + "async-lock 2.8.0", + "autocfg", + "blocking", + "futures-lite 1.13.0", +] + +[[package]] +name = "async-io" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +dependencies = [ + "async-lock 2.8.0", + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-lite 1.13.0", + "log", + "parking", + "polling 2.8.0", + "rustix 0.37.28", + "slab", + "socket2 0.4.10", + "waker-fn", +] + +[[package]] +name = "async-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" +dependencies = [ + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite 2.6.1", + "parking", + "polling 3.11.0", + "rustix 1.1.4", + "slab", + "windows-sys 0.61.2", +] + +[[package]] +name = "async-lock" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +dependencies = [ + "event-listener 2.5.3", +] + +[[package]] +name = "async-lock" +version = "3.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" +dependencies = [ + "event-listener 5.4.1", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-process" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6438ba0a08d81529c69b36700fa2f95837bfe3e776ab39cde9c14d9149da88" +dependencies = [ + "async-io 1.13.0", + "async-lock 2.8.0", + "async-signal", + "blocking", + "cfg-if", + "event-listener 3.1.0", + "futures-lite 1.13.0", + "rustix 0.38.44", + "windows-sys 0.48.0", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.45", "syn 2.0.117", ] [[package]] -name = "arrayvec" -version = "0.7.6" +name = "async-signal" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +checksum = "43c070bbf59cd3570b6b2dd54cd772527c7c3620fce8be898406dd3ed6adc64c" +dependencies = [ + "async-io 2.6.0", + "async-lock 3.4.2", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix 1.1.4", + "signal-hook-registry", + "slab", + "windows-sys 0.61.2", +] [[package]] -name = "as-slice" -version = "0.2.1" +name = "async-task" +version = "4.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ - "stable_deref_trait", + "proc-macro2", + "quote 1.0.45", + "syn 2.0.117", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "autocfg" version = "1.5.0" @@ -139,47 +254,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] -name = "av-scenechange" -version = "0.14.1" +name = "base64" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f321d77c20e19b92c39e7471cf986812cbb46659d2af674adc4331ef3f18394" -dependencies = [ - "aligned", - "anyhow", - "arg_enum_proc_macro", - "arrayvec", - "log", - "num-rational", - "num-traits", - "pastey", - "rayon", - "thiserror 2.0.18", - "v_frame", - "y4m", -] - -[[package]] -name = "av1-grain" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cfddb07216410377231960af4fcab838eaa12e013417781b78bd95ee22077f8" -dependencies = [ - "anyhow", - "arrayvec", - "log", - "nom 8.0.0", - "num-rational", - "v_frame", -] - -[[package]] -name = "avif-serialize" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "375082f007bd67184fb9c0374614b29f9aaa604ec301635f72338bb65386a53d" -dependencies = [ - "arrayvec", -] +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "bindgen" @@ -190,23 +268,17 @@ dependencies = [ "bitflags 2.11.0", "cexpr", "clang-sys", - "itertools 0.12.1", + "itertools", "lazy_static", "lazycell", "proc-macro2", - "quote", + "quote 1.0.45", "regex", "rustc-hash", "shlex", "syn 2.0.117", ] -[[package]] -name = "bit_field" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" - [[package]] name = "bitflags" version = "1.3.2" @@ -220,19 +292,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" [[package]] -name = "bitstream-io" -version = "4.9.0" +name = "block-buffer" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60d4bd9d1db2c6bdf285e223a7fa369d5ce98ec767dec949c6ca62863ce61757" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "core2", + "generic-array", ] [[package]] -name = "built" -version = "0.8.0" +name = "blocking" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4ad8f11f288f48ca24471bbd51ac257aaeaaa07adae295591266b792902ae64" +checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" +dependencies = [ + "async-channel", + "async-task", + "futures-io", + "futures-lite 2.6.1", + "piper", +] [[package]] name = "bumpalo" @@ -256,16 +335,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.45", "syn 2.0.117", ] +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "byteorder-lite" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" + [[package]] name = "cairo-rs" version = "0.20.12" @@ -297,10 +388,10 @@ checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" dependencies = [ "bitflags 2.11.0", "log", - "polling", + "polling 3.11.0", "rustix 0.38.44", "slab", - "thiserror 1.0.69", + "thiserror", ] [[package]] @@ -322,8 +413,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" dependencies = [ "find-msvc-tools", - "jobserver", - "libc", "shlex", ] @@ -333,7 +422,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" dependencies = [ - "nom 7.1.3", + "nom", ] [[package]] @@ -359,9 +448,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" dependencies = [ "iana-time-zone", - "js-sys", "num-traits", - "wasm-bindgen", "windows-link", ] @@ -377,9 +464,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.60" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2797f34da339ce31042b27d23607e051786132987f595b02ba4f6a6dffb7030a" +checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" dependencies = [ "clap_builder", "clap_derive", @@ -387,45 +474,37 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.60" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24a241312cea5059b13574bb9b3861cabf758b879c15190b37b6d6fd63ab6876" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ - "anstream", "anstyle", "clap_lex", - "strsim", ] [[package]] name = "clap_derive" -version = "4.5.55" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" +checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", - "quote", + "quote 1.0.45", "syn 2.0.117", ] [[package]] name = "clap_lex" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" - -[[package]] -name = "color_quant" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "colorchoice" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "concurrent-queue" @@ -436,6 +515,16 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -443,12 +532,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] -name = "core2" -version = "0.4.0" +name = "cpufeatures" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ - "memchr", + "libc", ] [[package]] @@ -460,25 +549,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "crossbeam-deque" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - [[package]] name = "crossbeam-utils" version = "0.8.21" @@ -486,10 +556,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] -name = "crunchy" -version = "0.2.4" +name = "crypto-common" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] [[package]] name = "cursor-icon" @@ -497,6 +571,95 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote 1.0.45", + "strsim", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core", + "quote 1.0.45", + "syn 1.0.109", +] + +[[package]] +name = "dbus" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b3aa68d7e7abee336255bd7248ea965cc393f3e70411135a6f6a4b651345d4" +dependencies = [ + "libc", + "libdbus-sys", + "windows-sys 0.59.0", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote 1.0.45", + "syn 1.0.109", +] + +[[package]] +name = "derive_is_enum_variant" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0ac8859845146979953797f03cc5b282fb4396891807cdb3d04929a88418197" +dependencies = [ + "heck 0.3.3", + "quote 0.3.15", + "syn 0.11.11", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote 1.0.45", + "syn 2.0.117", +] + [[package]] name = "downcast-rs" version = "1.2.1" @@ -509,6 +672,26 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "enum-kinds" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e40a16955681d469ab3da85aaa6b42ff656b3c67b52e1d8d3dd36afe97fd462" +dependencies = [ + "proc-macro2", + "quote 1.0.45", + "syn 1.0.109", +] + [[package]] name = "enum-repr" version = "0.2.6" @@ -516,10 +699,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bad30c9c0fa1aaf1ae5010dab11f1117b15d35faf62cda4bbbc53b9987950f18" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.45", "syn 1.0.109", ] +[[package]] +name = "enumflags2" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" +dependencies = [ + "proc-macro2", + "quote 1.0.45", + "syn 2.0.117", +] + [[package]] name = "env_filter" version = "1.0.0" @@ -527,7 +731,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a1c3cc8e57274ec99de65301228b537f1e4eedc1b8e0f9411c6caac8ae7308f" dependencies = [ "log", - "regex", ] [[package]] @@ -543,26 +746,6 @@ dependencies = [ "log", ] -[[package]] -name = "equator" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" -dependencies = [ - "equator-macro", -] - -[[package]] -name = "equator-macro" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "equivalent" version = "1.0.2" @@ -580,18 +763,41 @@ dependencies = [ ] [[package]] -name = "exr" -version = "1.74.0" +name = "event-listener" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4300e043a56aa2cb633c01af81ca8f699a321879a7854d3896a0ba89056363be" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "event-listener" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" dependencies = [ - "bit_field", - "half", - "lebe", - "miniz_oxide", - "rayon-core", - "smallvec", - "zune-inflate", + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener" +version = "5.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener 5.4.1", + "pin-project-lite", ] [[package]] @@ -601,24 +807,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8383bbc116936203138cc8fe615c6364790847af8985a4bf579baaa4a86dca2d" [[package]] -name = "fax" -version = "0.2.6" +name = "fastrand" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f05de7d48f37cd6730705cbca900770cab77a89f413d23e100ad7fad7795a0ab" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" dependencies = [ - "fax_derive", + "instant", ] [[package]] -name = "fax_derive" -version = "0.2.0" +name = "fastrand" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fdeflate" @@ -645,6 +846,48 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "from_variants" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e859c8f2057687618905dbe99fc76e836e0a69738865ef90e46fc214a41bbf2" +dependencies = [ + "from_variants_impl", +] + +[[package]] +name = "from_variants_impl" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55a5e644a80e6d96b2b4910fa7993301d7b7926c045b475b62202b20a36ce69e" +dependencies = [ + "darling", + "proc-macro2", + "quote 1.0.45", + "syn 1.0.109", +] + [[package]] name = "futures" version = "0.3.32" @@ -653,7 +896,6 @@ checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" dependencies = [ "futures-channel", "futures-core", - "futures-executor", "futures-io", "futures-sink", "futures-task", @@ -693,6 +935,34 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand 1.9.0", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + +[[package]] +name = "futures-lite" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" +dependencies = [ + "fastrand 2.3.0", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + [[package]] name = "futures-macro" version = "0.3.32" @@ -700,7 +970,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.45", "syn 2.0.117", ] @@ -734,25 +1004,79 @@ dependencies = [ ] [[package]] -name = "getrandom" -version = "0.3.4" +name = "gdk-pixbuf" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +checksum = "2fd242894c084f4beed508a56952750bce3e96e85eb68fdc153637daa163e10c" +dependencies = [ + "gdk-pixbuf-sys", + "gio", + "glib", + "libc", +] + +[[package]] +name = "gdk-pixbuf-sys" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b34f3b580c988bd217e9543a2de59823fafae369d1a055555e5f95a8b130b96" +dependencies = [ + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ "cfg-if", "libc", "r-efi", "wasip2", + "wasip3", ] [[package]] -name = "gif" -version = "0.14.1" +name = "gio" +version = "0.20.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5df2ba84018d80c213569363bdcd0c64e6933c67fe4c1d60ecf822971a3c35e" +checksum = "8e27e276e7b6b8d50f6376ee7769a71133e80d093bdc363bd0af71664228b831" dependencies = [ - "color_quant", - "weezl", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "gio-sys", + "glib", + "libc", + "pin-project-lite", + "smallvec", ] [[package]] @@ -795,10 +1119,10 @@ version = "0.20.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8084af62f09475a3f529b1629c10c429d7600ee1398ae12dd3bf175d74e7145" dependencies = [ - "heck", - "proc-macro-crate", + "heck 0.5.0", + "proc-macro-crate 3.5.0", "proc-macro2", - "quote", + "quote 1.0.45", "syn 2.0.117", ] @@ -830,14 +1154,31 @@ dependencies = [ ] [[package]] -name = "half" -version = "2.7.1" +name = "h2" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" dependencies = [ - "cfg-if", - "crunchy", - "zerocopy", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", ] [[package]] @@ -846,18 +1187,111 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "heck" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + [[package]] name = "hermit-abi" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "0.14.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2 0.5.10", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http", + "hyper", + "rustls", + "tokio", + "tokio-rustls", +] + [[package]] name = "iana-time-zone" version = "0.1.65" @@ -883,45 +1317,134 @@ dependencies = [ ] [[package]] -name = "image" -version = "0.25.9" +name = "icu_collections" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6506c6c10786659413faa717ceebcb8f70731c0a60cbae39795fdf114519c1a" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" + +[[package]] +name = "icu_properties" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" + +[[package]] +name = "icu_provider" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "image" +version = "0.25.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" dependencies = [ "bytemuck", "byteorder-lite", - "color_quant", - "exr", - "gif", - "image-webp", "moxcms", "num-traits", "png", - "qoi", - "ravif", - "rayon", - "rgb", - "tiff", - "zune-core 0.5.1", - "zune-jpeg 0.5.12", + "zune-core", + "zune-jpeg", ] -[[package]] -name = "image-webp" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3" -dependencies = [ - "byteorder-lite", - "quick-error", -] - -[[package]] -name = "imgref" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c5cedc30da3a610cac6b4ba17597bdf7152cf974e8aab3afb3d54455e371c8" - [[package]] name = "indexmap" version = "2.13.0" @@ -929,20 +1452,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.16.1", + "serde", + "serde_core", ] [[package]] -name = "interpolate_name" -version = "0.2.4" +name = "instant" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", + "cfg-if", ] +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi 0.3.9", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "ipnet" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" + [[package]] name = "is_terminal_polyfill" version = "1.70.2" @@ -958,15 +1498,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" -dependencies = [ - "either", -] - [[package]] name = "itoa" version = "1.0.17" @@ -993,20 +1524,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a8c8b344124222efd714b73bb41f8b5120b27a7cc1c75593a6ff768d9d05aa4" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.45", "syn 2.0.117", ] -[[package]] -name = "jobserver" -version = "0.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" -dependencies = [ - "getrandom", - "libc", -] - [[package]] name = "js-sys" version = "0.3.91" @@ -1030,10 +1551,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] -name = "lebe" -version = "0.5.3" +name = "leb128fmt" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" @@ -1042,15 +1563,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" [[package]] -name = "libfuzzer-sys" -version = "0.4.12" +name = "libdbus-sys" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f12a681b7dd8ce12bff52488013ba614b869148d54dd79836ab85aafdd53f08d" +checksum = "328c4789d42200f1eeec05bd86c9c13c7f091d2ba9a6ea35acdf51f31bc0f043" dependencies = [ - "arbitrary", - "cc", + "pkg-config", ] +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + [[package]] name = "linux-raw-sys" version = "0.4.15" @@ -1063,31 +1589,18 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" +[[package]] +name = "litemap" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" + [[package]] name = "log" version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" -[[package]] -name = "loop9" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" -dependencies = [ - "imgref", -] - -[[package]] -name = "maybe-rayon" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" -dependencies = [ - "cfg-if", - "rayon", -] - [[package]] name = "memchr" version = "2.8.0" @@ -1112,6 +1625,30 @@ dependencies = [ "libc", ] +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -1129,20 +1666,50 @@ dependencies = [ ] [[package]] -name = "moxcms" -version = "0.7.11" +name = "mio" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac9557c559cd6fc9867e122e20d2cbefc9ca29d80d027a8e39310920ed2f0a97" +checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "moxcms" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b" dependencies = [ "num-traits", "pxfm", ] [[package]] -name = "new_debug_unreachable" -version = "1.0.6" +name = "mpris" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" +checksum = "55cef955a7826b1e00e901a3652e7a895abd221fb4ab61547e7d0e4c235d7feb" +dependencies = [ + "dbus", + "derive_is_enum_variant", + "enum-kinds", + "from_variants", + "thiserror", +] + +[[package]] +name = "nix" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", + "memoffset 0.7.1", +] [[package]] name = "nom" @@ -1154,62 +1721,6 @@ dependencies = [ "minimal-lexical", ] -[[package]] -name = "nom" -version = "8.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" -dependencies = [ - "memchr", -] - -[[package]] -name = "noop_proc_macro" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-derive" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -1221,9 +1732,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.3" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "once_cell_polyfill" @@ -1231,6 +1742,16 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + [[package]] name = "pam-client" version = "0.5.0" @@ -1256,16 +1777,66 @@ dependencies = [ ] [[package]] -name = "paste" -version = "1.0.15" +name = "pango" +version = "0.20.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +checksum = "6576b311f6df659397043a5fa8a021da8f72e34af180b44f7d57348de691ab5c" +dependencies = [ + "gio", + "glib", + "libc", + "pango-sys", +] [[package]] -name = "pastey" -version = "0.1.1" +name = "pango-sys" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec" +checksum = "186909673fc09be354555c302c0b3dcf753cd9fa08dcb8077fa663c80fb243fa" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "pangocairo" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58890dc451db9964ac2d8874f903a4370a4b3932aa5281ff0c8d9810937ad84f" +dependencies = [ + "cairo-rs", + "glib", + "libc", + "pango", + "pangocairo-sys", +] + +[[package]] +name = "pangocairo-sys" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9952903f88aa93e2927e7bca2d1ebae64fc26545a9280b4ce6bddeda26b5c42" +dependencies = [ + "cairo-sys-rs", + "glib-sys", + "libc", + "pango-sys", + "system-deps", +] + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pin-project-lite" @@ -1273,6 +1844,17 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" +[[package]] +name = "piper" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" +dependencies = [ + "atomic-waker", + "fastrand 2.3.0", + "futures-io", +] + [[package]] name = "pkg-config" version = "0.3.32" @@ -1292,6 +1874,22 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "polling" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if", + "concurrent-queue", + "libc", + "log", + "pin-project-lite", + "windows-sys 0.48.0", +] + [[package]] name = "polling" version = "3.11.0" @@ -1300,7 +1898,7 @@ checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" dependencies = [ "cfg-if", "concurrent-queue", - "hermit-abi", + "hermit-abi 0.5.2", "pin-project-lite", "rustix 1.1.4", "windows-sys 0.61.2", @@ -1314,13 +1912,22 @@ checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" [[package]] name = "portable-atomic-util" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a9db96d7fa8782dd8c15ce32ffe8680bbd1e978a43bf51a34d39483540495f5" +checksum = "091397be61a01d4be58e7841595bd4bfedb15f1cd54977d79b8271e94ed799a3" dependencies = [ "portable-atomic", ] +[[package]] +name = "potential_utf" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +dependencies = [ + "zerovec", +] + [[package]] name = "ppv-lite86" version = "0.2.21" @@ -1330,13 +1937,33 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.117", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit 0.19.15", +] + [[package]] name = "proc-macro-crate" version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit", + "toml_edit 0.25.4+spec-1.1.0", ] [[package]] @@ -1348,46 +1975,12 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "profiling" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" -dependencies = [ - "profiling-procmacros", -] - -[[package]] -name = "profiling-procmacros" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b" -dependencies = [ - "quote", - "syn 2.0.117", -] - [[package]] name = "pxfm" version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5a041e753da8b807c9255f28de81879c78c876392ff2469cde94799b2896b9d" -[[package]] -name = "qoi" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "quick-error" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" - [[package]] name = "quick-xml" version = "0.38.4" @@ -1397,6 +1990,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "quote" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" + [[package]] name = "quote" version = "1.0.45" @@ -1408,25 +2007,26 @@ dependencies = [ [[package]] name = "r-efi" -version = "5.3.0" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "rand" -version = "0.9.2" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ + "libc", "rand_chacha", "rand_core", ] [[package]] name = "rand_chacha" -version = "0.9.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", "rand_core", @@ -1434,81 +2034,11 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.9.5" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", -] - -[[package]] -name = "rav1e" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43b6dd56e85d9483277cde964fd1bdb0428de4fec5ebba7540995639a21cb32b" -dependencies = [ - "aligned-vec", - "arbitrary", - "arg_enum_proc_macro", - "arrayvec", - "av-scenechange", - "av1-grain", - "bitstream-io", - "built", - "cfg-if", - "interpolate_name", - "itertools 0.14.0", - "libc", - "libfuzzer-sys", - "log", - "maybe-rayon", - "new_debug_unreachable", - "noop_proc_macro", - "num-derive", - "num-traits", - "paste", - "profiling", - "rand", - "rand_chacha", - "simd_helpers", - "thiserror 2.0.18", - "v_frame", - "wasm-bindgen", -] - -[[package]] -name = "ravif" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef69c1990ceef18a116855938e74793a5f7496ee907562bd0857b6ac734ab285" -dependencies = [ - "avif-serialize", - "imgref", - "loop9", - "quick-error", - "rav1e", - "rayon", - "rgb", -] - -[[package]] -name = "rayon" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", + "getrandom 0.2.17", ] [[package]] @@ -1541,10 +2071,59 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] -name = "rgb" -version = "0.8.53" +name = "reqwest" +version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b34b781b31e5d73e9fbc8689c70551fd1ade9a19e3e28cfec8580a79290cc4" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-rustls", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-rustls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots", + "winreg", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.17", + "libc", + "untrusted", + "windows-sys 0.52.0", +] [[package]] name = "rpassword" @@ -1564,6 +2143,20 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustix" +version = "0.37.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "519165d378b97752ca44bbe15047d5d3409e875f39327546b42ac81d7e18c1b6" +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.44" @@ -1595,27 +2188,71 @@ name = "rustlock" version = "0.1.0" dependencies = [ "anyhow", + "bytemuck", "cairo-rs", + "calloop", + "calloop-wayland-source", "chrono", "clap", "env_logger", "fastblur", "futures", + "gdk-pixbuf", + "gio", "image", "log", + "mpris", + "num-traits", "pam-client", - "secstr", + "pangocairo", + "rand", + "reqwest", "serde", "smithay-client-toolkit", - "toml 1.0.3+spec-1.1.0", + "thiserror", + "tokio", + "toml 1.0.6+spec-1.1.0", + "upower_dbus", "users", "wayland-client", "wayland-protocols", "wayland-protocols-wlr", "xkbcommon", + "zbus", "zeroize", ] +[[package]] +name = "rustls" +version = "0.21.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +dependencies = [ + "log", + "ring", + "rustls-webpki", + "sct", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.22" @@ -1623,14 +2260,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] -name = "secstr" -version = "0.5.1" +name = "ryu" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04f657244f605c4cf38f6de5993e8bd050c8a303f86aeabff142d5c7c113e12" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" + +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "libc", + "ring", + "untrusted", ] +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" + [[package]] name = "serde" version = "1.0.228" @@ -1657,7 +2307,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.45", "syn 2.0.117", ] @@ -1674,6 +2324,17 @@ dependencies = [ "zmij", ] +[[package]] +name = "serde_repr" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" +dependencies = [ + "proc-macro2", + "quote 1.0.45", + "syn 2.0.117", +] + [[package]] name = "serde_spanned" version = "1.0.4" @@ -1683,27 +2344,51 @@ dependencies = [ "serde_core", ] +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "shlex" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "signal-hook-registry" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + [[package]] name = "simd-adler32" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" -[[package]] -name = "simd_helpers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" -dependencies = [ - "quote", -] - [[package]] name = "slab" version = "0.4.12" @@ -1732,7 +2417,7 @@ dependencies = [ "memmap2 0.9.10", "pkg-config", "rustix 0.38.44", - "thiserror 1.0.69", + "thiserror", "wayland-backend", "wayland-client", "wayland-csd-frame", @@ -1744,6 +2429,36 @@ dependencies = [ "xkeysym", ] +[[package]] +name = "socket2" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "socket2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "socket2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + [[package]] name = "stable_deref_trait" version = "1.2.1" @@ -1751,10 +2466,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] -name = "strsim" -version = "0.11.1" +name = "static_assertions" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" +dependencies = [ + "quote 0.3.15", + "synom", + "unicode-xid 0.0.4", +] [[package]] name = "syn" @@ -1763,7 +2495,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.45", "unicode-ident", ] @@ -1774,10 +2506,57 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.45", "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "synom" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" +dependencies = [ + "unicode-xid 0.0.4", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote 1.0.45", + "syn 2.0.117", +] + +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "system-deps" version = "7.0.7" @@ -1785,7 +2564,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c8f33736f986f16d69b6cb8b03f55ddcad5c41acc4ccc39dd88e84aa805e7f" dependencies = [ "cfg-expr", - "heck", + "heck 0.5.0", "pkg-config", "toml 0.9.12+spec-1.1.0", "version-compare", @@ -1797,22 +2576,26 @@ version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df7f62577c25e07834649fc3b39fafdc597c0a3527dc1c60129201ccfcbaa50c" +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand 2.3.0", + "getrandom 0.4.2", + "once_cell", + "rustix 1.1.4", + "windows-sys 0.61.2", +] + [[package]] name = "thiserror" version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl 1.0.69", -] - -[[package]] -name = "thiserror" -version = "2.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" -dependencies = [ - "thiserror-impl 2.0.18", + "thiserror-impl", ] [[package]] @@ -1822,33 +2605,69 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.45", "syn 2.0.117", ] [[package]] -name = "thiserror-impl" -version = "2.0.18" +name = "tinystr" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tokio" +version = "1.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d" +dependencies = [ + "bytes", + "libc", + "mio", + "pin-project-lite", + "signal-hook-registry", + "socket2 0.6.3", + "tokio-macros", + "tracing", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-macros" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.45", "syn 2.0.117", ] [[package]] -name = "tiff" -version = "0.10.3" +name = "tokio-rustls" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af9605de7fee8d9551863fd692cce7637f548dbd9db9180fcc07ccc6d26c336f" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "fax", - "flate2", - "half", - "quick-error", - "weezl", - "zune-jpeg 0.4.21", + "rustls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", ] [[package]] @@ -1863,24 +2682,29 @@ dependencies = [ "toml_datetime 0.7.5+spec-1.1.0", "toml_parser", "toml_writer", - "winnow", + "winnow 0.7.14", ] [[package]] name = "toml" -version = "1.0.3+spec-1.1.0" +version = "1.0.6+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7614eaf19ad818347db24addfa201729cf2a9b6fdfd9eb0ab870fcacc606c0c" +checksum = "399b1124a3c9e16766831c6bba21e50192572cdd98706ea114f9502509686ffc" dependencies = [ - "indexmap", "serde_core", "serde_spanned", "toml_datetime 1.0.0+spec-1.1.0", "toml_parser", "toml_writer", - "winnow", + "winnow 0.7.14", ] +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" + [[package]] name = "toml_datetime" version = "0.7.5+spec-1.1.0" @@ -1899,6 +2723,17 @@ dependencies = [ "serde_core", ] +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap", + "toml_datetime 0.6.11", + "winnow 0.5.40", +] + [[package]] name = "toml_edit" version = "0.25.4+spec-1.1.0" @@ -1908,7 +2743,7 @@ dependencies = [ "indexmap", "toml_datetime 1.0.0+spec-1.1.0", "toml_parser", - "winnow", + "winnow 0.7.14", ] [[package]] @@ -1917,7 +2752,7 @@ version = "1.0.9+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4" dependencies = [ - "winnow", + "winnow 0.7.14", ] [[package]] @@ -1926,12 +2761,119 @@ version = "1.0.6+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607" +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote 1.0.45", + "syn 2.0.117", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typenum" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + +[[package]] +name = "uds_windows" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e" +dependencies = [ + "memoffset 0.9.1", + "tempfile", + "windows-sys 0.61.2", +] + [[package]] name = "unicode-ident" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode-xid" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "upower_dbus" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0b1d77de98ab2e5187f5fa2b045b8c4eecfc49e5ccd07f16f4c89f008116f8c" +dependencies = [ + "serde", + "serde_repr", + "zbus", +] + +[[package]] +name = "url" +version = "2.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + [[package]] name = "users" version = "0.11.0" @@ -1942,29 +2884,51 @@ dependencies = [ "log", ] +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" -[[package]] -name = "v_frame" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "666b7727c8875d6ab5db9533418d7c764233ac9c0cff1d469aec8fa127597be2" -dependencies = [ - "aligned-vec", - "num-traits", - "wasm-bindgen", -] - [[package]] name = "version-compare" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03c2856837ef78f57382f06b2b8563a2f512f7185d732608fd9176cb3b8edf0e" +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "waker-fn" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + [[package]] name = "wasip2" version = "1.0.2+wasi-0.2.9" @@ -1974,6 +2938,15 @@ dependencies = [ "wit-bindgen", ] +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen", +] + [[package]] name = "wasm-bindgen" version = "0.2.114" @@ -1987,13 +2960,27 @@ dependencies = [ "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9c5522b3a28661442748e09d40924dfb9ca614b21c00d3fd135720e48b67db8" +dependencies = [ + "cfg-if", + "futures-util", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "wasm-bindgen-macro" version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6" dependencies = [ - "quote", + "quote 1.0.45", "wasm-bindgen-macro-support", ] @@ -2005,7 +2992,7 @@ checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3" dependencies = [ "bumpalo", "proc-macro2", - "quote", + "quote 1.0.45", "syn 2.0.117", "wasm-bindgen-shared", ] @@ -2019,6 +3006,40 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.11.0", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + [[package]] name = "wayland-backend" version = "0.3.12" @@ -2099,7 +3120,7 @@ checksum = "5423e94b6a63e68e439803a3e153a9252d5ead12fd853334e2ad33997e3889e3" dependencies = [ "proc-macro2", "quick-xml", - "quote", + "quote 1.0.45", ] [[package]] @@ -2112,10 +3133,20 @@ dependencies = [ ] [[package]] -name = "weezl" -version = "0.1.12" +name = "web-sys" +version = "0.3.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" +checksum = "854ba17bb104abfb26ba36da9729addc7ce7f06f5c0f90f3c391f8461cca21f9" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "winapi" @@ -2159,7 +3190,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.45", "syn 2.0.117", ] @@ -2170,7 +3201,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.45", "syn 2.0.117", ] @@ -2198,13 +3229,31 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -2216,34 +3265,67 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "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.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "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.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -2256,30 +3338,63 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + [[package]] name = "winnow" version = "0.7.14" @@ -2289,11 +3404,109 @@ dependencies = [ "memchr", ] +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + [[package]] name = "wit-bindgen" version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck 0.5.0", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck 0.5.0", + "indexmap", + "prettyplease", + "syn 2.0.117", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote 1.0.45", + "syn 2.0.117", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.11.0", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid 0.2.6", + "wasmparser", +] + +[[package]] +name = "writeable" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] name = "xcursor" @@ -2301,6 +3514,16 @@ version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bec9e4a500ca8864c5b47b8b482a73d62e4237670e5b5f1d6b9e3cae50f28f2b" +[[package]] +name = "xdg-home" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec1cdab258fb55c0da61328dc52c8764709b249011b2cad0454c72f0bf10a1f6" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + [[package]] name = "xkbcommon" version = "0.7.0" @@ -2322,49 +3545,181 @@ dependencies = [ ] [[package]] -name = "y4m" -version = "0.8.0" +name = "yoke" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5a4b21e1a62b67a2970e6831bc091d7b87e119e7f9791aef9702e3bef04448" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +dependencies = [ + "proc-macro2", + "quote 1.0.45", + "syn 2.0.117", + "synstructure", +] + +[[package]] +name = "zbus" +version = "3.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "675d170b632a6ad49804c8cf2105d7c31eddd3312555cffd4b740e08e97c25e6" +dependencies = [ + "async-broadcast", + "async-executor", + "async-fs", + "async-io 1.13.0", + "async-lock 2.8.0", + "async-process", + "async-recursion", + "async-task", + "async-trait", + "blocking", + "byteorder", + "derivative", + "enumflags2", + "event-listener 2.5.3", + "futures-core", + "futures-sink", + "futures-util", + "hex", + "nix", + "once_cell", + "ordered-stream", + "rand", + "serde", + "serde_repr", + "sha1", + "static_assertions", + "tokio", + "tracing", + "uds_windows", + "winapi", + "xdg-home", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "3.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7131497b0f887e8061b430c530240063d33bf9455fa34438f388a245da69e0a5" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote 1.0.45", + "regex", + "syn 1.0.109", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "437d738d3750bed6ca9b8d423ccc7a8eb284f6b1d6d4e225a0e4e6258d864c8d" +dependencies = [ + "serde", + "static_assertions", + "zvariant", +] [[package]] name = "zerocopy" -version = "0.8.40" +version = "0.8.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a789c6e490b576db9f7e6b6d661bcc9799f7c0ac8352f56ea20193b2681532e5" +checksum = "f2578b716f8a7a858b7f02d5bd870c14bf4ddbbcf3a4c05414ba6503640505e3" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.40" +version = "0.8.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f65c489a7071a749c849713807783f70672b28094011623e200cb86dcb835953" +checksum = "7e6cc098ea4d3bd6246687de65af3f920c430e236bee1e3bf2e441463f08a02f" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.45", "syn 2.0.117", ] +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote 1.0.45", + "syn 2.0.117", + "synstructure", +] + [[package]] name = "zeroize" version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +[[package]] +name = "zerotrie" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +dependencies = [ + "proc-macro2", + "quote 1.0.45", + "syn 2.0.117", +] + [[package]] name = "zmij" version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" -[[package]] -name = "zune-core" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" - [[package]] name = "zune-core" version = "0.5.1" @@ -2372,28 +3727,48 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" [[package]] -name = "zune-inflate" -version = "0.2.54" +name = "zune-jpeg" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +checksum = "ec5f41c76397b7da451efd19915684f727d7e1d516384ca6bd0ec43ec94de23c" dependencies = [ - "simd-adler32", + "zune-core", ] [[package]] -name = "zune-jpeg" -version = "0.4.21" +name = "zvariant" +version = "3.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ce2c8a9384ad323cf564b67da86e21d3cfdff87908bc1223ed5c99bc792713" +checksum = "4eef2be88ba09b358d3b58aca6e41cd853631d44787f319a1383ca83424fb2db" dependencies = [ - "zune-core 0.4.12", + "byteorder", + "enumflags2", + "libc", + "serde", + "static_assertions", + "zvariant_derive", ] [[package]] -name = "zune-jpeg" -version = "0.5.12" +name = "zvariant_derive" +version = "3.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "410e9ecef634c709e3831c2cfdb8d9c32164fae1c67496d5b68fff728eec37fe" +checksum = "37c24dc0bed72f5f90d1f8bb5b07228cbf63b3c6e9f82d82559d4bae666e7ed9" dependencies = [ - "zune-core 0.5.1", + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote 1.0.45", + "syn 1.0.109", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7234f0d811589db492d16893e3f21e8e2fd282e6d01b0cddee310322062cc200" +dependencies = [ + "proc-macro2", + "quote 1.0.45", + "syn 1.0.109", ] diff --git a/Cargo.toml b/Cargo.toml index 76d46ee..1d7318a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,23 +4,47 @@ version = "0.1.0" edition = "2021" [dependencies] -smithay-client-toolkit = { version = "0.19", features = ["calloop"] } -wayland-client = "0.31" -wayland-protocols = { version = "0.32", features = ["client", "unstable"] } +smithay-client-toolkit = { version = "0.19", default-features = false, features = ["calloop", "xkbcommon"] } +wayland-client = { version = "0.31" } +wayland-protocols = { version = "0.32", features = ["client"] } wayland-protocols-wlr = { version = "0.3", features = ["client"] } anyhow = "1.0" -futures = "0.3" -cairo-rs = { version = "0.20", features = ["png"] } -image = "0.25" -fastblur = "0.1" -xkbcommon = "0.7" -pam-client = "0.5" -secstr = "0.5" -clap = { version = "4.5", features = ["derive"] } -toml = "1.0" -serde = { version = "1.0", features = ["derive"] } +futures = { version = "0.3", default-features = false, features = ["std"] } +cairo-rs = { version = "0.20", default-features = false, features = ["png"] } +gdk-pixbuf = { version = "0.20", default-features = false, features = ["v2_40"] } +gio = { version = "0.20" } +pangocairo = { version = "0.20" } +clap = { version = "4.4", default-features = false, features = ["derive", "std", "help", "usage", "error-context"] } +toml = { version = "1.0", default-features = false, features = ["parse", "display", "serde"] } +serde = { version = "1.0", default-features = false, features = ["derive", "std"] } zeroize = "1.7" log = "0.4" -env_logger = "0.11" -chrono = "0.4" +env_logger = { version = "0.11", default-features = false, features = ["color", "humantime"] } +chrono = { version = "0.4", default-features = false, features = ["clock", "std"] } users = "0.11" +zbus = { version = "3.15", default-features = false, features = ["tokio"] } +mpris = "2.0" +upower_dbus = "0.3" +tokio = { version = "1.0", default-features = false, features = ["rt", "rt-multi-thread", "macros", "time", "sync"] } +num-traits = { version = "0.2" } +rand = { version = "0.8" } +reqwest = { version = "0.11", default-features = false, features = ["blocking", "rustls-tls"], optional = true } +image = { version = "0.25", default-features = false, features = ["png", "jpeg"] } +fastblur = "0.1" +pam-client = "0.5" +thiserror = "1.0" +bytemuck = "1.14" +calloop = "0.13" +xkbcommon = "0.7" +calloop-wayland-source = "0.3" + +[features] +default = ["networking"] +networking = ["dep:reqwest", "tokio/net"] + +[profile.release] +opt-level = "z" # Optimize for size +lto = true # Enable Link Time Optimization +codegen-units = 1 # Reduce parallel code gen to allow better size optimization +panic = "abort" # Remove heavy stack unwinding code +strip = true # Automatically strip symbols and debug info diff --git a/README.md b/README.md index 141d4a4..1badfbc 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,6 @@ [![License](https://img.shields.io/badge/license-AGPL--3.0%2B-blue.svg)](https://github.com/yourusername/rustlock/blob/main/LICENSE) [![Version](https://img.shields.io/badge/version-0.1.0-green.svg)](https://github.com/yourusername/rustlock/releases) -[![Updated](https://img.shields.io/badge/updated-2026--03--07-blue.svg)](https://github.com/yourusername/rustlock/commits/main) A high-performance Wayland screen locker written in Rust, inspired by `swaylock-effects`. @@ -10,26 +9,40 @@ A high-performance Wayland screen locker written in Rust, inspired by `swaylock- ## ✨ Features -- ⚡ **Performance**: Written in safe Rust with minimal dependencies +- ⚡ **Performance**: Written in safe Rust, optimized binary size (~2.4MB without networking, ~4MB with) - 🎨 **Visual Effects**: - Gaussian blur (configurable radius and passes) - Vignette effect (configurable base and factor) + - Pixelate, Swirl, and Melting effects - Smooth fade-in animation - 🔐 **Password Indicator**: - Circular ring with configurable radius and thickness - Dynamic key highlight segments that rotate with each keystroke - - Customizable colors (ring, inside, separator, highlight) + - Caps lock indicator - 🕐 **Information Display**: - Centered clock (HH:MM format) - Full date - System uptime +- 📻 **Media & System Status** (optional): + - MPRIS media player integration with album art + - Battery percentage and charging status + - WiFi SSID and signal strength + - Bluetooth connected devices + - Keyboard layout indicator +- 🔑 **Session Management**: + - F1: Suspend + - F2: Reboot + - F3: Power Off - 📸 **Screenshot Support**: - Captures desktop background before locking - - Applies visual effects to background -- 🔑 **Authentication**: + - Custom background image support +- 🔐 **Authentication**: - PAM-based authentication - Configurable grace period (any key press within N seconds unlocks without password) -- 📝 **Logging**: Verbose debug logs written to `~/.rustlock.log` +- 🎯 **Customization**: + - Custom icons for WiFi, Bluetooth, Battery + - Theme presets (dark, light, nord, dracula) + - Configuration via config file or CLI --- @@ -61,67 +74,119 @@ rustlock \ --fade-in 0.2 ``` +### Session Controls + +When locked, use function keys to control the system: +- **F1**: Suspend to RAM +- **F2**: Reboot +- **F3**: Power Off + --- ## ⚙️ Configuration -Options can be provided via command line or a configuration file at `~/.config/rustlock/config.toml`. CLI arguments take precedence. +Options can be provided via command line or a configuration file at `~/.config/rustlock/config.toml`. CLI arguments take precedence over config file, which takes precedence over theme defaults. ### Options | Option | Description | |--------|-------------| +| **General** | | | `--screenshots` | Capture desktop background before locking | +| `--image ` | Use custom background image instead of screenshot | | `--clock` | Display centered clock and date | | `--indicator` | Show password entry ring (default: true) | | `--indicator-radius ` | Ring radius in pixels (default: 100) | | `--indicator-thickness ` | Ring thickness in pixels (default: 7) | +| **Effects** | | | `--effect-blur x

` | Gaussian blur: radius x passes (e.g., `7x5`) | +| `--effect-pixelate` | Pixelate effect | +| `--effect-swirl` | Swirl distortion effect | +| `--effect-melting` | Melting distortion effect | | `--effect-vignette :` | Vignette: base:factor (e.g., `0.5:0.5`) | +| **Colors** | | | `--ring-color ` | Outer ring color (hex, optional alpha) | | `--key-hl-color ` | Key highlight segment color | | `--line-color ` | Separator line color | | `--inside-color ` | Inner circle color | | `--separator-color ` | Ring separator color | +| **Display Options** | | +| `--show-media` | Show MPRIS media info (default: true) | +| `--show-battery` | Show battery status (default: true) | +| `--show-network` | Show WiFi status (default: true) | +| `--show-bluetooth` | Show Bluetooth status (default: true) | +| `--show-keyboard-layout` | Show keyboard layout indicator (default: true) | +| `--show-album-art` | Show album art (default: true) | +| **Custom Icons** | | +| `--wifi-icon ` | Custom WiFi icon (PNG/SVG) | +| `--bluetooth-icon ` | Custom Bluetooth icon (PNG/SVG) | +| `--battery-icon ` | Custom battery icon (PNG/SVG) | +| **Other** | | | `--grace ` | Grace period in seconds (default: 2) | | `--fade-in ` | Fade-in animation duration (default: 0.2) | | `--pam-service ` | PAM service name (default: "rustlock") | | `--config ` | Path to config file | +| `--theme ` | Theme preset: dark, light, nord, dracula | | `--debug` | Enable debug logging | | `--log-file` | Write logs to `~/.rustlock.log` | -| `--temp-screenshot` | Enable peek feature (press 'p' to temporarily show background) | --- ## 📦 Installation +### Using Nix (Recommended) + +```bash +nix-shell -p rustlock +``` + +Or with flakes: +```bash +nix run github:yourusername/rustlock +``` + +### From Source + ```bash cargo build --release ``` The binary will be available at `target/release/rustlock`. +### Build Options + +- **With networking** (default): Includes reqwest for album art fetching + ```bash + cargo build --release --features networking + ``` + +- **Without networking**: Smaller binary (~2.4MB) + ```bash + cargo build --release --no-default-features + ``` + --- ## ✅ Completed - [x] PAM-based authentication - [x] Grace period (any key unlocks within N seconds) -- [x] Screenshot capture with blur/vignette effects -- [x] Configuration file support (`~/.config/rustlock/config.toml`) +- [x] Screenshot capture with blur/vignette/pixelate/swirl/melting effects +- [x] Configuration file support (`~/.config/rustlock/config.toml`) with schema validation - [x] Debug logging to `~/.rustlock.log` - [x] Clock and date display - [x] Password indicator ring with rotating highlights - -## 🚧 TODO - -- [ ] Don't hardcode screen resolution (detect dynamically) -- [ ] Add multi-monitor support (handle multiple outputs) -- [ ] Automatically install PAM configuration file -- [ ] Configuration file schema validation -- [ ] Additional visual effects (pixelate, swirl, etc.) -- [ ] Theme/profile support with presets -- [ ] Wayland protocol stability updates +- [x] Dynamic screen resolution detection +- [x] Full multi-monitor support with different resolutions +- [x] Theme/profile support with presets (dark, light, nord, dracula) +- [x] Wayland protocol stability fixes +- [x] Media control integration (MPRIS support with Album Art) +- [x] Battery, WiFi, and Bluetooth status indicators +- [x] Custom background image support +- [x] Custom icons for status indicators +- [x] Keyboard layout indicator +- [x] Session management (F1-F3 keys) +- [x] Caps lock indicator --- diff --git a/default.nix b/default.nix index 8ed87cd..8df00a7 100644 --- a/default.nix +++ b/default.nix @@ -10,7 +10,10 @@ pkgs.rustPlatform.buildRustPackage { cairo pam gdk-pixbuf + librsvg + pango libxkbcommon + dbus ]; nativeBuildInputs = [ diff --git a/src/auth.rs b/src/auth.rs index d132ead..c1b951e 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -35,7 +35,7 @@ impl pam_client::ConversationHandler for LockConversation { } } -pub fn create_and_run_auth_loop() -> (channel::Sender>, channel::Channel) { +pub fn create_and_run_auth_loop() -> Option<(channel::Sender>, channel::Channel)> { let username = get_current_username() .expect("Failed to get username") .to_str() @@ -43,9 +43,16 @@ pub fn create_and_run_auth_loop() -> (channel::Sender>, channe .to_string(); let conversation = LockConversation { password: None }; - let _context = Context::new(SERVICE_NAME, Some(username.as_str()), conversation) - .expect("Failed to initialize PAM context"); - debug!("Prepared to authenticate user '{}'", username); + match Context::new(SERVICE_NAME, Some(username.as_str()), conversation) { + Ok(_) => { + debug!("Prepared to authenticate user '{}'", username); + } + Err(err) => { + error!("Failed to initialize PAM context: {:?}", err); + error!("Ensure that the PAM service '{}' is correctly configured.", SERVICE_NAME); + return None; + } + } let (auth_req_send, auth_req_recv) = channel::channel::>(); let (auth_res_send, auth_res_recv) = channel::channel::(); @@ -59,15 +66,20 @@ pub fn create_and_run_auth_loop() -> (channel::Sender>, channe let conversation = LockConversation { password: Some(password), }; - let mut context = - Context::new(SERVICE_NAME, Some(username.as_str()), conversation) - .expect("Failed to initialize PAM context"); - match context.authenticate(Flag::NONE) { - Ok(()) => { - auth_res_send.send(true).unwrap(); + match Context::new(SERVICE_NAME, Some(username.as_str()), conversation) { + Ok(mut context) => { + match context.authenticate(Flag::NONE) { + Ok(()) => { + auth_res_send.send(true).unwrap(); + } + Err(err) => { + error!("Pam authenticate failed with {:?}", err); + auth_res_send.send(false).unwrap(); + } + } } Err(err) => { - error!("Pam authenticate failed with {:?}", err); + error!("Failed to re-initialize PAM context: {:?}", err); auth_res_send.send(false).unwrap(); } } @@ -81,5 +93,5 @@ pub fn create_and_run_auth_loop() -> (channel::Sender>, channe } }); - (auth_req_send, auth_res_recv) + Some((auth_req_send, auth_res_recv)) } diff --git a/src/config.rs b/src/config.rs index 0a6d981..9cdb269 100644 --- a/src/config.rs +++ b/src/config.rs @@ -6,13 +6,13 @@ use std::path::PathBuf; #[derive(Parser, Debug, Clone, Serialize, Deserialize)] #[command(author, version, about, long_about = None)] pub struct Config { - #[arg(long)] + #[arg(long, action = clap::ArgAction::Set, num_args = 0..=1, default_value = "false", default_missing_value = "true")] pub screenshots: bool, - #[arg(long)] + #[arg(long, action = clap::ArgAction::Set, num_args = 0..=1, default_value = "false", default_missing_value = "true")] pub clock: bool, - #[arg(long, default_value = "true")] + #[arg(long, action = clap::ArgAction::Set, num_args = 0..=1, default_value = "true", default_missing_value = "true")] pub indicator: bool, #[arg(long, default_value = "100")] @@ -27,6 +27,15 @@ pub struct Config { #[arg(long, value_parser = util::parse_vignette_effect)] pub effect_vignette: Option<(f32, f32)>, + #[arg(long)] + pub effect_pixelate: Option, + + #[arg(long)] + pub effect_swirl: Option, + + #[arg(long)] + pub effect_melting: Option, + #[arg(long, default_value = "785412", value_parser = util::parse_hex_color)] pub ring_color: (f64, f64, f64, f64), @@ -61,17 +70,65 @@ pub struct Config { #[arg(long)] pub log_file: bool, - /// Show screen temporarily when a key is pressed (like swaylock-effects peek) + #[arg(long, action = clap::ArgAction::Set, num_args = 0..=1, default_value = "true", default_missing_value = "true")] + pub show_media: bool, + + #[arg(long, action = clap::ArgAction::Set, num_args = 0..=1, default_value = "true", default_missing_value = "true")] + pub show_battery: bool, + + #[arg(long, action = clap::ArgAction::Set, num_args = 0..=1, default_value = "true", default_missing_value = "true")] + pub show_network: bool, + + #[arg(long, action = clap::ArgAction::Set, num_args = 0..=1, default_value = "true", default_missing_value = "true")] + pub show_bluetooth: bool, + + #[arg(long, action = clap::ArgAction::Set, num_args = 0..=1, default_value = "true", default_missing_value = "true")] + pub show_album_art: bool, + #[arg(long)] - pub temp_screenshot: bool, + pub image: Option, + + #[arg(long)] + pub wifi_icon: Option, + + #[arg(long)] + pub bluetooth_icon: Option, + + #[arg(long)] + pub battery_icon: Option, + + #[arg(long)] + pub media_prev_icon: Option, + + #[arg(long)] + pub media_stop_icon: Option, + + #[arg(long)] + pub media_play_icon: Option, + + #[arg(long)] + pub media_next_icon: Option, + + /// Apply a pre-defined theme preset + #[arg(long)] + pub theme: Option, } impl Config { pub fn load() -> Self { - let cli_config = Config::parse(); + use clap::CommandFactory; + + let mut config = Config::parse(); + let cmd = Config::command(); + let matches = cmd.get_matches(); - // Use path from CLI if provided, otherwise default - let config_path = cli_config.config.clone().unwrap_or_else(|| { + // Helper to check if a value was explicitly set on command line + let is_cli = |key: &str| { + matches.value_source(key) == Some(clap::parser::ValueSource::CommandLine) + }; + + // 1. Config file layer (overrides defaults and themes) + let config_path = config.config.clone().unwrap_or_else(|| { let mut path = std::path::PathBuf::from(std::env::var("HOME").unwrap_or_default()); path.push(".config/rustlock/config.toml"); path @@ -79,12 +136,133 @@ impl Config { if config_path.exists() { if let Ok(file_content) = std::fs::read_to_string(&config_path) { - if let Ok(_file_config) = toml::from_str::(&file_content) { - return cli_config; + if let Ok(table) = toml::from_str::(&file_content) { + log::debug!("Loaded configuration from {:?}", config_path); + + let merge_bool = |val: &mut bool, key: &str| { + if !is_cli(key) { + if let Some(toml::Value::Boolean(b)) = table.get(key) { + *val = *b; + } + } + }; + + let merge_u32 = |val: &mut u32, key: &str| { + if !is_cli(key) { + if let Some(toml::Value::Integer(i)) = table.get(key) { + *val = *i as u32; + } + } + }; + + let merge_f32 = |val: &mut f32, key: &str| { + if !is_cli(key) { + if let Some(toml::Value::Float(f)) = table.get(key) { + *val = *f as f32; + } else if let Some(toml::Value::Integer(i)) = table.get(key) { + *val = *i as f32; + } + } + }; + + let merge_string = |val: &mut String, key: &str| { + if !is_cli(key) { + if let Some(toml::Value::String(s)) = table.get(key) { + *val = s.clone(); + } + } + }; + + merge_bool(&mut config.screenshots, "screenshots"); + merge_bool(&mut config.clock, "clock"); + merge_bool(&mut config.indicator, "indicator"); + merge_u32(&mut config.indicator_radius, "indicator_radius"); + merge_u32(&mut config.indicator_thickness, "indicator_thickness"); + merge_f32(&mut config.grace, "grace"); + merge_f32(&mut config.fade_in, "fade_in"); + merge_string(&mut config.pam_service, "pam_service"); + merge_bool(&mut config.show_media, "show_media"); + merge_bool(&mut config.show_battery, "show_battery"); + merge_bool(&mut config.show_network, "show_network"); + merge_bool(&mut config.show_bluetooth, "show_bluetooth"); + merge_bool(&mut config.show_album_art, "show_album_art"); + + if !is_cli("image") { + if let Some(toml::Value::String(s)) = table.get("image") { + config.image = Some(std::path::PathBuf::from(s)); + } + } + + if !is_cli("wifi_icon") { + if let Some(toml::Value::String(s)) = table.get("wifi_icon") { + config.wifi_icon = Some(s.clone()); + } + } + + if !is_cli("bluetooth_icon") { + if let Some(toml::Value::String(s)) = table.get("bluetooth_icon") { + config.bluetooth_icon = Some(s.clone()); + } + } + + if !is_cli("battery_icon") { + if let Some(toml::Value::String(s)) = table.get("battery_icon") { + config.battery_icon = Some(s.clone()); + } + } + + if !is_cli("media_prev_icon") { + if let Some(toml::Value::String(s)) = table.get("media_prev_icon") { + config.media_prev_icon = Some(s.clone()); + } + } + + if !is_cli("media_stop_icon") { + if let Some(toml::Value::String(s)) = table.get("media_stop_icon") { + config.media_stop_icon = Some(s.clone()); + } + } + + if !is_cli("media_play_icon") { + if let Some(toml::Value::String(s)) = table.get("media_play_icon") { + config.media_play_icon = Some(s.clone()); + } + } + + if !is_cli("media_next_icon") { + if let Some(toml::Value::String(s)) = table.get("media_next_icon") { + config.media_next_icon = Some(s.clone()); + } + } } } } - cli_config + // 2. Theme presets (applied to fields NOT set on CLI or in File) + if let Some(theme) = &config.theme { + match theme.as_str() { + "modern" => { + if config.effect_blur.is_none() && !is_cli("effect_blur") { config.effect_blur = Some((10, 3)); } + if config.effect_vignette.is_none() && !is_cli("effect_vignette") { config.effect_vignette = Some((0.5, 0.5)); } + if !is_cli("indicator_radius") { config.indicator_radius = 120; } + if !is_cli("ring_color") { config.ring_color = (0.2, 0.6, 0.8, 1.0); } + } + "pixel" => { + if config.effect_pixelate.is_none() && !is_cli("effect_pixelate") { config.effect_pixelate = Some(10); } + if !is_cli("indicator_radius") { config.indicator_radius = 80; } + if !is_cli("ring_color") { config.ring_color = (0.8, 0.2, 0.2, 1.0); } + } + "glass" => { + if config.effect_blur.is_none() && !is_cli("effect_blur") { config.effect_blur = Some((20, 5)); } + if !is_cli("inside_color") { config.inside_color = (1.0, 1.0, 1.0, 0.1); } + if !is_cli("ring_color") { config.ring_color = (1.0, 1.0, 1.0, 0.5); } + } + _ => { + log::warn!("Unknown theme: {}", theme); + } + } + } + + config } } diff --git a/src/input.rs b/src/input.rs index 584c292..859d8d7 100644 --- a/src/input.rs +++ b/src/input.rs @@ -4,24 +4,18 @@ use zeroize::Zeroizing; pub struct InputHandler { password_buffer: Zeroizing, cursor_position: usize, - config: crate::config::Config, wrong_password_timer: Option, key_highlight_timer: Option, - temp_screenshot_timer: Option, - temp_screenshot_active: bool, caps_lock: bool, } impl InputHandler { - pub fn new(config: crate::config::Config) -> Self { + pub fn new(_config: crate::config::Config) -> Self { Self { password_buffer: Zeroizing::new(String::new()), cursor_position: 0, - config, wrong_password_timer: None, key_highlight_timer: None, - temp_screenshot_timer: None, - temp_screenshot_active: false, caps_lock: false, } } @@ -30,117 +24,46 @@ impl InputHandler { pub fn handle_key_event( &mut self, keysym: smithay_client_toolkit::seat::keyboard::Keysym, - state: wayland_client::protocol::wl_keyboard::KeyState, + utf8: Option, modifiers: smithay_client_toolkit::seat::keyboard::Modifiers, ) -> InputAction { // Update Caps Lock state self.caps_lock = modifiers.caps_lock; - // Only process key press events - if state != wayland_client::protocol::wl_keyboard::KeyState::Pressed { - return InputAction::None; - } - - // Convert keysym to character - let ch = self.keysym_to_char(keysym, modifiers); - - match ch { - Some('\x08') | Some('\x7f') => { - // Backspace or Delete + // Handle special keys first using keysym + use smithay_client_toolkit::seat::keyboard::Keysym; + match keysym { + Keysym::BackSpace => { if !self.password_buffer.is_empty() && self.cursor_position > 0 { self.cursor_position -= 1; self.password_buffer.remove(self.cursor_position); } - InputAction::PasswordChanged + return InputAction::PasswordChanged; } - Some('\r') | Some('\n') => { - // Enter key - submit password + Keysym::Return | Keysym::KP_Enter => { let password = self.password_buffer.clone(); self.password_buffer.clear(); self.cursor_position = 0; - InputAction::SubmitPassword(password) + return InputAction::SubmitPassword(password); } - Some('\x1b') => { - // Escape key - cancel - InputAction::Cancel + Keysym::Escape => { + return InputAction::Cancel; } - Some('p') | Some('P') if self.config.temp_screenshot => { - // 'p' key for temp screenshot peek - self.activate_temp_screenshot(); - InputAction::TempScreenshot - } - Some(c) if c.is_ascii() && !c.is_control() => { - // Printable ASCII character - self.password_buffer.insert(self.cursor_position, c); - self.cursor_position += 1; - InputAction::PasswordChanged - } - _ => { - // Other keys (function keys, arrows, etc.) - InputAction::None - } - } - } - - /// Convert a keysym to a character, considering modifiers - fn keysym_to_char( - &self, - keysym: smithay_client_toolkit::seat::keyboard::Keysym, - modifiers: smithay_client_toolkit::seat::keyboard::Modifiers, - ) -> Option { - use smithay_client_toolkit::seat::keyboard::Keysym; - - // Handle special keys first - match keysym { - Keysym::BackSpace => return Some('\x08'), - Keysym::Delete => return Some('\x7f'), - Keysym::Return => return Some('\r'), - Keysym::KP_Enter => return Some('\n'), - Keysym::Escape => return Some('\x1b'), _ => {} } - // Convert keysym to character - let keysym_value = keysym.raw(); - - // Basic ASCII conversion (simplified - real implementation would use xkbcommon) - // This is a simplified mapping for demonstration - if keysym_value >= 0x20 && keysym_value <= 0x7e { - let mut ch = keysym_value as u8 as char; - - // Apply shift modifier - if modifiers.shift { - ch = match ch { - '`' => '~', - '1' => '!', - '2' => '@', - '3' => '#', - '4' => '$', - '5' => '%', - '6' => '^', - '7' => '&', - '8' => '*', - '9' => '(', - '0' => ')', - '-' => '_', - '=' => '+', - '[' => '{', - ']' => '}', - '\\' => '|', - ';' => ':', - '\'' => '"', - ',' => '<', - '.' => '>', - '/' => '?', - c if c.is_ascii_lowercase() => c.to_ascii_uppercase(), - _ => ch, - }; + // Use the UTF-8 string provided by SCTK for character input + if let Some(txt) = utf8 { + for c in txt.chars() { + if c.is_ascii() && !c.is_control() { + self.password_buffer.insert(self.cursor_position, c); + self.cursor_position += 1; + } } - - Some(ch) - } else { - None + return InputAction::PasswordChanged; } + + InputAction::None } /// Get the current password (for display purposes only - returns masked version) @@ -178,34 +101,6 @@ impl InputHandler { /// Update timers (should be called periodically) pub fn update(&mut self) { - // Update temp screenshot state - self.update_temp_screenshot(); - } - - /// Activate temporary screenshot display (peek feature) - pub fn activate_temp_screenshot(&mut self) { - self.temp_screenshot_timer = Some(std::time::Instant::now()); - self.temp_screenshot_active = true; - } - - /// Check if temporary screenshot should be shown - pub fn should_show_temp_screenshot(&self) -> bool { - if let Some(timer) = self.temp_screenshot_timer { - let elapsed = timer.elapsed(); - // Show for 2 seconds - if elapsed < std::time::Duration::from_secs(2) { - return true; - } - } - false - } - - /// Update temp screenshot state (call periodically) - pub fn update_temp_screenshot(&mut self) { - if self.temp_screenshot_active && !self.should_show_temp_screenshot() { - self.temp_screenshot_active = false; - self.temp_screenshot_timer = None; - } } } @@ -216,5 +111,4 @@ pub enum InputAction { PasswordChanged, SubmitPassword(Zeroizing), Cancel, - TempScreenshot, } diff --git a/src/lock.rs b/src/lock.rs index a117475..73a93e9 100644 --- a/src/lock.rs +++ b/src/lock.rs @@ -6,6 +6,7 @@ use wayland_client::protocol::{wl_output, wl_shm, wl_surface}; use crate::config::Config; use crate::input::{InputAction, InputHandler}; use crate::render::Renderer; +use crate::system::SystemStatus; use smithay_client_toolkit::seat::keyboard::KeyEvent; use smithay_client_toolkit::shm::slot::SlotPool; @@ -19,7 +20,6 @@ pub struct LockedSurface { fade_alpha: f64, wrong_password_shown: bool, key_highlight_shown: bool, - temp_screenshot_shown: bool, start_time: Instant, wayland_surface: Option, output: wl_output::WlOutput, @@ -50,7 +50,6 @@ impl LockedSurface { fade_alpha: 0.0, wrong_password_shown: false, key_highlight_shown: false, - temp_screenshot_shown: false, start_time: Instant::now(), wayland_surface: None, output, @@ -108,15 +107,6 @@ impl LockedSurface { self.key_highlight_shown = false; } - // Check if we should show/hide temp screenshot - if self.input_handler.should_show_temp_screenshot() && !self.temp_screenshot_shown { - self.renderer.set_fade_alpha(0.3); - self.temp_screenshot_shown = true; - } else if !self.input_handler.should_show_temp_screenshot() && self.temp_screenshot_shown { - self.renderer.set_fade_alpha(self.fade_alpha); - self.temp_screenshot_shown = false; - } - // Set background if available and not already applied if !self.background_applied { if let Some(ref background) = self.background { @@ -170,11 +160,12 @@ impl LockedSurface { pub fn handle_key_event( &mut self, event: smithay_client_toolkit::seat::keyboard::KeyEvent, + modifiers: smithay_client_toolkit::seat::keyboard::Modifiers, ) -> Option { let action = self.input_handler.handle_key_event( event.keysym, - wayland_client::protocol::wl_keyboard::KeyState::Pressed, - smithay_client_toolkit::seat::keyboard::Modifiers::default(), + event.utf8, + modifiers, ); match action { @@ -204,6 +195,10 @@ impl LockedSurface { self.background = Some(surface); self.background_applied = false; } + + pub fn set_system_status(&mut self, status: SystemStatus) { + self.renderer.system_status = status; + } } pub struct LockManager { @@ -252,19 +247,23 @@ impl LockManager { .find(|surface| surface.matches_surface(wayland_surface)) } - pub fn handle_key_event(&mut self, event: KeyEvent) -> Option { + pub fn handle_key_event( + &mut self, + event: KeyEvent, + modifiers: smithay_client_toolkit::seat::keyboard::Modifiers, + ) -> Option { let mut action = None; for surface in &mut self.surfaces { - if let Some(a) = surface.handle_key_event(event.clone()) { + if let Some(a) = surface.handle_key_event(event.clone(), modifiers) { action = Some(a); } } action } - pub fn toggle_peek(&mut self) { + pub fn set_system_status(&mut self, status: SystemStatus) { for surface in &mut self.surfaces { - surface.input_handler.update_temp_screenshot(); + surface.set_system_status(status.clone()); } } } diff --git a/src/main.rs b/src/main.rs index 968f244..a458bfa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,12 +4,14 @@ mod input; mod lock; mod render; mod screenshot; +mod system; mod timer; mod util; use config::Config; use lock::LockManager; use screenshot::{CaptureData, Screenshot, ScreenshotManager}; +use system::SystemManager; use std::error::Error; use std::fs::OpenOptions; use std::io::Write; @@ -125,6 +127,9 @@ struct WaylandLock { unlocking: bool, screenshot_manager: Option, grace_until: Option, + system_manager: Arc, + modifiers: Modifiers, + current_layout: u32, } impl WaylandLock { @@ -163,6 +168,41 @@ impl WaylandLock { } fn handle_key_event(&mut self, event: KeyEvent) { + use crate::input::InputAction; + use smithay_client_toolkit::seat::keyboard::Keysym; + + // Media and Session keys (Always handle these first and don't trigger grace unlock) + match event.keysym { + Keysym::XF86_AudioPlay | Keysym::XF86_AudioPause => { + self.system_manager.media_play_pause(); + return; + } + Keysym::XF86_AudioNext => { + self.system_manager.media_next(); + return; + } + Keysym::XF86_AudioPrev => { + self.system_manager.media_prev(); + return; + } + Keysym::F1 => { + self.system_manager + .send_command(system::SystemCommand::Suspend); + return; + } + Keysym::F2 => { + self.system_manager + .send_command(system::SystemCommand::Reboot); + return; + } + Keysym::F3 => { + self.system_manager + .send_command(system::SystemCommand::PowerOff); + return; + } + _ => {} + } + // Check if we're in the grace period (any key unlocks without password) if let Some(grace_until) = self.grace_until { if Instant::now() < grace_until { @@ -173,16 +213,14 @@ impl WaylandLock { } } - use crate::input::InputAction; - use smithay_client_toolkit::seat::keyboard::Keysym; - if event.keysym == Keysym::Return { log::info!("Enter pressed - submitting password"); if let Ok(mut lock_manager) = self.lock_manager.lock() { let mut password = Zeroizing::new(String::new()); + let modifiers = self.modifiers; for surface in &mut lock_manager.surfaces { if let Some(InputAction::SubmitPassword(p)) = - surface.handle_key_event(event.clone()) + surface.handle_key_event(event.clone(), modifiers) { password = p; } @@ -194,17 +232,12 @@ impl WaylandLock { } } } else { - let action = self + let modifiers = self.modifiers; + let _action = self .lock_manager .lock() - .map(|mut lm| lm.handle_key_event(event)) + .map(|mut lm| lm.handle_key_event(event, modifiers)) .unwrap_or(None); - - if let Some(InputAction::TempScreenshot) = action { - if let Ok(mut lm) = self.lock_manager.lock() { - lm.toggle_peek(); - } - } } } } @@ -372,9 +405,11 @@ impl KeyboardHandler for WaylandLock { _qh: &QueueHandle, _keyboard: &wayland_client::protocol::wl_keyboard::WlKeyboard, _serial: u32, - _modifiers: Modifiers, - _layout: u32, + modifiers: Modifiers, + layout: u32, ) { + self.modifiers = modifiers; + self.current_layout = layout; } } @@ -402,7 +437,9 @@ impl SeatHandler for WaylandLock { &seat, None, self.loop_handle.clone(), - Box::new(|_state, _kbd, _event| {}), + Box::new(|state, _kbd, event| { + state.handle_key_event(event); + }), ); } } @@ -453,6 +490,7 @@ impl Dispatch for WaylandLock { stride, } => { let format = format.into_result().unwrap(); + let mut info = data.info.lock().unwrap(); *info = Some(screenshot::BufferInfo { width, @@ -460,15 +498,22 @@ impl Dispatch for WaylandLock { stride, format, }); - match state - .pool - .create_buffer(width as i32, height as i32, stride as i32, format) - { - Ok((buffer, _canvas)) => { - frame.copy(buffer.wl_buffer()); - *data.buffer.lock().unwrap() = Some(buffer); + + // Create a dedicated pool for this screenshot to ensure offset 0 + // This matches swaylock-effects and fixes "invalid buffer" on some compositors + let size = (stride as usize) * (height as usize); + match SlotPool::new(size, &state.shm_state) { + Ok(mut pool) => { + match pool.create_buffer(width as i32, height as i32, stride as i32, format) { + Ok((buffer, _canvas)) => { + frame.copy(buffer.wl_buffer()); + *data.buffer.lock().unwrap() = Some(buffer); + *data.pool.lock().unwrap() = Some(pool); + } + Err(e) => log::error!("Screencopy: Buffer creation failed: {:?}", e), + } } - Err(e) => log::error!("Screencopy: Buffer creation failed: {:?}", e), + Err(e) => log::error!("Screencopy: Pool creation failed: {:?}", e), } } Event::Flags { flags } => { @@ -480,13 +525,15 @@ impl Dispatch for WaylandLock { let buffer = data.buffer.lock().unwrap().take(); let info = data.info.lock().unwrap().take(); let flags = data.flags.lock().unwrap().take(); - if let (Some(buffer), Some(info), Some(flags)) = (buffer, info, flags) { + let pool = data.pool.lock().unwrap().take(); + + if let (Some(buffer), Some(info), Some(flags), Some(mut pool)) = (buffer, info, flags, pool) { let handle = screenshot::ScreencopyBufferHandle { buffer, info, y_invert: flags.contains(Flags::YInvert), }; - if let Ok(surface) = mgr.buffer_to_surface(handle, &mut state.pool) { + if let Ok(surface) = mgr.buffer_to_surface(handle, &mut pool) { let mut ss = Screenshot::new(surface); let _ = ss.apply_effects(&state.config); if data.output_idx < state.captured_backgrounds.len() { @@ -547,11 +594,25 @@ fn main() -> Result<(), Box> { let qh: QueueHandle = event_queue.handle(); let shm_state = Shm::bind(&globals, &qh).map_err(|_| "wl_shm not supported")?; - let pool = SlotPool::new(1920 * 1080 * 4, &shm_state)?; - let (auth_tx_actual, auth_feedback_rx_actual) = auth::create_and_run_auth_loop(); + let system_manager = Arc::new(SystemManager::new()); + + let (auth_tx_actual, auth_feedback_rx_actual) = match auth::create_and_run_auth_loop() { + Some(channels) => channels, + None => { + log::error!("Failed to initialize authentication. This usually means PAM is not configured correctly."); + log::error!("Please ensure you have a PAM service file at /etc/pam.d/rustlock"); + std::process::exit(1); + } + }; let mut event_loop: EventLoop = EventLoop::try_new()?; + // Initialize state without pool first + // We'll create the pool after we know the output dimensions + + // Initialize pool with a minimal size, it will be resized once outputs are detected + let pool = SlotPool::new(1, &shm_state)?; + let mut state = WaylandLock { loop_handle: event_loop.handle(), lock_manager: lock_manager.clone(), @@ -563,7 +624,7 @@ fn main() -> Result<(), Box> { registry_state: RegistryState::new(&globals), session_lock_state: SessionLockState::new(&globals, &qh), seat_state: SeatState::new(&globals, &qh), - shm_state, + shm_state: shm_state, pool, session_lock: None, lock_surfaces: Vec::new(), @@ -575,10 +636,67 @@ fn main() -> Result<(), Box> { unlocking: false, screenshot_manager: ScreenshotManager::new(&globals, &qh).ok(), grace_until: None, + system_manager: system_manager.clone(), + modifiers: Modifiers::default(), + current_layout: 0, }; event_queue.blocking_dispatch(&mut state)?; + // Handle custom background image if provided (prioritize over screenshots) + if let Some(ref image_path) = state.config.image { + log::info!("Loading custom background image from {:?}", image_path); + if let Ok(img) = image::open(image_path) { + let img = img.to_rgba8(); + let (w, h) = img.dimensions(); + let mut surface = cairo::ImageSurface::create(cairo::Format::ARgb32, w as i32, h as i32).unwrap(); + { + let mut surface_data = surface.data().unwrap(); + for y in 0..h { + for x in 0..w { + let pixel = img.get_pixel(x, y); + let idx = ((y * w + x) * 4) as usize; + surface_data[idx] = pixel[2]; // B + surface_data[idx + 1] = pixel[1]; // G + surface_data[idx + 2] = pixel[0]; // R + surface_data[idx + 3] = pixel[3]; // A + } + } + } + + let mut ss = Screenshot::new(surface); + let _ = ss.apply_effects(&state.config); + let surface = ss.into_inner(); + + let num_outputs = state.output_state.outputs().count(); + state.captured_backgrounds = vec![Some(surface); num_outputs]; + + // Disable screenshots if image was successfully loaded + state.config.screenshots = false; + } else { + log::error!("Failed to load custom background image from {:?}", image_path); + } + } + + // Now that we have output info, we can resize the pool if needed + let mut total_size = 0; + for output in state.output_state.outputs() { + if let Some(info) = state.output_state.info(&output) { + if let Some(mode) = info.modes.first() { + let (w, h) = mode.dimensions; + total_size += (w as usize) * (h as usize) * 4; + } + } + } + if total_size > 0 { + // Resize pool to fit all outputs + // SlotPool doesn't have a direct resize, but we can just create a new one if needed, + // or rely on its internal growing if we use it that way. + // Actually SCTK SlotPool handles resizing when creating buffers if needed, + // but it's better to have a large enough base. + state.pool = SlotPool::new(total_size, &state.shm_state)?; + } + let _wayland_source = WaylandSource::new(conn.clone(), event_queue).insert(event_loop.handle())?; @@ -606,7 +724,11 @@ fn main() -> Result<(), Box> { return calloop::timer::TimeoutAction::ToDuration(Duration::from_millis(100)); } + let mut status = state.system_manager.get_status(); + status.keyboard_layout = Some(state.current_layout); + if let Ok(mut lm) = state.lock_manager.lock() { + lm.set_system_status(status); lm.update(); for surface in &mut lm.surfaces { let _ = surface.commit(&mut state.pool); @@ -619,6 +741,11 @@ fn main() -> Result<(), Box> { } })?; + // Dispatch to ensure outputs are ready before capture + if state.config.screenshots { + event_loop.dispatch(Duration::from_millis(50), &mut state)?; + } + if state.config.screenshots { state.outputs = state.output_state.outputs().collect(); log::info!( diff --git a/src/render.rs b/src/render.rs index 5a9f629..2db235a 100644 --- a/src/render.rs +++ b/src/render.rs @@ -2,6 +2,7 @@ use cairo::{Context, Format, ImageSurface}; use std::time::Instant; use crate::config::Config; +use crate::system::SystemStatus; /// Cairo-based renderer for the lock screen pub struct Renderer { @@ -21,6 +22,16 @@ pub struct Renderer { uptime_cache: String, last_uptime_update: Option, caps_lock: bool, + pub system_status: SystemStatus, + media_art_surface: Option, + last_art_url: Option, + wifi_icon_surface: Option, + bluetooth_icon_surface: Option, + battery_icon_surface: Option, + media_prev_icon_surface: Option, + media_stop_icon_surface: Option, + media_play_icon_surface: Option, + media_next_icon_surface: Option, } impl Renderer { @@ -31,10 +42,10 @@ impl Renderer { .expect("Failed to create Cairo surface"); let context = Context::new(&surface).expect("Failed to create Cairo context"); - Self { + let mut renderer = Self { width, height, - config, + config: config.clone(), surface, context, fade_alpha: 0.0, @@ -48,6 +59,85 @@ impl Renderer { uptime_cache: String::new(), last_uptime_update: None, caps_lock: false, + system_status: SystemStatus::default(), + media_art_surface: None, + last_art_url: None, + wifi_icon_surface: None, + bluetooth_icon_surface: None, + battery_icon_surface: None, + media_prev_icon_surface: None, + media_stop_icon_surface: None, + media_play_icon_surface: None, + media_next_icon_surface: None, + }; + + renderer.load_icons(); + renderer + } + + fn load_icons(&mut self) { + if let Some(ref path) = self.config.wifi_icon { + self.wifi_icon_surface = self.load_icon(path); + } + if let Some(ref path) = self.config.bluetooth_icon { + self.bluetooth_icon_surface = self.load_icon(path); + } + if let Some(ref path) = self.config.battery_icon { + self.battery_icon_surface = self.load_icon(path); + } + if let Some(ref path) = self.config.media_prev_icon { + self.media_prev_icon_surface = self.load_icon(path); + } + if let Some(ref path) = self.config.media_stop_icon { + self.media_stop_icon_surface = self.load_icon(path); + } + if let Some(ref path) = self.config.media_play_icon { + self.media_play_icon_surface = self.load_icon(path); + } + if let Some(ref path) = self.config.media_next_icon { + self.media_next_icon_surface = self.load_icon(path); + } + } + + fn load_icon(&self, identifier: &str) -> Option { + let path = if identifier.starts_with('/') { + std::path::PathBuf::from(identifier) + } else { + return None; + }; + + if let Ok(pixbuf) = gdk_pixbuf::Pixbuf::from_file(&path) { + let w = pixbuf.width(); + let h = pixbuf.height(); + let mut surface = ImageSurface::create(Format::ARgb32, w, h).ok()?; + { + let mut surface_data = surface.data().ok()?; + let pix_data = unsafe { pixbuf.pixels() }; + let n_channels = pixbuf.n_channels(); + let rowstride = pixbuf.rowstride() as usize; + + for y in 0..h as usize { + for x in 0..w as usize { + let pix_idx = y * rowstride + x * n_channels as usize; + let surf_idx = (y * w as usize + x) * 4; + + if n_channels == 4 { + surface_data[surf_idx] = pix_data[pix_idx + 2]; + surface_data[surf_idx + 1] = pix_data[pix_idx + 1]; + surface_data[surf_idx + 2] = pix_data[pix_idx]; + surface_data[surf_idx + 3] = pix_data[pix_idx + 3]; + } else if n_channels == 3 { + surface_data[surf_idx] = pix_data[pix_idx + 2]; + surface_data[surf_idx + 1] = pix_data[pix_idx + 1]; + surface_data[surf_idx + 2] = pix_data[pix_idx]; + surface_data[surf_idx + 3] = 255; + } + } + } + } + Some(surface) + } else { + None } } @@ -124,6 +214,22 @@ impl Renderer { self.draw_clock(); } + if self.config.show_media { + self.draw_media(); + } + + if self.config.show_network { + self.draw_network(); + } + + if self.config.show_battery { + self.draw_status(); + } + + if self.config.show_bluetooth { + self.draw_bluetooth(); + } + if !self.password_display.is_empty() { self.draw_password_display(); } @@ -368,4 +474,280 @@ impl Renderer { } } } + + fn draw_media(&mut self) { + if let Some(ref title) = self.system_status.media_title { + let center_x = self.width as f64 / 2.0; + let start_y = self.height as f64 - 120.0; + let art_size = 56.0; + let spacing = 80.0; + + if self.config.show_album_art { + if self.system_status.media_art_url != self.last_art_url { + self.last_art_url = self.system_status.media_art_url.clone(); + self.media_art_surface = None; + if let Some(ref data) = self.system_status.media_art_data { + if let Ok(img) = image::load_from_memory(data) { + let img = img.to_rgba8(); + let (w, h) = img.dimensions(); + let mut surface = ImageSurface::create(Format::ARgb32, w as i32, h as i32).unwrap(); + { + let mut surface_data = surface.data().unwrap(); + for y in 0..h { + for x in 0..w { + let pixel = img.get_pixel(x, y); + let idx = ((y * w + x) * 4) as usize; + surface_data[idx] = pixel[2]; + surface_data[idx + 1] = pixel[1]; + surface_data[idx + 2] = pixel[0]; + surface_data[idx + 3] = pixel[3]; + } + } + } + self.media_art_surface = Some(surface); + } + } + } + } + + let has_art = self.config.show_album_art && self.media_art_surface.is_some(); + let text_x = if has_art { center_x - spacing / 2.0 } else { center_x }; + let art_x = center_x - spacing - art_size / 2.0; + + if has_art { + if let Some(ref art) = self.media_art_surface { + self.context.save().unwrap(); + let scale = art_size / art.width() as f64; + self.context.translate(art_x, start_y); + self.context.scale(scale, scale); + self.context.set_source_surface(art, 0.0, 0.0).unwrap(); + self.context.paint_with_alpha(self.fade_alpha).unwrap(); + self.context.restore().unwrap(); + } + } + + self.context.new_path(); + self.context.set_source_rgba(1.0, 1.0, 1.0, self.fade_alpha * 0.9); + self.context.set_font_size(16.0); + + let display_text = if let Some(ref artist) = self.system_status.media_artist { + format!("{} - {}", artist, title) + } else { + title.clone() + }; + + let te = self.context.text_extents(&display_text).unwrap(); + self.context.move_to(text_x - te.width() / 2.0, start_y + 20.0); + self.context.show_text(&display_text).unwrap(); + + let status_text = if self.system_status.media_playing { + if let Some(ref icon) = self.media_play_icon_surface { + // Draw play icon instead of text + let play_y = start_y + 40.0; + self.draw_icon_at(center_x - icon.width() as f64 / 2.0, play_y - icon.height() as f64 / 2.0, icon); + "" + } else { + "▶ Playing" + } + } else { + "⏸ Paused" + }; + + if !status_text.is_empty() { + self.context.set_font_size(12.0); + let se = self.context.text_extents(status_text).unwrap(); + self.context.move_to(text_x - se.width() / 2.0, start_y + 40.0); + self.context.show_text(status_text).unwrap(); + } + + let controls_y = start_y + 65.0; + + // Draw media control icons + let icon_size = 20.0; + let icon_spacing = 40.0; + let controls_center_x = center_x; + + // Previous icon + if let Some(ref icon) = self.media_prev_icon_surface { + let ix = controls_center_x - icon_spacing; + self.draw_icon_at(ix - icon_size / 2.0, controls_y - icon_size / 2.0, icon); + } else { + self.context.set_source_rgba(1.0, 1.0, 1.0, self.fade_alpha * 0.7); + self.context.set_font_size(16.0); + self.context.move_to(controls_center_x - icon_spacing - 8.0, controls_y); + self.context.show_text("⏮").unwrap(); + } + + // Stop icon + if let Some(ref icon) = self.media_stop_icon_surface { + let ix = controls_center_x; + self.draw_icon_at(ix - icon_size / 2.0, controls_y - icon_size / 2.0, icon); + } else { + self.context.set_source_rgba(1.0, 1.0, 1.0, self.fade_alpha * 0.7); + self.context.set_font_size(16.0); + self.context.move_to(controls_center_x - 8.0, controls_y); + self.context.show_text("⏹").unwrap(); + } + + // Next icon + if let Some(ref icon) = self.media_next_icon_surface { + let ix = controls_center_x + icon_spacing; + self.draw_icon_at(ix - icon_size / 2.0, controls_y - icon_size / 2.0, icon); + } else { + self.context.set_source_rgba(1.0, 1.0, 1.0, self.fade_alpha * 0.7); + self.context.set_font_size(16.0); + self.context.move_to(controls_center_x + icon_spacing - 8.0, controls_y); + self.context.show_text("⏭").unwrap(); + } + } + } + + fn draw_network(&self) { + if !self.config.show_network { + return; + } + let margin = 20.0; + let x = margin; + let y = margin + 20.0; + + if let Some(ref ssid) = self.system_status.wifi_ssid { + if let Some(ref icon) = self.wifi_icon_surface { + self.draw_icon_at(x, y - 15.0, icon); + let text_x = x + icon.width() as f64 + 10.0; + self.context.new_path(); + self.context.set_source_rgba(1.0, 1.0, 1.0, self.fade_alpha); + self.context.set_font_size(16.0); + self.context.move_to(text_x, y); + self.context.show_text(ssid).unwrap(); + } else { + let strength = self.system_status.wifi_strength.unwrap_or(0); + let icon = if strength > 75 { "📶" } else if strength > 50 { "📶" } else if strength > 25 { "📶" } else { "📶" }; + let text = format!("{} {}", icon, ssid); + self.context.new_path(); + self.context.set_source_rgba(1.0, 1.0, 1.0, self.fade_alpha); + self.context.set_font_size(16.0); + self.context.move_to(x, y); + self.context.show_text(&text).unwrap(); + } + } else { + let text = "📵 No WiFi"; + self.context.new_path(); + self.context.set_source_rgba(1.0, 1.0, 1.0, self.fade_alpha * 0.5); + self.context.set_font_size(16.0); + self.context.move_to(x, y); + self.context.show_text(text).unwrap(); + } + } + + fn draw_status(&self) { + if let Some(percent) = self.system_status.battery_percent { + let margin = 20.0; + let icon_width = 30.0; + let x = self.width as f64 - margin - icon_width - 50.0; + let y = margin + 20.0; + + if let Some(ref icon) = self.battery_icon_surface { + self.draw_icon_at(x, y - 15.0, icon); + let text_x = x + icon.width() as f64 + 10.0; + let battery_text = format!("{:.0}%", percent); + self.context.new_path(); + self.context.set_source_rgba(1.0, 1.0, 1.0, self.fade_alpha); + self.context.set_font_size(16.0); + self.context.move_to(text_x, y); + self.context.show_text(&battery_text).unwrap(); + } else { + self.draw_battery_icon_at(x, y - 12.0, icon_width, 15.0, percent, self.system_status.is_charging); + let battery_text = format!("{:.0}%", percent); + self.context.new_path(); + self.context.set_source_rgba(1.0, 1.0, 1.0, self.fade_alpha); + self.context.set_font_size(16.0); + self.context.move_to(x + icon_width + 10.0, y); + self.context.show_text(&battery_text).unwrap(); + } + } + } + + fn draw_bluetooth(&self) { + if !self.config.show_bluetooth { + return; + } + let margin = 20.0; + let x = margin; + let y = margin + 50.0; + + if self.system_status.bluetooth_connected { + if let Some(ref icon) = self.bluetooth_icon_surface { + self.draw_icon_at(x, y - 12.0, icon); + let text_x = x + icon.width() as f64 + 10.0; + let devices = self.system_status.bluetooth_devices.join(", "); + self.context.new_path(); + self.context.set_source_rgba(1.0, 1.0, 1.0, self.fade_alpha); + self.context.set_font_size(14.0); + self.context.move_to(text_x, y); + self.context.show_text(&devices).unwrap(); + } else { + let text = format!("🔵 {} device(s)", self.system_status.bluetooth_devices.len()); + self.context.new_path(); + self.context.set_source_rgba(1.0, 1.0, 1.0, self.fade_alpha); + self.context.set_font_size(14.0); + self.context.move_to(x, y); + self.context.show_text(&text).unwrap(); + } + } else { + let text = "🔴 Bluetooth off"; + self.context.new_path(); + self.context.set_source_rgba(1.0, 1.0, 1.0, self.fade_alpha * 0.5); + self.context.set_font_size(14.0); + self.context.move_to(x, y); + self.context.show_text(text).unwrap(); + } + } + + fn draw_icon_at(&self, x: f64, y: f64, surface: &ImageSurface) { + self.context.save().unwrap(); + let target_size = 24.0; + let scale_x = target_size / surface.width() as f64; + let scale_y = target_size / surface.height() as f64; + let scale = scale_x.min(scale_y); + self.context.translate(x, y); + self.context.scale(scale, scale); + self.context.set_source_surface(surface, 0.0, 0.0).unwrap(); + self.context.paint_with_alpha(self.fade_alpha).unwrap(); + self.context.restore().unwrap(); + } + + fn draw_battery_icon_at(&self, x: f64, y: f64, width: f64, height: f64, percent: f64, charging: bool) { + let alpha = self.fade_alpha; + self.context.new_path(); + self.context.set_source_rgba(1.0, 1.0, 1.0, alpha * 0.5); + self.context.set_line_width(2.0); + self.context.rectangle(x, y, width, height); + self.context.stroke().unwrap(); + self.context.new_path(); + self.context.rectangle(x + width, y + height / 4.0, 3.0, height / 2.0); + self.context.fill().unwrap(); + let fill_width = (width - 4.0) * (percent / 100.0); + self.context.new_path(); + if percent < 20.0 { + self.context.set_source_rgba(1.0, 0.2, 0.2, alpha); + } else { + self.context.set_source_rgba(0.2, 1.0, 0.2, alpha * 0.8); + } + self.context.rectangle(x + 2.0, y + 2.0, fill_width, height - 4.0); + self.context.fill().unwrap(); + if charging { + self.context.new_path(); + self.context.set_source_rgba(1.0, 1.0, 0.0, alpha); + let bx = x + width / 2.0; + let by = y + height / 2.0; + self.context.move_to(bx - 3.0, by + 2.0); + self.context.line_to(bx + 1.0, by - 1.0); + self.context.line_to(bx - 1.0, by - 1.0); + self.context.line_to(bx + 3.0, by - 6.0); + self.context.line_to(bx - 1.0, by - 3.0); + self.context.line_to(bx + 1.0, by - 3.0); + self.context.close_path(); + self.context.fill().unwrap(); + } + } } diff --git a/src/screenshot.rs b/src/screenshot.rs index 6f23d72..4dd7d80 100644 --- a/src/screenshot.rs +++ b/src/screenshot.rs @@ -41,9 +41,161 @@ impl Screenshot { if let Some((base, factor)) = config.effect_vignette { self.apply_vignette(base, factor); } + if let Some(pixel_size) = config.effect_pixelate { + self.apply_pixelate(pixel_size); + } + if let Some(angle) = config.effect_swirl { + self.apply_swirl(angle); + } + if let Some(factor) = config.effect_melting { + self.apply_melting(factor); + } Ok(()) } + /// Apply a swirl effect. + pub fn apply_swirl(&mut self, angle: f32) { + let width = self.surface.width(); + let height = self.surface.height(); + let center_x = width as f32 / 2.0; + let center_y = height as f32 / 2.0; + let radius = center_x.min(center_y); + + let stride = self.surface.stride() as usize; + let mut data = vec![0u8; stride * height as usize]; + self.surface + .with_data(|src| data.copy_from_slice(src)) + .unwrap(); + let original = data.clone(); + + for y in 0..height { + for x in 0..width { + let dx = x as f32 - center_x; + let dy = y as f32 - center_y; + let d = (dx * dx + dy * dy).sqrt(); + + if d < radius { + let percent = (radius - d) / radius; + let theta = percent * percent * angle; + let s = theta.sin(); + let c = theta.cos(); + + let nx = (c * dx - s * dy + center_x) as i32; + let ny = (s * dx + c * dy + center_y) as i32; + + if nx >= 0 && nx < width && ny >= 0 && ny < height { + let src_idx = (ny as usize * stride) + (nx as usize * 4); + let dst_idx = (y as usize * stride) + (x as usize * 4); + data[dst_idx..dst_idx + 4].copy_from_slice(&original[src_idx..src_idx + 4]); + } + } + } + } + + let mut surface_data = self.surface.data().unwrap(); + surface_data.copy_from_slice(&data); + } + + /// Apply a melting effect (vertical smear). + pub fn apply_melting(&mut self, factor: f32) { + let width = self.surface.width(); + let height = self.surface.height(); + + let stride = self.surface.stride() as usize; + let mut data = vec![0u8; stride * height as usize]; + self.surface + .with_data(|src| data.copy_from_slice(src)) + .unwrap(); + + use rand::Rng; + let mut rng = rand::thread_rng(); + + for x in 0..width { + let mut melt_amount = 0.0; + for y in 0..height { + melt_amount += rng.gen_range(0.0..factor); + let src_y = (y as f32 - melt_amount).max(0.0) as i32; + + let src_idx = (src_y as usize * stride) + (x as usize * 4); + let dst_idx = (y as usize * stride) + (x as usize * 4); + + // Copy the pixel from above to create a smear + let pixel = [ + data[src_idx], + data[src_idx + 1], + data[src_idx + 2], + data[src_idx + 3], + ]; + data[dst_idx..dst_idx + 4].copy_from_slice(&pixel); + } + } + + let mut surface_data = self.surface.data().unwrap(); + surface_data.copy_from_slice(&data); + } + + /// Pixelate the surface. + pub fn apply_pixelate(&mut self, pixel_size: u32) { + if pixel_size <= 1 { + return; + } + + let width = self.surface.width(); + let height = self.surface.height(); + let stride = self.surface.stride() as usize; + let mut data = vec![0u8; stride * height as usize]; + self.surface + .with_data(|src| data.copy_from_slice(src)) + .unwrap(); + + for y in (0..height).step_by(pixel_size as usize) { + for x in (0..width).step_by(pixel_size as usize) { + let mut r = 0u32; + let mut g = 0u32; + let mut b = 0u32; + let mut count = 0u32; + + // Average pixels in the block + for py in 0..pixel_size { + for px in 0..pixel_size { + let cur_x = x + px as i32; + let cur_y = y + py as i32; + if cur_x < width && cur_y < height { + let index = (cur_y as usize * stride) + (cur_x as usize * 4); + r += data[index] as u32; + g += data[index + 1] as u32; + b += data[index + 2] as u32; + count += 1; + } + } + } + + if count > 0 { + let r = (r / count) as u8; + let g = (g / count) as u8; + let b = (b / count) as u8; + + // Fill the block + for py in 0..pixel_size { + for px in 0..pixel_size { + let cur_x = x + px as i32; + let cur_y = y + py as i32; + if cur_x < width && cur_y < height { + let index = (cur_y as usize * stride) + (cur_x as usize * 4); + data[index] = r; + data[index + 1] = g; + data[index + 2] = b; + } + } + } + } + } + } + + let mut surface_data = self.surface.data().unwrap(); + surface_data.copy_from_slice(&data); + } + /// Apply a Gaussian blur effect. pub fn apply_blur(&mut self, radius: u32, times: u32) -> Result<()> { if radius == 0 || times == 0 { @@ -304,6 +456,7 @@ pub struct CaptureData { pub info: Mutex>, pub flags: Mutex>, pub buffer: Mutex>, + pub pool: Mutex>, } impl CaptureData { @@ -314,6 +467,7 @@ impl CaptureData { info: Mutex::new(None), flags: Mutex::new(None), buffer: Mutex::new(None), + pool: Mutex::new(None), } } } diff --git a/src/system.rs b/src/system.rs new file mode 100644 index 0000000..8ce0661 --- /dev/null +++ b/src/system.rs @@ -0,0 +1,277 @@ +use std::sync::{Arc, Mutex}; +use mpris::PlayerFinder; +use zbus::Connection; +use log::{error, debug}; +use tokio::sync::mpsc; + +#[derive(Clone, Default)] +pub struct SystemStatus { + pub battery_percent: Option, + pub is_charging: bool, + pub media_title: Option, + pub media_artist: Option, + pub media_playing: bool, + pub media_art_url: Option, + pub media_art_data: Option>>, + pub wifi_ssid: Option, + pub wifi_strength: Option, + pub bluetooth_connected: bool, + pub bluetooth_devices: Vec, + pub keyboard_layout: Option, +} + +#[derive(Debug, Clone, Copy)] +pub enum SystemCommand { + PowerOff, + Reboot, + Suspend, +} + +pub struct SystemManager { + status: Arc>, + cmd_tx: mpsc::UnboundedSender, +} + +impl SystemManager { + pub fn new() -> Self { + let status = Arc::new(Mutex::new(SystemStatus::default())); + let s_clone = status.clone(); + let (cmd_tx, mut cmd_rx) = mpsc::unbounded_channel::(); + + // Spawn a thread to update status periodically and handle commands + std::thread::spawn(move || { + let rt = match tokio::runtime::Runtime::new() { + Ok(rt) => rt, + Err(e) => { + error!("Failed to create tokio runtime for SystemManager: {}", e); + return; + } + }; + + rt.block_on(async { + let mut conn: Option = None; + let mut interval = tokio::time::interval(tokio::time::Duration::from_secs(2)); + let mut last_art_url: Option = None; + let mut last_art_data: Option>> = None; + + loop { + // Try to connect to system DBus if not connected + if conn.is_none() { + match Connection::system().await { + Ok(c) => conn = Some(c), + Err(e) => { + error!("Failed to connect to system DBus: {}", e); + tokio::time::sleep(tokio::time::Duration::from_secs(5)).await; + } + } + } + + tokio::select! { + _ = interval.tick() => { + let mut new_status = SystemStatus::default(); + + if let Some(ref c) = conn { + // 1. Battery status + if let Ok(proxy) = upower_dbus::UPowerProxy::new(c).await { + if let Ok(display_device) = proxy.get_display_device().await { + new_status.battery_percent = display_device.percentage().await.ok(); + if let Ok(state) = display_device.state().await { + new_status.is_charging = format!("{:?}", state).contains("Charging"); + } + } + } + } + + // 2. MPRIS status + if let Ok(finder) = PlayerFinder::new() { + if let Ok(player) = finder.find_active() { + if let Ok(metadata) = player.get_metadata() { + new_status.media_title = metadata.title().map(|s| s.to_string()); + new_status.media_artist = metadata.artists().map(|a| a.join(", ")); + new_status.media_art_url = metadata.art_url().map(|u| u.to_string()); + + if new_status.media_art_url != last_art_url { + last_art_url = new_status.media_art_url.clone(); + last_art_data = None; + if let Some(ref url) = last_art_url { + if url.starts_with("file://") { + let path = url.trim_start_matches("file://"); + if let Ok(data) = std::fs::read(path) { + last_art_data = Some(Arc::new(data)); + } + } else if url.starts_with("http") { + #[cfg(feature = "networking")] + if let Ok(resp) = reqwest::get(url).await { + if let Ok(bytes) = resp.bytes().await { + last_art_data = Some(Arc::new(bytes.to_vec())); + } + } + #[cfg(not(feature = "networking"))] + { + log::debug!("Networking disabled, skipping remote album art: {}", url); + } + } + } + } + new_status.media_art_data = last_art_data.clone(); + } + new_status.media_playing = player.get_playback_status().map(|s| matches!(s, mpris::PlaybackStatus::Playing)).unwrap_or(false); + } + } + + // 3. WiFi status (NetworkManager) + if let Some(ref c) = conn { + if let Ok(reply) = c.call_method( + Some("org.freedesktop.NetworkManager"), + "/org/freedesktop/NetworkManager", + Some("org.freedesktop.NetworkManager"), + "GetDevices", + &(), + ).await { + let devices: Vec = reply.body().unwrap(); + for dev_path in devices { + if let Ok(dev_type_reply) = c.call_method( + Some("org.freedesktop.NetworkManager"), + &dev_path, + Some("org.freedesktop.DBus.Properties"), + "Get", + &("org.freedesktop.NetworkManager.Device", "DeviceType"), + ).await { + let dev_type: u32 = dev_type_reply.body::().unwrap().downcast().unwrap(); + if dev_type == 2 { // WiFi + if let Ok(active_ap_reply) = c.call_method( + Some("org.freedesktop.NetworkManager"), + &dev_path, + Some("org.freedesktop.DBus.Properties"), + "Get", + &("org.freedesktop.NetworkManager.Device.Wireless", "ActiveAccessPoint"), + ).await { + let ap_path: zbus::zvariant::OwnedObjectPath = active_ap_reply.body::().unwrap().downcast().unwrap(); + if ap_path.as_str() != "/" { + if let Ok(ssid_reply) = c.call_method( + Some("org.freedesktop.NetworkManager"), + &ap_path, + Some("org.freedesktop.DBus.Properties"), + "Get", + &("org.freedesktop.NetworkManager.AccessPoint", "Ssid"), + ).await { + let ssid_bytes: Vec = ssid_reply.body::().unwrap().downcast().unwrap(); + new_status.wifi_ssid = Some(String::from_utf8_lossy(&ssid_bytes).to_string()); + } + if let Ok(strength_reply) = c.call_method( + Some("org.freedesktop.NetworkManager"), + &ap_path, + Some("org.freedesktop.DBus.Properties"), + "Get", + &("org.freedesktop.NetworkManager.AccessPoint", "Strength"), + ).await { + new_status.wifi_strength = Some(strength_reply.body::().unwrap().downcast().unwrap()); + } + } + } + break; + } + } + } + } + + // 4. Bluetooth status (BlueZ) + if let Ok(objects_reply) = c.call_method( + Some("org.bluez"), + "/", + Some("org.freedesktop.DBus.ObjectManager"), + "GetManagedObjects", + &(), + ).await { + use std::collections::HashMap; + type ManagedObjects = HashMap>>; + if let Ok(objects) = objects_reply.body::() { + for (_path, interfaces) in objects { + if let Some(device) = interfaces.get("org.bluez.Device1") { + if let Some(connected) = device.get("Connected") { + if connected.downcast_ref::().copied().unwrap_or(false) { + new_status.bluetooth_connected = true; + if let Some(name) = device.get("Name") { + let name_str: String = name.downcast_ref::().map(|s| s.to_string()).unwrap_or_default(); + new_status.bluetooth_devices.push(name_str); + } + } + } + } + } + } + } + } + + { + if let Ok(mut s) = s_clone.lock() { + *s = new_status; + } + } + } + Some(command) = cmd_rx.recv() => { + if let Some(ref c) = conn { + let method = match command { + SystemCommand::PowerOff => "PowerOff", + SystemCommand::Reboot => "Reboot", + SystemCommand::Suspend => "Suspend", + }; + + debug!("Executing system command: {}", method); + // Set a timeout for the DBus call to prevent hanging the background thread + let result = tokio::time::timeout( + tokio::time::Duration::from_secs(5), + c.call_method( + Some("org.freedesktop.login1"), + "/org/freedesktop/login1", + Some("org.freedesktop.login1.Manager"), + method, + &(true), + ) + ).await; + + if let Err(_) = result { + error!("System command {} timed out", method); + } + } + } + } + } + }); + }); + + Self { status, cmd_tx } + } + + pub fn get_status(&self) -> SystemStatus { + self.status.lock().unwrap().clone() + } + + pub fn send_command(&self, cmd: SystemCommand) { + let _ = self.cmd_tx.send(cmd); + } + + pub fn media_play_pause(&self) { + if let Ok(finder) = PlayerFinder::new() { + if let Ok(player) = finder.find_active() { + let _ = player.play_pause(); + } + } + } + + pub fn media_next(&self) { + if let Ok(finder) = PlayerFinder::new() { + if let Ok(player) = finder.find_active() { + let _ = player.next(); + } + } + } + + pub fn media_prev(&self) { + if let Ok(finder) = PlayerFinder::new() { + if let Ok(player) = finder.find_active() { + let _ = player.previous(); + } + } + } +} diff --git a/src/timer.rs b/src/timer.rs deleted file mode 100644 index 8b13789..0000000 --- a/src/timer.rs +++ /dev/null @@ -1 +0,0 @@ -