diff --git a/.github/workflows/appimage.yml b/.github/workflows/appimage.yml index aa77aac..4a1f071 100644 --- a/.github/workflows/appimage.yml +++ b/.github/workflows/appimage.yml @@ -36,8 +36,7 @@ jobs: run: | sudo apt-get -o Acquire::Retries=3 update sudo apt-get -o Acquire::Retries=3 install -y --no-install-recommends \ - libgtk-3-dev libglib2.0-dev libxdo-dev libpipewire-0.3-dev \ - pkg-config imagemagick file + libpipewire-0.3-dev libwayland-dev pkg-config imagemagick file - name: Cache cargo registry and build uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 diff --git a/.github/workflows/aur.yml b/.github/workflows/aur.yml index d689482..9891171 100644 --- a/.github/workflows/aur.yml +++ b/.github/workflows/aur.yml @@ -34,7 +34,9 @@ jobs: fail-fast: false matrix: # honkhonk: source build. honkhonk-bin: .deb re-extract. - # honkhonk-git: VCS build from main. + # honkhonk-git: VCS build from main. PR validation rewrites it to the + # candidate head commit below so dependency removals are tested against + # the code that will become main. pkg: [honkhonk, honkhonk-bin, honkhonk-git] steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 @@ -59,6 +61,17 @@ jobs: sudo -u builder makepkg --printsrcinfo > /tmp/.SRCINFO.fresh diff -u .SRCINFO /tmp/.SRCINFO.fresh + - name: Point VCS package at PR head + if: github.event_name == 'pull_request' && matrix.pkg == 'honkhonk-git' + working-directory: packaging/aur/${{ matrix.pkg }} + env: + PR_REPO: ${{ github.event.pull_request.head.repo.full_name }} + PR_HEAD: ${{ github.event.pull_request.head.sha }} + run: | + sed -i \ + "s|^source=.*|source=(\"git+https://github.com/${PR_REPO}.git#commit=${PR_HEAD}\")|" \ + PKGBUILD + - name: Wait for release artifacts (tag push only) if: startsWith(github.ref, 'refs/tags/') && matrix.pkg != 'honkhonk-git' working-directory: packaging/aur/${{ matrix.pkg }} diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 3b64a38..0826aa5 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -29,7 +29,7 @@ jobs: run: | sudo apt-get -o Acquire::Retries=3 update sudo apt-get -o Acquire::Retries=3 install -y --no-install-recommends \ - libgtk-3-dev libglib2.0-dev libxdo-dev libpipewire-0.3-dev pkg-config + libpipewire-0.3-dev libwayland-dev pkg-config - name: Autobuild uses: github/codeql-action/autobuild@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5 diff --git a/.github/workflows/deb.yml b/.github/workflows/deb.yml index 33be5ea..ec70943 100644 --- a/.github/workflows/deb.yml +++ b/.github/workflows/deb.yml @@ -27,8 +27,7 @@ jobs: run: | sudo apt-get -o Acquire::Retries=3 update sudo apt-get -o Acquire::Retries=3 install -y --no-install-recommends \ - libgtk-3-dev libglib2.0-dev libxdo-dev libpipewire-0.3-dev \ - pkg-config lintian imagemagick + libpipewire-0.3-dev libwayland-dev pkg-config lintian imagemagick - name: Cache cargo registry and build uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 8975548..2279596 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -30,7 +30,7 @@ jobs: run: | sudo apt-get -o Acquire::Retries=3 update sudo apt-get -o Acquire::Retries=3 install -y --no-install-recommends \ - libgtk-3-dev libglib2.0-dev libxdo-dev libpipewire-0.3-dev pkg-config + libpipewire-0.3-dev libwayland-dev pkg-config - name: Cache cargo registry and build uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 @@ -87,7 +87,7 @@ jobs: run: | sudo apt-get -o Acquire::Retries=3 update sudo apt-get -o Acquire::Retries=3 install -y --no-install-recommends \ - libgtk-3-dev libglib2.0-dev libxdo-dev libpipewire-0.3-dev pkg-config + libpipewire-0.3-dev libwayland-dev pkg-config - name: Cache cargo registry and build uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 @@ -112,7 +112,7 @@ jobs: run: | sudo apt-get -o Acquire::Retries=3 update sudo apt-get -o Acquire::Retries=3 install -y --no-install-recommends \ - libgtk-3-dev libglib2.0-dev libxdo-dev libpipewire-0.3-dev pkg-config + libpipewire-0.3-dev libwayland-dev pkg-config - name: Cache cargo registry and build uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 diff --git a/AGENTS.md b/AGENTS.md index c68b71d..20760e4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -19,7 +19,7 @@ Wayland-native Linux soundboard. Pure Rust — Iced 0.14 GUI (Elm/MVU) + PipeWir - Iced 0.14 GUI (Elm/MVU); no other frontend framework — UI is `Element` functions. - PipeWire via pipewire-rs: one persistent virtual sink, no per-sound node churn. - Global shortcuts via ashpd (xdg-desktop-portal GlobalShortcuts v2) — Phase 2. -- Tray via tray-icon (StatusNotifierItem; cross-DE). Audio decode via symphonia (pure Rust). +- Tray via ksni (StatusNotifierItem over zbus; cross-DE). Audio decode via symphonia (pure Rust). - Renderer: wgpu default, tiny-skia software fallback (`HONKHONK_RENDERER=software`). - **Wayland-native only — no X11. PipeWire only — no direct PulseAudio.** @@ -63,8 +63,7 @@ specific APIs. One binary must work on KDE, GNOME, Hyprland, Sway: `org.freedesktop.portal.FileChooser` · Notifications `org.freedesktop.portal.Notification` · Autostart `org.freedesktop.portal.Background`. -Tray uses StatusNotifierItem (SNI) via tray-icon — no XEmbed. The `libayatana-appindicator` -deprecation warning on stderr is upstream and harmless — ignore it. +Tray uses StatusNotifierItem (SNI) via ksni — no XEmbed, no GTK/appindicator tray stack. ## Packaging / XDG diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 90ed8d9..de77f74 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -168,7 +168,7 @@ The complete HTML/JSX mockup lives in the design handoff bundle (exported from c | Renderer | **wgpu** (default) / **tiny-skia** (fallback) | GPU-accelerated by default, software renderer via env var for edge cases | | PipeWire | **pipewire-rs 0.8** | Official Rust bindings from PipeWire project. Production-proven | | Global Shortcuts | **ashpd 0.13** (`global_shortcuts` feature) | Full xdg-desktop-portal GlobalShortcuts API. Async/tokio | -| System Tray | **tray-icon 0.19** + **muda 0.15** | Actively maintained (Tauri team), standalone SNI, cross-DE | +| System Tray | **ksni 0.3** | Pure-Rust StatusNotifierItem over zbus, cross-DE | | Audio Decode | **symphonia 0.5** | Pure Rust. MP3, WAV, OGG, FLAC, AAC. No C dependencies | | Audio Playback | **pipewire-rs** streams | Direct PipeWire playback — no rodio/ALSA intermediary | @@ -225,8 +225,8 @@ Wayland sessions require GPU drivers (compositor needs them), so wgpu works on a │ Channels (no IPC serialization) ▼ ┌─────────────────────────────┐ ┌────────────────────┐ -│ AudioEngine (PipeWire │ │ tray-icon │ -│ thread) │ │ (main thread, │ +│ AudioEngine (PipeWire │ │ ksni tray service │ +│ thread) │ │ (D-Bus thread, │ │ - virtual sink │ │ channel → sub) │ │ - mic passthrough │ └────────────────────┘ │ - playback streams │ @@ -245,11 +245,12 @@ No IPC serialization. Direct Rust channel communication: 1. **UI → Audio (Commands):** Iced `Command::perform` sends `AudioCommand` via `tokio::sync::mpsc` to PipeWire thread. 2. **Audio → UI (Events):** PipeWire thread sends `AudioEvent` via channel. Iced `Subscription` polls receiver each frame. -3. **Tray → App:** `tray-icon` sends events via channel → Iced `Subscription`. +3. **Tray → App:** `ksni` sends SNI events via channel → Iced `Subscription`. ### Threading Model -- **Main thread:** Iced event loop + tray-icon (both need main thread on Linux) +- **Main thread:** Iced event loop. +- **Tray thread:** Blocking ksni D-Bus StatusNotifierItem service. - **PipeWire thread:** Dedicated thread running PipeWire's own event loop. Owns `AudioEngine`. - **Communication:** Bounded `mpsc` channels. Non-blocking sends from main thread. @@ -363,7 +364,7 @@ honkhonk/ │ │ └── playback.rs # Play sound to sink + monitor output │ ├── tray/ │ │ ├── mod.rs -│ │ └── icon.rs # tray-icon setup, menu, quit handler +│ │ └── icon.rs # ksni SNI setup, menu, quit handler │ ├── shortcuts/ # Phase 2 │ │ ├── mod.rs │ │ ├── error.rs # PortalError enum @@ -400,7 +401,10 @@ honkhonk/ │ ├── 002-pipewire-only-no-pulseaudio.md │ ├── 003-fixed-slot-hotkey-model.md │ ├── 004-persistent-sink-no-per-sound-nodes.md -│ └── 005-tray-icon-over-ksni.md +│ ├── 006-fundsp-over-rubberband-soundtouch.md +│ ├── 007-links-only-routing-over-pw-filter.md +│ ├── 008-subprocess-fallback-for-shortcut-config-ui.md +│ └── 009-canvas-sticker-tiles-rejected.md ├── .github/ │ └── workflows/ │ ├── ci.yml # Lint, test, build on PR @@ -422,8 +426,7 @@ iced = { version = "0.14", features = ["tokio", "tiny-skia"] } pipewire = "0.8" # pipewire-rs — official PipeWire Rust bindings ashpd = { version = "0.13", features = ["global_shortcuts", "tokio"] } # Phase 2 symphonia = { version = "0.5", features = ["mp3", "ogg", "flac", "wav", "pcm", "aac"] } -tray-icon = "0.19" # System tray (StatusNotifierItem) -muda = "0.15" # Menu for tray-icon +ksni = { version = "0.3", features = ["blocking"] } # System tray SNI over zbus thiserror = "2" # Typed error enums at module boundaries anyhow = "1" # Error context chains in glue/app layer serde = { version = "1", features = ["derive"] } @@ -530,14 +533,12 @@ This ensures cross-DE compatibility. KDE, GNOME, and Hyprland each implement the ### System Tray -StatusNotifierItem (SNI) is the standard. Implementation via `tray-icon` crate: -1. Initialize on main thread before Iced event loop -2. Menu via `muda` crate: "Show/Hide", separator, "Quit" +StatusNotifierItem (SNI) is the standard. Implementation via `ksni`: +1. Start a blocking SNI D-Bus service from the tray module +2. Provide icon pixmap plus DBusMenu entries: "Show/Hide", separator, "Quit" 3. Events communicated to Iced via channel → Subscription 4. No legacy XEmbed tray support -**Known warning:** `tray-icon` depends on `libappindicator` which loads `libayatana-appindicator` at runtime. This produces a harmless deprecation warning on stderr: `libayatana-appindicator is deprecated. Please use libayatana-appindicator-glib in newly written code.` This is an upstream issue in the `libappindicator` crate — not actionable from our code. Do not suppress it. - ### .desktop File ```ini diff --git a/Cargo.lock b/Cargo.lock index 4a0915e..228c848 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -147,7 +147,7 @@ version = "0.38.0+1.3.281" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f" dependencies = [ - "libloading 0.8.9", + "libloading", ] [[package]] @@ -259,7 +259,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -294,30 +294,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", -] - -[[package]] -name = "atk" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241b621213072e993be4f6f3a9e4b45f65b7e6faad43001be957184b7bb1824b" -dependencies = [ - "atk-sys", - "glib", - "libc", -] - -[[package]] -name = "atk-sys" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e48b684b0ca77d2bbadeef17424c2ea3c897d44d566a1617e7e8f30614d086" -dependencies = [ - "glib-sys", - "gobject-sys", - "libc", - "system-deps 6.2.2", + "syn", ] [[package]] @@ -348,7 +325,7 @@ dependencies = [ "regex", "rustc-hash 2.1.2", "shlex 1.3.0", - "syn 2.0.117", + "syn", ] [[package]] @@ -377,9 +354,6 @@ name = "bitflags" version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" -dependencies = [ - "serde_core", -] [[package]] name = "block" @@ -441,7 +415,7 @@ checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -456,31 +430,6 @@ version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" -[[package]] -name = "cairo-rs" -version = "0.18.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" -dependencies = [ - "bitflags 2.13.0", - "cairo-sys-rs", - "glib", - "libc", - "once_cell", - "thiserror 1.0.69", -] - -[[package]] -name = "cairo-sys-rs" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51" -dependencies = [ - "glib-sys", - "libc", - "system-deps 6.2.2", -] - [[package]] name = "calloop" version = "0.13.0" @@ -559,16 +508,6 @@ dependencies = [ "nom 7.1.3", ] -[[package]] -name = "cfg-expr" -version = "0.15.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" -dependencies = [ - "smallvec", - "target-lexicon 0.12.16", -] - [[package]] name = "cfg-expr" version = "0.20.8" @@ -576,7 +515,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb693542bcafa528e198be0ebd9d3632ca5b7c93dbe7237460e199910835997c" dependencies = [ "smallvec", - "target-lexicon 0.13.5", + "target-lexicon", ] [[package]] @@ -626,7 +565,7 @@ checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" dependencies = [ "glob", "libc", - "libloading 0.8.9", + "libloading", ] [[package]] @@ -875,15 +814,6 @@ dependencies = [ "itertools 0.10.5", ] -[[package]] -name = "crossbeam-channel" -version = "0.5.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" -dependencies = [ - "crossbeam-utils", -] - [[package]] name = "crossbeam-utils" version = "0.8.21" @@ -939,15 +869,6 @@ dependencies = [ "dirs-sys", ] -[[package]] -name = "dirs" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" -dependencies = [ - "dirs-sys", -] - [[package]] name = "dirs-sys" version = "0.5.0" @@ -984,7 +905,7 @@ checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -993,7 +914,7 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab8ecd87370524b461f8557c119c405552c396ed91fc0a8eec68679eab26f94a" dependencies = [ - "libloading 0.8.9", + "libloading", ] [[package]] @@ -1068,7 +989,7 @@ checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -1165,16 +1086,6 @@ dependencies = [ "thiserror 2.0.18", ] -[[package]] -name = "field-offset" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" -dependencies = [ - "memoffset", - "rustc_version", -] - [[package]] name = "find-msvc-tools" version = "0.1.9" @@ -1268,7 +1179,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -1389,7 +1300,7 @@ checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -1421,64 +1332,6 @@ dependencies = [ "slab", ] -[[package]] -name = "gdk" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9f245958c627ac99d8e529166f9823fb3b838d1d41fd2b297af3075093c2691" -dependencies = [ - "cairo-rs", - "gdk-pixbuf", - "gdk-sys", - "gio", - "glib", - "libc", - "pango", -] - -[[package]] -name = "gdk-pixbuf" -version = "0.18.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50e1f5f1b0bfb830d6ccc8066d18db35c487b1b2b1e8589b5dfe9f07e8defaec" -dependencies = [ - "gdk-pixbuf-sys", - "gio", - "glib", - "libc", - "once_cell", -] - -[[package]] -name = "gdk-pixbuf-sys" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9839ea644ed9c97a34d129ad56d38a25e6756f99f3a88e15cd39c20629caf7" -dependencies = [ - "gio-sys", - "glib-sys", - "gobject-sys", - "libc", - "system-deps 6.2.2", -] - -[[package]] -name = "gdk-sys" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c2d13f38594ac1e66619e188c6d5a1adb98d11b2fcf7894fc416ad76aa2f3f7" -dependencies = [ - "cairo-sys-rs", - "gdk-pixbuf-sys", - "gio-sys", - "glib-sys", - "gobject-sys", - "libc", - "pango-sys", - "pkg-config", - "system-deps 6.2.2", -] - [[package]] name = "generic-array" version = "1.4.3" @@ -1535,38 +1388,6 @@ dependencies = [ "wasip3", ] -[[package]] -name = "gio" -version = "0.18.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fc8f532f87b79cbc51a79748f16a6828fb784be93145a322fa14d06d354c73" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-util", - "gio-sys", - "glib", - "libc", - "once_cell", - "pin-project-lite", - "smallvec", - "thiserror 1.0.69", -] - -[[package]] -name = "gio-sys" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37566df850baf5e4cb0dfb78af2e4b9898d817ed9263d1090a2df958c64737d2" -dependencies = [ - "glib-sys", - "gobject-sys", - "libc", - "system-deps 6.2.2", - "winapi", -] - [[package]] name = "gl_generator" version = "0.14.0" @@ -1593,53 +1414,6 @@ dependencies = [ "libm", ] -[[package]] -name = "glib" -version = "0.18.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" -dependencies = [ - "bitflags 2.13.0", - "futures-channel", - "futures-core", - "futures-executor", - "futures-task", - "futures-util", - "gio-sys", - "glib-macros", - "glib-sys", - "gobject-sys", - "libc", - "memchr", - "once_cell", - "smallvec", - "thiserror 1.0.69", -] - -[[package]] -name = "glib-macros" -version = "0.18.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc" -dependencies = [ - "heck 0.4.1", - "proc-macro-crate 2.0.2", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "glib-sys" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063ce2eb6a8d0ea93d2bf8ba1957e78dbab6be1c2220dd3daca57d5a9d869898" -dependencies = [ - "libc", - "system-deps 6.2.2", -] - [[package]] name = "glob" version = "0.3.3" @@ -1667,17 +1441,6 @@ dependencies = [ "gl_generator", ] -[[package]] -name = "gobject-sys" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0850127b514d1c4a4654ead6dedadb18198999985908e6ffe4436f53c785ce44" -dependencies = [ - "glib-sys", - "libc", - "system-deps 6.2.2", -] - [[package]] name = "gpu-alloc" version = "0.6.0" @@ -1729,58 +1492,6 @@ dependencies = [ "bitflags 2.13.0", ] -[[package]] -name = "gtk" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd56fb197bfc42bd5d2751f4f017d44ff59fbb58140c6b49f9b3b2bdab08506a" -dependencies = [ - "atk", - "cairo-rs", - "field-offset", - "futures-channel", - "gdk", - "gdk-pixbuf", - "gio", - "glib", - "gtk-sys", - "gtk3-macros", - "libc", - "pango", - "pkg-config", -] - -[[package]] -name = "gtk-sys" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f29a1c21c59553eb7dd40e918be54dccd60c52b049b75119d5d96ce6b624414" -dependencies = [ - "atk-sys", - "cairo-sys-rs", - "gdk-pixbuf-sys", - "gdk-sys", - "gio-sys", - "glib-sys", - "gobject-sys", - "libc", - "pango-sys", - "system-deps 6.2.2", -] - -[[package]] -name = "gtk3-macros" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ff3c5b21f14f0736fed6dcfc0bfb4225ebf5725f3c0209edeec181e4d73e9d" -dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "guillotiere" version = "0.6.2" @@ -1852,12 +1563,6 @@ version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - [[package]] name = "heck" version = "0.5.0" @@ -1891,15 +1596,14 @@ dependencies = [ "criterion", "directories", "fundsp", - "gtk", "iced", "iced_core", "iced_graphics", "iced_runtime", "iced_tiny_skia", "iced_wgpu", + "ksni", "lofty", - "muda", "pipewire", "pitch_shift", "pollster", @@ -1912,7 +1616,6 @@ dependencies = [ "tokio", "tracing", "tracing-subscriber", - "tray-icon", "url", "walkdir", "zbus", @@ -2288,7 +1991,7 @@ dependencies = [ "quote", "rustc_version", "simd_cesu8", - "syn 2.0.117", + "syn", ] [[package]] @@ -2316,7 +2019,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" dependencies = [ "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -2340,17 +2043,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "keyboard-types" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a" -dependencies = [ - "bitflags 2.13.0", - "serde", - "unicode-segmentation", -] - [[package]] name = "khronos-egl" version = "6.0.0" @@ -2358,7 +2050,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" dependencies = [ "libc", - "libloading 0.8.9", + "libloading", "pkg-config", ] @@ -2368,6 +2060,19 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" +[[package]] +name = "ksni" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da9eeb3f510b6148ae68f963af2c1fbb0de4d9e4e05f82813cfb319837c3ad2b" +dependencies = [ + "futures-util", + "pastey", + "serde", + "tokio", + "zbus", +] + [[package]] name = "kurbo" version = "0.10.4" @@ -2390,46 +2095,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" -[[package]] -name = "libappindicator" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03589b9607c868cc7ae54c0b2a22c8dc03dd41692d48f2d7df73615c6a95dc0a" -dependencies = [ - "glib", - "gtk", - "gtk-sys", - "libappindicator-sys", - "log", -] - -[[package]] -name = "libappindicator-sys" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e9ec52138abedcc58dc17a7c6c0c00a2bdb4f3427c7f63fa97fd0d859155caf" -dependencies = [ - "gtk-sys", - "libloading 0.7.4", - "once_cell", -] - [[package]] name = "libc" version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" -[[package]] -name = "libloading" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" -dependencies = [ - "cfg-if", - "winapi", -] - [[package]] name = "libloading" version = "0.8.9" @@ -2472,7 +2143,7 @@ dependencies = [ "libspa-sys", "nix", "nom 8.0.0", - "system-deps 7.0.8", + "system-deps", ] [[package]] @@ -2483,7 +2154,7 @@ checksum = "901049455d2eb6decf9058235d745237952f4804bc584c5fcb41412e6adcc6e0" dependencies = [ "bindgen", "cc", - "system-deps 7.0.8", + "system-deps", ] [[package]] @@ -2557,7 +2228,7 @@ checksum = "458ace39169e4b83c4f77ae3d42d5d1d11c422feef590219a97c973d3b524557" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -2725,26 +2396,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "muda" -version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47a2e3dff89cd322c66647942668faee0a2b1f88ea6cbb4d374b4a8d7e92528c" -dependencies = [ - "crossbeam-channel", - "dpi", - "gtk", - "keyboard-types", - "objc2 0.6.4", - "objc2-app-kit 0.3.2", - "objc2-core-foundation", - "objc2-foundation 0.3.2", - "once_cell", - "png 0.18.1", - "thiserror 2.0.18", - "windows-sys 0.61.2", -] - [[package]] name = "mundy" version = "0.2.3" @@ -2921,10 +2572,10 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" dependencies = [ - "proc-macro-crate 3.5.0", + "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -3361,31 +3012,6 @@ dependencies = [ "ttf-parser", ] -[[package]] -name = "pango" -version = "0.18.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ca27ec1eb0457ab26f3036ea52229edbdb74dee1edd29063f5b9b010e7ebee4" -dependencies = [ - "gio", - "glib", - "libc", - "once_cell", - "pango-sys", -] - -[[package]] -name = "pango-sys" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436737e391a843e5933d6d9aa102cb126d501e815b83601365a948a518555dc5" -dependencies = [ - "glib-sys", - "gobject-sys", - "libc", - "system-deps 6.2.2", -] - [[package]] name = "parking" version = "2.2.1" @@ -3421,6 +3047,12 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pastey" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ee67f1008b1ba2321834326597b8e186293b049a023cdef258527550b9935b4" + [[package]] name = "percent-encoding" version = "2.3.2" @@ -3444,7 +3076,7 @@ checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -3495,7 +3127,7 @@ checksum = "cb028afee0d6ca17020b090e3b8fa2d7de23305aef975c7e5192a5050246ea36" dependencies = [ "bindgen", "libspa-sys", - "system-deps 7.0.8", + "system-deps", ] [[package]] @@ -3535,19 +3167,6 @@ dependencies = [ "miniz_oxide", ] -[[package]] -name = "png" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" -dependencies = [ - "bitflags 2.13.0", - "crc32fast", - "fdeflate", - "flate2", - "miniz_oxide", -] - [[package]] name = "polling" version = "3.11.0" @@ -3605,7 +3224,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.117", + "syn", ] [[package]] @@ -3617,57 +3236,13 @@ dependencies = [ "num-integer", ] -[[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 = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24" -dependencies = [ - "toml_datetime 0.6.3", - "toml_edit 0.20.2", -] - [[package]] name = "proc-macro-crate" version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit 0.25.12+spec-1.1.0", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", + "toml_edit", ] [[package]] @@ -3868,7 +3443,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8320af894782374141c8e0d4521ee613a8f24d7ab08b6ad359881311e37b9ef" dependencies = [ "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -4030,7 +3605,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -4054,16 +3629,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", -] - -[[package]] -name = "serde_spanned" -version = "0.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" -dependencies = [ - "serde", + "syn", ] [[package]] @@ -4527,16 +4093,6 @@ dependencies = [ "symphonia-metadata", ] -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "unicode-ident", -] - [[package]] name = "syn" version = "2.0.117" @@ -4556,7 +4112,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -4568,38 +4124,19 @@ dependencies = [ "libc", ] -[[package]] -name = "system-deps" -version = "6.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" -dependencies = [ - "cfg-expr 0.15.8", - "heck 0.5.0", - "pkg-config", - "toml 0.8.2", - "version-compare", -] - [[package]] name = "system-deps" version = "7.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "396a35feb67335377e0251fcbc1092fc85c484bd4e3a7a54319399da127796e7" dependencies = [ - "cfg-expr 0.20.8", - "heck 0.5.0", + "cfg-expr", + "heck", "pkg-config", - "toml 1.1.2+spec-1.1.0", + "toml", "version-compare", ] -[[package]] -name = "target-lexicon" -version = "0.12.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" - [[package]] name = "target-lexicon" version = "0.13.5" @@ -4663,7 +4200,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -4674,7 +4211,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -4697,7 +4234,7 @@ dependencies = [ "bytemuck", "cfg-if", "log", - "png 0.17.16", + "png", "tiny-skia-path", ] @@ -4720,7 +4257,7 @@ checksum = "a90a0ca3ee6a69f2ad28fd11621a4c3f03b371f366be500b64df260c4ffbafb4" dependencies = [ "as-raw-xcb-connection", "ctor", - "libloading 0.8.9", + "libloading", "pkg-config", "tracing", ] @@ -4785,19 +4322,7 @@ checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", -] - -[[package]] -name = "toml" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" -dependencies = [ - "serde", - "serde_spanned 0.6.9", - "toml_datetime 0.6.3", - "toml_edit 0.20.2", + "syn", ] [[package]] @@ -4808,20 +4333,11 @@ checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" dependencies = [ "indexmap", "serde_core", - "serde_spanned 1.1.1", - "toml_datetime 1.1.1+spec-1.1.0", + "serde_spanned", + "toml_datetime", "toml_parser", "toml_writer", - "winnow 1.0.3", -] - -[[package]] -name = "toml_datetime" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" -dependencies = [ - "serde", + "winnow", ] [[package]] @@ -4833,30 +4349,6 @@ 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.3", - "winnow 0.5.40", -] - -[[package]] -name = "toml_edit" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" -dependencies = [ - "indexmap", - "serde", - "serde_spanned 0.6.9", - "toml_datetime 0.6.3", - "winnow 0.5.40", -] - [[package]] name = "toml_edit" version = "0.25.12+spec-1.1.0" @@ -4864,9 +4356,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2153edc6955a6c354fad8f5efd38b6a8769bdccf9fe50f8e1329f81b0baa5d7" dependencies = [ "indexmap", - "toml_datetime 1.1.1+spec-1.1.0", + "toml_datetime", "toml_parser", - "winnow 1.0.3", + "winnow", ] [[package]] @@ -4875,7 +4367,7 @@ version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ - "winnow 1.0.3", + "winnow", ] [[package]] @@ -4904,7 +4396,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -4956,27 +4448,6 @@ dependencies = [ "strength_reduce", ] -[[package]] -name = "tray-icon" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65ba1e5f6b9ef9fd87e21b9c6f351554dbd717960089168fcfdef854686961dc" -dependencies = [ - "crossbeam-channel", - "dirs", - "libappindicator", - "muda", - "objc2 0.6.4", - "objc2-app-kit 0.3.2", - "objc2-core-foundation", - "objc2-core-graphics", - "objc2-foundation 0.3.2", - "once_cell", - "png 0.18.1", - "thiserror 2.0.18", - "windows-sys 0.61.2", -] - [[package]] name = "ttf-parser" version = "0.25.1" @@ -5168,7 +4639,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.117", + "syn", "wasm-bindgen-shared", ] @@ -5497,7 +4968,7 @@ dependencies = [ "js-sys", "khronos-egl", "libc", - "libloading 0.8.9", + "libloading", "log", "metal", "naga", @@ -5545,22 +5016,6 @@ dependencies = [ "safe_arch", ] -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - [[package]] name = "winapi-util" version = "0.1.11" @@ -5570,12 +5025,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - [[package]] name = "window_clipboard" version = "0.5.1" @@ -5666,7 +5115,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -5677,7 +5126,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -5688,7 +5137,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -5699,7 +5148,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -5907,15 +5356,6 @@ dependencies = [ "xkbcommon-dl", ] -[[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 = "1.0.3" @@ -5947,7 +5387,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" dependencies = [ "anyhow", - "heck 0.5.0", + "heck", "wit-parser", ] @@ -5958,10 +5398,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" dependencies = [ "anyhow", - "heck 0.5.0", + "heck", "indexmap", "prettyplease", - "syn 2.0.117", + "syn", "wasm-metadata", "wit-bindgen-core", "wit-component", @@ -5977,7 +5417,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn 2.0.117", + "syn", "wit-bindgen-core", "wit-bindgen-rust", ] @@ -6045,7 +5485,7 @@ dependencies = [ "as-raw-xcb-connection", "gethostname", "libc", - "libloading 0.8.9", + "libloading", "once_cell", "rustix 1.1.4", "x11rb-protocol", @@ -6113,7 +5553,7 @@ checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", "synstructure", ] @@ -6147,7 +5587,7 @@ dependencies = [ "uds_windows", "uuid", "windows-sys 0.61.2", - "winnow 1.0.3", + "winnow", "zbus_macros", "zbus_names", "zvariant", @@ -6159,10 +5599,10 @@ version = "5.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adf1bd45a81a103745b1757754762a26e8cd01e4532e4d6c8ec431624b80d1d6" dependencies = [ - "proc-macro-crate 3.5.0", + "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.117", + "syn", "zbus_names", "zvariant", "zvariant_utils", @@ -6175,7 +5615,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7074f3e50b894eac91750142016d30d0a89be8e67dbfd9704fb875825760e52d" dependencies = [ "serde", - "winnow 1.0.3", + "winnow", "zvariant", ] @@ -6202,7 +5642,7 @@ checksum = "1ae7f38b72ec2a254e2b87ef277cf2cd4fb97cbebf944faa6f33354da0867930" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -6222,7 +5662,7 @@ checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", "synstructure", ] @@ -6256,7 +5696,7 @@ checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -6274,7 +5714,7 @@ dependencies = [ "endi", "enumflags2", "serde", - "winnow 1.0.3", + "winnow", "zvariant_derive", "zvariant_utils", ] @@ -6285,10 +5725,10 @@ version = "5.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90bc6cde9c01c511074be97f7ccb6c19d0da89e3f8662e812e999dcfd4638737" dependencies = [ - "proc-macro-crate 3.5.0", + "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.117", + "syn", "zvariant_utils", ] @@ -6301,6 +5741,6 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.117", - "winnow 1.0.3", + "syn", + "winnow", ] diff --git a/Cargo.toml b/Cargo.toml index 9ea42a6..5a5f8d3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,24 +2,16 @@ name = "honkhonk" version = "0.1.0" edition = "2021" -rust-version = "1.75" +rust-version = "1.80" license = "MIT" description = "Wayland-native Linux soundboard" repository = "https://github.com/thewrz/HonkHonk" [dependencies] iced = { version = "0.14", features = ["tokio", "tiny-skia", "canvas"] } -# Wayland-only: disable default features on BOTH tray-icon and its (also-direct) -# muda dep to drop the `libxdo` X11 keystroke path. muda only uses libxdo for the -# predefined Copy/Cut/Paste/SelectAll items, which HonkHonk does not use (our tray -# menu is custom MenuItems + separator). Both must opt out — Cargo feature -# unification means muda's default features (which include `libxdo`) win if either -# dependency edge requests them. Keep `gtk` for the SNI tray (libgtk-3 + -# libayatana-appindicator). This removes the libxdo.so / libX11 / xdotool linkage -# entirely. See issue #98. -tray-icon = { version = "0.24", default-features = false, features = ["gtk"] } -muda = { version = "0.19", default-features = false, features = ["gtk"] } -gtk = "0.18" +# Pure-Rust StatusNotifierItem tray over zbus. Replaces tray-icon/muda/gtk so +# the Linux tray no longer pulls GTK3, libappindicator, or libxdo. +ksni = { version = "0.3.5", features = ["blocking"] } symphonia = { version = "0.5", features = ["mp3", "ogg", "vorbis", "flac", "wav", "pcm", "aac"] } tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } diff --git a/README.md b/README.md index 9be8244..1d930b3 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ HonkHonk is built from the ground up for the modern Linux desktop: | GUI | Iced (Rust, Elm architecture, wgpu) | | Audio | pipewire-rs | | Shortcuts | ashpd (xdg-desktop-portal) | -| System Tray | tray-icon (StatusNotifierItem) | +| System Tray | ksni (StatusNotifierItem over zbus) | | Audio Decode | symphonia | ## Status diff --git a/deny.toml b/deny.toml index 6a741ff..faaf2ba 100644 --- a/deny.toml +++ b/deny.toml @@ -11,19 +11,6 @@ targets = [ db-path = "~/.cargo/advisory-db" db-urls = ["https://github.com/rustsec/advisory-db"] ignore = [ - # gtk-rs GTK3 crates are unmaintained; they are transitive deps pulled in - # by tray-icon → libappindicator. No patched version exists. Tracked for - # replacement when tray-icon drops the GTK3 dependency. - { id = "RUSTSEC-2024-0412", reason = "transitive via tray-icon/libappindicator, no fix available" }, - { id = "RUSTSEC-2024-0413", reason = "transitive via tray-icon/libappindicator, no fix available" }, - { id = "RUSTSEC-2024-0415", reason = "transitive via tray-icon/libappindicator, no fix available" }, - { id = "RUSTSEC-2024-0416", reason = "transitive via tray-icon/libappindicator, no fix available" }, - { id = "RUSTSEC-2024-0418", reason = "transitive via tray-icon/libappindicator, no fix available" }, - { id = "RUSTSEC-2024-0419", reason = "transitive via tray-icon/libappindicator, no fix available" }, - { id = "RUSTSEC-2024-0420", reason = "transitive via tray-icon/libappindicator, no fix available" }, - # proc-macro-error is unmaintained; transitive dep, no patched alternative - # in use by our direct dependencies yet. - { id = "RUSTSEC-2024-0370", reason = "transitive dep, no patched version available upstream" }, # paste is unmaintained; transitive dep via lofty. No fix available without # lofty dropping its paste dependency upstream. { id = "RUSTSEC-2024-0436", reason = "transitive via lofty, no patched version available upstream" }, diff --git a/packaging/aur/README.md b/packaging/aur/README.md index 05a5e55..899ebbb 100644 --- a/packaging/aur/README.md +++ b/packaging/aur/README.md @@ -116,13 +116,7 @@ When auto-publish lands: ## Package strategy `honkhonk` (source) is the **primary** package: an Arch-native build compiled on -the user's machine, so it links the Arch `libxdo.so` directly (no foreign-soname -hack). `honkhonk-bin` was shipped first as the lowest-risk channel (it reuses the -`.deb` already attached to every tagged release), but a Debian-targeted `.deb` is -the wrong source of truth for an Arch package — it links `libxdo.so.3` against an -Arch `libxdo.so.4` (issue #98). `honkhonk-bin` is **kept as a convenience -secondary**, not removed. The real fix is on `main`: the `libxdo` Cargo feature is -disabled (see [`honkhonk/README.md`](honkhonk/README.md)), so once a release -carrying that change is tagged, both the source and `-bin` packages stop needing -`xdotool`/`libxdo` entirely. `honkhonk-git` is available for users who want +the user's machine from the tagged source release. `honkhonk-bin` re-extracts the +upstream `.deb` from GitHub Releases and is kept as a convenience secondary for +users who want a fast install. `honkhonk-git` is available for users who want current `main` before the next tagged release. diff --git a/packaging/aur/honkhonk-bin/.SRCINFO b/packaging/aur/honkhonk-bin/.SRCINFO index f856caa..518ee80 100644 --- a/packaging/aur/honkhonk-bin/.SRCINFO +++ b/packaging/aur/honkhonk-bin/.SRCINFO @@ -6,10 +6,10 @@ pkgbase = honkhonk-bin arch = x86_64 license = MIT depends = pipewire - depends = wayland - depends = libxkbcommon depends = gtk3 depends = libayatana-appindicator + depends = wayland + depends = libxkbcommon depends = xdg-desktop-portal provides = honkhonk conflicts = honkhonk diff --git a/packaging/aur/honkhonk-bin/PKGBUILD b/packaging/aur/honkhonk-bin/PKGBUILD index bf00df0..b75ff5f 100644 --- a/packaging/aur/honkhonk-bin/PKGBUILD +++ b/packaging/aur/honkhonk-bin/PKGBUILD @@ -9,16 +9,14 @@ pkgdesc="Wayland-native Linux soundboard — Iced GUI + PipeWire audio (binary r arch=('x86_64') url="https://github.com/wrzonance/HonkHonk" license=('MIT') -# NOTE: as of 0.1.0 the released binary no longer links libxdo.so (tray-icon/ -# muda built with default-features=false), so `xdotool` is not a dependency — -# this also ends the Debian libxdo.so.3 vs Arch libxdo.so.4 soname mismatch -# that blocked earlier versions of this package. +# The current 0.1.0 .deb was built before the ksni tray migration and still +# links GTK/appindicator. Drop those deps when _pkgtag points at a ksni release. depends=( 'pipewire' - 'wayland' - 'libxkbcommon' 'gtk3' 'libayatana-appindicator' + 'wayland' + 'libxkbcommon' 'xdg-desktop-portal' ) provides=('honkhonk') diff --git a/packaging/aur/honkhonk-git/.SRCINFO b/packaging/aur/honkhonk-git/.SRCINFO index 21d6e8d..a541019 100644 --- a/packaging/aur/honkhonk-git/.SRCINFO +++ b/packaging/aur/honkhonk-git/.SRCINFO @@ -11,8 +11,6 @@ pkgbase = honkhonk-git makedepends = clang makedepends = git depends = pipewire - depends = gtk3 - depends = libayatana-appindicator depends = wayland depends = libxkbcommon depends = xdg-desktop-portal diff --git a/packaging/aur/honkhonk-git/PKGBUILD b/packaging/aur/honkhonk-git/PKGBUILD index 980667b..a1c7bd2 100644 --- a/packaging/aur/honkhonk-git/PKGBUILD +++ b/packaging/aur/honkhonk-git/PKGBUILD @@ -10,8 +10,6 @@ url="https://github.com/wrzonance/HonkHonk" license=('MIT') depends=( 'pipewire' # libpipewire-0.3.so — audio engine (pipewire-sys) - 'gtk3' # libgtk-3.so / libgdk-3.so — tray menu (muda gtk feature) - 'libayatana-appindicator' # libayatana-appindicator3.so — SNI tray (dlopened) 'wayland' # libwayland-client.so — Iced/winit Wayland backend (dlopened) 'libxkbcommon' # libxkbcommon.so — keyboard mapping (winit, dlopened) 'xdg-desktop-portal' # D-Bus portal: file chooser + global shortcuts (ashpd) diff --git a/packaging/aur/honkhonk/PKGBUILD b/packaging/aur/honkhonk/PKGBUILD index 0b0ddf3..acf9010 100644 --- a/packaging/aur/honkhonk/PKGBUILD +++ b/packaging/aur/honkhonk/PKGBUILD @@ -12,9 +12,9 @@ license=('MIT') # Runtime deps — each is dynamically linked or dlopened by the binary. # See README.md in this directory for the full per-dependency justification. # -# NOTE: as of tag 0.1.0 the libxdo X11 linkage is gone (Cargo.toml: -# tray-icon/muda default-features=false), so `xdotool` is no longer a -# dependency. Verify on bumps with `namcap honkhonk-*.pkg.tar.zst`. +# This stable package still builds the 0.1.0 tag, whose tray backend uses GTK3 +# and libayatana-appindicator. Drop these when _pkgtag points at a release that +# includes the pure-Rust ksni tray backend. depends=( 'pipewire' # libpipewire-0.3.so — audio engine (pipewire-sys) 'gtk3' # libgtk-3.so / libgdk-3.so — tray menu (muda gtk feature) diff --git a/packaging/aur/honkhonk/README.md b/packaging/aur/honkhonk/README.md index 60c3f1e..d31f333 100644 --- a/packaging/aur/honkhonk/README.md +++ b/packaging/aur/honkhonk/README.md @@ -7,7 +7,7 @@ Alternatives live alongside this directory: - `honkhonk-bin` — re-extracts the upstream `.deb` from GitHub Releases. Kept as a convenience for users who want a fast install, but it is built on a Debian - base (see the libxdo note below for why source is preferred). + base, so the source package remains the Arch-native default. - `honkhonk-git` — VCS variant tracking `main`. ## Source @@ -28,47 +28,24 @@ offline against that freshly-pinned lockfile. ## Per-dependency justification -Every entry in `depends=()` is dynamically linked or dlopened by the binary. The -set was audited against issue #98 — anything not actually linked was dropped. +Every entry in `depends=()` is dynamically linked or dlopened by the tagged +binary this package builds. The current `pkgver=0.1.0` tag still uses the old +GTK3 tray backend; drop the GTK/appindicator entries when `_pkgtag` points at a +release that contains the pure-Rust `ksni` tray backend. | Dependency | Why it is required (binary links / dlopens it) | Arch | Fedora | Ubuntu/Debian | |-----------------------------|-------------------------------------------------------------------------|------|--------|---------------| | `pipewire` | `libpipewire-0.3.so` — audio engine (via the `pipewire` crate / -sys) | extra | Everything | main | -| `gtk3` | `libgtk-3.so` / `libgdk-3.so` — tray menu (`muda`/`tray-icon` `gtk`) | extra | Everything | main | -| `xdotool` | `libxdo.so` — `muda` `libxdo` feature (released tag only — see below) | extra | Everything | main/universe | -| `libayatana-appindicator` | `libayatana-appindicator3.so` — SNI tray (dlopened via `libappindicator`)| extra | Everything | universe | +| `gtk3` | `libgtk-3.so` / `libgdk-3.so` — tray menu in the 0.1.0 tag | extra | Everything | main | +| `libayatana-appindicator` | `libayatana-appindicator3.so` — SNI tray in the 0.1.0 tag | extra | Everything | main | | `wayland` | `libwayland-client.so` — Iced/winit Wayland backend (dlopened) | extra | Everything | main | | `libxkbcommon` | `libxkbcommon.so` — keyboard mapping (winit, dlopened) | extra | Everything | main | | `xdg-desktop-portal` | D-Bus service for file chooser + global shortcuts (`ashpd`, no link) | extra | Everything | main | -`pipewire` and `gtk3` pull `glib2` / `gdk-pixbuf2` transitively (namcap reports -those as implicitly satisfied), so they are not listed explicitly. - -### The `xdotool` / `libxdo` situation - -`tray-icon`'s and `muda`'s default Cargo features enable `libxdo`, which links -`libxdo.so` to synthesize X11 keystrokes for the predefined Copy/Cut/Paste/SelectAll -menu items. HonkHonk uses none of those (its tray menu is custom `MenuItem`s plus a -separator) and is Wayland-only per `CLAUDE.md`, so the X11 path is dead weight. - -The fix on `main` disables those features: - -```toml -tray-icon = { version = "0.24", default-features = false, features = ["gtk"] } -muda = { version = "0.19", default-features = false, features = ["gtk"] } -``` - -Both edges must opt out — HonkHonk depends on `muda` directly *and* transitively -(via `tray-icon`), and Cargo feature unification means `muda`'s default features -(which include `libxdo`) win if *either* edge requests them. With both disabled, -`cargo tree -i libxdo` is empty and `readelf -d` shows no `libxdo.so` in `NEEDED`. - -**This package builds the released tag (`$_pkgtag`), not `main`.** As of tag -`0.1.0` the libxdo fix is included, so the built binary has no `libxdo.so` in -`NEEDED` and `xdotool` was dropped from `depends`. This also ended the -Debian-vs-Arch `libxdo.so.3` / `libxdo.so.4` soname mismatch that blocked -`honkhonk-bin` on a clean Arch base for the alpha. Re-verify on each bump with -`namcap` on the built package. +The current development branch uses `ksni` (StatusNotifierItem over zbus), so +future release bumps should re-audit this table with `namcap` and `cargo tree` +and remove the GTK/appindicator entries once the package no longer builds the +0.1.0 tag. ## Per-release bump runbook diff --git a/packaging/flatpak/cargo-sources.json b/packaging/flatpak/cargo-sources.json index 63acb73..546b043 100644 --- a/packaging/flatpak/cargo-sources.json +++ b/packaging/flatpak/cargo-sources.json @@ -376,32 +376,6 @@ "dest": "cargo/vendor/async-trait-0.1.89", "dest-filename": ".cargo-checksum.json" }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/atk/atk-0.18.2.crate", - "sha256": "241b621213072e993be4f6f3a9e4b45f65b7e6faad43001be957184b7bb1824b", - "dest": "cargo/vendor/atk-0.18.2" - }, - { - "type": "inline", - "contents": "{\"package\": \"241b621213072e993be4f6f3a9e4b45f65b7e6faad43001be957184b7bb1824b\", \"files\": {}}", - "dest": "cargo/vendor/atk-0.18.2", - "dest-filename": ".cargo-checksum.json" - }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/atk-sys/atk-sys-0.18.2.crate", - "sha256": "c5e48b684b0ca77d2bbadeef17424c2ea3c897d44d566a1617e7e8f30614d086", - "dest": "cargo/vendor/atk-sys-0.18.2" - }, - { - "type": "inline", - "contents": "{\"package\": \"c5e48b684b0ca77d2bbadeef17424c2ea3c897d44d566a1617e7e8f30614d086\", \"files\": {}}", - "dest": "cargo/vendor/atk-sys-0.18.2", - "dest-filename": ".cargo-checksum.json" - }, { "type": "archive", "archive-type": "tar-gzip", @@ -610,32 +584,6 @@ "dest": "cargo/vendor/bytes-1.11.1", "dest-filename": ".cargo-checksum.json" }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/cairo-rs/cairo-rs-0.18.5.crate", - "sha256": "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2", - "dest": "cargo/vendor/cairo-rs-0.18.5" - }, - { - "type": "inline", - "contents": "{\"package\": \"8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2\", \"files\": {}}", - "dest": "cargo/vendor/cairo-rs-0.18.5", - "dest-filename": ".cargo-checksum.json" - }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/cairo-sys-rs/cairo-sys-rs-0.18.2.crate", - "sha256": "685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51", - "dest": "cargo/vendor/cairo-sys-rs-0.18.2" - }, - { - "type": "inline", - "contents": "{\"package\": \"685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51\", \"files\": {}}", - "dest": "cargo/vendor/cairo-sys-rs-0.18.2", - "dest-filename": ".cargo-checksum.json" - }, { "type": "archive", "archive-type": "tar-gzip", @@ -727,19 +675,6 @@ "dest": "cargo/vendor/cexpr-0.6.0", "dest-filename": ".cargo-checksum.json" }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/cfg-expr/cfg-expr-0.15.8.crate", - "sha256": "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02", - "dest": "cargo/vendor/cfg-expr-0.15.8" - }, - { - "type": "inline", - "contents": "{\"package\": \"d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02\", \"files\": {}}", - "dest": "cargo/vendor/cfg-expr-0.15.8", - "dest-filename": ".cargo-checksum.json" - }, { "type": "archive", "archive-type": "tar-gzip", @@ -1130,19 +1065,6 @@ "dest": "cargo/vendor/criterion-plot-0.5.0", "dest-filename": ".cargo-checksum.json" }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/crossbeam-channel/crossbeam-channel-0.5.15.crate", - "sha256": "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2", - "dest": "cargo/vendor/crossbeam-channel-0.5.15" - }, - { - "type": "inline", - "contents": "{\"package\": \"82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2\", \"files\": {}}", - "dest": "cargo/vendor/crossbeam-channel-0.5.15", - "dest-filename": ".cargo-checksum.json" - }, { "type": "archive", "archive-type": "tar-gzip", @@ -1234,19 +1156,6 @@ "dest": "cargo/vendor/directories-6.0.0", "dest-filename": ".cargo-checksum.json" }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/dirs/dirs-6.0.0.crate", - "sha256": "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e", - "dest": "cargo/vendor/dirs-6.0.0" - }, - { - "type": "inline", - "contents": "{\"package\": \"c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e\", \"files\": {}}", - "dest": "cargo/vendor/dirs-6.0.0", - "dest-filename": ".cargo-checksum.json" - }, { "type": "archive", "archive-type": "tar-gzip", @@ -1585,19 +1494,6 @@ "dest": "cargo/vendor/fft-convolver-0.3.0", "dest-filename": ".cargo-checksum.json" }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/field-offset/field-offset-0.3.6.crate", - "sha256": "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f", - "dest": "cargo/vendor/field-offset-0.3.6" - }, - { - "type": "inline", - "contents": "{\"package\": \"38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f\", \"files\": {}}", - "dest": "cargo/vendor/field-offset-0.3.6", - "dest-filename": ".cargo-checksum.json" - }, { "type": "archive", "archive-type": "tar-gzip", @@ -1923,58 +1819,6 @@ "dest": "cargo/vendor/futures-util-0.3.32", "dest-filename": ".cargo-checksum.json" }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/gdk/gdk-0.18.2.crate", - "sha256": "d9f245958c627ac99d8e529166f9823fb3b838d1d41fd2b297af3075093c2691", - "dest": "cargo/vendor/gdk-0.18.2" - }, - { - "type": "inline", - "contents": "{\"package\": \"d9f245958c627ac99d8e529166f9823fb3b838d1d41fd2b297af3075093c2691\", \"files\": {}}", - "dest": "cargo/vendor/gdk-0.18.2", - "dest-filename": ".cargo-checksum.json" - }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/gdk-pixbuf/gdk-pixbuf-0.18.5.crate", - "sha256": "50e1f5f1b0bfb830d6ccc8066d18db35c487b1b2b1e8589b5dfe9f07e8defaec", - "dest": "cargo/vendor/gdk-pixbuf-0.18.5" - }, - { - "type": "inline", - "contents": "{\"package\": \"50e1f5f1b0bfb830d6ccc8066d18db35c487b1b2b1e8589b5dfe9f07e8defaec\", \"files\": {}}", - "dest": "cargo/vendor/gdk-pixbuf-0.18.5", - "dest-filename": ".cargo-checksum.json" - }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/gdk-pixbuf-sys/gdk-pixbuf-sys-0.18.0.crate", - "sha256": "3f9839ea644ed9c97a34d129ad56d38a25e6756f99f3a88e15cd39c20629caf7", - "dest": "cargo/vendor/gdk-pixbuf-sys-0.18.0" - }, - { - "type": "inline", - "contents": "{\"package\": \"3f9839ea644ed9c97a34d129ad56d38a25e6756f99f3a88e15cd39c20629caf7\", \"files\": {}}", - "dest": "cargo/vendor/gdk-pixbuf-sys-0.18.0", - "dest-filename": ".cargo-checksum.json" - }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/gdk-sys/gdk-sys-0.18.2.crate", - "sha256": "5c2d13f38594ac1e66619e188c6d5a1adb98d11b2fcf7894fc416ad76aa2f3f7", - "dest": "cargo/vendor/gdk-sys-0.18.2" - }, - { - "type": "inline", - "contents": "{\"package\": \"5c2d13f38594ac1e66619e188c6d5a1adb98d11b2fcf7894fc416ad76aa2f3f7\", \"files\": {}}", - "dest": "cargo/vendor/gdk-sys-0.18.2", - "dest-filename": ".cargo-checksum.json" - }, { "type": "archive", "archive-type": "tar-gzip", @@ -2040,32 +1884,6 @@ "dest": "cargo/vendor/getrandom-0.4.2", "dest-filename": ".cargo-checksum.json" }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/gio/gio-0.18.4.crate", - "sha256": "d4fc8f532f87b79cbc51a79748f16a6828fb784be93145a322fa14d06d354c73", - "dest": "cargo/vendor/gio-0.18.4" - }, - { - "type": "inline", - "contents": "{\"package\": \"d4fc8f532f87b79cbc51a79748f16a6828fb784be93145a322fa14d06d354c73\", \"files\": {}}", - "dest": "cargo/vendor/gio-0.18.4", - "dest-filename": ".cargo-checksum.json" - }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/gio-sys/gio-sys-0.18.1.crate", - "sha256": "37566df850baf5e4cb0dfb78af2e4b9898d817ed9263d1090a2df958c64737d2", - "dest": "cargo/vendor/gio-sys-0.18.1" - }, - { - "type": "inline", - "contents": "{\"package\": \"37566df850baf5e4cb0dfb78af2e4b9898d817ed9263d1090a2df958c64737d2\", \"files\": {}}", - "dest": "cargo/vendor/gio-sys-0.18.1", - "dest-filename": ".cargo-checksum.json" - }, { "type": "archive", "archive-type": "tar-gzip", @@ -2105,45 +1923,6 @@ "dest": "cargo/vendor/glam-0.28.0", "dest-filename": ".cargo-checksum.json" }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/glib/glib-0.18.5.crate", - "sha256": "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5", - "dest": "cargo/vendor/glib-0.18.5" - }, - { - "type": "inline", - "contents": "{\"package\": \"233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5\", \"files\": {}}", - "dest": "cargo/vendor/glib-0.18.5", - "dest-filename": ".cargo-checksum.json" - }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/glib-macros/glib-macros-0.18.5.crate", - "sha256": "0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc", - "dest": "cargo/vendor/glib-macros-0.18.5" - }, - { - "type": "inline", - "contents": "{\"package\": \"0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc\", \"files\": {}}", - "dest": "cargo/vendor/glib-macros-0.18.5", - "dest-filename": ".cargo-checksum.json" - }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/glib-sys/glib-sys-0.18.1.crate", - "sha256": "063ce2eb6a8d0ea93d2bf8ba1957e78dbab6be1c2220dd3daca57d5a9d869898", - "dest": "cargo/vendor/glib-sys-0.18.1" - }, - { - "type": "inline", - "contents": "{\"package\": \"063ce2eb6a8d0ea93d2bf8ba1957e78dbab6be1c2220dd3daca57d5a9d869898\", \"files\": {}}", - "dest": "cargo/vendor/glib-sys-0.18.1", - "dest-filename": ".cargo-checksum.json" - }, { "type": "archive", "archive-type": "tar-gzip", @@ -2183,19 +1962,6 @@ "dest": "cargo/vendor/glutin_wgl_sys-0.6.1", "dest-filename": ".cargo-checksum.json" }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/gobject-sys/gobject-sys-0.18.0.crate", - "sha256": "0850127b514d1c4a4654ead6dedadb18198999985908e6ffe4436f53c785ce44", - "dest": "cargo/vendor/gobject-sys-0.18.0" - }, - { - "type": "inline", - "contents": "{\"package\": \"0850127b514d1c4a4654ead6dedadb18198999985908e6ffe4436f53c785ce44\", \"files\": {}}", - "dest": "cargo/vendor/gobject-sys-0.18.0", - "dest-filename": ".cargo-checksum.json" - }, { "type": "archive", "archive-type": "tar-gzip", @@ -2261,45 +2027,6 @@ "dest": "cargo/vendor/gpu-descriptor-types-0.2.0", "dest-filename": ".cargo-checksum.json" }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/gtk/gtk-0.18.2.crate", - "sha256": "fd56fb197bfc42bd5d2751f4f017d44ff59fbb58140c6b49f9b3b2bdab08506a", - "dest": "cargo/vendor/gtk-0.18.2" - }, - { - "type": "inline", - "contents": "{\"package\": \"fd56fb197bfc42bd5d2751f4f017d44ff59fbb58140c6b49f9b3b2bdab08506a\", \"files\": {}}", - "dest": "cargo/vendor/gtk-0.18.2", - "dest-filename": ".cargo-checksum.json" - }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/gtk-sys/gtk-sys-0.18.2.crate", - "sha256": "8f29a1c21c59553eb7dd40e918be54dccd60c52b049b75119d5d96ce6b624414", - "dest": "cargo/vendor/gtk-sys-0.18.2" - }, - { - "type": "inline", - "contents": "{\"package\": \"8f29a1c21c59553eb7dd40e918be54dccd60c52b049b75119d5d96ce6b624414\", \"files\": {}}", - "dest": "cargo/vendor/gtk-sys-0.18.2", - "dest-filename": ".cargo-checksum.json" - }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/gtk3-macros/gtk3-macros-0.18.2.crate", - "sha256": "52ff3c5b21f14f0736fed6dcfc0bfb4225ebf5725f3c0209edeec181e4d73e9d", - "dest": "cargo/vendor/gtk3-macros-0.18.2" - }, - { - "type": "inline", - "contents": "{\"package\": \"52ff3c5b21f14f0736fed6dcfc0bfb4225ebf5725f3c0209edeec181e4d73e9d\", \"files\": {}}", - "dest": "cargo/vendor/gtk3-macros-0.18.2", - "dest-filename": ".cargo-checksum.json" - }, { "type": "archive", "archive-type": "tar-gzip", @@ -2391,19 +2118,6 @@ "dest": "cargo/vendor/hashbrown-0.17.1", "dest-filename": ".cargo-checksum.json" }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/heck/heck-0.4.1.crate", - "sha256": "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8", - "dest": "cargo/vendor/heck-0.4.1" - }, - { - "type": "inline", - "contents": "{\"package\": \"95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8\", \"files\": {}}", - "dest": "cargo/vendor/heck-0.4.1", - "dest-filename": ".cargo-checksum.json" - }, { "type": "archive", "archive-type": "tar-gzip", @@ -2898,19 +2612,6 @@ "dest": "cargo/vendor/js-sys-0.3.102", "dest-filename": ".cargo-checksum.json" }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/keyboard-types/keyboard-types-0.7.0.crate", - "sha256": "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a", - "dest": "cargo/vendor/keyboard-types-0.7.0" - }, - { - "type": "inline", - "contents": "{\"package\": \"b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a\", \"files\": {}}", - "dest": "cargo/vendor/keyboard-types-0.7.0", - "dest-filename": ".cargo-checksum.json" - }, { "type": "archive", "archive-type": "tar-gzip", @@ -2937,6 +2638,19 @@ "dest": "cargo/vendor/khronos_api-3.1.0", "dest-filename": ".cargo-checksum.json" }, + { + "type": "archive", + "archive-type": "tar-gzip", + "url": "https://static.crates.io/crates/ksni/ksni-0.3.5.crate", + "sha256": "da9eeb3f510b6148ae68f963af2c1fbb0de4d9e4e05f82813cfb319837c3ad2b", + "dest": "cargo/vendor/ksni-0.3.5" + }, + { + "type": "inline", + "contents": "{\"package\": \"da9eeb3f510b6148ae68f963af2c1fbb0de4d9e4e05f82813cfb319837c3ad2b\", \"files\": {}}", + "dest": "cargo/vendor/ksni-0.3.5", + "dest-filename": ".cargo-checksum.json" + }, { "type": "archive", "archive-type": "tar-gzip", @@ -2976,32 +2690,6 @@ "dest": "cargo/vendor/leb128fmt-0.1.0", "dest-filename": ".cargo-checksum.json" }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/libappindicator/libappindicator-0.9.0.crate", - "sha256": "03589b9607c868cc7ae54c0b2a22c8dc03dd41692d48f2d7df73615c6a95dc0a", - "dest": "cargo/vendor/libappindicator-0.9.0" - }, - { - "type": "inline", - "contents": "{\"package\": \"03589b9607c868cc7ae54c0b2a22c8dc03dd41692d48f2d7df73615c6a95dc0a\", \"files\": {}}", - "dest": "cargo/vendor/libappindicator-0.9.0", - "dest-filename": ".cargo-checksum.json" - }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/libappindicator-sys/libappindicator-sys-0.9.0.crate", - "sha256": "6e9ec52138abedcc58dc17a7c6c0c00a2bdb4f3427c7f63fa97fd0d859155caf", - "dest": "cargo/vendor/libappindicator-sys-0.9.0" - }, - { - "type": "inline", - "contents": "{\"package\": \"6e9ec52138abedcc58dc17a7c6c0c00a2bdb4f3427c7f63fa97fd0d859155caf\", \"files\": {}}", - "dest": "cargo/vendor/libappindicator-sys-0.9.0", - "dest-filename": ".cargo-checksum.json" - }, { "type": "archive", "archive-type": "tar-gzip", @@ -3015,19 +2703,6 @@ "dest": "cargo/vendor/libc-0.2.186", "dest-filename": ".cargo-checksum.json" }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/libloading/libloading-0.7.4.crate", - "sha256": "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f", - "dest": "cargo/vendor/libloading-0.7.4" - }, - { - "type": "inline", - "contents": "{\"package\": \"b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f\", \"files\": {}}", - "dest": "cargo/vendor/libloading-0.7.4", - "dest-filename": ".cargo-checksum.json" - }, { "type": "archive", "archive-type": "tar-gzip", @@ -3444,19 +3119,6 @@ "dest": "cargo/vendor/mio-1.2.1", "dest-filename": ".cargo-checksum.json" }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/muda/muda-0.19.2.crate", - "sha256": "47a2e3dff89cd322c66647942668faee0a2b1f88ea6cbb4d374b4a8d7e92528c", - "dest": "cargo/vendor/muda-0.19.2" - }, - { - "type": "inline", - "contents": "{\"package\": \"47a2e3dff89cd322c66647942668faee0a2b1f88ea6cbb4d374b4a8d7e92528c\", \"files\": {}}", - "dest": "cargo/vendor/muda-0.19.2", - "dest-filename": ".cargo-checksum.json" - }, { "type": "archive", "archive-type": "tar-gzip", @@ -4159,32 +3821,6 @@ "dest": "cargo/vendor/owned_ttf_parser-0.25.1", "dest-filename": ".cargo-checksum.json" }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/pango/pango-0.18.3.crate", - "sha256": "7ca27ec1eb0457ab26f3036ea52229edbdb74dee1edd29063f5b9b010e7ebee4", - "dest": "cargo/vendor/pango-0.18.3" - }, - { - "type": "inline", - "contents": "{\"package\": \"7ca27ec1eb0457ab26f3036ea52229edbdb74dee1edd29063f5b9b010e7ebee4\", \"files\": {}}", - "dest": "cargo/vendor/pango-0.18.3", - "dest-filename": ".cargo-checksum.json" - }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/pango-sys/pango-sys-0.18.0.crate", - "sha256": "436737e391a843e5933d6d9aa102cb126d501e815b83601365a948a518555dc5", - "dest": "cargo/vendor/pango-sys-0.18.0" - }, - { - "type": "inline", - "contents": "{\"package\": \"436737e391a843e5933d6d9aa102cb126d501e815b83601365a948a518555dc5\", \"files\": {}}", - "dest": "cargo/vendor/pango-sys-0.18.0", - "dest-filename": ".cargo-checksum.json" - }, { "type": "archive", "archive-type": "tar-gzip", @@ -4237,6 +3873,19 @@ "dest": "cargo/vendor/paste-1.0.15", "dest-filename": ".cargo-checksum.json" }, + { + "type": "archive", + "archive-type": "tar-gzip", + "url": "https://static.crates.io/crates/pastey/pastey-0.2.3.crate", + "sha256": "2ee67f1008b1ba2321834326597b8e186293b049a023cdef258527550b9935b4", + "dest": "cargo/vendor/pastey-0.2.3" + }, + { + "type": "inline", + "contents": "{\"package\": \"2ee67f1008b1ba2321834326597b8e186293b049a023cdef258527550b9935b4\", \"files\": {}}", + "dest": "cargo/vendor/pastey-0.2.3", + "dest-filename": ".cargo-checksum.json" + }, { "type": "archive", "archive-type": "tar-gzip", @@ -4393,19 +4042,6 @@ "dest": "cargo/vendor/png-0.17.16", "dest-filename": ".cargo-checksum.json" }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/png/png-0.18.1.crate", - "sha256": "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61", - "dest": "cargo/vendor/png-0.18.1" - }, - { - "type": "inline", - "contents": "{\"package\": \"60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61\", \"files\": {}}", - "dest": "cargo/vendor/png-0.18.1", - "dest-filename": ".cargo-checksum.json" - }, { "type": "archive", "archive-type": "tar-gzip", @@ -4510,32 +4146,6 @@ "dest": "cargo/vendor/primal-check-0.3.4", "dest-filename": ".cargo-checksum.json" }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/proc-macro-crate/proc-macro-crate-1.3.1.crate", - "sha256": "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919", - "dest": "cargo/vendor/proc-macro-crate-1.3.1" - }, - { - "type": "inline", - "contents": "{\"package\": \"7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919\", \"files\": {}}", - "dest": "cargo/vendor/proc-macro-crate-1.3.1", - "dest-filename": ".cargo-checksum.json" - }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/proc-macro-crate/proc-macro-crate-2.0.2.crate", - "sha256": "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24", - "dest": "cargo/vendor/proc-macro-crate-2.0.2" - }, - { - "type": "inline", - "contents": "{\"package\": \"b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24\", \"files\": {}}", - "dest": "cargo/vendor/proc-macro-crate-2.0.2", - "dest-filename": ".cargo-checksum.json" - }, { "type": "archive", "archive-type": "tar-gzip", @@ -4549,32 +4159,6 @@ "dest": "cargo/vendor/proc-macro-crate-3.5.0", "dest-filename": ".cargo-checksum.json" }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/proc-macro-error/proc-macro-error-1.0.4.crate", - "sha256": "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c", - "dest": "cargo/vendor/proc-macro-error-1.0.4" - }, - { - "type": "inline", - "contents": "{\"package\": \"da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c\", \"files\": {}}", - "dest": "cargo/vendor/proc-macro-error-1.0.4", - "dest-filename": ".cargo-checksum.json" - }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/proc-macro-error-attr/proc-macro-error-attr-1.0.4.crate", - "sha256": "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869", - "dest": "cargo/vendor/proc-macro-error-attr-1.0.4" - }, - { - "type": "inline", - "contents": "{\"package\": \"a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869\", \"files\": {}}", - "dest": "cargo/vendor/proc-macro-error-attr-1.0.4", - "dest-filename": ".cargo-checksum.json" - }, { "type": "archive", "archive-type": "tar-gzip", @@ -5147,19 +4731,6 @@ "dest": "cargo/vendor/serde_repr-0.1.20", "dest-filename": ".cargo-checksum.json" }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/serde_spanned/serde_spanned-0.6.9.crate", - "sha256": "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3", - "dest": "cargo/vendor/serde_spanned-0.6.9" - }, - { - "type": "inline", - "contents": "{\"package\": \"bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3\", \"files\": {}}", - "dest": "cargo/vendor/serde_spanned-0.6.9", - "dest-filename": ".cargo-checksum.json" - }, { "type": "archive", "archive-type": "tar-gzip", @@ -5706,19 +5277,6 @@ "dest": "cargo/vendor/symphonia-utils-xiph-0.5.5", "dest-filename": ".cargo-checksum.json" }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/syn/syn-1.0.109.crate", - "sha256": "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237", - "dest": "cargo/vendor/syn-1.0.109" - }, - { - "type": "inline", - "contents": "{\"package\": \"72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237\", \"files\": {}}", - "dest": "cargo/vendor/syn-1.0.109", - "dest-filename": ".cargo-checksum.json" - }, { "type": "archive", "archive-type": "tar-gzip", @@ -5758,19 +5316,6 @@ "dest": "cargo/vendor/sys-locale-0.3.2", "dest-filename": ".cargo-checksum.json" }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/system-deps/system-deps-6.2.2.crate", - "sha256": "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349", - "dest": "cargo/vendor/system-deps-6.2.2" - }, - { - "type": "inline", - "contents": "{\"package\": \"a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349\", \"files\": {}}", - "dest": "cargo/vendor/system-deps-6.2.2", - "dest-filename": ".cargo-checksum.json" - }, { "type": "archive", "archive-type": "tar-gzip", @@ -5784,19 +5329,6 @@ "dest": "cargo/vendor/system-deps-7.0.8", "dest-filename": ".cargo-checksum.json" }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/target-lexicon/target-lexicon-0.12.16.crate", - "sha256": "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1", - "dest": "cargo/vendor/target-lexicon-0.12.16" - }, - { - "type": "inline", - "contents": "{\"package\": \"61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1\", \"files\": {}}", - "dest": "cargo/vendor/target-lexicon-0.12.16", - "dest-filename": ".cargo-checksum.json" - }, { "type": "archive", "archive-type": "tar-gzip", @@ -6031,19 +5563,6 @@ "dest": "cargo/vendor/tokio-macros-2.7.0", "dest-filename": ".cargo-checksum.json" }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/toml/toml-0.8.2.crate", - "sha256": "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d", - "dest": "cargo/vendor/toml-0.8.2" - }, - { - "type": "inline", - "contents": "{\"package\": \"185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d\", \"files\": {}}", - "dest": "cargo/vendor/toml-0.8.2", - "dest-filename": ".cargo-checksum.json" - }, { "type": "archive", "archive-type": "tar-gzip", @@ -6057,19 +5576,6 @@ "dest": "cargo/vendor/toml-1.1.2+spec-1.1.0", "dest-filename": ".cargo-checksum.json" }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/toml_datetime/toml_datetime-0.6.3.crate", - "sha256": "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b", - "dest": "cargo/vendor/toml_datetime-0.6.3" - }, - { - "type": "inline", - "contents": "{\"package\": \"7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b\", \"files\": {}}", - "dest": "cargo/vendor/toml_datetime-0.6.3", - "dest-filename": ".cargo-checksum.json" - }, { "type": "archive", "archive-type": "tar-gzip", @@ -6083,32 +5589,6 @@ "dest": "cargo/vendor/toml_datetime-1.1.1+spec-1.1.0", "dest-filename": ".cargo-checksum.json" }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/toml_edit/toml_edit-0.19.15.crate", - "sha256": "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421", - "dest": "cargo/vendor/toml_edit-0.19.15" - }, - { - "type": "inline", - "contents": "{\"package\": \"1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421\", \"files\": {}}", - "dest": "cargo/vendor/toml_edit-0.19.15", - "dest-filename": ".cargo-checksum.json" - }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/toml_edit/toml_edit-0.20.2.crate", - "sha256": "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338", - "dest": "cargo/vendor/toml_edit-0.20.2" - }, - { - "type": "inline", - "contents": "{\"package\": \"396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338\", \"files\": {}}", - "dest": "cargo/vendor/toml_edit-0.20.2", - "dest-filename": ".cargo-checksum.json" - }, { "type": "archive", "archive-type": "tar-gzip", @@ -6226,19 +5706,6 @@ "dest": "cargo/vendor/transpose-0.2.3", "dest-filename": ".cargo-checksum.json" }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/tray-icon/tray-icon-0.24.1.crate", - "sha256": "65ba1e5f6b9ef9fd87e21b9c6f351554dbd717960089168fcfdef854686961dc", - "dest": "cargo/vendor/tray-icon-0.24.1" - }, - { - "type": "inline", - "contents": "{\"package\": \"65ba1e5f6b9ef9fd87e21b9c6f351554dbd717960089168fcfdef854686961dc\", \"files\": {}}", - "dest": "cargo/vendor/tray-icon-0.24.1", - "dest-filename": ".cargo-checksum.json" - }, { "type": "archive", "archive-type": "tar-gzip", @@ -6889,32 +6356,6 @@ "dest": "cargo/vendor/wide-1.5.0", "dest-filename": ".cargo-checksum.json" }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/winapi/winapi-0.3.9.crate", - "sha256": "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419", - "dest": "cargo/vendor/winapi-0.3.9" - }, - { - "type": "inline", - "contents": "{\"package\": \"5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419\", \"files\": {}}", - "dest": "cargo/vendor/winapi-0.3.9", - "dest-filename": ".cargo-checksum.json" - }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/winapi-i686-pc-windows-gnu/winapi-i686-pc-windows-gnu-0.4.0.crate", - "sha256": "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6", - "dest": "cargo/vendor/winapi-i686-pc-windows-gnu-0.4.0" - }, - { - "type": "inline", - "contents": "{\"package\": \"ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6\", \"files\": {}}", - "dest": "cargo/vendor/winapi-i686-pc-windows-gnu-0.4.0", - "dest-filename": ".cargo-checksum.json" - }, { "type": "archive", "archive-type": "tar-gzip", @@ -6928,19 +6369,6 @@ "dest": "cargo/vendor/winapi-util-0.1.11", "dest-filename": ".cargo-checksum.json" }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/winapi-x86_64-pc-windows-gnu/winapi-x86_64-pc-windows-gnu-0.4.0.crate", - "sha256": "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f", - "dest": "cargo/vendor/winapi-x86_64-pc-windows-gnu-0.4.0" - }, - { - "type": "inline", - "contents": "{\"package\": \"712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f\", \"files\": {}}", - "dest": "cargo/vendor/winapi-x86_64-pc-windows-gnu-0.4.0", - "dest-filename": ".cargo-checksum.json" - }, { "type": "archive", "archive-type": "tar-gzip", @@ -7344,19 +6772,6 @@ "dest": "cargo/vendor/winit-0.30.13", "dest-filename": ".cargo-checksum.json" }, - { - "type": "archive", - "archive-type": "tar-gzip", - "url": "https://static.crates.io/crates/winnow/winnow-0.5.40.crate", - "sha256": "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876", - "dest": "cargo/vendor/winnow-0.5.40" - }, - { - "type": "inline", - "contents": "{\"package\": \"f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876\", \"files\": {}}", - "dest": "cargo/vendor/winnow-0.5.40", - "dest-filename": ".cargo-checksum.json" - }, { "type": "archive", "archive-type": "tar-gzip", diff --git a/packaging/flatpak/io.github.thewrz.HonkHonk.yml b/packaging/flatpak/io.github.thewrz.HonkHonk.yml index 23fc499..e64afa9 100644 --- a/packaging/flatpak/io.github.thewrz.HonkHonk.yml +++ b/packaging/flatpak/io.github.thewrz.HonkHonk.yml @@ -33,21 +33,6 @@ finish-args: - --filesystem=xdg-data/honkhonk:create modules: - # muda (tray-icon menu library) links libxdo unconditionally on Linux. - # Not in the freedesktop SDK — build from source. - - name: xdotool - buildsystem: simple - build-options: - env: - PREFIX: /app - build-commands: - - make - - make install PREFIX=/app - sources: - - type: archive - url: https://github.com/jordansissel/xdotool/archive/refs/tags/v3.20211022.1.tar.gz - sha256: 82b15a944a5e82fee15e0f6116bd9f642bc3d0bb6989fc0ca5ad9dfe35de0847 - - name: honkhonk buildsystem: simple build-commands: diff --git a/src/app/mod.rs b/src/app/mod.rs index eea874e..cc6f57a 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -568,10 +568,6 @@ impl HonkHonk { self.update(msg) } Message::TrayPoll => { - while gtk::events_pending() { - gtk::main_iteration_do(false); - } - let event = self.tray_rx.lock().ok().and_then(|rx| rx.try_recv().ok()); if let Some(e) = event { let msg = Message::from_tray_event(e); diff --git a/src/main.rs b/src/main.rs index e216b86..a946441 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,9 +19,9 @@ fn main() -> iced::Result { } }; - // Set ICED_BACKEND before any subsystem init — pipewire::init() and - // gtk::init() do not document that they avoid spawning background threads, - // so set_var must run before them to satisfy its SAFETY requirement. + // Set ICED_BACKEND before any subsystem init — pipewire::init() does not + // document that it avoids spawning background threads, so set_var must run + // before it to satisfy its SAFETY requirement. let renderer = effective_renderer( std::env::var("HONKHONK_RENDERER").ok().as_deref(), config.renderer, @@ -41,11 +41,6 @@ fn main() -> iced::Result { pipewire::init(); - if let Err(e) = gtk::init() { - tracing::error!(error = %e, "failed to initialize GTK (required for system tray); exiting"); - std::process::exit(1); - } - let sounds = match honkhonk::state::Library::scan(&config.sound_directories) { Ok(s) => s, Err(e) => { diff --git a/src/tray/icon.rs b/src/tray/icon.rs index ef440a0..5ce9185 100644 --- a/src/tray/icon.rs +++ b/src/tray/icon.rs @@ -1,6 +1,11 @@ -use muda::{Menu, MenuEvent, MenuItem, PredefinedMenuItem}; -use std::sync::mpsc::{self, Receiver}; -use tray_icon::{TrayIcon, TrayIconBuilder}; +use ksni::blocking::{Handle, TrayMethods}; +use ksni::menu::{MenuItem, StandardItem}; +use std::sync::mpsc::{self, Receiver, Sender}; + +const TRAY_ID: &str = "honkhonk"; +const TRAY_TITLE: &str = "HonkHonk"; +const ICON_SIZE: i32 = 64; +const ICON_RGBA: [u8; 4] = [96, 96, 96, 255]; #[derive(Debug, Clone, PartialEq)] pub enum TrayEvent { @@ -10,9 +15,7 @@ pub enum TrayEvent { pub struct TrayHandle { event_rx: Option>, - _icon: TrayIcon, - _show_hide_id: muda::MenuId, - _quit_id: muda::MenuId, + handle: Handle, } impl TrayHandle { @@ -21,47 +24,146 @@ impl TrayHandle { } } +impl Drop for TrayHandle { + fn drop(&mut self) { + self.handle.shutdown().wait(); + } +} + pub fn build_tray() -> Result> { let (event_tx, event_rx) = mpsc::channel::(); + let handle = HonkTray::new(event_tx) + .disable_dbus_name(ashpd::is_sandboxed()) + .assume_sni_available(true) + .spawn()?; - let menu = Menu::new(); - let show_hide = MenuItem::new("Show/Hide", true, None); - let quit = MenuItem::new("Quit", true, None); + Ok(TrayHandle { + event_rx: Some(event_rx), + handle, + }) +} - menu.append(&show_hide)?; - menu.append(&PredefinedMenuItem::separator())?; - menu.append(&quit)?; +struct HonkTray { + event_tx: Sender, +} - let show_hide_id = show_hide.id().clone(); - let quit_id = quit.id().clone(); +impl HonkTray { + fn new(event_tx: Sender) -> Self { + Self { event_tx } + } - let icon = load_icon(); - let tray = TrayIconBuilder::new() - .with_menu(Box::new(menu)) - .with_tooltip("HonkHonk") - .with_icon(icon) - .build()?; + fn emit(&self, event: TrayEvent) { + let _ = self.event_tx.send(event); + } +} - let sh_id = show_hide_id.clone(); - let q_id = quit_id.clone(); +impl ksni::Tray for HonkTray { + fn id(&self) -> String { + TRAY_ID.into() + } + + fn title(&self) -> String { + TRAY_TITLE.into() + } - MenuEvent::set_event_handler(Some(move |event: MenuEvent| { - if event.id() == &sh_id { - let _ = event_tx.send(TrayEvent::ToggleVisibility); - } else if event.id() == &q_id { - let _ = event_tx.send(TrayEvent::Quit); + fn icon_name(&self) -> String { + TRAY_ID.into() + } + + fn icon_pixmap(&self) -> Vec { + solid_icon_pixmap(ICON_SIZE, ICON_RGBA) + } + + fn tool_tip(&self) -> ksni::ToolTip { + ksni::ToolTip { + title: TRAY_TITLE.into(), + description: "Wayland-native soundboard".into(), + ..Default::default() } - })); + } - Ok(TrayHandle { - event_rx: Some(event_rx), - _icon: tray, - _show_hide_id: show_hide_id, - _quit_id: quit_id, - }) + fn activate(&mut self, _x: i32, _y: i32) { + self.emit(TrayEvent::ToggleVisibility); + } + + fn secondary_activate(&mut self, _x: i32, _y: i32) { + self.emit(TrayEvent::ToggleVisibility); + } + + fn menu(&self) -> Vec> { + vec![ + menu_item("Show/Hide", TrayEvent::ToggleVisibility), + MenuItem::Separator, + menu_item("Quit", TrayEvent::Quit), + ] + } +} + +fn menu_item(label: &str, event: TrayEvent) -> MenuItem { + StandardItem { + label: label.into(), + activate: Box::new(move |tray: &mut HonkTray| tray.emit(event.clone())), + ..Default::default() + } + .into() +} + +fn solid_icon_pixmap(size: i32, rgba: [u8; 4]) -> Vec { + let dimension = size.max(1) as usize; + let pixel_count = dimension * dimension; + let mut data = Vec::with_capacity(pixel_count * 4); + for _ in 0..pixel_count { + data.extend_from_slice(&[rgba[3], rgba[0], rgba[1], rgba[2]]); + } + + vec![ksni::Icon { + width: dimension as i32, + height: dimension as i32, + data, + }] } -fn load_icon() -> tray_icon::Icon { - let rgba = vec![96u8; 64 * 64 * 4]; - tray_icon::Icon::from_rgba(rgba, 64, 64).expect("valid icon dimensions") +#[cfg(test)] +mod tests { + use super::*; + use ksni::Tray; + + #[test] + fn icon_pixmap_uses_sni_argb32_channel_order() { + let icon = solid_icon_pixmap(1, [0x11, 0x22, 0x33, 0x44]) + .pop() + .expect("icon pixmap should contain one size"); + + assert_eq!(icon.width, 1); + assert_eq!(icon.height, 1); + assert_eq!(icon.data, vec![0x44, 0x11, 0x22, 0x33]); + } + + #[test] + fn tray_menu_actions_emit_app_events() { + let (tx, rx) = mpsc::channel(); + let mut tray = HonkTray::new(tx); + let menu = tray.menu(); + + activate_menu_item(&menu, "Show/Hide", &mut tray); + activate_menu_item(&menu, "Quit", &mut tray); + + assert_eq!( + rx.recv().expect("show/hide event"), + TrayEvent::ToggleVisibility + ); + assert_eq!(rx.recv().expect("quit event"), TrayEvent::Quit); + } + + fn activate_menu_item(menu: &[MenuItem], label: &str, tray: &mut HonkTray) { + let item = menu + .iter() + .find_map(|item| match item { + MenuItem::Standard(item) if item.label == label => Some(item), + _ => None, + }) + .unwrap_or_else(|| panic!("{label} menu item missing")); + + (item.activate)(tray); + } } diff --git a/src/ui/settings.rs b/src/ui/settings.rs index 14a4a8e..ce55420 100644 --- a/src/ui/settings.rs +++ b/src/ui/settings.rs @@ -939,7 +939,7 @@ pub fn view_about_section(t: Theme) -> Element<'static, Message> { text("pipewire-rs — PipeWire project") .size(theme::font::LABEL) .color(t.ink_dim()), - text("tray-icon — tauri-apps") + text("ksni — iovxw") .size(theme::font::LABEL) .color(t.ink_dim()), ]