mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-07-09 03:49:52 +02:00
## Summary Fixes stuck modifier keys and silently-dropped remaps on Keyboard Manager's **single key → text** path, and adds unit coverage (including a mockable injection-failure seam). ## What this changes 1. **Insert a dummy key event before releasing held modifiers.** Releasing a lone Win or Alt key-up otherwise triggers the Start Menu / menu bar. The dummy key absorbs it so the release is inert. The dummy + releases are only injected when a modifier is actually held. 2. **Accept `WM_SYSKEYDOWN` as well as `WM_KEYDOWN`.** While Alt is held the system delivers `WM_SYSKEYDOWN`, so the previous `WM_KEYDOWN`-only guard silently dropped the remap whenever Alt was down. 3. **Route `Helpers::SendTextInput` through `InputInterface`** instead of calling Win32 `SendInput` directly. Besides making the path mockable, this stops the existing unit tests from injecting real keystrokes into the OS during a test run. Text is still flushed per character to preserve the existing batching workaround. 4. **Never re-press released modifiers.** Once a modifier key-up is injected, `GetAsyncKeyState` reports it as up, so re-pressing risks leaving it stuck if the user let go during injection. Leaving it released is always safe. ## Testing - New `MockedInput` failure seam (`SetSendVirtualInputShouldFail`). - `RemappedKey_ShouldPassOriginalKeyThrough_WhenInjectionFails` — verifies the original key is passed through when injection fails (the core stuck-key behavior, previously untestable because the mock always succeeded). - `HandleSingleKeyToTextRemapEvent_ShouldFireAndReleaseAlt_WhenAltIsHeld` — covers fix #2 by asserting the remap still fires (and releases the held Alt) when the key arrives as `WM_SYSKEYDOWN`. - Full Keyboard Manager engine suite: **98/98 passing**, Release x64, against current `main`. This is one of a small set of related "stuck key" hardening fixes; each stands alone. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>