Skip to content

Re-apply dimming as the reconfiguration shades come off, silence Option plus volume, and fix the panel's text sizing - #91

Merged
Rydersel merged 9 commits into
mainfrom
fix/panel-and-settings-stabilization
Sep 11, 2026
Merged

Re-apply dimming as the reconfiguration shades come off, silence Option plus volume, and fix the panel's text sizing#91
Rydersel merged 9 commits into
mainfrom
fix/panel-and-settings-stabilization

Conversation

@Rydersel

@Rydersel Rydersel commented Sep 10, 2026

Copy link
Copy Markdown
Owner

Part of #56: three of its four open items. The panel-height item stays open there.

What changed

Reconfiguration flashes. The reconfiguration handler used to reset gamma and remove every shade, then await two HDR reads per display before re-applying the dim, so a software-dimmed display sat at full brightness for the whole loop. The HDR pass now runs first, over a snapshot of the displays, and the gamma reset, the shade removal and the re-apply follow in one synchronous turn. The wholesale removal stays unconditional, because it is what keeps a shade from stranding when mirroring engages; it now runs a little later than before, and the mirroring coordinator's own teardown from the raw notification is what keeps that backstop timely. The engine-side re-apply records that it must stay free of suspension points for this to hold, and the tests pin the order: nothing awaits between the removal and the re-apply, the reads all precede the reset, and both displays are re-applied from one snapshot.

Hardware verification exposed two additional transitions. WindowServer could reset gamma before the topology debounce finished, and AppKit's automatic window animations could overlap the old and new shades. Direct SDR displays now get a bounded recovery window that reasserts only a recognized reset to the cached ColorSync baseline. It checks the full RGB curve, fresh HDR state, the display identity and reconfiguration generation, and stops on an unfamiliar curve or uncertain state. Repeated notifications cannot renew the deadline or write allowance, and a stopped owner cannot restart without a fresh brightness write. Recovery stays active through the HDR preparation, pauses immediately before the final reset and baseline recapture, and starts a fresh five-second settling watch after the final pass. A physical multi-display reconfiguration exposed an additional system reset about 3.6 seconds after that pass; regression tests now cover it. The first topology change after a completed pass starts its own bounded window, so a new reconnect cannot inherit an expired deadline. Later events in that burst retain the deadline and eight-write allowance. A raw CoreGraphics signal now queues recovery through the main run loop’s common modes, outside the callback, before the delayed AppKit notification. Dimming windows also disable AppKit's automatic show/hide animations; OLED care retains its intentional entry fade.

Option plus a volume key. The feedback sound now plays only when the preceding key-down for that key routed to a volume step. Option plus a volume key opens Sound settings and stays silent; a plain volume key at maximum or minimum still plays, because the latch tracks the step, not whether the value changed. This is a deliberate departure from the behaviour inherited from the earlier code base, which played the sound on every volume key release. The key router and its tests are untouched.

Text size in the panel. Three elements scaled with the system text size while the two dozen around them did not: the percent readout, its column width, and the hover caption. All three are now fixed, at the sizes the system text style resolved to on this machine, so the panel is internally consistent and the readout column still fits "100%" with headroom. This makes the panel fully non-scaling, which is an accessibility trade made on purpose rather than by accident: real scaling of the whole panel is a larger job and is gated on the panel-height work. A render test proves the readout still fits its column at the fixed size; the render pipeline ignores the dynamic type setting on macOS, so the large-text behaviour itself is a hardware step.

Not in this change

  • The panel height bound and the scrolling display list. Its first step is a rig measurement of whether a scroll view inside an open menu's tracking session receives scroll events at all, which needs a person at the desk; it runs in the combined hardware sitting and ships separately.

Hardware verification

Verified locally on signed Release builds with the Dell U2725QE and MSI MAG 341C OLED connected.

  • Repeated physical reconnects with gamma and screen-overlay dimming looked steady. Both closed- and open-popover cases were exercised. The original display modes, arrangement, brightness, and dimming-backend preference were restored.
  • Before the recovery changes, a refresh-rate change left the Dell's gamma undimmed for about 1.36 seconds. With recovery enabled, both refresh-rate directions held the expected 0.745 table peak throughout the recording. A later two-direction check held that value in all 582 samples, including a change after the previous recovery deadline expired.
  • Disabling AppKit's automatic window animations removed the shade overlap in the controlled refresh-rate check. The same crop remained between mean pixel values 65.137 and 65.139 across 3,456 frames. Physical reconnects temporarily rotate and reposition the Dell, so those changing-content samples are not treated as a luminance comparison.
  • Plain Volume Up at maximum emitted one digital feedback burst. Option plus Volume Up opened Sound settings without a second burst. Physical playback from the MSI's audio jack was not exercised because no speakers or headphones were connected.
  • At the system's 29 pt reading size, the 100% label fit, the slider retained its space, and the disabled-volume explanation remained readable. The original reading size and audio settings were restored.
  • Live VoiceOver testing was deliberately skipped. Accessibility labels remain in place.

Transfer-table sampling does not establish zero physical flash duration. Earlier traces exposed expired recovery budgets and a newer dimming write superseding the recovery snapshot. Those cases, including the first change after startup, now have failing-then-passing regression tests. A handoff obtains fresh HDR observations and retains the existing deadline and write allowance. The last small refinements were checked with automated regressions rather than another round of manual cable swaps.

Validation: 2,591 engine tests and 714 app tests passed on this branch. The final combined build passed 2,632 engine tests and 762 app tests, plus the Release marker gate. Developer ID signing was verified on the installed test builds. Independent reviews found no actionable issues, and all required CI checks passed on a4f284c.

…on plus volume, and fix the panel's text sizing

The reconfiguration pass now re-evaluates HDR first and then resets gamma,
removes every shade and re-applies the dim in one synchronous turn, so a
software-dimmed display no longer flashes to full brightness while the
per-display reads run. The volume feedback sound plays only when the
key-down for that key was a volume step, so Option plus a volume key opens
Sound settings in silence while a plain key at the limits still blips. The
percent readout, its column and the hover caption are fixed at the sizes
the system text styles resolved to, so the panel scales consistently: not
at all, a trade recorded at the readout width until the panel has a bounded
height.
@Rydersel Rydersel added the needs-hardware Verification needs hardware this setup cannot provide label Sep 10, 2026
@Rydersel
Rydersel merged commit 69d61fa into main Sep 11, 2026
8 checks passed
@Rydersel
Rydersel deleted the fix/panel-and-settings-stabilization branch September 11, 2026 21:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-hardware Verification needs hardware this setup cannot provide

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant