Skip to content

Recover a crash-interrupted dim, fade dim entry, and name dimming on the Protection pane - #90

Merged
Rydersel merged 5 commits into
mainfrom
fix/care-interrupted-dim
Sep 11, 2026
Merged

Recover a crash-interrupted dim, fade dim entry, and name dimming on the Protection pane#90
Rydersel merged 5 commits into
mainfrom
fix/care-interrupted-dim

Conversation

@Rydersel

@Rydersel Rydersel commented Sep 10, 2026

Copy link
Copy Markdown
Owner

Closes #53.

What changed

Crash recovery for the temporary dim. A crash or force-quit while a lock dim was engaged left a display's DDC register dimmed with the slider showing full brightness, and on a write-only display nothing could tell. A per-display marker is now written before the dim's first submit and cleared after the restoring one. At the next launch a surviving marker runs the restore pass's own memo reset and reassert for that display, gated on Safe Mode directly. The launch readback holds off while a marker stands, because on a display that answers reads it would otherwise import the dim as the user's value and overwrite the store the recovery needs. The startup caption for "Trust the last saved values" now names this one exception.

Entry fade. Idle dim and blackout entries fade in over about 400 milliseconds on the overlay's content view. Every decrease and every removal still lands in one write, so restore timing is unchanged, and the lock dim's ramp is untouched. A nudge from the care loop's verify pass declines while a fade toward the same state is in flight, bounded in time so a completion that never arrives cannot park the loop, and a declined nudge counts as settling rather than a mismatch. The blackout's click swallow deliberately leads the pixels.

Protection pane. The pane opens with a Dimming row that reveals OLED Care and says how many displays are enrolled, or Paused while Safe Mode holds the care loop, with one sentence on what the other half of the pillar does.

Shared display identities. Recovery snapshots the interrupted-dim markers before processing any display. Displays sharing one saved identity all receive recovery; the shared marker is cleared only after the whole group is considered, and remains set if a member is still dimming. Regression tests cover both discovery orders.

Scope limits, recorded on purpose

  • A display plugged in after launch with a surviving marker is not recovered until the next launch; its readback stays off for the session, which keeps its stored value intact.
  • A display lock-dimmed before it ever had a stored brightness has its marker cleared without a write; nothing safe exists to write.
  • The native adoption path (the poller, and a panel opening) can persist a native read that carries a dead process's dim under HDR before the recovery runs; it is a pre-existing gap and is filed separately.

Hardware verification

Verified locally with the Dell U2725QE and MSI MAG 341C OLED on a signed Release build combining the five pending fixes.

  • An actual screen lock dimmed both hardware brightness registers to zero. Force-quitting left both registers at zero and both interrupted-dim markers set. Relaunch restored the Dell to 100 and the MSI to 95, matching their pre-lock combined-brightness state; stored brightness values were unchanged. The recovery log recorded two evaluated and two reasserted displays.
  • The clean-quit control restored both registers before exit and cleared both markers. The next launch recorded two evaluated and zero reasserted displays. The MSI's clean-quit value was 97 because quit restores using the full-range mapping.
  • The Protection row reads “On for 1 display,” updates its count when another display is enrolled, and opens OLED Care.
  • Live VoiceOver testing was deliberately skipped. The Protection row's accessibility label and display count were verified.
  • An actual Shift launch entered Safe Mode; the staged recovery marker survived without recovery writes. The idle dim faded smoothly and restored immediately by eye. A full-black click restored the picture and did not activate the control underneath.
  • A physical wake measurement on the earlier combined build crossed the restored-picture midpoint in about 75 ms, within the 100 ms gate, but reached full restoration in about 225 ms. This exposed AppKit's automatic window-closing animation; Re-apply dimming as the reconfiguration shades come off, silence Option plus volume, and fix the panel's text sizing #91 now disables that animation while preserving the intentional entry fade. The later full-restoration measurement was not repeated; the original midpoint gate passed, and the automatic-window-animation change has an automated regression.
  • The manual click check during the first 200 ms of blackout entry passed. The click was swallowed as intended. This is a manual result, not a new instrumented latency measurement. Merge Re-apply dimming as the reconfiguration shades come off, silence Option plus volume, and fix the panel's text sizing #91 first so its overlay-animation fix is present.

The shared-identity regression failed before the fix and passed afterward. The final combined build passed 2,632 engine tests and 762 app tests, plus the Release marker gate. Required CI checks passed on this branch, and independent review found no actionable issues. The physical crash and clean-quit checks preceded the shared-identity fix and used two distinct panel identities.

…the Protection pane

A crash or force-quit while a lock dim was engaged left a display's DDC
register dimmed with the slider showing full brightness, and on a write-only
display nothing could tell. A per-display marker is now written before the
dim's first submit and cleared after the restoring one; at the next launch a
surviving marker runs the restore pass's own memo reset and reassert, gated
on Safe Mode directly. The launch readback holds off while a marker stands,
because on a display that answers reads it would otherwise import the dim as
the user's value. The startup caption names the one exception it makes.

Idle dim and blackout entries now fade in over about 400 milliseconds on the
overlay's content view; every decrease and every removal still lands in one
write, so restore timing is unchanged. A nudge from the care loop's verify
pass declines while a fade toward the same state is in flight, bounded in
time so a completion that never arrives cannot park the loop, and the
declined nudge counts as settling rather than a mismatch.

The Protection pane opens with a Dimming row that reveals OLED Care and says
how many displays are enrolled, or Paused while Safe Mode holds the care
loop, with one sentence on what the other half of the pillar does.
@Rydersel Rydersel added the needs-hardware Verification needs hardware this setup cannot provide label Sep 10, 2026
@Rydersel
Rydersel merged commit c53bf71 into main Sep 11, 2026
8 checks passed
@Rydersel
Rydersel deleted the fix/care-interrupted-dim branch September 11, 2026 21:50
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.

Care: recover interrupted dimming, fade idle and blackout entry, and explain protection

1 participant