fix(poweraccent): Add injection hygiene and focus-loss cleanup#10
fix(poweraccent): Add injection hygiene and focus-loss cleanup#10crutkas wants to merge 3 commits into
Conversation
This comment has been minimized.
This comment has been minimized.
|
Incomplete locking around the new
So this is real cross-thread mutation: the hook-thread writers race the UI-thread reset. Without a guard on OnKeyDown/OnKeyUp the reset can observe partial state, miss writes, or race a flag flip and on the hook thread we can lose a write that ForceReset just did. Two safe fixes:
Either way, the current "lock only one writer" pattern is the canonical incomplete-locking shape and undoes most of the safety the mutex was meant to add. |
- Filter LLKHF_INJECTED events in LL hook to prevent cross-module triggers - Tag all SendInput output with dwExtraInfo for cross-hook identification - Add ForceReset() for focus-loss cleanup - Replace SendKeys.SendWait with tagged SendInput for arrow keys Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Selector_Deactivated now calls ForceReset, so losing focus mid-accent clears any half-pressed state instead of leaving the toolbar or shift modifiers stuck. OnKeyDown/OnKeyUp run on the low-level keyboard hook thread while ForceReset runs on the UI thread. The PowerAccent.cs callbacks Dispatcher.Invoke synchronously onto that UI thread, so holding a lock across the hook callbacks would deadlock against ForceReset. The shared flags and letterPressed are therefore std::atomic rather than mutex-guarded - race-free and lock-free on the hot hook path. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2dcbe36 to
f421f92
Compare
|
Went with the atomics option and dropped the mutex. Locking I also removed a broad |
PowerAccent injects VK_LEFT / VK_RIGHT to move the caret while selecting an accent. Without KEYEVENTF_EXTENDEDKEY the synthesized arrow keys carry the non-extended scan code, which some apps interpret as numpad navigation (affected by NumLock) rather than the dedicated arrow cluster. Set the extended-key flag on both the key-down and key-up INPUTs, matching how WinForms SendKeys synthesizes these keys. Also resolve two StyleCop errors in code this change set introduced, so the project builds clean: rename the POWERTOYS_INJECTED_TAG constant to PascalCase PowerToysInjectedTag (SA1310) and add the required blank line after the backspace send-failure check (SA1513). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Superseded by the upstream PR against microsoft/PowerToys: microsoft#48572 (rebased onto current main, builds/tests verified). Closing this intra-fork review PR. |
Summary
Add injection hygiene and focus-loss cleanup to PowerAccent (Quick Accent) to prevent cross-module stuck keys and stuck accent mode.
Changes
D1: Add
LLKHF_INJECTEDfilter to LL keyboard hookSkip injected events in
LowLevelKeyboardProc. Prevents Keyboard Manager remapped keys from triggering accent mode — e.g., if KBM remaps Q to A, pressing Q should not activate the accent toolbar for 'A'.D2: Tag all
SendInputoutput withdwExtraInfoPOWERTOYS_INJECTED_TAG = 0x110constantdwExtraInfoon allKEYBDINPUTstructs (backspace, character insertion)SendInputreturn value checking with error loggingD3: Add
ForceReset()for focus-loss cleanupForceReset()method onKeyboardListenerclears all state:letterPressed,m_toolbarVisible, trigger flags, shift flagsPowerAccent.Core.ForceResetKeyboardState()Selector.OnDeactivated— accent mode now cleans up when the window loses focus (Alt+Tab, click away, etc.)D4: Replace
SendKeys.SendWaitwith taggedSendInputSendKeys.SendWait("{RIGHT}")/"{LEFT}"withWindowsFunctions.SendArrowKey()SendInputinstead of blockingSendKeys.SendWaitdwExtraInfoso other hooks identify them as syntheticHow to Reproduce
D1 — Cross-module trigger:
D3 — Stuck accent mode:
Coordination
microsoft/PowerToysis also modifying PowerAccent shift state handling. Review both PRs together to avoid conflicts.PR Checklist