mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-16 19:57:57 +01:00
Remove "Link all monitor brightness" feature
Eliminates the UI and backend logic for synchronizing all monitor brightness levels. Refactors monitor list update logic to distinguish between initial load and refresh, introducing RestoreMonitorSettings for startup state restoration. Streamlines feature visibility application and settings handling for improved maintainability.
This commit is contained in:
@@ -182,28 +182,6 @@ namespace PowerDisplay.Helpers
|
|||||||
(mon, val) => mon.UpdateStatus(val, true),
|
(mon, val) => mon.UpdateStatus(val, true),
|
||||||
cancellationToken);
|
cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Set brightness of all monitors
|
|
||||||
/// </summary>
|
|
||||||
public async Task<IEnumerable<MonitorOperationResult>> SetAllBrightnessAsync(int brightness, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
var tasks = _monitors
|
|
||||||
.Where(m => m.IsAvailable)
|
|
||||||
.Select(async monitor =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return await SetBrightnessAsync(monitor.Id, brightness, cancellationToken);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return MonitorOperationResult.Failure($"Failed to set brightness for {monitor.Name}: {ex.Message}");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return await Task.WhenAll(tasks);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Set contrast of the specified monitor
|
/// Set contrast of the specified monitor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -387,13 +387,6 @@
|
|||||||
</Flyout>
|
</Flyout>
|
||||||
</Button.Flyout>
|
</Button.Flyout>
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
|
||||||
x:Name="LinkButton"
|
|
||||||
x:Uid="SyncAllMonitorsTooltip"
|
|
||||||
Click="OnLinkClick"
|
|
||||||
Content="{ui:FontIcon Glyph=,
|
|
||||||
FontSize=16}"
|
|
||||||
Style="{StaticResource SubtleButtonStyle}" />
|
|
||||||
<Button
|
<Button
|
||||||
x:Name="RefreshButton"
|
x:Name="RefreshButton"
|
||||||
x:Uid="RefreshTooltip"
|
x:Uid="RefreshTooltip"
|
||||||
|
|||||||
@@ -394,24 +394,6 @@ namespace PowerDisplay
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnLinkClick(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Link all monitor brightness (synchronized adjustment)
|
|
||||||
if (_viewModel != null && _viewModel.Monitors.Count > 0)
|
|
||||||
{
|
|
||||||
// Get first monitor brightness as reference
|
|
||||||
var baseBrightness = _viewModel.Monitors.First().Brightness;
|
|
||||||
_ = _viewModel.SetAllBrightnessAsync(baseBrightness);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.LogError($"OnLinkClick failed: {ex}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnSettingsClick(object sender, RoutedEventArgs e)
|
private void OnSettingsClick(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
// Open PowerDisplay settings in PowerToys Settings UI
|
// Open PowerDisplay settings in PowerToys Settings UI
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ public partial class MainViewModel
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
UpdateMonitorList(monitors);
|
UpdateMonitorList(monitors, isInitialLoad: true);
|
||||||
IsScanning = false;
|
IsScanning = false;
|
||||||
IsInitialized = true;
|
IsInitialized = true;
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ public partial class MainViewModel
|
|||||||
|
|
||||||
_dispatcherQueue.TryEnqueue(() =>
|
_dispatcherQueue.TryEnqueue(() =>
|
||||||
{
|
{
|
||||||
UpdateMonitorList(monitors);
|
UpdateMonitorList(monitors, isInitialLoad: false);
|
||||||
IsScanning = false;
|
IsScanning = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -87,7 +87,7 @@ public partial class MainViewModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateMonitorList(IReadOnlyList<Monitor> monitors)
|
private void UpdateMonitorList(IReadOnlyList<Monitor> monitors, bool isInitialLoad)
|
||||||
{
|
{
|
||||||
Monitors.Clear();
|
Monitors.Clear();
|
||||||
|
|
||||||
@@ -105,26 +105,20 @@ public partial class MainViewModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
var vm = new MonitorViewModel(monitor, _monitorManager, this);
|
var vm = new MonitorViewModel(monitor, _monitorManager, this);
|
||||||
|
ApplyFeatureVisibility(vm, settings);
|
||||||
Monitors.Add(vm);
|
Monitors.Add(vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
OnPropertyChanged(nameof(HasMonitors));
|
OnPropertyChanged(nameof(HasMonitors));
|
||||||
OnPropertyChanged(nameof(ShowNoMonitorsMessage));
|
OnPropertyChanged(nameof(ShowNoMonitorsMessage));
|
||||||
|
|
||||||
// Save monitor information to settings and reload
|
// Save monitor information to settings
|
||||||
SaveMonitorsToSettings();
|
SaveMonitorsToSettings();
|
||||||
_ = ReloadMonitorSettingsAsync(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task SetAllBrightnessAsync(int brightness)
|
// Only restore settings on initial load, not on refresh
|
||||||
{
|
if (isInitialLoad && settings.Properties.RestoreSettingsOnStartup)
|
||||||
try
|
|
||||||
{
|
{
|
||||||
await _monitorManager.SetAllBrightnessAsync(brightness, _cancellationTokenSource.Token);
|
RestoreMonitorSettings();
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.LogError($"[SetAllBrightnessAsync] Failed to set brightness: {ex.Message}");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public partial class MainViewModel
|
|||||||
|
|
||||||
// Rebuild monitor list with updated hidden monitor settings
|
// Rebuild monitor list with updated hidden monitor settings
|
||||||
// UpdateMonitorList already handles filtering hidden monitors
|
// UpdateMonitorList already handles filtering hidden monitors
|
||||||
UpdateMonitorList(_monitorManager.Monitors);
|
UpdateMonitorList(_monitorManager.Monitors, isInitialLoad: false);
|
||||||
|
|
||||||
// Apply UI configuration changes only (feature visibility toggles, etc.)
|
// Apply UI configuration changes only (feature visibility toggles, etc.)
|
||||||
// Hardware parameters (brightness, color temperature) are applied via custom actions
|
// Hardware parameters (brightness, color temperature) are applied via custom actions
|
||||||
@@ -322,122 +322,58 @@ public partial class MainViewModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reload monitor settings from configuration - ONLY called at startup
|
/// Restore monitor settings from state file - ONLY called at startup when RestoreSettingsOnStartup is enabled
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="colorTempInitTasks">Optional tasks for color temperature initialization to wait for</param>
|
public void RestoreMonitorSettings()
|
||||||
public async Task ReloadMonitorSettingsAsync(List<Task>? colorTempInitTasks = null)
|
|
||||||
{
|
{
|
||||||
Logger.LogInfo($"[ReloadMonitorSettingsAsync] Method called with {colorTempInitTasks?.Count ?? 0} color temp tasks");
|
|
||||||
|
|
||||||
// Prevent duplicate calls
|
|
||||||
if (IsLoading)
|
|
||||||
{
|
|
||||||
Logger.LogInfo("[Startup] ReloadMonitorSettingsAsync already in progress, skipping");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Set loading state to block UI interactions
|
|
||||||
IsLoading = true;
|
IsLoading = true;
|
||||||
|
|
||||||
// Read current settings
|
foreach (var monitorVm in Monitors)
|
||||||
var settings = _settingsUtils.GetSettingsOrDefault<PowerDisplaySettings>("PowerDisplay");
|
|
||||||
|
|
||||||
// Note: Profiles are now quick-apply templates, not startup states
|
|
||||||
// We only restore from monitor_state.json, not from profiles
|
|
||||||
if (settings.Properties.RestoreSettingsOnStartup)
|
|
||||||
{
|
{
|
||||||
// Restore saved settings from configuration file
|
// Find and apply corresponding saved settings from state file using stable HardwareId
|
||||||
foreach (var monitorVm in Monitors)
|
var savedState = _stateManager.GetMonitorParameters(monitorVm.HardwareId);
|
||||||
|
if (!savedState.HasValue)
|
||||||
{
|
{
|
||||||
var hardwareId = monitorVm.HardwareId;
|
continue;
|
||||||
|
|
||||||
// Find and apply corresponding saved settings from state file using stable HardwareId
|
|
||||||
var savedState = _stateManager.GetMonitorParameters(hardwareId);
|
|
||||||
if (savedState.HasValue)
|
|
||||||
{
|
|
||||||
// Validate and apply saved values (skip invalid values)
|
|
||||||
// Use UpdatePropertySilently to avoid triggering hardware updates during initialization
|
|
||||||
if (IsValueInRange(savedState.Value.Brightness, monitorVm.MinBrightness, monitorVm.MaxBrightness))
|
|
||||||
{
|
|
||||||
monitorVm.UpdatePropertySilently(nameof(monitorVm.Brightness), savedState.Value.Brightness);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Logger.LogWarning($"[Startup] Invalid brightness value {savedState.Value.Brightness} for HardwareId '{hardwareId}'");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Color temperature: VCP 0x14 preset value (discrete values, no range check needed)
|
|
||||||
// Note: ColorTemperature is now read-only in flyout UI, controlled via Settings UI
|
|
||||||
if (savedState.Value.ColorTemperatureVcp > 0)
|
|
||||||
{
|
|
||||||
// Validation will happen in Settings UI when applying preset values
|
|
||||||
monitorVm.UpdatePropertySilently(nameof(monitorVm.ColorTemperature), savedState.Value.ColorTemperatureVcp);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Contrast validation - only apply if hardware supports it
|
|
||||||
if (monitorVm.ShowContrast &&
|
|
||||||
IsValueInRange(savedState.Value.Contrast, monitorVm.MinContrast, monitorVm.MaxContrast))
|
|
||||||
{
|
|
||||||
monitorVm.UpdatePropertySilently(nameof(monitorVm.Contrast), savedState.Value.Contrast);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Volume validation - only apply if hardware supports it
|
|
||||||
if (monitorVm.ShowVolume &&
|
|
||||||
IsValueInRange(savedState.Value.Volume, monitorVm.MinVolume, monitorVm.MaxVolume))
|
|
||||||
{
|
|
||||||
monitorVm.UpdatePropertySilently(nameof(monitorVm.Volume), savedState.Value.Volume);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply feature visibility settings using HardwareId
|
|
||||||
ApplyFeatureVisibility(monitorVm, settings);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Save current hardware values to configuration file
|
|
||||||
// Wait for color temperature initialization to complete (if any)
|
|
||||||
if (colorTempInitTasks != null && colorTempInitTasks.Count > 0)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await Task.WhenAll(colorTempInitTasks);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.LogWarning($"[Startup] Some color temperature initializations failed: {ex.Message}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var monitorVm in Monitors)
|
// Validate and apply saved values (skip invalid values)
|
||||||
|
// Use UpdatePropertySilently to avoid triggering hardware updates during initialization
|
||||||
|
if (IsValueInRange(savedState.Value.Brightness, monitorVm.MinBrightness, monitorVm.MaxBrightness))
|
||||||
{
|
{
|
||||||
// Save current hardware values to settings
|
monitorVm.UpdatePropertySilently(nameof(monitorVm.Brightness), savedState.Value.Brightness);
|
||||||
SaveMonitorSettingDirect(monitorVm.HardwareId, "Brightness", monitorVm.Brightness);
|
|
||||||
SaveMonitorSettingDirect(monitorVm.HardwareId, "ColorTemperature", monitorVm.ColorTemperature);
|
|
||||||
SaveMonitorSettingDirect(monitorVm.HardwareId, "Contrast", monitorVm.Contrast);
|
|
||||||
SaveMonitorSettingDirect(monitorVm.HardwareId, "Volume", monitorVm.Volume);
|
|
||||||
|
|
||||||
// Apply feature visibility settings
|
|
||||||
ApplyFeatureVisibility(monitorVm, settings);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// No need to flush - MonitorStateManager now saves directly!
|
// Color temperature: VCP 0x14 preset value (discrete values, no range check needed)
|
||||||
|
if (savedState.Value.ColorTemperatureVcp > 0)
|
||||||
|
{
|
||||||
|
monitorVm.UpdatePropertySilently(nameof(monitorVm.ColorTemperature), savedState.Value.ColorTemperatureVcp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contrast validation - only apply if hardware supports it
|
||||||
|
if (monitorVm.ShowContrast &&
|
||||||
|
IsValueInRange(savedState.Value.Contrast, monitorVm.MinContrast, monitorVm.MaxContrast))
|
||||||
|
{
|
||||||
|
monitorVm.UpdatePropertySilently(nameof(monitorVm.Contrast), savedState.Value.Contrast);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Volume validation - only apply if hardware supports it
|
||||||
|
if (monitorVm.ShowVolume &&
|
||||||
|
IsValueInRange(savedState.Value.Volume, monitorVm.MinVolume, monitorVm.MaxVolume))
|
||||||
|
{
|
||||||
|
monitorVm.UpdatePropertySilently(nameof(monitorVm.Volume), savedState.Value.Volume);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.LogError($"[ReloadMonitorSettingsAsync] Failed to reload settings: {ex.Message}");
|
Logger.LogError($"[RestoreMonitorSettings] Failed: {ex.Message}");
|
||||||
Logger.LogError($"[ReloadMonitorSettingsAsync] Stack trace: {ex.StackTrace}");
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
Logger.LogInfo("[ReloadMonitorSettingsAsync] In finally block, setting IsLoading = false");
|
|
||||||
|
|
||||||
// Clear loading state to enable UI interactions
|
|
||||||
IsLoading = false;
|
IsLoading = false;
|
||||||
Logger.LogInfo("[ReloadMonitorSettingsAsync] IsLoading set to false, method exiting");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -156,15 +156,6 @@ public partial class MainViewModel : INotifyPropertyChanged, IDisposable
|
|||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
private async Task RefreshAsync() => await RefreshMonitorsAsync();
|
private async Task RefreshAsync() => await RefreshMonitorsAsync();
|
||||||
|
|
||||||
[RelayCommand]
|
|
||||||
private async Task SetAllBrightness(int? brightness)
|
|
||||||
{
|
|
||||||
if (brightness.HasValue)
|
|
||||||
{
|
|
||||||
await SetAllBrightnessAsync(brightness.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
private void IdentifyMonitors()
|
private void IdentifyMonitors()
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user