niri and Dank Material Shell integration pack #22

Closed
opened 2026-11-05 17:00:39 +00:00 by xavierk · 2 comments
Owner

Parent

Spec: Voculinux — Void Linux (glibc) Wayland/niri port of Vocalinux

What to build

A niri user gets first-class activation and a working tray with no compositor-specific code. Documentation gains a niri integration page with a ready-to-use keybind snippet (ideally an optional include file) that spawns the renamed toggle triggers, marked non-repeating, with a plain warning that a key is either a compositor bind or an in-app shortcut, never both, and a note that hold-to-talk stays in the app until a numbered niri release ships press/release binds. The same ticket settles the tray watcher question by observation on a real Dank Material Shell session: if the shell's watcher owns only the freedesktop watcher name, the tray-presence probe is widened to accept both watcher names so no false warning appears; if the current probe is already correct, that evidence is recorded and no code changes.

Acceptance criteria

  • Following only the new documentation, a fresh niri configuration toggles dictation from the documented bind, once per press.
  • The docs carry the compositor-bind-XOR-in-app-shortcut warning and the hold-to-talk status note.
  • Recorded evidence on this ticket names the StatusNotifier watcher bus name(s) observed under Dank Material Shell.
  • If the probe needed widening, the tray appears under Dank Material Shell with no false missing-tray warning, and behaviour tests cover both watcher names; if it did not, no probe code changed.
  • No niri- or shell-internal APIs are used anywhere; hold-to-talk behaviour is unchanged.

Blocked by

## Parent [Spec: Voculinux — Void Linux (glibc) Wayland/niri port of Vocalinux](https://git.bongbetic.com/xavierk/voculinux/issues/16) ## What to build A niri user gets first-class activation and a working tray with no compositor-specific code. Documentation gains a niri integration page with a ready-to-use keybind snippet (ideally an optional include file) that spawns the renamed toggle triggers, marked non-repeating, with a plain warning that a key is either a compositor bind or an in-app shortcut, never both, and a note that hold-to-talk stays in the app until a numbered niri release ships press/release binds. The same ticket settles the tray watcher question by observation on a real Dank Material Shell session: if the shell's watcher owns only the freedesktop watcher name, the tray-presence probe is widened to accept both watcher names so no false warning appears; if the current probe is already correct, that evidence is recorded and no code changes. ## Acceptance criteria - [ ] Following only the new documentation, a fresh niri configuration toggles dictation from the documented bind, once per press. - [ ] The docs carry the compositor-bind-XOR-in-app-shortcut warning and the hold-to-talk status note. - [ ] Recorded evidence on this ticket names the StatusNotifier watcher bus name(s) observed under Dank Material Shell. - [ ] If the probe needed widening, the tray appears under Dank Material Shell with no false missing-tray warning, and behaviour tests cover both watcher names; if it did not, no probe code changed. - [ ] No niri- or shell-internal APIs are used anywhere; hold-to-talk behaviour is unchanged. ## Blocked by - [Rename user-visible identity to voculinux with one-time legacy import](https://git.bongbetic.com/xavierk/voculinux/issues/18)
xavierk added the ready-for-agent label 2026-11-05 17:00:39 +00:00
Author
Owner

#22 evidence: niri and Dank Material Shell integration (2026-11-06)

