Two fixes from the niri hardware acceptance run (#22, #32), one commit each.
#45, example keybind. The shipped toggle Mod+Shift+D is Move Column Right in Dank Material Shell's niri binds (dms/binds.kdl), so the example competed with it silently. The toggle moves to Mod+Shift+M, which is free in niri's stock binds and in DMS's binds. The commented start/stop examples move off Mod+Shift+E (stock niri quit, also bound by DMS) to Mod+Shift+S and Mod+Shift+X. docs/NIRI.md gains a "Check a key before you bind it" section with grep commands. The overlay pointer is corrected from Mod+H to Mod+Shift+Slash.
#46, inject-probe.inject-probe reported portal_available: true on niri, but the injector never selects the RemoteDesktop portal there. The probe now reuses the injector's _is_niri_session() guard. On niri it skips the portal and reports portal_available: false with portal_skip_reason: "niri". Off niri the report is unchanged.
Documentation updated when user-facing behavior or install steps change
Tests added or updated for the change
Local tests pass (pytest), related files only (see notes)
Conventional commit message style
Screenshots (if applicable)
N/A (no UI change).
Notes for reviewers
Validation.niri validate -c passes on the shipped include file, on a scratch copy of the user config with the documented include line, and on the commented start/stop variants and the Flatpak gdbus replacement. Two binds for one key in the same binds {} block fail; the same key across blocks passes silently. That is why the docs say validation cannot detect conflicts and point to grep.
Conflict check. The documented grep was run against this machine's config: Mod+Shift+M, Mod+Shift+S and Mod+Shift+X show no hits. Mod+Shift+D hits dms/binds.kdl:131. A positive control on the embedded stock binds finds Mod+Shift+E (quit).
Tests. Related files, run with PYTHONPATH=src: test_perf_baseline_protocol, test_niri_pack, test_injection_ladder, test_host_process, test_text_injector_ext, test_rename_sweep: 179 passed. The full suite was not run because of the known order-dependent failures on main. The new niri probe tests were red before the fix.
Pre-existing findings, not touched here.mypy src/ reports one error in src/vocalinux/ui/dictation_overlay.py:252. isort flags src/vocalinux/ui/tray_indicator.py and tests/test_recognition_manager_helpers.py. flake8 default-config findings in the two test/script files predate this PR. The CI critical flake8 selection is clean.
Not changed, for follow-up.web/src/app/hyprland-sway/page.tsx and web/src/app/global-shortcuts/page.tsx show $mod+Shift+d and Super+Shift+D. Those are Sway and Hyprland examples, not niri. RemoteDesktopPortal.probe() itself is unchanged. #32 saw it answer AvailableDeviceTypes = 0, and the probe may still treat that as available off niri. docs/PERF_BASELINE_PROTOCOL.md describes a session-establishment attempt that inject-probe does not make.
Still needs a human. A live press of the new bind on niri, and the DMS bar icon. Both are in the #32 checklist.
## Description
Two fixes from the niri hardware acceptance run (#22, #32), one commit each.
- **#45, example keybind.** The shipped toggle `Mod+Shift+D` is Move Column Right in Dank Material Shell's niri binds (`dms/binds.kdl`), so the example competed with it silently. The toggle moves to `Mod+Shift+M`, which is free in niri's stock binds and in DMS's binds. The commented start/stop examples move off `Mod+Shift+E` (stock niri quit, also bound by DMS) to `Mod+Shift+S` and `Mod+Shift+X`. `docs/NIRI.md` gains a "Check a key before you bind it" section with grep commands. The overlay pointer is corrected from `Mod+H` to `Mod+Shift+Slash`.
- **#46, inject-probe.** `inject-probe` reported `portal_available: true` on niri, but the injector never selects the RemoteDesktop portal there. The probe now reuses the injector's `_is_niri_session()` guard. On niri it skips the portal and reports `portal_available: false` with `portal_skip_reason: "niri"`. Off niri the report is unchanged.
## Related issue
Fixes #45
Fixes #46
## Type of change
- [x] Bug fix
- [x] Documentation
- [x] Tests
## Checklist
- [x] Code follows project style (Black, isort, flake8)
- [x] Documentation updated when user-facing behavior or install steps change
- [x] Tests added or updated for the change
- [x] Local tests pass (`pytest`), related files only (see notes)
- [x] Conventional commit message style
## Screenshots (if applicable)
N/A (no UI change).
## Notes for reviewers
- **Validation.** `niri validate -c` passes on the shipped include file, on a scratch copy of the user config with the documented include line, and on the commented start/stop variants and the Flatpak `gdbus` replacement. Two binds for one key in the same `binds {}` block fail; the same key across blocks passes silently. That is why the docs say validation cannot detect conflicts and point to grep.
- **Conflict check.** The documented grep was run against this machine's config: `Mod+Shift+M`, `Mod+Shift+S` and `Mod+Shift+X` show no hits. `Mod+Shift+D` hits `dms/binds.kdl:131`. A positive control on the embedded stock binds finds `Mod+Shift+E` (quit).
- **Tests.** Related files, run with `PYTHONPATH=src`: `test_perf_baseline_protocol`, `test_niri_pack`, `test_injection_ladder`, `test_host_process`, `test_text_injector_ext`, `test_rename_sweep`: 179 passed. The full suite was not run because of the known order-dependent failures on `main`. The new niri probe tests were red before the fix.
- **Pre-existing findings, not touched here.** `mypy src/` reports one error in `src/vocalinux/ui/dictation_overlay.py:252`. isort flags `src/vocalinux/ui/tray_indicator.py` and `tests/test_recognition_manager_helpers.py`. flake8 default-config findings in the two test/script files predate this PR. The CI critical flake8 selection is clean.
- **Not changed, for follow-up.** `web/src/app/hyprland-sway/page.tsx` and `web/src/app/global-shortcuts/page.tsx` show `$mod+Shift+d` and `Super+Shift+D`. Those are Sway and Hyprland examples, not niri. `RemoteDesktopPortal.probe()` itself is unchanged. #32 saw it answer `AvailableDeviceTypes = 0`, and the probe may still treat that as available off niri. `docs/PERF_BASELINE_PROTOCOL.md` describes a session-establishment attempt that `inject-probe` does not make.
- **Still needs a human.** A live press of the new bind on niri, and the DMS bar icon. Both are in the #32 checklist.
The injector never offers the RemoteDesktop portal on niri, but inject-probe
ran the portal probe unguarded and reported portal_available: true there.
The probe now reuses the injector's _is_niri_session guard: on niri it skips
the portal and reports portal_skip_reason "niri" with portal_available false.
Off niri the probe runs and reports its answer as before.
Fixes#46
Mod+Shift+D is Move Column Right in Dank Material Shell's niri binds
(dms/binds.kdl), so the shipped example competed with it silently. The
toggle moves to Mod+Shift+M, which is free in niri's stock binds and in
DMS's binds. The start and stop examples move off Mod+Shift+E, which is
stock niri's quit, to Mod+Shift+S and Mod+Shift+X.
niri validate rejects a key bound twice in one binds block but not across
blocks, so validation cannot show a conflict. The docs now give a grep
over the config tree and niri's embedded stock binds for checking a key
before binding it. The overlay pointer is corrected to Mod+Shift+Slash.
A test pins the doc and the include to one toggle key that is not
Mod+Shift+D.
Fixes#45
niri accepts lowercase and mixed-case key names such as mod+shift+m, so
the grep in the conflict check must ignore case too. strings comes from
binutils, which is now said in the docs.
Refs #45
Follow-up notes for this PR. Neither is changed here.
Second diagnostic with the same disagreement as #46.src/vocalinux/text_injection/text_injector.py, around line 928: when portal is pinned and not applied, the "was not applied" warning calls _portal_probe() without the niri guard. On niri that can produce a warning with an empty reason even though autodetection never offers the portal there. The fix is larger than a one-line guard, so it is left for a separate change.
DMS template check. The DMS 2.1.1 launcher (/usr/bin/dms) embeds its niri bind template. Its Mod+Shift+ literals include E (quit) and no M, S or X, so the chosen keys are also free in that template, not only in this machine's dms/binds.kdl. Mod+Shift+D is not in that template either, so the Move Column Right bind on this machine was a local edit.
Follow-up notes for this PR. Neither is changed here.
- **Second diagnostic with the same disagreement as #46.** `src/vocalinux/text_injection/text_injector.py`, around line 928: when `portal` is pinned and not applied, the "was not applied" warning calls `_portal_probe()` without the niri guard. On niri that can produce a warning with an empty reason even though autodetection never offers the portal there. The fix is larger than a one-line guard, so it is left for a separate change.
- **DMS template check.** The DMS 2.1.1 launcher (`/usr/bin/dms`) embeds its niri bind template. Its `Mod+Shift+` literals include `E` (quit) and no `M`, `S` or `X`, so the chosen keys are also free in that template, not only in this machine's `dms/binds.kdl`. `Mod+Shift+D` is not in that template either, so the Move Column Right bind on this machine was a local edit.
xavierk
merged commit a451e1d512 into main2026-11-06 18:29:29 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Description
Two fixes from the niri hardware acceptance run (#22, #32), one commit each.
Mod+Shift+Dis Move Column Right in Dank Material Shell's niri binds (dms/binds.kdl), so the example competed with it silently. The toggle moves toMod+Shift+M, which is free in niri's stock binds and in DMS's binds. The commented start/stop examples move offMod+Shift+E(stock niri quit, also bound by DMS) toMod+Shift+SandMod+Shift+X.docs/NIRI.mdgains a "Check a key before you bind it" section with grep commands. The overlay pointer is corrected fromMod+HtoMod+Shift+Slash.inject-probereportedportal_available: trueon niri, but the injector never selects the RemoteDesktop portal there. The probe now reuses the injector's_is_niri_session()guard. On niri it skips the portal and reportsportal_available: falsewithportal_skip_reason: "niri". Off niri the report is unchanged.Related issue
Fixes #45
Fixes #46
Type of change
Checklist
pytest), related files only (see notes)Screenshots (if applicable)
N/A (no UI change).
Notes for reviewers
niri validate -cpasses on the shipped include file, on a scratch copy of the user config with the documented include line, and on the commented start/stop variants and the Flatpakgdbusreplacement. Two binds for one key in the samebinds {}block fail; the same key across blocks passes silently. That is why the docs say validation cannot detect conflicts and point to grep.Mod+Shift+M,Mod+Shift+SandMod+Shift+Xshow no hits.Mod+Shift+Dhitsdms/binds.kdl:131. A positive control on the embedded stock binds findsMod+Shift+E(quit).PYTHONPATH=src:test_perf_baseline_protocol,test_niri_pack,test_injection_ladder,test_host_process,test_text_injector_ext,test_rename_sweep: 179 passed. The full suite was not run because of the known order-dependent failures onmain. The new niri probe tests were red before the fix.mypy src/reports one error insrc/vocalinux/ui/dictation_overlay.py:252. isort flagssrc/vocalinux/ui/tray_indicator.pyandtests/test_recognition_manager_helpers.py. flake8 default-config findings in the two test/script files predate this PR. The CI critical flake8 selection is clean.web/src/app/hyprland-sway/page.tsxandweb/src/app/global-shortcuts/page.tsxshow$mod+Shift+dandSuper+Shift+D. Those are Sway and Hyprland examples, not niri.RemoteDesktopPortal.probe()itself is unchanged. #32 saw it answerAvailableDeviceTypes = 0, and the probe may still treat that as available off niri.docs/PERF_BASELINE_PROTOCOL.mddescribes a session-establishment attempt thatinject-probedoes not make.Follow-up notes for this PR. Neither is changed here.
src/vocalinux/text_injection/text_injector.py, around line 928: whenportalis pinned and not applied, the "was not applied" warning calls_portal_probe()without the niri guard. On niri that can produce a warning with an empty reason even though autodetection never offers the portal there. The fix is larger than a one-line guard, so it is left for a separate change./usr/bin/dms) embeds its niri bind template. ItsMod+Shift+literals includeE(quit) and noM,SorX, so the chosen keys are also free in that template, not only in this machine'sdms/binds.kdl.Mod+Shift+Dis not in that template either, so the Move Column Right bind on this machine was a local edit.