Add InternalName for monitor identification

Enhanced monitor identification by introducing the `InternalName`
property as a unique identifier, with fallback to `HardwareId`
for backward compatibility. Updated `MainViewModel` logic,
logging, and UI bindings to use `InternalName`.

Extended `ProfileMonitorSetting` to include `MonitorInternalName`
for serialization and profile management. Adjusted profile
creation and pre-fill logic to support the new property.

These changes improve robustness, maintain compatibility with
older profiles, and enhance clarity in logging and the UI.
This commit is contained in:
Yu Leng
2025-11-20 16:36:37 +08:00
parent 8aec939c9d
commit 336234d05b
6 changed files with 28 additions and 9 deletions

View File

@@ -591,16 +591,27 @@ public partial class MainViewModel : INotifyPropertyChanged, IDisposable
foreach (var setting in monitorSettings) foreach (var setting in monitorSettings)
{ {
// Find monitor by HardwareId // Find monitor by InternalName first (unique identifier), fallback to HardwareId for old profiles
var monitorVm = Monitors.FirstOrDefault(m => m.HardwareId == setting.HardwareId); MonitorViewModel? monitorVm = null;
if (!string.IsNullOrEmpty(setting.MonitorInternalName))
{
monitorVm = Monitors.FirstOrDefault(m => m.InternalName == setting.MonitorInternalName);
}
// Fallback to HardwareId for backward compatibility with old profiles
if (monitorVm == null)
{
monitorVm = Monitors.FirstOrDefault(m => m.HardwareId == setting.HardwareId);
}
if (monitorVm == null) if (monitorVm == null)
{ {
Logger.LogWarning($"[Profile] Monitor with HardwareId '{setting.HardwareId}' not found (disconnected?)"); Logger.LogWarning($"[Profile] Monitor with InternalName '{setting.MonitorInternalName}' or HardwareId '{setting.HardwareId}' not found (disconnected?)");
continue; continue;
} }
Logger.LogInfo($"[Profile] Applying settings to monitor '{monitorVm.Name}' (HardwareId: {setting.HardwareId})"); Logger.LogInfo($"[Profile] Applying settings to monitor '{monitorVm.Name}' (InternalName: {setting.MonitorInternalName}, HardwareId: {setting.HardwareId})");
// Apply brightness if included in profile // Apply brightness if included in profile
if (setting.Brightness.HasValue && if (setting.Brightness.HasValue &&

View File

@@ -324,6 +324,8 @@ public partial class MonitorViewModel : INotifyPropertyChanged, IDisposable
public string HardwareId => _monitor.HardwareId; public string HardwareId => _monitor.HardwareId;
public string InternalName => _monitor.Id;
public string Name => _monitor.Name; public string Name => _monitor.Name;
public string Manufacturer => _monitor.Manufacturer; public string Manufacturer => _monitor.Manufacturer;

View File

@@ -26,18 +26,23 @@ namespace Microsoft.PowerToys.Settings.UI.Library
[JsonPropertyName("colorTemperature")] [JsonPropertyName("colorTemperature")]
public int? ColorTemperature { get; set; } public int? ColorTemperature { get; set; }
[JsonPropertyName("monitorInternalName")]
public string MonitorInternalName { get; set; }
public ProfileMonitorSetting() public ProfileMonitorSetting()
{ {
HardwareId = string.Empty; HardwareId = string.Empty;
MonitorInternalName = string.Empty;
} }
public ProfileMonitorSetting(string hardwareId, int? brightness = null, int? colorTemperature = null, int? contrast = null, int? volume = null) public ProfileMonitorSetting(string hardwareId, int? brightness = null, int? colorTemperature = null, int? contrast = null, int? volume = null, string monitorInternalName = "")
{ {
HardwareId = hardwareId; HardwareId = hardwareId;
Brightness = brightness; Brightness = brightness;
ColorTemperature = colorTemperature; ColorTemperature = colorTemperature;
Contrast = contrast; Contrast = contrast;
Volume = volume; Volume = volume;
MonitorInternalName = monitorInternalName;
} }
} }
} }

View File

@@ -70,7 +70,7 @@
Style="{StaticResource BodyStrongTextBlockStyle}" Style="{StaticResource BodyStrongTextBlockStyle}"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"/> Foreground="{ThemeResource TextFillColorSecondaryBrush}"/>
<TextBlock <TextBlock
Text="{x:Bind Monitor.HardwareId}" Text="{x:Bind Monitor.InternalName}"
Style="{StaticResource CaptionTextBlockStyle}" Style="{StaticResource CaptionTextBlockStyle}"
Foreground="{ThemeResource TextFillColorTertiaryBrush}" /> Foreground="{ThemeResource TextFillColorTertiaryBrush}" />
</StackPanel> </StackPanel>
@@ -100,7 +100,7 @@
Text="{x:Bind Monitor.Name}" Text="{x:Bind Monitor.Name}"
Style="{StaticResource BodyStrongTextBlockStyle}" /> Style="{StaticResource BodyStrongTextBlockStyle}" />
<TextBlock <TextBlock
Text="{x:Bind Monitor.HardwareId}" Text="{x:Bind Monitor.InternalName}"
Style="{StaticResource CaptionTextBlockStyle}" Style="{StaticResource CaptionTextBlockStyle}"
Foreground="{ThemeResource TextFillColorSecondaryBrush}" /> Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
</StackPanel> </StackPanel>

View File

@@ -57,7 +57,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
// Pre-fill monitor settings from existing profile // Pre-fill monitor settings from existing profile
foreach (var monitorSetting in profile.MonitorSettings) foreach (var monitorSetting in profile.MonitorSettings)
{ {
var monitorItem = ViewModel.Monitors.FirstOrDefault(m => m.Monitor.HardwareId == monitorSetting.HardwareId); var monitorItem = ViewModel.Monitors.FirstOrDefault(m => m.Monitor.InternalName == monitorSetting.MonitorInternalName);
if (monitorItem != null) if (monitorItem != null)
{ {
monitorItem.IsSelected = true; monitorItem.IsSelected = true;

View File

@@ -108,7 +108,8 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
m.IncludeBrightness ? (int?)m.Brightness : null, m.IncludeBrightness ? (int?)m.Brightness : null,
m.IncludeColorTemperature && m.SupportsColorTemperature ? (int?)m.ColorTemperature : null, m.IncludeColorTemperature && m.SupportsColorTemperature ? (int?)m.ColorTemperature : null,
m.IncludeContrast && m.SupportsContrast ? (int?)m.Contrast : null, m.IncludeContrast && m.SupportsContrast ? (int?)m.Contrast : null,
m.IncludeVolume && m.SupportsVolume ? (int?)m.Volume : null)) m.IncludeVolume && m.SupportsVolume ? (int?)m.Volume : null,
m.Monitor.InternalName))
.ToList(); .ToList();
return new PowerDisplayProfile(_profileName, settings); return new PowerDisplayProfile(_profileName, settings);