Skip to content

Implement keyboard event hook on Windows - #212

Merged
micahrj merged 13 commits into
RustAudio:masterfrom
estroBiologist:keyboard-hook
Oct 29, 2025
Merged

micahrj merged 13 commits into
RustAudio:masterfrom
estroBiologist:keyboard-hook

Conversation

@estroBiologist

Copy link
Copy Markdown
Contributor

This PR implements keyboard event hooking on Windows, a technique also used by JUCE to get around restrictions on keyboard input imposed by various hosts. By intercepting Win32 messages using SetWindowsHookEx, we can bypass the host and forward keyboard messages to the baseview window directly.

This resolves the longstanding issue with keyboard input in Ableton, and likely renders many existing hacks for this problem obsolete (though I haven't tested that part yet.)

The meat of the implementation is in the new src/win/hook.rs module, which registers a simple event hook that intercepts keyboard-related WM_ events addressed to baseview windows, and forwards them into the relevant window's event handler directly, consuming the message in the process.

Couple notes:

  • There's some pretty nasty code for detecting baseview windows and forwarding events to them in hook.rs. If anyone has any better ideas for how to achieve this, I'm all ears, but it does seem to work as is.
  • I had to add the dtor crate to the windows dependencies to properly detach the hook on DLL exit. Hope that's okay!
  • I tried to keep the code reasonably clean, but neither my Win32 nor my Unsafe Rust skills are particularly great, so I hope it's all up to snuff.

The keyboard hook in action:
yesssss

Comment thread src/win/hook.rs Outdated
Comment thread src/win/hook.rs Outdated
Comment thread src/win/hook.rs Outdated
Comment thread src/win/hook.rs
Comment thread src/win/hook.rs Outdated
@estroBiologist

Copy link
Copy Markdown
Contributor Author

(Just for the record: it turns out the message zeroing is in fact important (causes duplicate inputs if omitted) and we agreed in the Discord to leave it in)

Comment thread src/win/hook.rs Outdated
@micahrj
micahrj merged commit 101c864 into RustAudio:master Oct 29, 2025
3 checks passed
Hornfisk added a commit to hyperfocusdsp/niner that referenced this pull request Apr 22, 2026
The pinned nih-plug commit `28b149e` transitively pulls baseview at
`9a0b42c` (via egui-baseview) and `579130e` (direct). Both pins predate
RustAudio/baseview#212 — "Implement keyboard event hook on Windows" —
which adds a `SetWindowsHookEx` keyboard hook that forwards WM_KEYDOWN
to the baseview window. Without it, Win32 hosts (and the standalone
harness here) never deliver key events to egui.

Confirmed via diagnostic logging in the previous commit: zero
`[keyboard] event #...` lines in slammer.log after a full user test
session on Windows, despite audio and mouse input working fine.

Patch baseview via a `[patch."https://github.com/RustAudio/baseview.git"]`
entry pointing at a Hornfisk/baseview fork at master (237d323, which
includes #212). Cargo requires the patch source URL to differ from the
URL being patched, hence the fork. The PR is a pure add with no public
API change — both dependents compile unchanged.

Lockfile delta: only the two baseview entries are replaced. All other
pinned versions are preserved.
Hornfisk added a commit to hyperfocusdsp/niner that referenced this pull request Apr 22, 2026
Windows standalone is now usable end-to-end: T/Space shortcuts fire,
BOUNCE renders without crashing the paint thread, and any future panic
lands in the persistent log with location + backtrace. Baseview patched
to RustAudio/baseview#212 so plugin hosts that intercept keyboard
messages (Ableton etc.) route them to Slammer.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
BurningTreeC added a commit to BurningTreeC/gainstagefx that referenced this pull request Sep 24, 2026
A Windows host's message loop sees every keystroke before the plugin.
The reporting host dispatches the key-down but keeps the WM_CHAR for its
own shortcuts, and baseview holds each key-down back until its WM_CHAR
arrives, so every letter was lost while Delete and the arrows worked.

Backport upstream baseview's WH_GETMESSAGE keyboard hook
(RustAudio/baseview#212), narrowed to exist only while a text field is
open, so the host keeps the space bar the rest of the time. The editor
switches it with the new baseview::set_text_input, kept in step with the
save dialog. While a field is open the window also takes Win32 focus and
gives it back afterwards. The hook is reference-counted per thread and
removed when the last field closes or its window is destroyed.

Saving from scratch no longer offers the "-" (nothing loaded) as a name.

Native tests under Wine reproduce the lost letter and cover the fix,
gating, focus and hook lifetime.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XDe7439i4Ka11arrBhnXq2
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