Skip to content

[PowerDisplay] Add linked brightness control#48207

Open
gilnatab wants to merge 11 commits into
microsoft:mainfrom
gilnatab:feature/pd/link-monitors
Open

[PowerDisplay] Add linked brightness control#48207
gilnatab wants to merge 11 commits into
microsoft:mainfrom
gilnatab:feature/pd/link-monitors

Conversation

@gilnatab
Copy link
Copy Markdown

@gilnatab gilnatab commented May 29, 2026

Summary of the Pull Request

Adds linked brightness control to PowerDisplay so multiple brightness-capable monitors can be controlled from a single "All Displays" slider.

This PR:

  • Adds a linked brightness mode with one master brightness slider.
  • Seeds the master slider from the linked display with the lowest Windows DISPLAY number, falling back to monitor ID for determinism.
  • Persists linked mode enabled/disabled state.
  • Persists per-monitor exclusions by monitor ID.
  • Keeps individual display cards available under an expandable section while linked mode is enabled.
  • Shows linked-state guidance in the link icon tooltip instead of a separate info banner.
  • Allows excluded displays to keep their own independent brightness slider.
  • Keeps profiles as per-monitor snapshots; applying a profile turns linked brightness off before applying the profile values.
  • Adds unit tests for linked-brightness selection/seed behavior and settings compatibility.

PR Checklist

Detailed Description of the Pull Request / Additional comments

Screenshots

State Light Dark
Linked mode off image image
Linked mode on image image
Linked mode on — individual displays expanded image image

The first version is intentionally scoped to brightness-only linked control. Contrast, volume, color temperature, input source, and LightSwitch-specific behavior remain independent.

Linked brightness is stored as global PowerDisplay settings:

  • linked_levels_active
  • excluded_from_sync_monitor_ids

Newly connected brightness-capable monitors are included by default, because the exclusion list is the explicit exception. Hotplugging a monitor does not immediately write brightness; linked hardware writes happen only after the user changes the master slider.

Profiles remain per-monitor snapshots. This PR does not add profile-level linked brightness configuration. If linked brightness is active when a profile is applied, linked mode is turned off first, then the saved per-monitor profile values are applied. That avoids leaving the master linked slider active while hardware brightness has been changed independently per monitor.

When linked mode is turned on, the master slider is seeded from the linked brightness-capable display with the lowest Windows DISPLAY number, falling back to monitor ID for determinism. Excluded displays and displays without brightness support are ignored; if no linked target remains, the master slider stays disabled. The seed only positions the slider; it is never written to hardware, so the first user gesture is the first broadcast.

Validation Steps Performed

  • Built PowerDisplay.Lib.UnitTests Debug x64:
.\tools\build\build.ps1 -Platform x64 -Configuration Debug -Path src\modules\powerdisplay\PowerDisplay.Lib.UnitTests
  • Ran PowerDisplay.Lib.UnitTests with vstest.console.exe
  • Ran the XAML styling script:
.\.pipelines\applyXamlStyling.ps1 -Main
  • Result: the XAML styling script completed successfully and processed src/modules/powerdisplay/PowerDisplay/PowerDisplayXAML/MainWindow.xaml.

@github-actions

This comment has been minimized.

@gilnatab
Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

@moooyo moooyo self-requested a review May 29, 2026 16:34
@niels9001
Copy link
Copy Markdown
Collaborator

@gilnatab Would you mind posting a video/screenshots in the PR description?

@github-actions

This comment has been minimized.

@gilnatab
Copy link
Copy Markdown
Author

gilnatab commented Jun 1, 2026

@gilnatab Would you mind posting a video/screenshots in the PR description?

@niels9001 Screenshots have been added to the PR description. I also implemented the primary-display read: when linked mode is enabled, the master slider now seeds from the Windows primary display, with a fallback if that cannot be resolved.

@moooyo I think there should be no more planned feature work to add from my side for this PR. Does the current scope look ready for review, or is there anything else you would like me to address first?

@niels9001
Copy link
Copy Markdown
Collaborator

@gilnatab Awesome! Thank you!

I'm wondering, would it make sense to get rid of the info banner and move the message to the tooltip of the link icon?

image

My thinking is that we can then ensure that the UI stays clean as possible, especially with multiple monitors?

@gilnatab
Copy link
Copy Markdown
Author

gilnatab commented Jun 1, 2026

@gilnatab Awesome! Thank you!

I'm wondering, would it make sense to get rid of the info banner and move the message to the tooltip of the link icon?

image My thinking is that we can then ensure that the UI stays clean as possible, especially with multiple monitors?

