Repository navigation
[KBM] New editor: honor the PowerToys language setting - #51147
Open
Niels Laute (niels9001) wants to merge 1 commit into
Open
Niels Laute (niels9001) wants to merge 1 commit into
Niels Laute (niels9001) wants to merge 1 commit into
Conversation
Apply LanguageHelper.LoadLanguage() as PrimaryLanguageOverride at startup, matching other WinUI 3 modules, so the editor no longer follows the OS region language. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
The focused change follows the established WinUI 3 localization pattern without unresolved issues.
0 open findings
What changed in this PR
Applies the configured PowerToys language to the new Keyboard Manager editor at startup.
Changes:
- Loads the shared PowerToys language setting.
- Sets the WinUI 3 primary language override before resource initialization.
| File | Description |
|---|---|
src/modules/keyboardmanager/KeyboardManagerEditorUI/KeyboardManagerEditorXAML/App.xaml.cs |
Initializes the editor with the configured PowerToys language. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Niels Laute (niels9001)
marked this pull request as ready for review
October 9, 2026 14:34
Yu Leng (moooyo)
pushed a commit
that referenced
this pull request
Oct 14, 2026
…e editor (#51150) <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request This PR fixes two related input gaps in the new WinUI 3 Keyboard Manager editor compared with the classic editor. 1. **Keys that can't be recorded have no fallback.** When a mapping starts empty, the trigger and action showed only the "press keys" recording area. Keys you can't press (media keys, or keys missing from your keyboard) or that the hook can't capture could not be chosen. The classic editor always showed a dropdown. An empty mapping now shows a caption hint ("Press to start recording keys or") followed by a "Select key" `KeyDropDownButton`, so any key can be picked from the list. The dropdown's flyout has a search box at the top that filters the key list. Picking a modifier adds another empty dropdown, so a full shortcut can be built with the mouse. 2. **Recording leaked and trapped focus.** The low-level recording hook stayed active even when the editor wasn't in the foreground, so keystrokes typed in other apps got recorded. While recording, the editor also swallowed Tab, so keyboard users couldn't leave the field. Now: - The hook only records when the editor is in the foreground. - Tab (or Shift+Tab) with no other keys held stops recording and moves focus forward (or backward). Keys you already recorded are kept; the previous keys come back only if nothing was recorded. - The recording toggle unchecks when recording stops. <img width="880" height="724" alt="Image" src="https://github.com/user-attachments/assets/aa266b16-43d8-4ab5-a582-e5dc8a18c590" /> <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #50852 - [x] Closes: #50360 - [x] Closes: #49158 - [ ] **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 - [x] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments - **`KeyDropDownButton`**: - Shows a localized "Select key" placeholder (`KeyDropDownButton_SelectKeyPlaceholder`) when `KeyName` is empty. - The flyout now has an `AutoSuggestBox` ("Search keys") above the `ListView`. It gets focus when the flyout opens and filters by display name, ignoring case. Enter picks the first match, and "No keys found" shows when nothing matches. The search text resets each time the flyout opens. - **`UnifiedMappingControl`**: - New `TriggerEmptyKeyPickerPanel` and `ActionEmptyKeyPickerPanel` appear when the trigger or action has no keys. Each shows a `CaptionTextBlockStyle` hint ("Press to start recording keys or") and an empty `KeyDropDownButton`. - Picking a key from the dropdown fills the first slot (`TrySetFirstDropDownKey`). - Before recording starts, the previous keys are saved. If recording ends with nothing captured, they are restored. - Key getters ignore empty placeholder entries, so an empty slot is never saved as a key. - **`KeyboardHookHelper`**: - The hook's "is active" predicate is now `IsEditorForeground`: the foreground window's process must be the editor's own process. - `ShouldHandleKeyboardEvent` treats Tab or Shift+Tab with no other keys held as "exit recording". It restores the previous keys only if nothing was captured (or only the Shift held for Shift+Tab). For Shift+Tab it swallows the Tab, because the hook already swallowed Shift and the window would see a plain Tab, and the control moves focus backward with `FocusManager.TryMoveFocus` scoped to the dialog. - Cleanup is deferred to the `DispatcherQueue` because the native `KeyboardHook::HookProc` is still running the callback, and disposing the hook from inside it is unsafe. - `CleanupHook` tells the target through the new `IKeyboardHookTarget.OnRecordingStopped(bool)`, so the toggle unchecks and keys are restored when needed. **Trade-offs:** - A lone Tab can no longer be recorded. You can still pick it from the dropdown, which this PR makes always available. Part of the new-vs-classic KBM editor parity work. Other draft PRs from the same work: #51147 (language), #51148 (engine suspend) and #51149 (orphaned-key warning). <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed - `tools\build\build.cmd` in `src\modules\keyboardmanager\KeyboardManagerEditorUI` (arm64 Debug): passed, exit code 0. - No new unit tests: the changes are in UI and hook plumbing, which the existing unit test project doesn't cover. - Manually tested on an arm64 Debug dev runner: new mappings show the caption hint and "Select key" for both trigger and action. The search box gets focus when the flyout opens, and typing "k" filters the list. Typing in the search box doesn't start key recording. - Other manual checks: - Add a new mapping and confirm the empty trigger and action show "Select key". Pick a media key (e.g. Play/Pause) from the dropdown and save. - Start recording, switch to another app and type there. Confirm nothing is recorded in the editor. - Start recording and press Tab. Confirm recording stops, the toggle unchecks and focus moves on. Record a key, release it, then press Tab: the recorded key stays. Press Shift+Tab: focus moves backward. - Start recording and stop without pressing a key. Confirm the previous keys come back. --------- Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4c7f42fd-7fad-43c2-9281-e581ddfd45eb
Boliang Zhang (LegendaryBlair)
pushed a commit
that referenced
this pull request
Oct 15, 2026
…e editor (#51150) <!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request This PR fixes two related input gaps in the new WinUI 3 Keyboard Manager editor compared with the classic editor. 1. **Keys that can't be recorded have no fallback.** When a mapping starts empty, the trigger and action showed only the "press keys" recording area. Keys you can't press (media keys, or keys missing from your keyboard) or that the hook can't capture could not be chosen. The classic editor always showed a dropdown. An empty mapping now shows a caption hint ("Press to start recording keys or") followed by a "Select key" `KeyDropDownButton`, so any key can be picked from the list. The dropdown's flyout has a search box at the top that filters the key list. Picking a modifier adds another empty dropdown, so a full shortcut can be built with the mouse. 2. **Recording leaked and trapped focus.** The low-level recording hook stayed active even when the editor wasn't in the foreground, so keystrokes typed in other apps got recorded. While recording, the editor also swallowed Tab, so keyboard users couldn't leave the field. Now: - The hook only records when the editor is in the foreground. - Tab (or Shift+Tab) with no other keys held stops recording and moves focus forward (or backward). Keys you already recorded are kept; the previous keys come back only if nothing was recorded. - The recording toggle unchecks when recording stops. <img width="880" height="724" alt="Image" src="https://github.com/user-attachments/assets/aa266b16-43d8-4ab5-a582-e5dc8a18c590" /> <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #50852 - [x] Closes: #50360 - [x] Closes: #49158 - [ ] **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 - [x] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments - **`KeyDropDownButton`**: - Shows a localized "Select key" placeholder (`KeyDropDownButton_SelectKeyPlaceholder`) when `KeyName` is empty. - The flyout now has an `AutoSuggestBox` ("Search keys") above the `ListView`. It gets focus when the flyout opens and filters by display name, ignoring case. Enter picks the first match, and "No keys found" shows when nothing matches. The search text resets each time the flyout opens. - **`UnifiedMappingControl`**: - New `TriggerEmptyKeyPickerPanel` and `ActionEmptyKeyPickerPanel` appear when the trigger or action has no keys. Each shows a `CaptionTextBlockStyle` hint ("Press to start recording keys or") and an empty `KeyDropDownButton`. - Picking a key from the dropdown fills the first slot (`TrySetFirstDropDownKey`). - Before recording starts, the previous keys are saved. If recording ends with nothing captured, they are restored. - Key getters ignore empty placeholder entries, so an empty slot is never saved as a key. - **`KeyboardHookHelper`**: - The hook's "is active" predicate is now `IsEditorForeground`: the foreground window's process must be the editor's own process. - `ShouldHandleKeyboardEvent` treats Tab or Shift+Tab with no other keys held as "exit recording". It restores the previous keys only if nothing was captured (or only the Shift held for Shift+Tab). For Shift+Tab it swallows the Tab, because the hook already swallowed Shift and the window would see a plain Tab, and the control moves focus backward with `FocusManager.TryMoveFocus` scoped to the dialog. - Cleanup is deferred to the `DispatcherQueue` because the native `KeyboardHook::HookProc` is still running the callback, and disposing the hook from inside it is unsafe. - `CleanupHook` tells the target through the new `IKeyboardHookTarget.OnRecordingStopped(bool)`, so the toggle unchecks and keys are restored when needed. **Trade-offs:** - A lone Tab can no longer be recorded. You can still pick it from the dropdown, which this PR makes always available. Part of the new-vs-classic KBM editor parity work. Other draft PRs from the same work: #51147 (language), #51148 (engine suspend) and #51149 (orphaned-key warning). <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed - `tools\build\build.cmd` in `src\modules\keyboardmanager\KeyboardManagerEditorUI` (arm64 Debug): passed, exit code 0. - No new unit tests: the changes are in UI and hook plumbing, which the existing unit test project doesn't cover. - Manually tested on an arm64 Debug dev runner: new mappings show the caption hint and "Select key" for both trigger and action. The search box gets focus when the flyout opens, and typing "k" filters the list. Typing in the search box doesn't start key recording. - Other manual checks: - Add a new mapping and confirm the empty trigger and action show "Select key". Pick a media key (e.g. Play/Pause) from the dropdown and save. - Start recording, switch to another app and type there. Confirm nothing is recorded in the editor. - Start recording and press Tab. Confirm recording stops, the toggle unchecks and focus moves on. Record a key, release it, then press Tab: the recorded key stays. Press Shift+Tab: focus moves backward. - Start recording and stop without pressing a key. Confirm the previous keys come back. --------- Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4c7f42fd-7fad-43c2-9281-e581ddfd45eb (cherry picked from commit 9501b98) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Muyuan Li (MuyuanMS)
approved these changes
Oct 29, 2026
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary of the Pull Request
The new Keyboard Manager editor (WinUI 3) ignored the PowerToys language setting and always used the OS region language. It now applies
LanguageHelper.LoadLanguage()asApplicationLanguages.PrimaryLanguageOverrideat startup, the same way other WinUI 3 modules do (e.g. File Locksmith).PR Checklist
Detailed Description of the Pull Request / Additional comments
The override is set at the top of the
App()constructor, before any resources load. OnlyKeyboardManagerEditorXAML/App.xaml.cschanges.Part of the new-vs-classic KBM editor parity work. Other draft PRs from the same work: #51148 (engine suspend), #51149 (orphaned-key warning), and #51150 (empty key slot + recording fixes).
Validation Steps Performed
tools\build\build.cmdinsrc\modules\keyboardmanager\KeyboardManagerEditorUI(arm64 Debug): passed, exit code 0.