Skip to content

fix(linux): add 'None' keyboard implementation for Wayland compositors#1300

Open
aasmall wants to merge 1 commit intocjpais:mainfrom
aasmall:linux-none-keyboard
Open

fix(linux): add 'None' keyboard implementation for Wayland compositors#1300
aasmall wants to merge 1 commit intocjpais:mainfrom
aasmall:linux-none-keyboard

Conversation

@aasmall
Copy link
Copy Markdown

@aasmall aasmall commented Apr 15, 2026

Before Submitting This PR

Human Written Description

When running Handy on Arch/Omarchy/Wayland systems, none of the hotkey subsystems are compatible. Wayland compositor itself is effective, so suggesting a "none" keyboard shortcut option to disable both handykeys and Tauri.

Prior art and why this is still useful

Wayland keyboard shortcuts are an active area with multiple open PRs taking different approaches. I want to be explicit that this PR is complementary, not competing, with that work:

  • PR #1287 — "xdg-desktop-portal GlobalShortcuts backend for Wayland" is the "proper" freedesktop-standard approach. It works well on KDE Plasma. Notably, its own description acknowledges that "GNOME 49's portal (v1) rejects bind_shortcuts for non-Flatpak apps" — so there are real compositors where it falls back to Tauri (which doesn't work on Wayland).
  • PR #572 — "Wayland support with GNOME system shortcuts" is a GNOME-specific gsettings + SIGUSR2 workaround. Only supports toggle mode (no push-to-talk) and is GNOME-only.
  • Discussion #294 — "Is there any command line can trigger the voice recording? global key not work on wayland" asks for exactly the workflow this PR enables.
  • Discussion #415 — "Support for COSMIC 24.04 Wayland" — another compositor that needs a path forward.

Why "None" still has value when #1287 exists: The portal approach works where portals are implemented correctly. The "None" approach works anywhere the user can bind a keyboard shortcut to a command — which is every Wayland compositor on earth (Hyprland, Sway, Niri, River, COSMIC, KDE, GNOME, anything wlroots-based, etc.). These are complementary:

Mode Best for Limitations
Tauri X11 only Broken on Wayland
Handy Keys X11 Broken on Wayland
Portal (PR #1287) KDE, Flatpak builds on GNOME Not all compositors implement portal; GNOME portal rejects non-Flatpak bind_shortcuts
None (this PR) Any compositor with keybind config User has to set up the keybind manually

I'd be happy to defer to #1287 being merged first if @cjpais prefers — the two can coexist, and having "None" as a documented escape hatch for users where the portal doesn't work seems valuable regardless.

Related Issues/Discussions

Relevant to several open bugs around broken keyboard shortcuts on Linux/Wayland:

  • #102 — Keyboard shortcuts not working on Ubuntu/Wayland. "None" mode lets users bypass broken global shortcut detection entirely.
  • #1162 — Push-to-talk stuck in cancel state on Linux. Related to unreliable global shortcut grabbing — "None" mode avoids this by deferring to the compositor.
  • #1019 — Linux version does not allow single-key transcribe shortcut. Compositor keybinds don't have this limitation.

Changes

  • New KeyboardImplementation::None variant handled in all match arms (init, register, unregister, validate, parse, get)
  • "None (Compositor Only)" is only exposed in the dropdown on Linux. Tauri and Handy Keys work reliably on macOS and Windows, so surfacing a "disable all hotkeys" option there would be a footgun. The enum variant exists cross-platform for data model completeness, but the UI gates it behind a runtime platform check.
  • When None is selected, the shortcut binding UI is hidden and replaced with a hint explaining compositor keybind setup
  • Updated keyboard implementation description to mention the "None" option for Wayland users
  • Full translations for the new shortcutsDisabledHint string across all 19 non-English locales

Files changed: settings.rs (None variant + tests with local settings_with_keyboard_override helper), shortcut/mod.rs (match arms + parse tests), bindings.ts, KeyboardImplementationSelector.tsx (platform-gated dropdown), GeneralSettings.tsx (hint when disabled), translation.json + 19 locale files

Testing

  • Tested on Framework 13 AMD (Ryzen AI 300, Radeon 880M) running Arch Linux with Hyprland
  • "None" keyboard mode: compositor keybind (Ctrl+Shift+Space → handy --toggle-transcription) works reliably, no stuck states
  • UX hint displays correctly when "None" is selected, shortcut binding UI hides properly
  • Switching back to Tauri/Handy Keys restores shortcut UI
  • No regressions on existing keyboard implementation behavior

Auto-triggered CI checks verified locally before marking ready:

  • cargo fmt --check, cargo test (new KeyboardImplementation::None parse + deserialize tests pass)
  • bun run lint, bun run format:check (excluding upstream's pre-existing AGENTS.md prettier issue)
  • bun run check:translations — all 20 languages have complete keys
  • bun run test:playwright — passes

Screenshots/Videos

screenshot-2026-04-17_11-45-41

AI Assistance

  • AI was used (please describe below)

If AI was used:

  • Tools used: Claude Code (Claude Opus 4.7), with code review from CodeRabbit, OpenAI Codex (GPT-5.2), and Grok
  • How extensively: Claude Opus wrote the implementation with human direction on approach (first-class "None" option rather than patching global shortcuts, platform-gating the dropdown). Multiple rounds of independent AI code review — every actionable finding was either addressed or consciously declined with a documented reason. Translations for the 19 non-English locales generated by Claude. Human tested on real hardware, surveyed existing PRs for positioning, and made scope decisions.

@aasmall aasmall force-pushed the linux-none-keyboard branch 5 times, most recently from 3357c0a to 7cac7d7 Compare April 17, 2026 18:55
Tauri Global Shortcut and Handy Keys both have reliability issues on
Wayland (lost modifier state, missed keypresses, dynamic shortcut
instability). Adds a 'None' variant that disables built-in hotkey
handling so users can bind 'handy --toggle-transcription' in their
compositor instead (e.g. Hyprland, Sway, KDE KWin).

When 'None' is selected, the shortcut binding UI is hidden and replaced
with a hint explaining the compositor keybind workflow.
@aasmall aasmall force-pushed the linux-none-keyboard branch from 7cac7d7 to 95df489 Compare April 17, 2026 19:09
@aasmall aasmall marked this pull request as ready for review April 17, 2026 19:20
@blockedby
Copy link
Copy Markdown

bump

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants