Skip to content

Put the configure sheet back, and document why Options dies - #6

Merged
winebarrel merged 1 commit into
mainfrom
revert-sheet-reuse
Aug 10, 2026
Merged

winebarrel merged 1 commit into
mainfrom
revert-sheet-reuse

Conversation

@winebarrel

Copy link
Copy Markdown
Owner

Reverts #5 and documents the actual cause of the Options button doing nothing.

#5 was wrong

Its reasoning does not survive contact with the machine. Tracing the installed
bundle at the moment of the click shows hosts read configureSheet once per
click
, so the "second read drops the first window" hazard it was built around
was never firing. The reuse it replaced that with was no better and no worse — the
symptom is unchanged either way.

What is left is the shape every screen saver uses, and the one Apple's own
guidance shows: build a controller, hand over its window.

isReleasedWhenClosed stays off. ARC owns the window through the controller, and
the default would let a host that closes the sheet rather than ordering it out
release it a second time. Real, if latent, and unrelated to any of the above.

The Options button is a host bug

Reproduces every time: switch the screen saver away and back, then press Options.
A freshly spawned host never shows it.

Traced from inside the bundle, one second after handing the window over:

works   sheet:  occlusion=8194  frame={{2119, 312}, {410, 274}}
        parent: NSServiceViewControllerWindow num=4188 frame={{2104, 479}, {66, 16}} occlusion=8194

fails   sheet:  occlusion=8192  frame={{0,    6}, {410, 274}}
        parent: NSServiceViewControllerWindow num=4197 frame={{2074, 173}, {440, 20}} occlusion=8192

8194 = 8192 | 2, and 2 is NSWindow.OcclusionState.visible. In the failing
case the sheet is attached (sheetParent is live, isVisible == true) and never
drawn — and so is the parent it was attached to. The parent differs between the
two: a different remote view window, one left over from before the switch.

Which window the host attaches the sheet to is not something configureSheet can
influence. The saver hands over an identically prepared window in both cases.

System Settings on macOS 26 spawns duplicate legacyScreenSaver instances and
loses track of them — Apple has it as FB19201567, with FB19204084 for the
ScreenSaverView instances that pile up alongside. Neither is fixed as of
26.1b3. See
macOS 26 Tahoe Screen Saver issues,
where "Options panel does not open" is reported directly.

The README now carries this as a known issue, with the way out: killall legacyScreenSaver, then quit and reopen System Settings.

Not done

A workaround is possible — wait for the host to have its go, and if
occlusionState still lacks .visible, take the window back and put it up
ourselves. It orders a window front from a process that is not the active
application, so it is not dependable, and it papers over a system bug in every
user's install to fix a case a restart already fixes. Left out.

Verified

Both schemes build and analyse; swiftlint --strict, swiftlint analyze --strict
and swiftformat --lint are clean. The behaviour of the Options button is
unchanged by this PR — it was unchanged by #5 too, which is the point.

Reverts the sheet lifetime change. The reasoning behind it does not survive
contact with the machine: the second read was never the failure, and neither was
holding one controller. Reading the property twice does drop the first window,
but hosts read it once per click — traced from inside the installed bundle — so
nothing was being dropped in practice. The reuse it replaced that with was no
better and no worse. What is left is the shape every screen saver uses, and the
one Apple's own guidance shows: build a controller, hand over its window.

`isReleasedWhenClosed` stays off. ARC owns the window through the controller, and
the default would let a host that closes the sheet rather than ordering it out
release it a second time. That is a real if latent bug, and unrelated to any of
the above.

The Options button dying is a host bug. System Settings on macOS 26 spawns
duplicate legacyScreenSaver instances and loses track of them, so the sheet is
handed over, attached and ordered in — against a remote view window that is no
longer on screen. Traced at the moment of the click, the sheet reports
isVisible == true with a live sheetParent while occlusionState never gains
.visible: attached to a ghost, never drawn. Switching the screen saver away and
back reproduces it every time; a freshly spawned host never shows it.

Apple has it as FB19201567, with FB19204084 for the ScreenSaverView instances
that pile up alongside. Neither is fixed as of 26.1b3. Nothing in configureSheet
chooses the parent window, so there is nothing here to fix — the README now says
so, and says to restart the host.
@winebarrel
winebarrel merged commit 02e35db into main Aug 10, 2026
3 checks passed
@winebarrel
winebarrel deleted the revert-sheet-reuse branch August 10, 2026 04:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant