Win32: keys stay in heldKeys after the window loses the keyboard #180

Open
opened 2026-10-31 17:22:45 +00:00 by jorijnvdgraaf · 0 comments

Summary

On Win32 nothing empties Window::heldKeys when the window loses the keyboard. A key held while the user Alt+Tabs away, or clicks another window, stays in heldKeys, because its WM_KEYUP goes to the window that has the focus by then. Line numbers refer to 852ae8a.

  • heldKeys is written only by the WM_KEYDOWN/WM_SYSKEYDOWN and WM_KEYUP/WM_SYSKEYUP cases (implementations/Crafter.Graphics-Window.cpp:189, :198). WndProc has no WM_KILLFOCUS or WM_ACTIVATE case.
  • Wayland empties it on wl_keyboard.leave (implementations/Crafter.Graphics-Device.cpp:582).
  • Input reads it on every tick (implementations/Crafter.Graphics-Input.cpp:53, :98-101).

So: hold W, Alt+Tab away, release both keys in the other window. W and Alt stay in heldKeys, and every KeyBind or WASDBind on them reads as held, in the background and after the window comes back, until each key is pressed and released in this window again.

Found while reviewing claude/win32-title.

Suggested fix

Handle WM_KILLFOCUS: clear heldKeys, as Wayland's leave does (or fire onRawKeyUp for each key first, if the backends should agree on that), and pass the message on to DefWindowProc. A Win32 test can post WM_KEYDOWN, then WM_KILLFOCUS, and expect heldKeys empty.

## Summary On Win32 nothing empties `Window::heldKeys` when the window loses the keyboard. A key held while the user Alt+Tabs away, or clicks another window, stays in `heldKeys`, because its `WM_KEYUP` goes to the window that has the focus by then. Line numbers refer to `852ae8a`. - `heldKeys` is written only by the `WM_KEYDOWN`/`WM_SYSKEYDOWN` and `WM_KEYUP`/`WM_SYSKEYUP` cases (`implementations/Crafter.Graphics-Window.cpp:189`, `:198`). `WndProc` has no `WM_KILLFOCUS` or `WM_ACTIVATE` case. - Wayland empties it on `wl_keyboard.leave` (`implementations/Crafter.Graphics-Device.cpp:582`). - `Input` reads it on every tick (`implementations/Crafter.Graphics-Input.cpp:53`, `:98-101`). So: hold W, Alt+Tab away, release both keys in the other window. W and Alt stay in `heldKeys`, and every `KeyBind` or `WASDBind` on them reads as held, in the background and after the window comes back, until each key is pressed and released in this window again. Found while reviewing `claude/win32-title`. ## Suggested fix Handle `WM_KILLFOCUS`: clear `heldKeys`, as Wayland's leave does (or fire `onRawKeyUp` for each key first, if the backends should agree on that), and pass the message on to `DefWindowProc`. A Win32 test can post `WM_KEYDOWN`, then `WM_KILLFOCUS`, and expect `heldKeys` empty.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Catcrafts/Crafter.Graphics#180
No description provided.