diff --git a/src/common/interop/shared_constants.h b/src/common/interop/shared_constants.h index ce85b97706..adb7c8cad1 100644 --- a/src/common/interop/shared_constants.h +++ b/src/common/interop/shared_constants.h @@ -140,6 +140,10 @@ namespace CommonSharedConstants const wchar_t APPLY_COLOR_TEMPERATURE_POWER_DISPLAY_EVENT[] = L"Local\\PowerToysPowerDisplay-ApplyColorTemperatureEvent-4b7e9f2a-3c6d-5a8e-7f1b-9d2e4c6a8b0d"; const wchar_t APPLY_PROFILE_POWER_DISPLAY_EVENT[] = L"Local\\PowerToysPowerDisplay-ApplyProfileEvent-6e8a3c9d-4f7b-5d2e-8a1c-3e9f7b6d2a5c"; + // Path to the events used by LightSwitch to notify PowerDisplay of theme changes + const wchar_t LIGHT_SWITCH_LIGHT_THEME_EVENT[] = L"Local\\PowerToysLightSwitch-LightThemeEvent-50077121-2ffc-4841-9c86-ab1bd3f9baca"; + const wchar_t LIGHT_SWITCH_DARK_THEME_EVENT[] = L"Local\\PowerToysLightSwitch-DarkThemeEvent-b3a835c0-eaa2-49b0-b8eb-f793e3df3368"; + // used from quick access window const wchar_t CMDPAL_SHOW_EVENT[] = L"Local\\PowerToysCmdPal-ShowEvent-62336fcd-8611-4023-9b30-091a6af4cc5a"; const wchar_t CMDPAL_EXIT_EVENT[] = L"Local\\PowerToysCmdPal-ExitEvent-eb73f6be-3f22-4b36-aee3-62924ba40bfd"; diff --git a/src/modules/LightSwitch/LightSwitchService/LightSwitchStateManager.cpp b/src/modules/LightSwitch/LightSwitchService/LightSwitchStateManager.cpp index a08b35b546..ac86d9bb2b 100644 --- a/src/modules/LightSwitch/LightSwitchService/LightSwitchStateManager.cpp +++ b/src/modules/LightSwitch/LightSwitchService/LightSwitchStateManager.cpp @@ -4,6 +4,7 @@ #include #include "ThemeScheduler.h" #include +#include void ApplyTheme(bool shouldBeLight); @@ -300,8 +301,8 @@ void LightSwitchStateManager::NotifyPowerDisplay(bool isLight) // Using separate events for light/dark eliminates race conditions where PowerDisplay // might read the registry before LightSwitch has finished updating it const wchar_t* eventName = isLight - ? L"Local\\PowerToys_LightSwitch_LightTheme" - : L"Local\\PowerToys_LightSwitch_DarkTheme"; + ? CommonSharedConstants::LIGHT_SWITCH_LIGHT_THEME_EVENT + : CommonSharedConstants::LIGHT_SWITCH_DARK_THEME_EVENT; Logger::info(L"[LightSwitchStateManager] Notifying PowerDisplay about theme change (isLight: {})", isLight); diff --git a/src/modules/powerdisplay/PowerDisplay.Lib/PathConstants.cs b/src/modules/powerdisplay/PowerDisplay.Lib/PathConstants.cs index 70d22b1aa2..4dd92d9666 100644 --- a/src/modules/powerdisplay/PowerDisplay.Lib/PathConstants.cs +++ b/src/modules/powerdisplay/PowerDisplay.Lib/PathConstants.cs @@ -79,14 +79,16 @@ namespace PowerDisplay.Common /// /// Event name for LightSwitch light theme change notifications. /// Signaled when LightSwitch switches to light mode. + /// Must match CommonSharedConstants::LIGHT_SWITCH_LIGHT_THEME_EVENT in shared_constants.h. /// - public const string LightSwitchLightThemeEventName = "Local\\PowerToys_LightSwitch_LightTheme"; + public const string LightSwitchLightThemeEventName = "Local\\PowerToysLightSwitch-LightThemeEvent-50077121-2ffc-4841-9c86-ab1bd3f9baca"; /// /// Event name for LightSwitch dark theme change notifications. /// Signaled when LightSwitch switches to dark mode. + /// Must match CommonSharedConstants::LIGHT_SWITCH_DARK_THEME_EVENT in shared_constants.h. /// - public const string LightSwitchDarkThemeEventName = "Local\\PowerToys_LightSwitch_DarkTheme"; + public const string LightSwitchDarkThemeEventName = "Local\\PowerToysLightSwitch-DarkThemeEvent-b3a835c0-eaa2-49b0-b8eb-f793e3df3368"; /// /// Ensures the PowerDisplay folder exists. Creates it if necessary. diff --git a/src/modules/powerdisplay/PowerDisplay/ViewModels/MainViewModel.cs b/src/modules/powerdisplay/PowerDisplay/ViewModels/MainViewModel.cs index f66935ddc8..387bfb58e2 100644 --- a/src/modules/powerdisplay/PowerDisplay/ViewModels/MainViewModel.cs +++ b/src/modules/powerdisplay/PowerDisplay/ViewModels/MainViewModel.cs @@ -327,13 +327,20 @@ public partial class MainViewModel : INotifyPropertyChanged, IDisposable /// private async void OnDisplayChanged(object? sender, EventArgs e) { - Logger.LogInfo("[MainViewModel] Display change detected, will refresh after 5 second delay..."); + // Get the delay from settings (default to 5 seconds if not configured) + var settings = _settingsUtils.GetSettingsOrDefault(PowerDisplaySettings.ModuleName); + int delaySeconds = settings?.Properties?.MonitorRefreshDelay ?? 5; + + // Clamp to reasonable range (1-30 seconds) + delaySeconds = Math.Clamp(delaySeconds, 1, 30); + + Logger.LogInfo($"[MainViewModel] Display change detected, will refresh after {delaySeconds} second delay..."); // Set scanning state immediately to provide visual feedback IsScanning = true; // Wait for hardware to stabilize (DDC/CI may not be ready immediately after plug) - await Task.Delay(TimeSpan.FromSeconds(5)); + await Task.Delay(TimeSpan.FromSeconds(delaySeconds)); // Perform actual refresh - skip scanning check since we already set IsScanning above Logger.LogInfo("[MainViewModel] Delay complete, now refreshing monitors..."); diff --git a/src/settings-ui/Settings.UI.Library/PowerDisplayProperties.cs b/src/settings-ui/Settings.UI.Library/PowerDisplayProperties.cs index 95b8ebfcac..2cb688510b 100644 --- a/src/settings-ui/Settings.UI.Library/PowerDisplayProperties.cs +++ b/src/settings-ui/Settings.UI.Library/PowerDisplayProperties.cs @@ -17,7 +17,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library public PowerDisplayProperties() { ActivationShortcut = DefaultActivationShortcut; - BrightnessUpdateRate = "1s"; + MonitorRefreshDelay = 5; Monitors = new List(); RestoreSettingsOnStartup = true; ShowSystemTrayIcon = true; @@ -29,8 +29,12 @@ namespace Microsoft.PowerToys.Settings.UI.Library [JsonPropertyName("activation_shortcut")] public HotkeySettings ActivationShortcut { get; set; } - [JsonPropertyName("brightness_update_rate")] - public string BrightnessUpdateRate { get; set; } + /// + /// Gets or sets delay in seconds before refreshing monitors after display changes (hot-plug). + /// This allows hardware to stabilize before querying DDC/CI. + /// + [JsonPropertyName("monitor_refresh_delay")] + public int MonitorRefreshDelay { get; set; } [JsonPropertyName("monitors")] public List Monitors { get; set; } diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/PowerDisplayPage.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Views/PowerDisplayPage.xaml index f16a5248de..1a9383daf2 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/PowerDisplayPage.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/PowerDisplayPage.xaml @@ -45,11 +45,11 @@ - + + ItemsSource="{x:Bind ViewModel.MonitorRefreshDelayOptions}" + SelectedItem="{x:Bind ViewModel.MonitorRefreshDelay, Mode=TwoWay}" /> diff --git a/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw b/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw index d8c6941672..f61c023b95 100644 --- a/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw +++ b/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw @@ -5689,11 +5689,11 @@ To record a specific window, enter the hotkey with the Alt key in the opposite m Choose if PowerDisplay is visible in the system tray - - Brightness update rate + + Monitor refresh delay - - How frequently to update brightness values + + Seconds to wait after display changes before refreshing monitors. Increase if monitors are not detected after hot-plug. Profiles diff --git a/src/settings-ui/Settings.UI/ViewModels/PowerDisplayViewModel.cs b/src/settings-ui/Settings.UI/ViewModels/PowerDisplayViewModel.cs index 71184634f2..b67622bc3a 100644 --- a/src/settings-ui/Settings.UI/ViewModels/PowerDisplayViewModel.cs +++ b/src/settings-ui/Settings.UI/ViewModels/PowerDisplayViewModel.cs @@ -154,22 +154,18 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels set => SetSettingsProperty(_settings.Properties.ActivationShortcut, value, v => _settings.Properties.ActivationShortcut = v); } - public string BrightnessUpdateRate + /// + /// Gets or sets the delay in seconds before refreshing monitors after display changes. + /// + public int MonitorRefreshDelay { - get => _settings.Properties.BrightnessUpdateRate; - set => SetSettingsProperty(_settings.Properties.BrightnessUpdateRate, value, v => _settings.Properties.BrightnessUpdateRate = v); + get => _settings.Properties.MonitorRefreshDelay; + set => SetSettingsProperty(_settings.Properties.MonitorRefreshDelay, value, v => _settings.Properties.MonitorRefreshDelay = v); } - private readonly List _brightnessUpdateRateOptions = new List - { - "never", - "250ms", - "500ms", - "1s", - "2s", - }; + private readonly List _monitorRefreshDelayOptions = new List { 1, 2, 3, 5, 10 }; - public List BrightnessUpdateRateOptions => _brightnessUpdateRateOptions; + public List MonitorRefreshDelayOptions => _monitorRefreshDelayOptions; public ObservableCollection Monitors {