Preserve the brightness offset between displays while syncing - #1906
Open
anandghegde wants to merge 1 commit into
Open
anandghegde wants to merge 1 commit into
anandghegde wants to merge 1 commit into
Conversation
…rControl#1781) Brightness sync added the reported delta to each display and clamped the result to 0...1, so whatever part of the change did not fit was dropped. A display parked near the top of its range therefore lost ground on every ambient light swing up but got the whole change back on the way down, and the displays crept together until the sliders were aligned. BrightnessSync keeps an unclamped anchor per display: the position the display would be at if it had no ends. The change is applied to the anchor and the display is driven to the clamped value, so the part that did not fit is given back on the way down instead of being lost. The anchor re-anchors itself whenever the display is no longer where the last sync left it, which is how a brightness the user set by hand becomes the new relationship to keep. Nothing else has to know about it.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1781.
The problem
AppDelegate.job()synced by adding the reported delta to each display and clamping the result:Whatever part of the change did not fit was dropped. A display parked near the top of its range loses ground on every ambient light swing up, but gets the whole change back on the way down — so the displays creep together until the sliders are aligned, which is what the issue describes ("especially when the external monitor reaches its maximum brightness and then scales back — the brightness sliders often end up aligned").
The change
BrightnessSynckeeps an unclamped anchor per display: where the display would be if it had no ends. The delta is applied to the anchor, the display is driven to the clamped anchor. The part that did not fit is therefore given back on the way down instead of being lost, and the offset survives.The anchor re-anchors itself whenever the display is no longer where the last sync left it — so a brightness the user sets by hand simply becomes the new relationship to keep, and no other code path has to know the anchor exists. The anchors are also dropped when the sync checkbox is toggled, since the user was free to move the displays apart while it was off.
Two small side effects, both intentional:
-1...2. Two displays can never be further apart than the whole range, so this only matters if several displays report changes of their own at the same time.Verification
xcodebuild -scheme MonitorControl -configuration Debug -destination 'platform=macOS' build→ BUILD SUCCEEDEDswiftformat --lint MonitorControl→0/30 files require formattingswiftlint→ no new violations (the existing ones inKeyboardShortcuts.swift,DisplayManager.swift,MenuslidersPrefsViewController.swiftandAppDelegate.swift:89are untouched)BrightnessSync.swiftonly imports Foundation, so the arithmetic can be driven directly. Replaying a day of ambient light against the realAppleDisplay.refreshBrightness()easing, starting from a built-in at 0.50 and an external parked 0.40 higher:Before, the offset decays to zero the first time the built-in reaches the top and never comes back. After, the external is still compressed while it sits at its own maximum (+0.10, +0.25 above) — nothing can be done about that, it has nowhere higher to go — but the full +0.40 is restored as soon as the built-in is back in range.
The harness, if you want to re-run it
What I could not verify
No run on real hardware. This machine has no external display and no Apple Developer signing identity, so the build above needed
CODE_SIGNING_ALLOWED=NOand I could not exercise the actual loop. So these are reasoned, not observed:OtherDisplay.getBrightness()reads the saved pref rather than the panel, so I do not believe it can, but a real monitor is the only way to be sure;Worth a run on your setup before merging. Happy to adjust the tolerance, or to put the old behaviour back behind the checkbox if you would rather have it opt-in.