@niels9001 Thanks for the suggestion. I understand the goal of keeping the panel compact, but I would prefer to keep the inline brightness row rather than move the explanation entirely into the link icon tooltip.

In linked mode, the individual displays section is already collapsed by default, so the primary UI remains compact even with multiple monitors. When a user manually expands that section, I think it is reasonable to assume that they want more information and more granular control. In that context, keeping the layout consistent with the unlinked mode seems preferable: it preserves visual consistency and reduces the need for users to relearn where information has moved.

Discoverability is also a concern. Some displays, such as built-in laptop panels, may only support brightness control. If the brightness row is removed in linked mode, the display card may become almost empty. Users may wonder where the brightness control went, and the current state would no longer be immediately visible in a quick-control flyout. A tooltip requires users to already know that the link icon is relevant and hover over it.

There is also a possible extensibility concern. Linked mode currently applies only to brightness, so the tooltip would remain short. If we later support linking contrast, volume, or other controls, the tooltip could become increasingly complicated. Keeping the rows visible also leaves room for a future design where individual settings can be excluded from linking independently, rather than excluding an entire display at once. I am not sure users will actually need that level of control, but removing the rows now narrows that option.

That said, these are only my thoughts, and I am not a UI designer. If you still prefer the tooltip-only approach after considering the trade-offs, I am happy to follow your direction and update the PR.

Comment thread src/modules/powerdisplay/PowerDisplay/Helpers/VisibilityConverter.cs Outdated
Comment thread src/modules/powerdisplay/PowerDisplay.Lib/Services/LinkedBrightnessPlanner.cs Outdated
}

private void ScheduleLinkedBrightnessCommit()
{
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why don't u use ScheduleCommit?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed linked brightness to use the same ScheduleCommit debounce pattern

@moooyo
Copy link
Copy Markdown
Contributor

moooyo commented Jun 4, 2026

@gilnatab

code side looks good overall.

about UI part, I agree niels idea. I don't think we need a separate info banner. Add some hints into the hover message is good enough.

yeah, we currently only support brighness, and future will support more feature. But I don't think we need to support a very detailed control (e.g., a monitor needs to be linked, but its contrast do not).

If many user asked this control behaviour, we can consider in the future, but now I think we can just keep it simple.

@moooyo
Copy link
Copy Markdown
Contributor

moooyo commented Jun 4, 2026

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@moooyo
Copy link
Copy Markdown
Contributor

moooyo commented Jun 4, 2026

And please call this script to fix xaml style issue. C:\a_work\1\s.pipelines\applyXamlStyling.ps1 : XAML Styling is incorrect, please run .\.pipelines\applyXamlStyling.ps1 -Main locally.

@gilnatab
Copy link
Copy Markdown
Author

gilnatab commented Jun 4, 2026

@gilnatab

code side looks good overall.

about UI part, I agree niels idea. I don't think we need a separate info banner. Add some hints into the hover message is good enough.

yeah, we currently only support brighness, and future will support more feature. But I don't think we need to support a very detailed control (e.g., a monitor needs to be linked, but its contrast do not).

If many user asked this control behaviour, we can consider in the future, but now I think we can just keep it simple.

@moooyo Thanks for the feedback. I pushed updates to remove the separate info banner and move the linked-brightness hint into the link icon tooltip. I also fixed the XAML styling/layout issue, simplified the seed logic, and updated the linked brightness debounce handling.

Could you please take another look?

string Id,
int MonitorNumber,
int Brightness,
bool SupportsBrightness,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the different between SupportsBrightness and HasValidBrightness? And what's the purpose?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, this was over-engineered. I removed HasValidBrightness and the seed-validity gate, and also removed a few similar helper/suppression paths that were no longer really needed. The seed logic now only considers brightness-capable, non-excluded monitors and picks the lowest Windows DISPLAY number, with Id ordering as the fallback.

/// </summary>
private void SetLinkedBrightnessSilently(int value)
{
_suppressLinkedBrightnessBroadcast = true;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we need _suppressLinkedBrightnessBroadcast ?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We still need this is to avoid changing hardware brightness during initialization. When linked mode is restored on startup, or when the toggle is turned on, we programmatically set LinkedBrightness only to position the master slider. Without this flag, that setter would trigger OnLinkedBrightnessChanged and schedule a brightness broadcast. The intended behavior is that the first hardware write happens only after the user moves the master slider.

@niels9001 niels9001 added Area-Localization issues regarding to Localization the application Product-PowerDisplay Product-Settings The standalone PowerToys Settings application and removed Product-Settings The standalone PowerToys Settings application Area-Localization issues regarding to Localization the application labels Jun 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Power Display: link multiple monitors

4 participants