Skip to content

feat(win32): support dead-key hotkeys via native keyboard hook#341

Open
hanselstner wants to merge 1 commit intoOpenWhispr:mainfrom
hanselstner:feat/dead-key-hotkey
Open

feat(win32): support dead-key hotkeys via native keyboard hook#341
hanselstner wants to merge 1 commit intoOpenWhispr:mainfrom
hanselstner:feat/dead-key-hotkey

Conversation

@hanselstner
Copy link

Summary

Adds native Windows low-level keyboard hook support for dead-key hotkeys (e.g., ^ on German QWERTZ, ` on US layouts). These keys are consumed by the OS input method before Electron's globalShortcut API can detect them.

Changes

  • resources/windows-key-listener.c: Add dead-key virtual key code mapping (VK_OEM_1VK_OEM_8) so the native listener recognises keys like ^, `, ~, ´
  • src/helpers/windowsKeyManager.js: Map dead-key characters to their VK names and route them to the native binary
  • src/helpers/hotkeyManager.js: Detect dead keys and delegate to the native Windows listener instead of Electron's globalShortcut
  • src/components/ui/HotkeyInput.tsx: Capture raw event.code for dead keys (which produce no event.key value) and map to the printable character
  • src/hooks/useHotkey.js: Skip globalShortcut polling for dead-key hotkeys since they're handled natively

Test plan

  1. On a German QWERTZ keyboard, set ^ as the dictation hotkey
  2. Verify the hotkey registers and starts/stops recording
  3. Verify pressing ^ does not leak the character into focused text fields
  4. Verify non-dead-key hotkeys (e.g., F8) still work as before
  5. Verify macOS/Linux are unaffected (no dead-key code paths execute)

Pull Request opened by Augment Code with guidance from the PR author

On non-US keyboard layouts (e.g. German QWERTZ), certain keys like
the circumflex are dead keys -- they do not produce a character on
their own and are invisible to Electron's globalShortcut API.

This commit adds support for dead-key hotkeys by:

- Mapping circumflex/Caret to VK_OEM_5 in the native Windows key
  listener (windows-key-listener.c)
- Detecting dead keys (e.key === "Dead") in HotkeyInput and resolving
  them via a dead-key override map
- Adding a hasNonStandardKey() helper that routes these keys through
  the native Windows keyboard hook instead of globalShortcut
- Swallowing captured key events in the hook to prevent dead-key
  characters from leaking into focused text fields

Tested on Windows 11 with German QWERTZ layout using circumflex as
the dictation hotkey in both tap and push-to-talk modes.
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.

1 participant