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)
{
// Find monitor by HardwareId
var monitorVm = Monitors.FirstOrDefault(m => m.HardwareId == setting.HardwareId);
// Find monitor by InternalName first (unique identifier), fallback to HardwareId for old profiles
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)
{
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;
}
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
if (setting.Brightness.HasValue &&

View File

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

View File

@@ -26,18 +26,23 @@ namespace Microsoft.PowerToys.Settings.UI.Library
[JsonPropertyName("colorTemperature")]
public int? ColorTemperature { get; set; }
[JsonPropertyName("monitorInternalName")]
public string MonitorInternalName { get; set; }
public ProfileMonitorSetting()
{
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;
Brightness = brightness;
ColorTemperature = colorTemperature;
Contrast = contrast;
Volume = volume;
MonitorInternalName = monitorInternalName;
}
}
}

View File

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

View File

@@ -57,7 +57,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
// Pre-fill monitor settings from existing profile
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)
{
monitorItem.IsSelected = true;

View File

@@ -108,7 +108,8 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
m.IncludeBrightness ? (int?)m.Brightness : null,
m.IncludeColorTemperature && m.SupportsColorTemperature ? (int?)m.ColorTemperature : 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();
return new PowerDisplayProfile(_profileName, settings);