StatusNotifier watcher under Dank Material Shell (DMS)

  • busctl --user list: org.kde.StatusNotifierWatcher is owned by PID 2478 (qs, DMS), with org.kde.StatusNotifierHost-2478-* registered. org.freedesktop.StatusNotifierWatcher is not owned; only org.x.StatusNotifierWatcher is activatable.
  • busctl --user get-property org.kde.StatusNotifierWatcher /StatusNotifierWatcher org.kde.StatusNotifierWatcher IsStatusNotifierHostRegistered returns b true.
  • With voculinux running, RegisteredStatusNotifierItems returns as 1 ":<bus>/org/ayatana/NotificationItem/voculinux", so the app's item is registered with DMS's watcher.
  • Installed probe, run with /usr/bin/python3 and no code change: TrayIndicator._check_status_notifier_watcher() from /usr/lib/python3.14/site-packages/vocalinux/ui/tray_indicator.py returns True.
  • App logs contain no "tray icon may not appear" or missing-watcher line (0 matches across three instances).
  • Verdict: the current probe already accepts the name DMS owns, so no probe code changes (the spec's "already correct" branch). Seeing the icon in the DMS bar is NEEDS-HUMAN.

Keybind example (docs-style text)

Ready-made file: resources/niri/voculinux.kdl. Copy it to ~/.config/niri/voculinux.kdl and add include "~/.config/niri/voculinux.kdl" near the top of config.kdl. Prerequisite: Settings, Shortcuts, External Activation on.

binds {
    Mod+Shift+D repeat=false hotkey-overlay-title="Toggle Voculinux dictation" {
        spawn "voculinux" "--toggle";
    }
}

Warning, as the spec requires: a key is either a compositor bind or an in-app Voculinux shortcut, never both. A key claimed on both sides fires twice. Hold-to-talk stays in the app: a compositor bind sends only the press, so push-to-talk keeps working only through the built-in shortcut until a numbered niri release ships press/release binds.

Verification

  • niri validate -c, all rc=0:
    • (a) the bind block alone;
    • (b) a scratch copy of the user's config with the include line appended, under HOME=<scratch> so the ~ expands there;
    • (c) resources/niri/voculinux.kdl standalone.
  • Conflict found: Mod+Shift+D is already bound on this machine in ~/.config/niri/dms/binds.kdl:131 (Move Column Right). niri validate accepts the duplicate, so the shipped example silently competes with DMS. Finding for the docs: choose a free default key, or add a conflict-check line.
  • Spawn path: /usr/sbin/voculinux --toggle with no running instance exits 1 with the expected ServiceUnknown D-Bus error. niri msg action spawn -- /usr/sbin/voculinux --toggle is accepted (rc 0). No instance was started.
  • Hold-to-talk status note and compositor-bind/in-app warning: present in docs/NIRI.md (checked by reading).
  • Live "one press = one toggle" from a fresh niri config: NEEDS-HUMAN (see the #32 checklist).
  • No niri- or DMS-internal API is used; the example relies only on spawn.
## #22 evidence: niri and Dank Material Shell integration (2026-11-06) ### StatusNotifier watcher under Dank Material Shell (DMS) - `busctl --user list`: `org.kde.StatusNotifierWatcher` is owned by PID 2478 (`qs`, DMS), with `org.kde.StatusNotifierHost-2478-*` registered. `org.freedesktop.StatusNotifierWatcher` is **not** owned; only `org.x.StatusNotifierWatcher` is activatable. - `busctl --user get-property org.kde.StatusNotifierWatcher /StatusNotifierWatcher org.kde.StatusNotifierWatcher IsStatusNotifierHostRegistered` returns `b true`. - With voculinux running, `RegisteredStatusNotifierItems` returns `as 1 ":<bus>/org/ayatana/NotificationItem/voculinux"`, so the app's item is registered with DMS's watcher. - Installed probe, run with `/usr/bin/python3` and no code change: `TrayIndicator._check_status_notifier_watcher()` from `/usr/lib/python3.14/site-packages/vocalinux/ui/tray_indicator.py` returns `True`. - App logs contain no "tray icon may not appear" or missing-watcher line (0 matches across three instances). - Verdict: the current probe already accepts the name DMS owns, so **no probe code changes** (the spec's "already correct" branch). Seeing the icon in the DMS bar is NEEDS-HUMAN. ### Keybind example (docs-style text) Ready-made file: `resources/niri/voculinux.kdl`. Copy it to `~/.config/niri/voculinux.kdl` and add `include "~/.config/niri/voculinux.kdl"` near the top of `config.kdl`. Prerequisite: Settings, Shortcuts, External Activation on. ```kdl binds { Mod+Shift+D repeat=false hotkey-overlay-title="Toggle Voculinux dictation" { spawn "voculinux" "--toggle"; } } ``` Warning, as the spec requires: a key is either a compositor bind or an in-app Voculinux shortcut, never both. A key claimed on both sides fires twice. Hold-to-talk stays in the app: a compositor bind sends only the press, so push-to-talk keeps working only through the built-in shortcut until a numbered niri release ships press/release binds. ### Verification - `niri validate -c`, all rc=0: - (a) the bind block alone; - (b) a scratch copy of the user's config with the include line appended, under `HOME=<scratch>` so the `~` expands there; - (c) `resources/niri/voculinux.kdl` standalone. - **Conflict found:** `Mod+Shift+D` is already bound on this machine in `~/.config/niri/dms/binds.kdl:131` (`Move Column Right`). `niri validate` accepts the duplicate, so the shipped example silently competes with DMS. Finding for the docs: choose a free default key, or add a conflict-check line. - Spawn path: `/usr/sbin/voculinux --toggle` with no running instance exits 1 with the expected `ServiceUnknown` D-Bus error. `niri msg action spawn -- /usr/sbin/voculinux --toggle` is accepted (rc 0). No instance was started. - Hold-to-talk status note and compositor-bind/in-app warning: present in `docs/NIRI.md` (checked by reading). - Live "one press = one toggle" from a fresh niri config: NEEDS-HUMAN (see the #32 checklist). - No niri- or DMS-internal API is used; the example relies only on `spawn`.
Author
Owner

Human session (2026-11-07) on the installed build from main 0c48db5. Tray icon visible in the Dank Material Shell bar, registered with org.kde.StatusNotifierWatcher (no probe change needed). The niri keybind include works live; the user rebound the toggle to Mod+Alt+V, which is free in niri and DMS, and niri validate passes. The example key conflict was fixed in #45. Full results are on #32.

Human session (2026-11-07) on the installed build from main 0c48db5. Tray icon visible in the Dank Material Shell bar, registered with org.kde.StatusNotifierWatcher (no probe change needed). The niri keybind include works live; the user rebound the toggle to Mod+Alt+V, which is free in niri and DMS, and niri validate passes. The example key conflict was fixed in #45. Full results are on #32.
Sign in to join this conversation.