Skip to content

[Keyboard Manager] Toggle module hotkey/shortcut#42472

Merged
niels9001 merged 14 commits intomicrosoft:mainfrom
weikequ:keyboard-manager-toggle-shortcut
Feb 12, 2026
Merged

[Keyboard Manager] Toggle module hotkey/shortcut#42472
niels9001 merged 14 commits intomicrosoft:mainfrom
weikequ:keyboard-manager-toggle-shortcut

Conversation

@weikequ
Copy link
Copy Markdown
Contributor

@weikequ weikequ commented Oct 17, 2025

Summary of the Pull Request

Adds a keyboard shortcut to be able to toggle the Keyboard Manager module on and off.

PR Checklist

Detailed Description of the Pull Request / Additional comments

Modeled the changes and addition of a global shortcut using the Color Picker module.

Notes:

  • This uses KeyboardManagerSettings and the associated .json settings file. I don't think there's anything else in this module that uses this.
  • The default key binding for this is winkey + shift + k
  • I've had to update the KeyboardManagerViewModel to extend PageViewModelBase as opposed to Observable to get it to work. But I will say that there were some things in here that I didn't fully dig into, so let me know if there's any potential things I'm missing.
  • I'm not too sure how to update the Settings UI after a hotkey is pressed (pressing the hotkey currently will not show the module being toggled off) - can't find a good way to refresh the settings ui after enabling/disabling the module. Any pointers here would be appreciated!

Validation Steps Performed

  • Manually validated the following items:
    • Using the default shortcut (winkey + shift + k)
    • Changing the shortcut
    • Ensuring the change is persistent

Media

Screen.Recording.2025-10-21.173753.mp4

@weikequ
Copy link
Copy Markdown
Contributor Author

weikequ commented Oct 17, 2025

@microsoft-github-policy-service agree

@weikequ weikequ marked this pull request as ready for review October 23, 2025 21:13
@mike-mgt
Copy link
Copy Markdown

Thanks for posting this as a PR. I was going to install your release, but I'll wait for this to be merged to prod.

@niels9001
Copy link
Copy Markdown
Collaborator

@weikequ we want to get this in for the next release. Would you mind resolving the remaining conflicts so that we can get this reviewed and merged in :)?

@weikequ
Copy link
Copy Markdown
Contributor Author

weikequ commented Dec 11, 2025

@weikequ we want to get this in for the next release. Would you mind resolving the remaining conflicts so that we can get this reviewed and merged in :)?

Awesome to hear. Just pushed a fix to resolve the merge conflicts. Let me know if there's anything else you need on my end. Thanks!

@lei9444
Copy link
Copy Markdown
Contributor

lei9444 commented Jan 5, 2026

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

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

This PR adds a keyboard shortcut feature to toggle the Keyboard Manager module on and off, addressing issue #4879. The implementation follows the pattern used in the Color Picker module, with a default hotkey of Win+Shift+K.

Key changes:

  • Adds toggle hotkey infrastructure to Keyboard Manager with configurable shortcut
  • Extends KeyboardManagerViewModel to inherit from PageViewModelBase for hotkey support
  • Implements hotkey parsing and toggle functionality in the C++ module DLL

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/settings-ui/Settings.UI/ViewModels/KeyboardManagerViewModel.cs Refactors ViewModel to extend PageViewModelBase and implements GetAllHotkeySettings() method to expose the toggle shortcut configuration
src/settings-ui/Settings.UI/Strings/en-us/Resources.resw Adds localized strings for the toggle shortcut UI header and description
src/settings-ui/Settings.UI/SettingsXAML/Views/KeyboardManagerPage.xaml Adds ShortcutControl UI element for configuring the toggle shortcut
src/settings-ui/Settings.UI/SerializationContext/SourceGenerationContextContext.cs Registers KeyboardManagerSettings for JSON serialization context
src/settings-ui/Settings.UI.Library/KeyboardManagerSettings.cs Implements GetAllHotkeyAccessors() method to provide access to the toggle shortcut setting
src/settings-ui/Settings.UI.Library/KeyboardManagerProperties.cs Adds ToggleShortcut property with default value (Win+Shift+K)
src/modules/keyboardmanager/dll/dllmain.cpp Implements hotkey parsing, storage, and toggle handler that enables/disables the module with toast notifications
src/modules/keyboardmanager/dll/KeyboardManager.vcxproj Adds project reference to the notifications library for toast support

