Files
PowerToys/src/settings-ui/Settings.UI/SettingsXAML/Views/PowerDisplayPage.xaml
moooyo 0d41d45a64 [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>
2026-03-24 07:06:07 +00:00

303 lines
23 KiB
XML

<local:NavigablePage
x:Class="Microsoft.PowerToys.Settings.UI.Views.PowerDisplayPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:library="using:Microsoft.PowerToys.Settings.UI.Library"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.Helpers"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:pdmodels="using:PowerDisplay.Common.Models"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
xmlns:ui="using:CommunityToolkit.WinUI"
AutomationProperties.LandmarkType="Main"
mc:Ignorable="d">
<controls:SettingsPageControl x:Uid="PowerDisplay" ModuleImageSource="ms-appx:///Assets/Settings/Modules/PowerDisplay.png">
<controls:SettingsPageControl.ModuleContent>
<StackPanel ChildrenTransitions="{StaticResource SettingsCardsAnimations}" Orientation="Vertical">
<controls:GPOInfoControl ShowWarning="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}">
<tkcontrols:SettingsCard
x:Uid="PowerDisplay_Enable_PowerDisplay"
HeaderIcon="{ui:BitmapIcon Source=/Assets/Settings/Icons/PowerDisplay.png}"
IsEnabled="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}">
<ToggleSwitch IsOn="{x:Bind ViewModel.IsEnabled, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</tkcontrols:SettingsCard>
</controls:GPOInfoControl>
<controls:SettingsGroup x:Uid="Shortcut" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsCard x:Uid="PowerDisplay_ActivationShortcut" HeaderIcon="{ui:FontIcon Glyph=&#xEDA7;}">
<controls:ShortcutControl HotkeySettings="{x:Bind Path=ViewModel.ActivationShortcut, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
</controls:SettingsGroup>
<controls:SettingsGroup x:Uid="PowerDisplay_Configuration_GroupSettings" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsCard
x:Uid="PowerDisplay_LaunchButtonControl"
ActionIcon="{ui:FontIcon Glyph=&#xE8A7;}"
Command="{x:Bind ViewModel.LaunchEventHandler}"
HeaderIcon="{ui:FontIcon Glyph=&#xE770;}"
IsClickEnabled="True" />
<tkcontrols:SettingsCard x:Uid="PowerDisplay_RestoreSettingsOnStartup" HeaderIcon="{ui:FontIcon Glyph=&#xE7B8;}">
<ToggleSwitch x:Uid="PowerDisplay_RestoreSettingsOnStartup_ToggleSwitch" IsOn="{x:Bind ViewModel.RestoreSettingsOnStartup, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard x:Uid="PowerDisplay_ShowSystemTrayIcon" HeaderIcon="{ui:FontIcon Glyph=&#xE75B;}">
<ToggleSwitch IsOn="{x:Bind ViewModel.ShowSystemTrayIcon, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard x:Uid="PowerDisplay_MonitorRefreshDelay" HeaderIcon="{ui:FontIcon Glyph=&#xE916;}">
<ComboBox
MinWidth="120"
ItemsSource="{x:Bind ViewModel.MonitorRefreshDelayOptions}"
SelectedItem="{x:Bind ViewModel.MonitorRefreshDelay, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
</controls:SettingsGroup>
<controls:SettingsGroup x:Uid="PowerDisplay_FlyoutOptions_GroupSettings" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsCard x:Uid="PowerDisplay_ShowProfileSwitcher" HeaderIcon="{ui:FontIcon Glyph=&#xE748;}">
<ToggleSwitch IsOn="{x:Bind ViewModel.ShowProfileSwitcher, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard x:Uid="PowerDisplay_ShowIdentifyMonitorsButton" HeaderIcon="{ui:FontIcon Glyph=&#xE9D9;}">
<ToggleSwitch IsOn="{x:Bind ViewModel.ShowIdentifyMonitorsButton, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
</controls:SettingsGroup>
<!-- Custom VCP Name Mappings -->
<controls:SettingsGroup x:Uid="PowerDisplay_CustomVcpMappings_GroupSettings" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsExpander
x:Uid="PowerDisplay_CustomVcpMappings"
HeaderIcon="{ui:FontIcon Glyph=&#xE70F;}"
IsExpanded="{x:Bind ViewModel.HasCustomVcpMappings, Mode=OneWay}"
ItemsSource="{x:Bind ViewModel.CustomVcpMappings, Mode=OneWay}">
<tkcontrols:SettingsExpander.ItemTemplate>
<DataTemplate x:DataType="library:CustomVcpValueMapping">
<tkcontrols:SettingsCard Description="{x:Bind VcpCodeDisplayName}" Header="{x:Bind DisplaySummary}">
<StackPanel Orientation="Horizontal" Spacing="8">
<Button
Click="EditCustomMapping_Click"
Content="{ui:FontIcon Glyph=&#xE70F;,
FontSize=14}"
Style="{StaticResource SubtleButtonStyle}"
Tag="{x:Bind}"
ToolTipService.ToolTip="Edit" />
<Button
Click="DeleteCustomMapping_Click"
Content="{ui:FontIcon Glyph=&#xE74D;,
FontSize=14}"
Style="{StaticResource SubtleButtonStyle}"
Tag="{x:Bind}"
ToolTipService.ToolTip="Delete" />
</StackPanel>
</tkcontrols:SettingsCard>
</DataTemplate>
</tkcontrols:SettingsExpander.ItemTemplate>
<!-- Add mapping button -->
<Button x:Uid="PowerDisplay_AddCustomMappingButton" Click="AddCustomMapping_Click">
<StackPanel Orientation="Horizontal" Spacing="6">
<FontIcon FontSize="14" Glyph="&#xE710;" />
<TextBlock x:Uid="PowerDisplay_AddCustomMapping_Text" />
</StackPanel>
</Button>
</tkcontrols:SettingsExpander>
</controls:SettingsGroup>
<controls:SettingsGroup x:Uid="PowerDisplay_Profiles_GroupSettings" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsExpander
x:Uid="PowerDisplay_QuickProfiles"
HeaderIcon="{ui:FontIcon Glyph=&#xE8B7;}"
IsExpanded="{x:Bind ViewModel.HasProfiles, Mode=OneWay}"
ItemsSource="{x:Bind ViewModel.Profiles, Mode=OneWay}">
<tkcontrols:SettingsExpander.ItemTemplate>
<DataTemplate x:DataType="pdmodels:PowerDisplayProfile">
<tkcontrols:SettingsCard Header="{x:Bind Name}">
<StackPanel Orientation="Horizontal" Spacing="8">
<Button
x:Uid="PowerDisplay_Profile_ApplyButton"
Click="ProfileButton_Click"
Tag="{x:Bind}" />
<Button
x:Uid="PowerDisplay_Profile_MoreButton"
Content="{ui:FontIcon Glyph=&#xE712;,
FontSize=16}"
Style="{StaticResource SubtleButtonStyle}"
Tag="{x:Bind}">
<Button.Flyout>
<MenuFlyout>
<MenuFlyoutItem
x:Uid="PowerDisplay_Profile_EditMenuItem"
Click="EditProfile_Click"
Icon="{ui:FontIcon Glyph=&#xE70F;}"
Tag="{x:Bind}" />
<MenuFlyoutSeparator />
<MenuFlyoutItem
x:Uid="PowerDisplay_Profile_DeleteMenuItem"
Click="DeleteProfile_Click"
Icon="{ui:FontIcon Glyph=&#xE74D;}"
Tag="{x:Bind}" />
</MenuFlyout>
</Button.Flyout>
</Button>
</StackPanel>
</tkcontrols:SettingsCard>
</DataTemplate>
</tkcontrols:SettingsExpander.ItemTemplate>
<!-- Add profile button -->
<Button x:Uid="PowerDisplay_AddProfileButton" Click="AddProfileButton_Click">
<StackPanel Orientation="Horizontal" Spacing="6">
<FontIcon FontSize="14" Glyph="&#xE710;" />
<TextBlock x:Uid="PowerDisplay_AddProfile_Text" />
</StackPanel>
</Button>
</tkcontrols:SettingsExpander>
</controls:SettingsGroup>
<controls:SettingsGroup x:Uid="PowerDisplay_Monitors" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<!-- Empty state hint -->
<TextBlock
x:Uid="PowerDisplay_NoMonitorsDetected"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Visibility="{x:Bind ViewModel.HasMonitors, Mode=OneWay, Converter={StaticResource ReverseBoolToVisibilityConverter}}" />
<!-- Monitor list -->
<ItemsControl
x:Name="MonitorsList"
HorizontalAlignment="Stretch"
ItemsSource="{x:Bind ViewModel.Monitors, Mode=OneWay}"
Visibility="{x:Bind ViewModel.HasMonitors, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="library:MonitorInfo">
<tkcontrols:SettingsExpander
Margin="0,0,0,2"
Description="{x:Bind Id, Mode=OneWay}"
Header="{x:Bind DisplayName, Mode=OneWay}"
IsExpanded="False">
<tkcontrols:SettingsExpander.HeaderIcon>
<FontIcon Glyph="{x:Bind MonitorIconGlyph, Mode=OneWay}" />
</tkcontrols:SettingsExpander.HeaderIcon>
<TextBlock Text="{x:Bind CommunicationMethod, Mode=OneWay}" />
<tkcontrols:SettingsExpander.ItemsHeader>
<!-- Capabilities warning -->
<InfoBar
x:Uid="PowerDisplay_Monitor_CapabilitiesWarning"
BorderThickness="0"
CornerRadius="0"
IsClosable="False"
IsOpen="True"
Severity="Warning"
Visibility="{x:Bind ShowCapabilitiesWarning, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" />
</tkcontrols:SettingsExpander.ItemsHeader>
<tkcontrols:SettingsExpander.Items>
<tkcontrols:SettingsCard ContentAlignment="Left" IsEnabled="{x:Bind SupportsContrast, Mode=OneWay}">
<CheckBox x:Uid="PowerDisplay_Monitor_EnableContrast" IsChecked="{x:Bind EnableContrast, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard ContentAlignment="Left" IsEnabled="{x:Bind SupportsVolume, Mode=OneWay}">
<CheckBox x:Uid="PowerDisplay_Monitor_EnableVolume" IsChecked="{x:Bind EnableVolume, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard ContentAlignment="Left" IsEnabled="{x:Bind SupportsInputSource, Mode=OneWay}">
<CheckBox x:Uid="PowerDisplay_Monitor_EnableInputSource" IsChecked="{x:Bind EnableInputSource, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard ContentAlignment="Left">
<CheckBox x:Uid="PowerDisplay_Monitor_EnableRotation" IsChecked="{x:Bind EnableRotation, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard ContentAlignment="Left" IsEnabled="{x:Bind SupportsColorTemperature, Mode=OneWay}">
<CheckBox
x:Uid="PowerDisplay_Monitor_EnableColorTemperature"
Click="EnableColorTemperature_Click"
IsChecked="{x:Bind EnableColorTemperature, Mode=TwoWay}"
Tag="{x:Bind}" />
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard ContentAlignment="Left" IsEnabled="{x:Bind SupportsPowerState, Mode=OneWay}">
<CheckBox x:Uid="PowerDisplay_Monitor_EnablePowerState" IsChecked="{x:Bind EnablePowerState, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard ContentAlignment="Left">
<CheckBox x:Uid="PowerDisplay_Monitor_HideMonitor" IsChecked="{x:Bind IsHidden, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<!-- VCP Capabilities -->
<tkcontrols:SettingsCard x:Uid="PowerDisplay_Monitor_VcpCapabilities" Visibility="{x:Bind HasCapabilities, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}">
<Button
x:Uid="PowerDisplay_Monitor_VcpDetails_Button"
Content="&#xE946;"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
Style="{StaticResource SubtleButtonStyle}">
<Button.Flyout>
<Flyout ShouldConstrainToRootBounds="False">
<Grid Width="420">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- Header with Copy Button -->
<Grid Margin="0,0,0,12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock
x:Uid="PowerDisplay_Monitor_VcpCodes_Header"
Grid.Column="0"
VerticalAlignment="Center"
FontSize="13"
FontWeight="SemiBold" />
<Button
x:Uid="PowerDisplay_Monitor_VcpCodes_CopyButton"
Grid.Column="1"
Padding="8,4"
VerticalAlignment="Center"
Click="CopyVcpCodes_Click"
Tag="{x:Bind}">
<StackPanel Orientation="Horizontal" Spacing="4">
<FontIcon FontSize="12" Glyph="&#xE8C8;" />
<TextBlock x:Uid="PowerDisplay_Monitor_VcpCodes_CopyText" FontSize="12" />
</StackPanel>
</Button>
</Grid>
<!-- VCP Codes List -->
<ScrollViewer
Grid.Row="1"
MaxHeight="480"
HorizontalScrollBarVisibility="Disabled"
HorizontalScrollMode="Disabled"
VerticalScrollBarVisibility="Auto">
<ItemsControl HorizontalAlignment="Stretch" ItemsSource="{x:Bind VcpCodesFormatted, Mode=OneWay}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="library:VcpCodeDisplayInfo">
<StackPanel HorizontalAlignment="Stretch" Orientation="Vertical">
<TextBlock
FontSize="12"
Text="{x:Bind Title}"
TextWrapping="Wrap" />
<TextBlock
Margin="0,0,0,8"
FontSize="12"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="{x:Bind Values}"
TextWrapping="Wrap"
Visibility="{x:Bind HasValues}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
</Flyout>
</Button.Flyout>
</Button>
</tkcontrols:SettingsCard>
</tkcontrols:SettingsExpander.Items>
</tkcontrols:SettingsExpander>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</controls:SettingsGroup>
</StackPanel>
</controls:SettingsPageControl.ModuleContent>
<controls:SettingsPageControl.PrimaryLinks>
<controls:PageLink x:Uid="LearnMore_PowerDisplay" Link="https://aka.ms/PowerToysOverview_PowerDisplay" />
</controls:SettingsPageControl.PrimaryLinks>
</controls:SettingsPageControl>
</local:NavigablePage>