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); }