Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
83125aa
Extract PowerDisplay.Models to decouple Settings.UI from PowerDisplay…
Mar 25, 2026
5e36753
Re-enable and modernize PowerDisplay module
Mar 31, 2026
3a9e4e3
Adjust control grid spacing and fix monitor number scaling
Mar 31, 2026
604831c
Add "NOTOPMOST" to term list in expect.txt
Mar 31, 2026
17917ea
Fix DPI handling for multi-monitor window positioning in PowerDisplay
Mar 31, 2026
c4ec095
update
Mar 31, 2026
b370b96
Refine PowerDisplay DPI-aware layout semantics
Mar 31, 2026
e0e291a
Improve PowerDisplay flyout layout adaptability
Mar 31, 2026
40952bb
Adjust PowerDisplay flyout spacing and tray activation
Mar 31, 2026
298a098
Add Mdt to spell-check allowlist for MDT_EFFECTIVE_DPI Win32 API
Mar 31, 2026
002e806
Make ProfileHelper compound ops atomic; simplify ProfileService facade
Mar 31, 2026
2c278a2
Fix missing trailing backslash in PowerDisplay depsPath
Mar 31, 2026
42f9e9b
Fix SA1512 and CS0117 build errors
Mar 31, 2026
0d6dccf
Enforce GPO policy and fix toggle-listener lifecycle in PowerDisplay
Mar 31, 2026
7126690
Add upserts to spell-check allowlist
Apr 1, 2026
0c88136
Apply XamlStyler formatting to MainWindow and MonitorIcon
Apr 1, 2026
e6ef3bb
Styling tweaks in the flyout
niels9001 Apr 3, 2026
a75d52b
Small settings tweaks
niels9001 Apr 3, 2026
a1a0958
Updating icon and fix settings crash
niels9001 Apr 3, 2026
c58ca16
PowerDisplay: fix rotation binding, single-click tray, profile editor…
Apr 7, 2026
4b3ac64
Merge branch 'main' into yuleng/pd/1
Apr 8, 2026
497ab30
Fix window positioning and activation for multi-monitor
Apr 8, 2026
41c3dbb
Suppress WM_DPICHANGED during cross-DPI window moves
Apr 8, 2026
4eaac9e
Remove minimum window height constraints for flexibility
Apr 8, 2026
4e5f952
Fix spelling issue
Apr 8, 2026
a4a4888
Add PowerDisplay.Models.dll to ESRP signing configuration
Apr 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/actions/spell-check/allow/code.txt
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ REGSTR
INVOKEIDLIST
MEMORYSTATUSEX
ABE
Mdt
HTCAPTION
POSCHANGED
QUERYPOS
Expand Down
3 changes: 2 additions & 1 deletion .github/actions/spell-check/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1694,6 +1694,7 @@ UOI
UPDATENOW
updown
UPGRADINGPRODUCTCODE
upserts
Uptool
urld
Usb
Expand Down Expand Up @@ -2176,7 +2177,7 @@ nodiscard
nologo
nomove
nosize
notopmost
NOTOPMOST
Notupdated
notwindows
nowarn
Expand Down
4 changes: 4 additions & 0 deletions .pipelines/ESRPSigning_core.json
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,11 @@
"PowerToys.PowerAccentModuleInterface.dll",
"PowerToys.PowerAccentKeyboardService.dll",

"PowerToys.PowerDisplayModuleInterface.dll",
"WinUI3Apps\\PowerToys.PowerDisplay.dll",
"WinUI3Apps\\PowerToys.PowerDisplay.exe",
"PowerDisplay.Lib.dll",
"PowerDisplay.Models.dll",

