Skip to content

CmdPal: Fix crash on summon when UseLowLevelGlobalHotkey is enabled#47409

Draft
Copilot wants to merge 2 commits into
mainfrom
copilot/fix-cmdpal-crash-on-summon
Draft

CmdPal: Fix crash on summon when UseLowLevelGlobalHotkey is enabled#47409
Copilot wants to merge 2 commits into
mainfrom
copilot/fix-cmdpal-crash-on-summon

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 29, 2026

Summary of the Pull Request

Fixes RPC_E_CANTCALLOUT_ININPUTSYNCCALL (0x8001010D) crash when CmdPal is summoned via the low-level keyboard hook (UseLowLevelGlobalHotkey). The WH_KEYBOARD_LL hook fires on an input-synchronous thread; calling HandleSummon directly from it triggered HideWindow()ShowWindow → WinUI COM calls, which COM forbids in that context.

PR Checklist

  • Communication: I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected
  • Tests: Added/updated and all pass
  • Localization: All end-user-facing strings can be localized
  • Dev docs: Added/updated
  • New binaries: Added on the required places
  • Documentation updated: If checked, please file a pull request on our docs repo and link it here: #xxx

Detailed Description of the Pull Request / Additional comments

MainWindow.xaml.csSetProcessCommand registration

The ProcessCommand delegate passed to KeyboardListener was a direct method reference, so HandleSummon ran synchronously on the hook thread. Wrapping it with DispatcherQueue.TryEnqueue posts the work to the UI thread's message queue, ensuring it executes after the hook callback returns:

// Before
_keyboardListener.SetProcessCommand(new CmdPalKeyboardService.ProcessCommand(HandleSummon));

// After
_keyboardListener.SetProcessCommand(new CmdPalKeyboardService.ProcessCommand(
    (id) => DispatcherQueue.TryEnqueue(() => HandleSummon(id))));

The WM_HOTKEY path (HotKeyPrc) is unaffected — it already runs on the UI thread's message pump.

Validation Steps Performed

  • Code review and static analysis passed with no blocking issues.
  • The fix is logically equivalent to the existing pattern used elsewhere in MainWindow (e.g. SettingsChangedHandler, DragCompletedMessage) where off-thread callbacks are marshalled to the UI thread via DispatcherQueue.TryEnqueue.

Copilot AI linked an issue Apr 29, 2026 that may be closed by this pull request
When UseLowLevelGlobalHotkey is enabled, the ProcessCommand callback is
invoked directly from the WH_KEYBOARD_LL low-level keyboard hook, which
is an input-synchronous context. Calling ShowWindow/Hide from that
context triggers WinUI COM calls that COM forbids inside input-sync
calls, causing RPC_E_CANTCALLOUT_ININPUTSYNCCALL (0x8001010D).

Fix: wrap the callback with DispatcherQueue.TryEnqueue so HandleSummon
runs on the UI thread after the hook callback returns.

Agent-Logs-Url: https://github.com/microsoft/PowerToys/sessions/17ab0175-9459-4b42-928e-5f7f27b97f6a

Co-authored-by: MuyuanMS <116717757+MuyuanMS@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix CmdPal crash on summon CmdPal: Fix crash on summon when UseLowLevelGlobalHotkey is enabled Apr 29, 2026
Copilot AI requested a review from MuyuanMS April 29, 2026 10:02
@niels9001 niels9001 added the Product-Command Palette Refers to the Command Palette utility label Apr 29, 2026
@MuyuanMS MuyuanMS requested a review from Copilot May 14, 2026 03:09
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a crash when Command Palette is summoned via the low-level global hotkey (UseLowLevelGlobalHotkey) by ensuring the summon handler runs on the UI thread rather than directly on the WH_KEYBOARD_LL hook callback thread (which is an input-synchronous context and can’t safely perform WinUI/COM window operations).

Changes:

  • Wrapes the KeyboardListener ProcessCommand callback to enqueue HandleSummon onto the window DispatcherQueue.
  • Adds detailed inline documentation explaining the RPC_E_CANTCALLOUT_ININPUTSYNCCALL (0x8001010D) failure mode and why dispatching resolves it.

Comment on lines +146 to 147
(id) => DispatcherQueue.TryEnqueue(() => HandleSummon(id))));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Product-Command Palette Refers to the Command Palette utility

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CmdPal: Crash on summon

4 participants