From e0c0e7bb76dfd2fa627e281d0aa48bc70d673358 Mon Sep 17 00:00:00 2001 From: Shawn Yuan <128874481+shuaiyuanxx@users.noreply.github.com> Date: Mon, 5 Jan 2026 13:38:43 +0800 Subject: [PATCH] Fixed keyvisual issue for pt run (#41539) ## Summary of the Pull Request ## PR Checklist - [x] Closes: #41468 - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [x] **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 - [ ] [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 ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed --------- Signed-off-by: Shawn Yuan --- src/runner/settings_window.cpp | 28 +++++++++++++++---- .../PowerLauncherProperties.cs | 3 ++ .../ViewModels/PowerLauncherViewModel.cs | 8 ++++++ .../ViewModels/ShortcutConflictViewModel.cs | 9 ++++++ 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/src/runner/settings_window.cpp b/src/runner/settings_window.cpp index 473fa7ebe3..e31b934d40 100644 --- a/src/runner/settings_window.cpp +++ b/src/runner/settings_window.cpp @@ -148,16 +148,19 @@ std::optional dispatch_json_action_to_module(const json::JsonObjec return result; } -void send_json_config_to_module(const std::wstring& module_key, const std::wstring& settings) +void send_json_config_to_module(const std::wstring& module_key, const std::wstring& settings, bool hotkeyUpdated) { auto moduleIt = modules().find(module_key); if (moduleIt != modules().end()) { moduleIt->second->set_config(settings.c_str()); - moduleIt->second.remove_hotkey_records(); - moduleIt->second.update_hotkeys(); - moduleIt->second.UpdateHotkeyEx(); + if (hotkeyUpdated) + { + moduleIt->second.remove_hotkey_records(); + moduleIt->second.update_hotkeys(); + moduleIt->second.UpdateHotkeyEx(); + } } } @@ -166,7 +169,22 @@ void dispatch_json_config_to_modules(const json::JsonObject& powertoys_configs) for (const auto& powertoy_element : powertoys_configs) { const auto element = powertoy_element.Value().Stringify(); - send_json_config_to_module(powertoy_element.Key().c_str(), element.c_str()); + + /* As PowerToys Run hotkeys are not registered by the runner, hotkey updates are + * triggered only when hotkey properties change to avoid incorrect conflict detection; + * otherwise, the existing logic remains. + */ + auto settings = powertoy_element.Value().GetObjectW(); + bool hotkeyUpdated = true; + if (settings.HasKey(L"properties")) + { + const auto properties = settings.GetNamedObject(L"properties"); + + // Currently, only PowerToys Run settings use the 'hotkey_changed' property. + json::get(properties, L"hotkey_changed", hotkeyUpdated, true); + } + + send_json_config_to_module(powertoy_element.Key().c_str(), element.c_str(), hotkeyUpdated); } }; diff --git a/src/settings-ui/Settings.UI.Library/PowerLauncherProperties.cs b/src/settings-ui/Settings.UI.Library/PowerLauncherProperties.cs index 590fb2e290..08eb16a389 100644 --- a/src/settings-ui/Settings.UI.Library/PowerLauncherProperties.cs +++ b/src/settings-ui/Settings.UI.Library/PowerLauncherProperties.cs @@ -94,6 +94,9 @@ namespace Microsoft.PowerToys.Settings.UI.Library [JsonPropertyName("generate_thumbnails_from_files")] public bool GenerateThumbnailsFromFiles { get; set; } + [JsonPropertyName("hotkey_changed")] + public bool HotkeyChanged { get; set; } = false; + [CmdConfigureIgnoreAttribute] public HotkeySettings DefaultOpenPowerLauncher => new HotkeySettings(false, false, true, false, 32); diff --git a/src/settings-ui/Settings.UI/ViewModels/PowerLauncherViewModel.cs b/src/settings-ui/Settings.UI/ViewModels/PowerLauncherViewModel.cs index 31efe28260..ee5b6e2f7c 100644 --- a/src/settings-ui/Settings.UI/ViewModels/PowerLauncherViewModel.cs +++ b/src/settings-ui/Settings.UI/ViewModels/PowerLauncherViewModel.cs @@ -31,6 +31,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels private bool _enabledStateIsGPOConfigured; private bool _isEnabled; private string _searchText; + private bool _hotkeyChanged; private GeneralSettings GeneralSettingsConfig { get; set; } @@ -162,6 +163,12 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels // Notify UI of property change OnPropertyChanged(propertyName); + // Since PowerLauncher registers its hotkeys independently within the module process, + // the runner is notified to update PowerLauncher’s hotkeys only when changes occur. + // This prevents incorrect conflict detection results. + settings.Properties.HotkeyChanged = _hotkeyChanged; + _hotkeyChanged = false; + callback(settings); } @@ -335,6 +342,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels if (settings.Properties.OpenPowerLauncher != value) { settings.Properties.OpenPowerLauncher = value ?? settings.Properties.DefaultOpenPowerLauncher; + _hotkeyChanged = true; UpdateSettings(); } } diff --git a/src/settings-ui/Settings.UI/ViewModels/ShortcutConflictViewModel.cs b/src/settings-ui/Settings.UI/ViewModels/ShortcutConflictViewModel.cs index 6c6d624f97..48d1d09a40 100644 --- a/src/settings-ui/Settings.UI/ViewModels/ShortcutConflictViewModel.cs +++ b/src/settings-ui/Settings.UI/ViewModels/ShortcutConflictViewModel.cs @@ -242,6 +242,15 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels // No need to save settings here, the runner will call module interface to save it // SaveSettingsToFile(settings); + // For PowerToys Run, we should set the 'HotkeyChanged' property here to avoid issue #41468 + if (string.Equals(moduleName, PowerLauncherSettings.ModuleName, StringComparison.OrdinalIgnoreCase)) + { + if (settings is PowerLauncherSettings powerLauncherSettings) + { + powerLauncherSettings.Properties.HotkeyChanged = true; + } + } + // Send IPC notification using the same format as other ViewModels SendConfigMSG(settingsConfig, moduleName); }