"WinUI3Apps\\PowerToys.PowerRenameExt.dll",
"WinUI3Apps\\PowerToys.PowerRename.exe",
Expand Down
6 changes: 4 additions & 2 deletions PowerToys.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -709,17 +709,19 @@
</Project>
</Folder>
<Folder Name="/modules/PowerDisplay/">
<Project Path="src/modules/powerdisplay/PowerDisplay.Models/PowerDisplay.Models.csproj">
<Platform Solution="*|ARM64" Project="ARM64" />
<Platform Solution="*|x64" Project="x64" />
</Project>
<Project Path="src/modules/powerdisplay/PowerDisplay.Lib/PowerDisplay.Lib.csproj">
<Platform Solution="*|ARM64" Project="ARM64" />
<Platform Solution="*|x64" Project="x64" />
</Project>
<!-- TEMPORARILY_DISABLED: PowerDisplay
<Project Path="src/modules/powerdisplay/PowerDisplay/PowerDisplay.csproj">
<Platform Solution="*|ARM64" Project="ARM64" />
<Platform Solution="*|x64" Project="x64" />
</Project>
<Project Path="src/modules/powerdisplay/PowerDisplayModuleInterface/PowerDisplayModuleInterface.vcxproj" Id="d1234567-8901-2345-6789-abcdef012345" />
-->
</Folder>
<Folder Name="/modules/PowerDisplay/Tests/">
<Project Path="src/modules/powerdisplay/PowerDisplay.Lib.UnitTests/PowerDisplay.Lib.UnitTests.csproj">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1594,6 +1594,7 @@ UINT __stdcall TerminateProcessesCA(MSIHANDLE hInstall)
L"PowerToys.PowerRename.exe",
L"PowerToys.ImageResizer.exe",
L"PowerToys.LightSwitchService.exe",
L"PowerToys.PowerDisplay.exe",
L"PowerToys.GcodeThumbnailProvider.exe",
L"PowerToys.BgcodeThumbnailProvider.exe",
L"PowerToys.PdfThumbnailProvider.exe",
Expand Down
2 changes: 2 additions & 0 deletions installer/PowerToysSetupVNext/PowerToysInstallerVNext.wixproj
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ call powershell.exe -NonInteractive -executionpolicy Unrestricted -File $(MSBuil
call move /Y ..\..\..\NewPlus.wxs.bk ..\..\..\NewPlus.wxs
call move /Y ..\..\..\Peek.wxs.bk ..\..\..\Peek.wxs
call move /Y ..\..\..\PowerRename.wxs.bk ..\..\..\PowerRename.wxs
call move /Y ..\..\..\PowerDisplay.wxs.bk ..\..\..\PowerDisplay.wxs
call move /Y ..\..\..\Product.wxs.bk ..\..\..\Product.wxs
call move /Y ..\..\..\RegistryPreview.wxs.bk ..\..\..\RegistryPreview.wxs
call move /Y ..\..\..\Resources.wxs.bk ..\..\..\Resources.wxs
Expand Down Expand Up @@ -123,6 +124,7 @@ call powershell.exe -NonInteractive -executionpolicy Unrestricted -File $(MSBuil
<Compile Include="KeyboardManager.wxs" />
<Compile Include="Peek.wxs" />
<Compile Include="PowerRename.wxs" />
<Compile Include="PowerDisplay.wxs" />
<Compile Include="DscResources.wxs" />
<Compile Include="RegistryPreview.wxs" />
<Compile Include="Run.wxs" />
Expand Down
1 change: 1 addition & 0 deletions installer/PowerToysSetupVNext/Product.wxs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
<ComponentGroupRef Id="LightSwitchComponentGroup" />
<ComponentGroupRef Id="PeekComponentGroup" />
<ComponentGroupRef Id="PowerRenameComponentGroup" />
<ComponentGroupRef Id="PowerDisplayComponentGroup" />
<ComponentGroupRef Id="RegistryPreviewComponentGroup" />
<ComponentGroupRef Id="RunComponentGroup" />
<ComponentGroupRef Id="SettingsComponentGroup" />
Expand Down
4 changes: 4 additions & 0 deletions installer/PowerToysSetupVNext/generateAllFileComponents.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,10 @@ Generate-FileComponents -fileListName "PeekAssetsFiles" -wxsFilePath $PSScriptRo
Generate-FileList -fileDepsJson "" -fileListName PowerRenameAssetsFiles -wxsFilePath $PSScriptRoot\PowerRename.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\PowerRename\"
Generate-FileComponents -fileListName "PowerRenameAssetsFiles" -wxsFilePath $PSScriptRoot\PowerRename.wxs

#PowerDisplay
Generate-FileList -fileDepsJson "" -fileListName PowerDisplayAssetsFiles -wxsFilePath $PSScriptRoot\PowerDisplay.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\PowerDisplay\"
Generate-FileComponents -fileListName "PowerDisplayAssetsFiles" -wxsFilePath $PSScriptRoot\PowerDisplay.wxs

#RegistryPreview
Generate-FileList -fileDepsJson "" -fileListName RegistryPreviewAssetsFiles -wxsFilePath $PSScriptRoot\RegistryPreview.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\RegistryPreview\"
Generate-FileComponents -fileListName "RegistryPreviewAssetsFiles" -wxsFilePath $PSScriptRoot\RegistryPreview.wxs
Expand Down
2 changes: 0 additions & 2 deletions src/gpo/assets/PowerToys.admx
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,6 @@
<decimal value="0" />
</disabledValue>
</policy>
<!-- TEMPORARILY_DISABLED: PowerDisplay
<policy name="ConfigureEnabledUtilityPowerDisplay" class="Both" displayName="$(string.ConfigureEnabledUtilityPowerDisplay)" explainText="$(string.ConfigureEnabledUtilityDescription)" key="Software\Policies\PowerToys" valueName="ConfigureEnabledUtilityPowerDisplay">
<parentCategory ref="PowerToys" />
<supportedOn ref="SUPPORTED_POWERTOYS_0_95_0" />
Expand All @@ -161,7 +160,6 @@
<decimal value="0" />
</disabledValue>
</policy>
-->
<policy name="ConfigureEnabledUtilityEnvironmentVariables" class="Both" displayName="$(string.ConfigureEnabledUtilityEnvironmentVariables)" explainText="$(string.ConfigureEnabledUtilityDescription)" key="Software\Policies\PowerToys" valueName="ConfigureEnabledUtilityEnvironmentVariables">
<parentCategory ref="PowerToys" />
<supportedOn ref="SUPPORTED_POWERTOYS_0_75_0" />
Expand Down
2 changes: 1 addition & 1 deletion src/gpo/assets/en-US/PowerToys.adml
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ If you don't configure this policy, the user will be able to control the setting
<string id="ConfigureEnabledUtilityCmdPal">CmdPal: Configure enabled state</string>
<string id="ConfigureEnabledUtilityCropAndLock">Crop And Lock: Configure enabled state</string>
<string id="ConfigureEnabledUtilityLightSwitch">Light Switch: Configure enabled state</string>
<!-- <string id="ConfigureEnabledUtilityPowerDisplay">PowerDisplay: Configure enabled state</string> --><!-- TEMPORARILY_DISABLED: PowerDisplay -->
<string id="ConfigureEnabledUtilityPowerDisplay">PowerDisplay: Configure enabled state</string>
<string id="ConfigureEnabledUtilityEnvironmentVariables">Environment Variables: Configure enabled state</string>
<string id="ConfigureEnabledUtilityFancyZones">FancyZones: Configure enabled state</string>
<string id="ConfigureEnabledUtilityFileLocksmith">File Locksmith: Configure enabled state</string>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// 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 PowerDisplay.Common.Utils;
using PowerDisplay.Models;

namespace PowerDisplay.Common.Extensions
{
/// <summary>
/// Extension methods for <see cref="CustomVcpValueMapping"/> that provide display-related properties.
/// These depend on <see cref="VcpNames"/> and are therefore kept in PowerDisplay.Lib
/// rather than in the shared PowerDisplay.Models project.
/// </summary>
public static class CustomVcpValueMappingExtensions
{
/// <summary>
/// Gets the display name for the VCP code (e.g., "Select Color Preset").
/// </summary>
public static string GetVcpCodeDisplayName(this CustomVcpValueMapping mapping)
{
return VcpNames.GetCodeName(mapping.VcpCode);
}

/// <summary>
/// Gets the formatted display name for the VCP value (e.g., "6500K (0x05)").
/// </summary>
public static string GetValueDisplayName(this CustomVcpValueMapping mapping)
{
return VcpNames.GetFormattedValueName(mapping.VcpCode, mapping.Value);
}

/// <summary>
/// Gets a summary string for display in the UI list.
/// Format: "OriginalValue → CustomName" or "OriginalValue → CustomName (MonitorName)"
/// </summary>
public static string GetDisplaySummary(this CustomVcpValueMapping mapping)
{
var baseSummary = $"{VcpNames.GetValueName(mapping.VcpCode, mapping.Value) ?? $"0x{mapping.Value:X2}"} \u2192 {mapping.CustomName}";
if (!mapping.ApplyToAll && !string.IsNullOrEmpty(mapping.TargetMonitorName))
{
return $"{baseSummary} ({mapping.TargetMonitorName})";
}

return baseSummary;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using PowerDisplay.Common.Models;
using PowerDisplay.Models;

namespace PowerDisplay.Common.Interfaces
{
/// <summary>
/// Interface for profile management service.
/// Provides abstraction for loading, saving, and managing PowerDisplay profiles.
/// Provides abstraction for loading and saving PowerDisplay profiles.
/// Enables dependency injection and unit testing.
/// </summary>
public interface IProfileService
Expand All @@ -25,38 +25,5 @@ public interface IProfileService
/// <param name="profiles">The profiles collection to save.</param>
/// <returns>True if save was successful, false otherwise.</returns>
bool SaveProfiles(PowerDisplayProfiles profiles);

/// <summary>
/// Adds or updates a profile in the collection and persists to disk.
/// </summary>
/// <param name="profile">The profile to add or update.</param>
/// <returns>True if operation was successful, false otherwise.</returns>
bool AddOrUpdateProfile(PowerDisplayProfile profile);

/// <summary>
/// Removes a profile by name and persists to disk.
/// </summary>
/// <param name="profileName">The name of the profile to remove.</param>
/// <returns>True if profile was found and removed, false otherwise.</returns>
bool RemoveProfile(string profileName);

/// <summary>
/// Gets a profile by name.
/// </summary>
/// <param name="profileName">The name of the profile to retrieve.</param>
/// <returns>The profile if found, null otherwise.</returns>
PowerDisplayProfile? GetProfile(string profileName);

/// <summary>
/// Checks if the profiles file exists.
/// </summary>
/// <returns>True if profiles file exists, false otherwise.</returns>
bool ProfilesFileExists();

/// <summary>
/// Gets the path to the profiles file.
/// </summary>
/// <returns>The full path to the profiles file.</returns>
string GetProfilesFilePath();
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,6 @@
<ProjectReference Include="..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
<ProjectReference Include="..\..\..\common\ManagedCsWin32\ManagedCsWin32.csproj" />
<ProjectReference Include="..\..\..\common\interop\PowerToys.Interop.vcxproj" />
<ProjectReference Include="..\PowerDisplay.Models\PowerDisplay.Models.csproj" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// 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.Collections.Generic;
using System.Text.Json.Serialization;
using PowerDisplay.Common.Models;

namespace PowerDisplay.Common.Serialization
{
/// <summary>
/// JSON serialization context for MonitorState types.
/// Provides source-generated serialization for Native AOT compatibility.
/// Separated from ProfileSerializationContext which moved to PowerDisplay.Models.
/// </summary>
[JsonSourceGenerationOptions(
WriteIndented = false,
DefaultIgnoreCondition = JsonIgnoreCondition.Never,
IncludeFields = true)]
[JsonSerializable(typeof(MonitorStateFile))]
[JsonSerializable(typeof(MonitorStateEntry))]
[JsonSerializable(typeof(Dictionary<string, MonitorStateEntry>))]
public partial class MonitorStateSerializationContext : JsonSerializerContext
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ private void LoadStateFromDisk()
}

var json = File.ReadAllText(_stateFilePath);
var stateFile = JsonSerializer.Deserialize(json, ProfileSerializationContext.Default.MonitorStateFile);
var stateFile = JsonSerializer.Deserialize(json, MonitorStateSerializationContext.Default.MonitorStateFile);

if (stateFile?.Monitors != null)
{
Expand Down Expand Up @@ -257,7 +257,7 @@ private string BuildStateJson()
};
}

return JsonSerializer.Serialize(stateFile, ProfileSerializationContext.Default.MonitorStateFile);
return JsonSerializer.Serialize(stateFile, MonitorStateSerializationContext.Default.MonitorStateFile);
}

/// <summary>
Expand Down
Loading
Loading