diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 322fce5..4d2207e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -283,11 +283,10 @@ jobs: Tagged releases also attach `vocalinux_${{ steps.get_version.outputs.VERSION }}_amd64.snap` and try the Snap Store (`edge` and `candidate`). `stable` is promoted from candidate after QA by the `snap-promote.yml` dispatch workflow. - Super-privileged plugs such as `uinput` can hold the Store revision in human - review; the GitHub `.snap` is the sideload in that case: + Wayland typing runs through the RemoteDesktop portal; the snap ships no `uinput` plug. + The GitHub `.snap` is also the sideload while a Store revision lags: ```bash sudo snap install --dangerous ./vocalinux_${{ steps.get_version.outputs.VERSION }}_amd64.snap - sudo snap connect vocalinux:uinput ``` `--dangerous` is required because this file is not a Store revision. It will not refresh from the Store. amd64 only. @@ -983,8 +982,8 @@ jobs: ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }} commit_message: 'Release ${{ github.ref_name }}' - # GitHub Release first, Store second. uinput is super-privileged, so the - # Store can queue a human review and refuse edge/candidate; the .snap still + # GitHub Release first, Store second. A super-privileged plug can still + # queue a human review and refuse edge/candidate; the .snap still # has to land on the tag for sideload. grade: stable allows candidate; do # not auto-release to stable — promote after QA via snap-promote.yml (#783). # Secret: SNAPCRAFT_STORE_CREDENTIALS (snapcraft export-login). diff --git a/README.md b/README.md index 979bf3d..96e07ee 100644 --- a/README.md +++ b/README.md @@ -217,16 +217,15 @@ sudo snap install vocalinux --edge sudo snap connect vocalinux:audio-record # if mic is not auto-connected sudo snap connect vocalinux:raw-input # global keyboard shortcuts (evdev) sudo snap connect vocalinux:hardware-observe # list keyboards (/proc/bus/input/devices) -sudo snap connect vocalinux:uinput # native Wayland typing (ydotool) ``` -v0.18.2 includes ydotool and the `uinput` plug. The Store still has to finish review of that plug, so `snap info vocalinux` may still show **v0.16.2** (rev 7) on edge. That revision has no `uinput` plug; `snap connect vocalinux:uinput` fails until a 0.18.0+ revision is listed. +Native Wayland typing uses the RemoteDesktop portal: the compositor asks once on first dictation, nothing to connect. The recipe ships **no `uinput` plug** and no ydotool; the Store denied the super-privileged grant, which held the 0.17.0+ revisions and left **v0.16.2 (rev 7)** on edge. On KDE Plasma, KWin's portal can mistype letter case ([KDE bug 489021](https://bugs.kde.org/show_bug.cgi?id=489021)); set Virtual Keyboard to "IBus Wayland" so dictation types correctly. -Until then, sideload the GitHub file: +The v0.18.x GitHub `.snap` still declares `uinput`, so KDE users who want ydotool can sideload it and connect the plug manually: ```bash sudo snap install --dangerous ./vocalinux_0.18.2_amd64.snap -sudo snap connect vocalinux:uinput +sudo snap connect vocalinux:uinput # only in the v0.18.x sideload; the recipe no longer ships it ``` ### Nix / NixOS (flake) diff --git a/docs/INSTALL.md b/docs/INSTALL.md index da2c711..b960910 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -169,22 +169,21 @@ sudo snap install vocalinux --edge sudo snap connect vocalinux:audio-record # if mic is not auto-connected sudo snap connect vocalinux:raw-input # global keyboard shortcuts (evdev) sudo snap connect vocalinux:hardware-observe # list keyboards (/proc/bus/input/devices) -sudo snap connect vocalinux:uinput # native Wayland typing (ydotool) ``` -**v0.18.2** ships ydotool and the `uinput` plug. That plug is super-privileged, so the Store held 0.18.0 for human review (`allow-installation`). Until a 0.18.0+ revision is listed, `snap info vocalinux` still shows **v0.16.2 (rev 7)** on edge. That revision has no `uinput` plug; `sudo snap connect vocalinux:uinput` fails. +Native Wayland typing uses the RemoteDesktop portal: the compositor asks once on first dictation, nothing to connect. The recipe ships **no `uinput` plug** and no ydotool; the Store denied the super-privileged grant ([the request thread](https://forum.snapcraft.io/t/53528)), which held the 0.17.0+ revisions and left **v0.16.2 (rev 7)** on edge. On KDE Plasma, KWin's portal can mistype letter case ([KDE bug 489021](https://bugs.kde.org/show_bug.cgi?id=489021)); set Virtual Keyboard to "IBus Wayland" so dictation types correctly. -Sideload the GitHub `.snap` (amd64) while the Store is waiting: +The v0.18.x GitHub `.snap` still declares `uinput`, so KDE users who want ydotool can sideload it and connect the plug manually: ```bash sudo snap install --dangerous ./vocalinux_0.18.2_amd64.snap sudo snap connect vocalinux:audio-record sudo snap connect vocalinux:raw-input sudo snap connect vocalinux:hardware-observe -sudo snap connect vocalinux:uinput +sudo snap connect vocalinux:uinput # only in the v0.18.x sideload; the recipe no longer ships it ``` -`--dangerous` is required because this file is not a Store revision. It will not refresh from the Store. After Canonical grants `uinput`, switch to `sudo snap install vocalinux --edge` (or `snap refresh`). +`--dangerous` is required because this file is not a Store revision and will not refresh from the Store; once the Store carries a newer revision, `sudo snap install vocalinux --edge` (or `snap refresh`) replaces it. ## Nix / NixOS diff --git a/docs/RELEASE_PROCESS.md b/docs/RELEASE_PROCESS.md index 510f4c5..d2da311 100644 --- a/docs/RELEASE_PROCESS.md +++ b/docs/RELEASE_PROCESS.md @@ -397,8 +397,8 @@ After pushing the tag, the GitHub Actions workflow will automatically: docs/FLATPAK_REMOTE.md) 8. Deploy the website to vocalinux.com 9. Build the amd64 snap, attach it to the GitHub Release, and try Snap Store - `edge`/`candidate`. Store human review (for example `uinput` allow-installation) - must not block the GitHub `.snap`. `stable` does not auto-release (#783): + `edge`/`candidate`. Store human review (for example a super-privileged + `allow-installation` plug) must not block the GitHub `.snap`. `stable` does not auto-release (#783): after candidate QA, dispatch `snap-promote.yml`, which releases the candidate revision to `latest/stable` 10. Mark as pre-release if version contains alpha/beta/rc @@ -412,7 +412,7 @@ Monitor at: https://github.com/VocaHQ/vocalinux/actions both AppImages, both Flatpaks, the amd64 snap, the `.deb` and `.rpm` for both arches) - the release notes tell users to run `sha256sum -c` against it -- [ ] If the Store held the snap for `uinput` review, confirm the GitHub `.snap` +- [ ] If the Store holds the snap for human review, confirm the GitHub `.snap` is still attached and the notes document `snap install --dangerous` - [ ] After candidate QA (install, tray, mic, model download, typing into a real app), promote the snap to stable: diff --git a/docs/UPDATE.md b/docs/UPDATE.md index b9be644..bf3f822 100644 --- a/docs/UPDATE.md +++ b/docs/UPDATE.md @@ -38,7 +38,7 @@ git pull origin main |--------|---------| | AUR | `yay -S vocalinux` (or your AUR helper) | | AppImage | Download the new file from [Releases](https://github.com/VocaHQ/vocalinux/releases) | -| Snap | Store: `sudo snap refresh vocalinux` (`--edge` until stable is promoted). Until Canonical lists 0.18.2, sideload `vocalinux_0.18.2_amd64.snap` from the GitHub Release (`sudo snap install --dangerous ./vocalinux_0.18.2_amd64.snap`), then `sudo snap connect vocalinux:uinput`. v0.16.2 rev 7 has no such plug. | +| Snap | Store: `sudo snap refresh vocalinux` (`--edge` until stable is promoted). The recipe ships no `uinput` plug (the Store denied the grant); Wayland typing uses the RemoteDesktop portal. The GitHub `vocalinux_0.18.2_amd64.snap` still declares `uinput` for KDE users who want ydotool (`sudo snap install --dangerous`, then `sudo snap connect vocalinux:uinput`). | | Flatpak (release bundle) | Install the new `.flatpak` from Releases; bundles do not auto-update | | PyPI | Reinstall in the same venv after system packages are current | @@ -200,7 +200,7 @@ See the [full changelog](https://github.com/VocaHQ/vocalinux/releases/tag/v0.18. | **Searchable open picker** | Language list filters while open (#798) | | **Localized punctuation commands** | it/fr/de/es/pt/nl/pl/ru; English phrases still work (#642) | | **Bare F-keys** | F1–F24 are valid push-to-talk shortcuts (#815) | -| **Snap** | Store listing, ydotool + `uinput` for native Wayland; GitHub `.snap` for sideload while Store review is pending (#519, #823, #822) | +| **Snap** | Store listing, ydotool + `uinput` for native Wayland. The Store later denied the `uinput` grant, so the plug was dropped and Wayland typing moved to the RemoteDesktop portal (#519, #823, #822) | | **Flatpak on the tag** | Workflow attaches `.flatpak` assets and checksums them (#786) | ### Also in v0.17.0 @@ -260,7 +260,7 @@ See the [full changelog](https://github.com/VocaHQ/vocalinux/releases/tag/v0.17. - **CI**: gate AUR PKGBUILD builds on every PR (#772 by @sesav) - **CI / docs**: test the distros the docs promise and fix docs drift (#773 by @sesav) - **Site**: VocaGateway family card is Beta; README logo, badges, and privacy copy (#765 by @jatinkrmalik, #764) -- **Snap**: v0.16.2 `latest/edge` (rev 7) has no `uinput` plug. `sudo snap connect vocalinux:uinput` errors with `snap "vocalinux" has no plug named "uinput"`. Dictation only reaches XWayland apps. A later store snap ships ydotool and the plug; then `snap refresh` and `snap connect vocalinux:uinput` (#823) +- **Snap**: v0.16.2 `latest/edge` (rev 7) has no `uinput` plug. `sudo snap connect vocalinux:uinput` errors with `snap "vocalinux" has no plug named "uinput"`. Dictation only reaches XWayland apps. (v0.17.0+ added the plug, but the Store denied it, so later revisions drop it again and type via the RemoteDesktop portal.) (#823) See the [full changelog](https://github.com/VocaHQ/vocalinux/releases/tag/v0.16.2). diff --git a/docs/USER_GUIDE.md b/docs/USER_GUIDE.md index 23595b7..7bfde58 100644 --- a/docs/USER_GUIDE.md +++ b/docs/USER_GUIDE.md @@ -304,7 +304,7 @@ Pin the backend explicitly in `~/.config/vocalinux/config.json`: |---|---| | `auto` | Autodetect (default; autodetection may select IBus) | | `ibus` | IBus input method; on Wayland, bypasses compositor checks and may silently do nothing in native Wayland apps | -| `portal` | RemoteDesktop portal (Wayland; the sandboxed path, asks for permission once, works under Flatpak) | +| `portal` | RemoteDesktop portal (Wayland; the sandboxed path, asks for permission once, works under Flatpak and Snap) | | `wtype` | wtype virtual keyboard (Wayland) | | `ydotool` | ydotool uinput (Wayland; needs `ydotoold`) | | `xdotool` | xdotool (X11). On Wayland it only turns IBus off -- the Wayland tool is still picked automatically | diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 55e3450..911612d 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -1,7 +1,7 @@ # Vocalinux Snap packaging # # First ship: strict confinement, default whisper.cpp engine path, GTK tray UI, -# mic capture, model download, and text injection (ydotool/uinput, wtype, xdotool). +# mic capture, model download, and text injection (RemoteDesktop portal, wtype, xdotool). # Informed by issue #48 and packaging/flatpak lessons on feat/flatpak-packaging. # # Build (from repo root, with snapcraft + LXD or Multipass): @@ -26,13 +26,16 @@ description: | - System tray control and GTK settings - Offline dictation (models download on first use) - Microphone capture and short feedback tones - - Text injection via ydotool (native Wayland/X11), wtype, or xdotool + - Text injection via the Wayland RemoteDesktop portal, wtype, or xdotool Sandbox notes: - Global hotkeys need: sudo snap connect vocalinux:raw-input and sudo snap connect vocalinux:hardware-observe - - Native Wayland typing needs: sudo snap connect vocalinux:uinput - (v0.17.0 ships the plug; v0.16.2 edge (rev 7) has no uinput plug; refresh first) + - Native Wayland typing uses the RemoteDesktop portal: the compositor + asks once on first dictation. The snap ships no uinput plug and no + ydotool; the Store denied the super-privileged grant. + - KDE Plasma: KWin's portal can mistype letter case (KDE bug 489021); + set "Virtual Keyboard = IBus Wayland" so the IBus path delivers text. - Microphone may need: sudo snap connect vocalinux:audio-record - Config and models live under ~/snap/vocalinux/ @@ -65,10 +68,10 @@ apps: # Needed for /proc/bus/input/devices; not auto-connected: # sudo snap connect vocalinux:hardware-observe - hardware-observe - # ydotool writes to /dev/uinput so dictation reaches native Wayland apps. - # Super-privileged: not auto-connected; user must: - # sudo snap connect vocalinux:uinput - - uinput + # No uinput plug; the RemoteDesktop portal types on Wayland instead. + # The Store denied the super-privileged grant + # (https://forum.snapcraft.io/t/53528), and ydotool is not staged + # because it cannot reach /dev/uinput under confinement. common-id: com.vocalinux.Vocalinux desktop: usr/share/applications/vocalinux.desktop environment: @@ -122,7 +125,6 @@ parts: - pulseaudio-utils # paplay for start/stop UI sounds - xdotool - wtype # virtual-keyboard protocol (GNOME often rejects this) - - ydotool # uinput; reaches native Wayland apps (needs vocalinux:uinput) - x11-utils # xprop for XWayland WM_CLASS - xsel - xclip diff --git a/src/vocalinux/text_injection/text_injector.py b/src/vocalinux/text_injection/text_injector.py index a701f26..f91b647 100644 --- a/src/vocalinux/text_injection/text_injector.py +++ b/src/vocalinux/text_injection/text_injector.py @@ -507,7 +507,9 @@ class TextInjector: start the daemon on demand when the app is granted device access. Host ydotool 0.1.x often works without a daemon; starting one is still safe when ydotoold is installed. The CLI still needs a writable - /dev/uinput (Snap: ``snap connect vocalinux:uinput``). + /dev/uinput (the v0.18.x GitHub sideload Snap declares the plug: + ``snap connect vocalinux:uinput``; the Store snap ships neither plug + nor ydotool). """ if self._is_ydotoold_running(): return True @@ -594,7 +596,8 @@ class TextInjector: """How to grant ydotool access to ``/dev/uinput`` in this install.""" if os.environ.get("SNAP"): return ( - "ydotool cannot open /dev/uinput. For the Snap, run: " + "ydotool cannot open /dev/uinput. The Store snap ships no " + "uinput plug; only the v0.18.x GitHub sideload declares it: " "sudo snap connect vocalinux:uinput" ) return ( @@ -609,8 +612,9 @@ class TextInjector: if not os.environ.get("SNAP"): return logger.warning( - "Snap XWayland fallback only types into X11/XWayland apps. " - "Native Wayland apps need: sudo snap connect vocalinux:uinput" + "Snap XWayland fallback only types into X11/XWayland apps. The " + "Store snap ships no uinput plug; native Wayland typing needs the " + "RemoteDesktop portal or, on KDE, IBus Wayland." ) @staticmethod diff --git a/tests/test_snap_packaging.py b/tests/test_snap_packaging.py index b82095a..09a60e4 100644 --- a/tests/test_snap_packaging.py +++ b/tests/test_snap_packaging.py @@ -26,9 +26,11 @@ def test_snapcraft_recipe_and_gui_assets() -> None: assert "raw-input" in plugs assert "hardware-observe" in plugs assert "audio-record" in plugs - assert "uinput" in plugs + # The Store denied the super-privileged uinput grant; the plug (and the + # uinput-only ydotool) must stay out or every revision is held in review. + assert "uinput" not in plugs stage = doc["parts"]["vocalinux"].get("stage-packages") or [] - assert "ydotool" in stage + assert "ydotool" not in stage recipe_text = SNAPCRAFT_YAML.read_text(encoding="utf-8") assert "sudo snap connect vocalinux:raw-input" in recipe_text @@ -65,8 +67,8 @@ def test_snap_docs_tell_users_to_connect_hardware_observe() -> None: assert "sudo snap connect vocalinux:hardware-observe" in text -def test_snap_docs_warn_that_0162_has_no_uinput_plug() -> None: - """v0.16.2 edge (rev 7) has no uinput plug; the connect command must not stand alone.""" +def test_snap_docs_explain_typing_without_uinput_plug() -> None: + """The Store denied the uinput grant; docs must point at the portal, not a connect.""" readme = (REPO_ROOT / "README.md").read_text(encoding="utf-8") install = (REPO_ROOT / "docs" / "INSTALL.md").read_text(encoding="utf-8") update = (REPO_ROOT / "docs" / "UPDATE.md").read_text(encoding="utf-8") @@ -78,8 +80,8 @@ def test_snap_docs_warn_that_0162_has_no_uinput_plug() -> None: uinput_lines = "\n".join(line for line in text.splitlines() if "uinput" in line.lower()) lowered = uinput_lines.lower() assert "uinput" in lowered - assert "0.16.2" in uinput_lines or "rev 7" in lowered assert "plug" in lowered and "no" in lowered + assert "portal" in lowered def test_snap_strips_pygobject_and_uses_gnome_gi() -> None: @@ -96,7 +98,7 @@ def test_snap_strips_pygobject_and_uses_gnome_gi() -> None: def test_release_attaches_snap_then_tries_the_store() -> None: - """Store review of uinput must not swallow the GitHub .snap (v0.17.0).""" + """A Store human review must not swallow the GitHub .snap (v0.17.0, uinput).""" text = (REPO_ROOT / ".github" / "workflows" / "release.yml").read_text(encoding="utf-8") assert " build-snap:\n" in text assert " attach-snap:\n" in text @@ -137,7 +139,8 @@ def test_release_attaches_snap_then_tries_the_store() -> None: def test_release_notes_document_snap_sideload() -> None: body = (REPO_ROOT / ".github" / "workflows" / "release.yml").read_text(encoding="utf-8") assert "snap install --dangerous" in body - assert "snap connect vocalinux:uinput" in body + assert "RemoteDesktop portal" in body + assert "no `uinput` plug" in body assert "vocalinux_${{ steps.get_version.outputs.VERSION }}_amd64.snap" in body diff --git a/web/src/app/changelog/page.tsx b/web/src/app/changelog/page.tsx index c307ca1..243c27a 100644 --- a/web/src/app/changelog/page.tsx +++ b/web/src/app/changelog/page.tsx @@ -87,7 +87,7 @@ const releases = [ "Recommended model button sets size and specialization together and will not ignore a file already on disk (PR #797, #778)", "Localized punctuation voice commands for it/fr/de/es/pt/nl/pl/ru (PR #642, #640)", "Bare F1–F24 push-to-talk shortcuts (PR #815)", - "Snap packaging with ydotool and uinput for native Wayland; GitHub .snap sideload while Store review of uinput is pending (PR #519, #823, #822)", + "Snap packaging with ydotool and uinput for native Wayland; the Store denied the uinput grant, so later revisions drop the plug and type via the RemoteDesktop portal (PR #519, #823, #822)", "Release workflow attaches Vocalinux--{x86_64,aarch64}.flatpak (PR #786, #784)", "XWayland clipboard paste instead of layout-garbled xdotool type (PR #680, #657)", "Layout-aware Ctrl+V paste; ydotool releases Ctrl after a timed-out paste (PR #788, #675, #658)", @@ -116,7 +116,7 @@ const releases = [ "CI: gate AUR PKGBUILD builds on every PR; test the distros the docs promise and fix docs drift (PR #772, #773)", "Site: VocaGateway family card is Beta; README logo, badges, and privacy copy (PR #765, #764)", "Deps: bump the github-actions group (PR #766)", - "Snap 0.16.2 edge (rev 7) has no uinput plug: snap connect vocalinux:uinput fails, and dictation only reaches XWayland apps. A later store snap ships ydotool; refresh, then connect uinput (PR #823)", + "Snap 0.16.2 edge (rev 7) has no uinput plug: snap connect vocalinux:uinput fails, and dictation only reaches XWayland apps. Later revisions ship the RemoteDesktop portal instead; the Store denied the uinput grant (PR #823)", ], }, {