Comment on lines +285 to +290
notifications::show_toast(L"Keyboard Manager Disabled", L"");
}
else
{
enable();
notifications::show_toast(L"Keyboard Manager Enabled", L"");
Copy link

Copilot AI Jan 6, 2026

Choose a reason for hiding this comment

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

The notification strings "Keyboard Manager Disabled" and "Keyboard Manager Enabled" are hardcoded and not localized. These should use GET_RESOURCE_STRING with appropriate resource IDs defined in the Resources.resx file to support internationalization, similar to how app_name uses GET_RESOURCE_STRING(IDS_KEYBOARDMANAGER) on line 51.

Suggested change
notifications::show_toast(L"Keyboard Manager Disabled", L"");
}
else
{
enable();
notifications::show_toast(L"Keyboard Manager Enabled", L"");
notifications::show_toast(GET_RESOURCE_STRING(IDS_KEYBOARDMANAGER_DISABLED), L"");
}
else
{
enable();
notifications::show_toast(GET_RESOURCE_STRING(IDS_KEYBOARDMANAGER_ENABLED), L"");

Copilot uses AI. Check for mistakes.
@lei9444
Copy link
Copy Markdown
Contributor

lei9444 commented Jan 6, 2026

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@yeelam-gordon
Copy link
Copy Markdown
Contributor

@weikequ and @niels9001 , should we consider another existing pattern in PowerToys?
Like below screenshot.
image

  1. Disable the module in specific scenarios (e.g., GameMode).
  2. Disable the module for specific apps.
    This pattern is more feasible because it can be configured to disable the module in specific situations, rather than requiring people to remember to use a hotkey.

@lei9444
Copy link
Copy Markdown
Contributor

lei9444 commented Jan 6, 2026

Hi @weikequ @niels9001,
directly toggling the whole module feels a bit odd.
Should we follow a similar approach to Mouse Utilities — use a shortcut to enable/disable the functionality, e.g. stop listening to keyboard events, instead of turning the entire module on and off?

@mike-mgt
Copy link
Copy Markdown

mike-mgt commented Jan 6, 2026

Hi @weikequ @niels9001, directly toggling the whole module feels a bit odd. Should we follow a similar approach to Mouse Utilities — use a shortcut to enable/disable the functionality, e.g. stop listening to keyboard events, instead of turning the entire module on and off?

Nope. The module itself is problematic when it is on in certain scenarios. If you're suggesting an additional setting, great, but this is a much-needed feature.

@mike-mgt
Copy link
Copy Markdown

mike-mgt commented Jan 6, 2026

@weikequ and @niels9001 , should we consider another existing pattern in PowerToys? Like below screenshot. image

  1. Disable the module in specific scenarios (e.g., GameMode).
  2. Disable the module for specific apps.
    This pattern is more feasible because it can be configured to disable the module in specific situations, rather than requiring people to remember to use a hotkey.

I do like this as an option, but I think it should also be added as an extra setting on top of the proposed one here by @weikequ.

@lei9444
Copy link
Copy Markdown
Contributor

lei9444 commented Jan 6, 2026

Hi @weikequ @niels9001, directly toggling the whole module feels a bit odd. Should we follow a similar approach to Mouse Utilities — use a shortcut to enable/disable the functionality, e.g. stop listening to keyboard events, instead of turning the entire module on and off?

Nope. The module itself is problematic when it is on in certain scenarios. If you're suggesting an additional setting, great, but this is a much-needed feature.

Thanks @mike-mgt for the comments.
My suggestion is like this: the shortcut will activate (enable) and deactivate (disable) the module, but it will not change the module’s settings state shown in Settings.

So it behaves like this:
When the module is enabled in Settings, we can toggle the module active/inactive via the shortcut:
image

When the module is disabled in Settings, the shortcut does nothing:
image

This way, our implementation stays consistent with others.
Does this approach satisfy your requirements?

// Process the hotkey event
virtual bool on_hotkey(size_t /*hotkeyId*/) override
{
if (m_enabled)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We currently only use notifications to communicate updates and other 'critical' things as we know users don't like to get too many notifications.

Since enabling/disabling KMB is a deliberate action by the user, notifications seem excessive.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

When I was testing it, it was really helpful to know when the action was successful, hence the notification. Having the user press a hotkey and receive no feedback is unintuitive imo , as it makes them question if anything happened. I still prefer somehow letting the user know when it has succeeded, do you have any other thoughts on how we might be able to do it without using the notification system?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Thanks for sprinkling some good US @weikequ. Being notified of a successful activation is essential. I use SoundSwitch and I love seeing the notification that clearly states whether the input has switched or there's been an error.

Copy link
Copy Markdown
Collaborator

@niels9001 niels9001 left a comment

Choose a reason for hiding this comment

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

Great work! See comment about notifications.

And to @lei9444 's comment; we should follow the activation behavior that other utilities are using so we are in line. This would also set us up for success on the longer term as we are planning a UI revamp of the KBM editor :)!

@weikequ
Copy link
Copy Markdown
Contributor Author

weikequ commented Jan 6, 2026

1. Disable the module in specific scenarios (e.g., GameMode).
2. Disable the module for specific apps.

I think it would be hard to capture all scenarios/apps where this would help the user, and using a specific keyboard press helps solidify user intent on performing this action. Though for my own purposes, this does work as well (maybe a blacklist to select from a list of processes?).

The other option is to have no shortcut by default, that way, it is opt-in only for those who need it.

@vanzue vanzue self-assigned this Feb 11, 2026
@vanzue
Copy link
Copy Markdown
Contributor

vanzue commented Feb 11, 2026

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

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

Copilot reviewed 9 out of 10 changed files in this pull request and generated 4 comments.

<value>Toggle shortcut</value>
</data>
<data name="KeyboardManager_Toggle_Shortcut.Description" xml:space="preserve">
<value>Use a shortcut to toggle this module on or off (note that the Settings UI will not update)</value>
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

The description text mentions that "the Settings UI will not update" when the hotkey is pressed. This is a user-facing limitation that should ideally be addressed. Consider implementing a mechanism to notify the Settings UI of the state change, similar to how GeneralSettings.Enabled is updated in other toggle scenarios. This could involve sending an IPC message back to the Settings UI or implementing a polling/refresh mechanism.

Suggested change
<value>Use a shortcut to toggle this module on or off (note that the Settings UI will not update)</value>
<value>Use a shortcut to toggle this module on or off from anywhere</value>

Copilot uses AI. Check for mistakes.
Comment on lines +338 to +365
// Process the hotkey event
virtual bool on_hotkey(size_t /*hotkeyId*/) override
{
if (!m_enabled)
{
return false;
}

constexpr ULONGLONG hotkeyToggleDebounceMs = 500;
const auto now = GetTickCount64();
if (now - m_lastHotkeyToggleTime < hotkeyToggleDebounceMs)
{
return true;
}
m_lastHotkeyToggleTime = now;

refresh_process_state();
if (m_active)
{
stop_engine();
}
else
{
start_engine();
}

return true;
}
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

When toggling the engine via hotkey, no telemetry is sent, unlike the enable/disable methods which call Trace::EnableKeyboardManager. Consider whether telemetry should be tracked for hotkey toggles to understand user behavior, or document why it's intentionally omitted (e.g., to avoid spam from frequent toggling).

Copilot uses AI. Check for mistakes.
Comment on lines +190 to +202
public HotkeySettings ToggleShortcut
{
get => Settings.Properties.ToggleShortcut;
set
{
if (Settings.Properties.ToggleShortcut != value)
{
Settings.Properties.ToggleShortcut = value ?? Settings.Properties.DefaultToggleShortcut;
OnPropertyChanged(nameof(ToggleShortcut));
NotifySettingsChanged();
}
}
}
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

Consider adding unit tests for the new toggle shortcut functionality, similar to the tests in ViewModelTests/ColorPicker.cs that verify the ActivationShortcut property. Tests should verify that the ToggleShortcut property is correctly initialized, persisted, and updated. This aligns with the PR checklist item for tests that is currently unchecked.

Copilot uses AI. Check for mistakes.
vanzue and others added 2 commits February 11, 2026 23:15
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@vanzue
Copy link
Copy Markdown
Contributor

vanzue commented Feb 11, 2026

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@vanzue
Copy link
Copy Markdown
Contributor

vanzue commented Feb 11, 2026

Addressed the comments:

  1. Hotkey toggle will not enable disable the entire module, use a slightly light weighted approach to start the engine/kill the engine process
  2. Removed the notification

@vanzue vanzue requested a review from niels9001 February 11, 2026 16:17
@niels9001 niels9001 merged commit f88a490 into microsoft:main Feb 12, 2026
11 checks passed
@zateutsch zateutsch added this to the PowerToys 0.98 milestone Mar 4, 2026
@zateutsch zateutsch added the Product-Keyboard Shortcut Manager Issues regarding Keyboard Shortcut Manager label Mar 5, 2026
@jefflord
Copy link
Copy Markdown
Contributor

Wow, so long over due and it's brilliant.

Couple if nits:

  • Tab Order: The tab order is inconsistent. When a shortcut has focus, pressing Tab again focuses on nothing (likely hidden elements) rather than moving to the next visible control.
  • Menu Options: The "..." (meatballs) menu should include an "Edit" option.
  • Broken Icon: The "folder-with-arrow" icon currently has no associated action.
  • Chord Regressions: Double-key chords (e.g., CTRL+6, 6) no longer work. The UI prevents the second part of the chord from being entered (see Image 1)
  • Chord Timing: The timeout for entering the second character of a chord is far too short. Unlike standard chord entries that often have no strict "allotted time," this screen resets too quickly. If a timeout is necessary, please add a hint when "Allow chords" is checked: "Enter the second part of the chord within 1 second, or the input will reset."
  • UI Guidance: There should be a label below the shortcut display saying: "Click or focus here to enter a shortcut."
  • Keyboard Accessibility: "Esc" should not be a valid shortcut key. Instead, pressing "Esc" should blur the input and disable shortcut entry. Currently, it's impossible to navigate or configure the shortcut settings using only the keyboard.
  • Dropdown Redundancy: Why is "Trigger" a dropdown menu if it only contains one option?

Image 1: Double same number chords
image

Again I will say, OMG this is great. I have personally waited for this for a long time.

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

Labels

In for .98 Product-Keyboard Shortcut Manager Issues regarding Keyboard Shortcut Manager

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[KBM] Add a hotkey key to turn it on/off

9 participants