Commit Graph

2 Commits

Author SHA1 Message Date
moooyo
2b8e6247fc [PowerDisplay] Add stable profile IDs (#49175)
## Summary of the Pull Request

Gives every saved PowerDisplay profile a stable, auto-incrementing
integer ID and makes the app address profiles by that ID instead of by
name. Duplicate profile names are allowed, renames preserve identity,
and LightSwitch stores stable profile references.

> Split out of the PowerDisplay CLI branch (#48632). CLI-specific
contracts and commands remain in that stacked PR.

## PR Checklist

- [x] **Closes:** N/A - split from #48632.
- [x] **Communication:** Discussed with core contributors.
- [x] **Tests:** Added and passing in `PowerDisplay.Lib.UnitTests`.
- [x] **Localization:** The composed profile label uses a shared
localized format resource.
- [x] **New binaries:** None.
- [x] **Documentation updated:**
`doc/devdocs/modules/powerdisplay/design.md`.

## Implementation

### Profile model and persistence

- `PowerDisplayProfile.Id` is the stable JSON `id`; `0` means
unassigned.
- `PowerDisplayProfiles.NextId` is monotonic and IDs are never reused.
- `SetProfile` assigns IDs to new profiles and replaces existing
profiles by ID.
- Duplicate names are supported; name lookup remains only for migration
of legacy references.
- `ProfileStore` serializes cross-process load/modify/save operations
with a named mutex and atomically replaces `profiles.json`.
- Production callers use asynchronous `ProfileHelper` APIs.

### Migration and application

- Initial PowerDisplay discovery assigns missing profile IDs and
migrates legacy monitor IDs.
- LightSwitch legacy name references are reconciled to IDs and written
back to the current typed settings schema.
- Native LightSwitch publishes pure light/dark theme events;
PowerDisplay exclusively validates profile enablement and stable IDs.
- Settings UI and Named Pipe ApplyProfile actions send invariant
positive profile IDs.
- PowerDisplay validates the ID, loads the current profile, and applies
its monitor settings.

### Settings UI

- Create, edit, apply, and delete operations use stable IDs.
- LightSwitch selectors store profile IDs and keep legacy name fields
only for migration.
- Profile lists use a localized name-and-ID label so duplicate names
remain distinguishable.

## Accepted Trade-offs

- Profile ID migration remains dependent on the initial monitor
discovery; a failed or delayed discovery can temporarily hide legacy
ID-less profiles.
- The one-time PowerDisplay LightSwitch migration rewrites the complete
current typed settings object and does not add a new cross-process
settings transaction.

## Validation

- Built the affected x64 Debug projects with the repository build
scripts.
- `PowerDisplay.Lib.UnitTests`: 186 passed, 0 failed.

---------

Co-authored-by: Yu Leng (from Dev Box) <yuleng@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-16 14:33:21 +08:00
moooyo
18efa0559c Introduce new utility PowerDisplay to control your monitor settings (#42642)
<!-- 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
Introduce a new PowerToys' module PowerDisplay to let user can control
their monitor settings without touching monitor's button.

Support feature list:
Common:
1. Profiles support
2. Integration with LightSwitch (auto switch profile when theme change)
3. TrayIcon
4. Save and restore settings when startup
5. Shortcut
6. Rotation
7. GPO support
8. Auto re-discovery monitor when plugging and unplugging monitors.
9. Identify Monitors
10. Quick profile switch

Especially for DDC/CI monitor:
1. Brightness
2. Contrast
3. Volume
4. Color temperature (preset profile)
5. Input source
6. Power State (poweroff)


Design doc:
https://github.com/microsoft/PowerToys/blob/yuleng/display/pr/3/doc/devdocs/modules/powerdisplay/design.md

AOT compatibility:
I designed this module for AOT from the start, so I'm pretty sure at
least 95% of it is AOT compatible. But unfortunately, PowerToys still
have a AOT blocker to block this module publish with AOT.

Currently PowerToys will check the .net file version (file version not
lib version) to avoid crash. So, all modules should reference Common.UI
or add UseWPF to avoid overwrite the .net file with different version
(which may cause crash).

Todo:
- [ ] BugBash
- [ ] Icon
- [ ] IdentifyWindow UI improvement


Demo

Main UI:
<img width="546" height="671" alt="image"
src="https://github.com/user-attachments/assets/b0ad9ac5-8000-4365-a192-ab8c2d66d4f1"
/>

Input Source:
<img width="536" height="674" alt="image"
src="https://github.com/user-attachments/assets/80f9ccd7-4f8c-4201-b177-cc86c5bcc9e3"
/>


Settings UI:
<img width="1581" height="1191" alt="image"
src="https://github.com/user-attachments/assets/6a82e4bb-8f96-4f28-abf9-d7c45e1c8ef7"
/>

<img width="1525" height="1146" alt="image"
src="https://github.com/user-attachments/assets/aae81e65-08fd-453a-bf52-02a74f2fdea0"
/>



Closes: 
#42942
#42678
#41117
#38109
#35564
#34932
#28500
#1052
#18149

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [x] Closes: #1052
- [x] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** Added/updated and all pass
- [x] **Localization:** All end-user-facing strings can be localized
- [x] **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 <yuleng@microsoft.com>
Co-authored-by: Niels Laute <niels.laute@live.nl>
Co-authored-by: moooyo <lengyuchn@gmail.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 13:53:25 +08:00