mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-03 01:36:31 +02:00
[Settings] Decouple Settings.UI.Library from PowerDisplay.Lib to fix … (#46325)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request Fixes PowerToys Run crash (`FileNotFoundException` for `PowerDisplay.Lib.dll`) caused by `Settings.UI.Library` having a transitive dependency on `PowerDisplay.Lib`. `SettingsSerializationContext` registered PowerDisplay profile types (`PowerDisplayProfile`, `PowerDisplayProfiles`, `ProfileMonitorSetting`) via `[JsonSerializable]` attributes, which forced the CLR to load `PowerDisplay.Lib.dll` at startup. PowerToys Run depends on `Settings.UI.Library` but does not ship `PowerDisplay.Lib.dll`, causing the crash. <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #46261 <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed Co-authored-by: Yu Leng (from Dev Box) <yuleng@microsoft.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,89 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation
|
||||||
|
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||||
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
|
namespace Microsoft.PowerToys.Settings.UI.Library
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a color temperature preset item for VCP code 0x14.
|
||||||
|
/// Used to display available color temperature presets in UI components.
|
||||||
|
/// This is a local copy maintained in Settings.UI.Library to avoid a dependency on PowerDisplay.Lib.
|
||||||
|
/// </summary>
|
||||||
|
public partial class ColorPresetItem : INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
private int _vcpValue;
|
||||||
|
private string _displayName = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="ColorPresetItem"/> class.
|
||||||
|
/// </summary>
|
||||||
|
public ColorPresetItem()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="ColorPresetItem"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="vcpValue">The VCP value for the color temperature preset.</param>
|
||||||
|
/// <param name="displayName">The display name for UI.</param>
|
||||||
|
public ColorPresetItem(int vcpValue, string displayName)
|
||||||
|
{
|
||||||
|
_vcpValue = vcpValue;
|
||||||
|
_displayName = displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when a property value changes.
|
||||||
|
/// </summary>
|
||||||
|
public event PropertyChangedEventHandler? PropertyChanged;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the VCP value for this color temperature preset.
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("vcpValue")]
|
||||||
|
public int VcpValue
|
||||||
|
{
|
||||||
|
get => _vcpValue;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_vcpValue != value)
|
||||||
|
{
|
||||||
|
_vcpValue = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the display name for UI.
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("displayName")]
|
||||||
|
public string DisplayName
|
||||||
|
{
|
||||||
|
get => _displayName;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_displayName != value)
|
||||||
|
{
|
||||||
|
_displayName = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raises the PropertyChanged event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="propertyName">The name of the property that changed.</param>
|
||||||
|
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
|
||||||
|
{
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
// Copyright (c) Microsoft Corporation
|
||||||
|
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||||
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Microsoft.PowerToys.Settings.UI.Library
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a custom name mapping for a VCP code value.
|
||||||
|
/// Used to override the default VCP value names with user-defined names.
|
||||||
|
/// This is a local copy maintained in Settings.UI.Library to avoid a dependency on PowerDisplay.Lib.
|
||||||
|
/// </summary>
|
||||||
|
public class CustomVcpValueMapping
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the VCP code (e.g., 0x14 for color temperature, 0x60 for input source).
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("vcpCode")]
|
||||||
|
public byte VcpCode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the VCP value to map (e.g., 0x11 for HDMI-1).
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("value")]
|
||||||
|
public int Value { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the custom name to display instead of the default name.
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("customName")]
|
||||||
|
public string CustomName { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether this mapping applies to all monitors.
|
||||||
|
/// When true, the mapping is applied globally. When false, only applies to TargetMonitorId.
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("applyToAll")]
|
||||||
|
public bool ApplyToAll { get; set; } = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the target monitor ID when ApplyToAll is false.
|
||||||
|
/// This is the monitor's unique identifier.
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("targetMonitorId")]
|
||||||
|
public string TargetMonitorId { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the target monitor display name (for UI display only, not serialized).
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public string TargetMonitorName { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the display name for the VCP code (for UI display).
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public string VcpCodeDisplayName => $"VCP 0x{VcpCode:X2}";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the display name for the VCP value.
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public string ValueDisplayName => $"0x{Value:X2}";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a summary string for display in the UI list.
|
||||||
|
/// Format: "0xVV → CustomName" or "0xVV → CustomName (MonitorName)"
|
||||||
|
/// </summary>
|
||||||
|
[JsonIgnore]
|
||||||
|
public string DisplaySummary
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var baseSummary = $"0x{Value:X2} \u2192 {CustomName}";
|
||||||
|
if (!ApplyToAll && !string.IsNullOrEmpty(TargetMonitorName))
|
||||||
|
{
|
||||||
|
return $"{baseSummary} ({TargetMonitorName})";
|
||||||
|
}
|
||||||
|
|
||||||
|
return baseSummary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,14 +8,13 @@ using System.Collections.ObjectModel;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
|
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
|
||||||
using PowerDisplay.Common.Drivers;
|
|
||||||
using PowerDisplay.Common.Models;
|
|
||||||
using PowerDisplay.Common.Utils;
|
|
||||||
|
|
||||||
namespace Microsoft.PowerToys.Settings.UI.Library
|
namespace Microsoft.PowerToys.Settings.UI.Library
|
||||||
{
|
{
|
||||||
public class MonitorInfo : Observable
|
public class MonitorInfo : Observable
|
||||||
{
|
{
|
||||||
|
private const byte VcpCodeSelectColorPreset = 0x14;
|
||||||
|
|
||||||
private string _name = string.Empty;
|
private string _name = string.Empty;
|
||||||
private string _id = string.Empty;
|
private string _id = string.Empty;
|
||||||
private string _communicationMethod = string.Empty;
|
private string _communicationMethod = string.Empty;
|
||||||
@@ -532,7 +531,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
|||||||
System.Globalization.NumberStyles.HexNumber,
|
System.Globalization.NumberStyles.HexNumber,
|
||||||
System.Globalization.CultureInfo.InvariantCulture,
|
System.Globalization.CultureInfo.InvariantCulture,
|
||||||
out int code) &&
|
out int code) &&
|
||||||
code == NativeConstants.VcpCodeSelectColorPreset);
|
code == VcpCodeSelectColorPreset);
|
||||||
|
|
||||||
// No VCP 0x14 or no values
|
// No VCP 0x14 or no values
|
||||||
if (colorTempVcp == null || colorTempVcp.ValueList == null || colorTempVcp.ValueList.Count == 0)
|
if (colorTempVcp == null || colorTempVcp.ValueList == null || colorTempVcp.ValueList.Count == 0)
|
||||||
@@ -556,9 +555,10 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
|||||||
})
|
})
|
||||||
.Where(x => x.VcpValue > 0);
|
.Where(x => x.VcpValue > 0);
|
||||||
|
|
||||||
// Use shared helper to compute presets, then convert to nested type for XAML compatibility
|
// Compute presets inline (avoiding dependency on PowerDisplay.Lib's ColorTemperatureHelper)
|
||||||
var basePresets = ColorTemperatureHelper.ComputeColorPresets(colorTempValues);
|
var presetList = colorTempValues
|
||||||
var presetList = basePresets.Select(p => new ColorPresetItem(p.VcpValue, p.DisplayName));
|
.Select(item => new ColorPresetItem(item.VcpValue, !string.IsNullOrEmpty(item.Name) ? item.Name : "Manufacturer Defined"))
|
||||||
|
.OrderBy(p => p.VcpValue);
|
||||||
return new ObservableCollection<ColorPresetItem>(presetList);
|
return new ObservableCollection<ColorPresetItem>(presetList);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -598,8 +598,8 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
|||||||
// Current value is not in the preset list - add it at the beginning
|
// Current value is not in the preset list - add it at the beginning
|
||||||
var displayList = new List<ColorPresetItem>();
|
var displayList = new List<ColorPresetItem>();
|
||||||
|
|
||||||
// Add current value with "Custom" indicator using shared helper
|
// Add current value with "Custom" indicator
|
||||||
var displayName = ColorTemperatureHelper.FormatCustomColorTemperatureDisplayName(_colorTemperatureVcp);
|
var displayName = $"Custom (0x{_colorTemperatureVcp:X2})";
|
||||||
displayList.Add(new ColorPresetItem(_colorTemperatureVcp, displayName));
|
displayList.Add(new ColorPresetItem(_colorTemperatureVcp, displayName));
|
||||||
|
|
||||||
// Add all supported presets
|
// Add all supported presets
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
using PowerDisplay.Common.Models;
|
|
||||||
using Settings.UI.Library.Attributes;
|
using Settings.UI.Library.Attributes;
|
||||||
|
|
||||||
namespace Microsoft.PowerToys.Settings.UI.Library
|
namespace Microsoft.PowerToys.Settings.UI.Library
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
<ProjectReference Include="..\..\common\ManagedCommon\ManagedCommon.csproj" />
|
<ProjectReference Include="..\..\common\ManagedCommon\ManagedCommon.csproj" />
|
||||||
<ProjectReference Include="..\..\common\ManagedTelemetry\Telemetry\ManagedTelemetry.csproj" />
|
<ProjectReference Include="..\..\common\ManagedTelemetry\Telemetry\ManagedTelemetry.csproj" />
|
||||||
<ProjectReference Include="..\..\modules\MouseUtils\MouseJump.Common\MouseJump.Common.csproj" />
|
<ProjectReference Include="..\..\modules\MouseUtils\MouseJump.Common\MouseJump.Common.csproj" />
|
||||||
<ProjectReference Include="..\..\modules\powerdisplay\PowerDisplay.Lib\PowerDisplay.Lib.csproj" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
using PowerDisplay.Common.Models;
|
|
||||||
using SettingsUILibrary = Settings.UI.Library;
|
using SettingsUILibrary = Settings.UI.Library;
|
||||||
using SettingsUILibraryHelpers = Settings.UI.Library.Helpers;
|
using SettingsUILibraryHelpers = Settings.UI.Library.Helpers;
|
||||||
|
|
||||||
@@ -158,13 +157,6 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
|||||||
[JsonSerializable(typeof(PasteAIProviderDefinition))]
|
[JsonSerializable(typeof(PasteAIProviderDefinition))]
|
||||||
[JsonSerializable(typeof(System.Collections.ObjectModel.ObservableCollection<PasteAIProviderDefinition>))]
|
[JsonSerializable(typeof(System.Collections.ObjectModel.ObservableCollection<PasteAIProviderDefinition>))]
|
||||||
|
|
||||||
// PowerDisplay Profile Types (for AOT compatibility)
|
|
||||||
[JsonSerializable(typeof(PowerDisplayProfile))]
|
|
||||||
[JsonSerializable(typeof(List<PowerDisplayProfile>))]
|
|
||||||
[JsonSerializable(typeof(PowerDisplayProfiles))]
|
|
||||||
[JsonSerializable(typeof(ProfileMonitorSetting))]
|
|
||||||
[JsonSerializable(typeof(List<ProfileMonitorSetting>))]
|
|
||||||
|
|
||||||
// IPC Send Message Wrapper Classes (Snd*)
|
// IPC Send Message Wrapper Classes (Snd*)
|
||||||
[JsonSerializable(typeof(SndAwakeSettings))]
|
[JsonSerializable(typeof(SndAwakeSettings))]
|
||||||
[JsonSerializable(typeof(SndCursorWrapSettings))]
|
[JsonSerializable(typeof(SndCursorWrapSettings))]
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ using Microsoft.UI.Xaml;
|
|||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
using PowerDisplay.Common.Models;
|
using PowerDisplay.Common.Models;
|
||||||
using PowerDisplay.Common.Utils;
|
using PowerDisplay.Common.Utils;
|
||||||
|
using CustomVcpValueMapping = Microsoft.PowerToys.Settings.UI.Library.CustomVcpValueMapping;
|
||||||
|
|
||||||
namespace Microsoft.PowerToys.Settings.UI.Views
|
namespace Microsoft.PowerToys.Settings.UI.Views
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -71,7 +71,7 @@
|
|||||||
IsExpanded="{x:Bind ViewModel.HasCustomVcpMappings, Mode=OneWay}"
|
IsExpanded="{x:Bind ViewModel.HasCustomVcpMappings, Mode=OneWay}"
|
||||||
ItemsSource="{x:Bind ViewModel.CustomVcpMappings, Mode=OneWay}">
|
ItemsSource="{x:Bind ViewModel.CustomVcpMappings, Mode=OneWay}">
|
||||||
<tkcontrols:SettingsExpander.ItemTemplate>
|
<tkcontrols:SettingsExpander.ItemTemplate>
|
||||||
<DataTemplate x:DataType="pdmodels:CustomVcpValueMapping">
|
<DataTemplate x:DataType="library:CustomVcpValueMapping">
|
||||||
<tkcontrols:SettingsCard Description="{x:Bind VcpCodeDisplayName}" Header="{x:Bind DisplaySummary}">
|
<tkcontrols:SettingsCard Description="{x:Bind VcpCodeDisplayName}" Header="{x:Bind DisplaySummary}">
|
||||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ using Microsoft.UI.Xaml.Controls;
|
|||||||
using PowerDisplay.Common.Models;
|
using PowerDisplay.Common.Models;
|
||||||
using PowerDisplay.Common.Utils;
|
using PowerDisplay.Common.Utils;
|
||||||
using Windows.ApplicationModel.DataTransfer;
|
using Windows.ApplicationModel.DataTransfer;
|
||||||
|
using CustomVcpValueMapping = Microsoft.PowerToys.Settings.UI.Library.CustomVcpValueMapping;
|
||||||
|
|
||||||
namespace Microsoft.PowerToys.Settings.UI.Views
|
namespace Microsoft.PowerToys.Settings.UI.Views
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ using PowerDisplay.Common.Models;
|
|||||||
using PowerDisplay.Common.Services;
|
using PowerDisplay.Common.Services;
|
||||||
using PowerDisplay.Common.Utils;
|
using PowerDisplay.Common.Utils;
|
||||||
using PowerToys.Interop;
|
using PowerToys.Interop;
|
||||||
|
using CustomVcpValueMapping = Microsoft.PowerToys.Settings.UI.Library.CustomVcpValueMapping;
|
||||||
|
|
||||||
namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user