Skip to content

cocoa: an empty display list is a failed read, not a Mac with no screens - #113

Merged
tannevaled merged 1 commit into
mainfrom
an-empty-display-list-is-not-an-answer
Sep 8, 2026
Merged

tannevaled merged 1 commit into
mainfrom
an-empty-display-list-is-not-an-answer

Conversation

@tannevaled

Copy link
Copy Markdown
Contributor

liveDisplays answered (nil, nil) when CGGetActiveDisplayList counted zero, so "I could not tell you" and "there are none" arrived as the same value. Screens passed the second one on, and every caller believed it.

A machine running a window server has at least one display: somebody is looking at something. A count of zero with no CGError means this process could not see the list, not that the hardware went away.

What it cost

Measured 2026-09-08, twice in one evening, on a desk somebody was wearing. go-xrkit/desk looks its display up by name and quit with:

desk: "VITURE Beast" is not attached any more; there is  -- stopping, and putting back everything this changed

Note what follows there is: nothing. That message names every attached display, and it named none. The desk put the arrangement back and took a person's screens away over an answer this package never had. An earlier unexplained closure — no crash report, no panic, exit status 0 — has the same shape.

The package already agreed, either side of it

  • primaryBounds calls a display list with nothing in it ErrDisplayList.
  • The portable layer has ErrScreensUnsupported for a back-end that cannot enumerate.

This was the one path that answered with a fact instead of an error.

The test fakes the count, not the machine

Unplugging every display from a Mac is not a test, and a runner with one display would never take the branch — so cgGetActiveDisplayList is replaced with one that counts zero and reports no error, which is exactly the shape that was believed. Proved by sabotage: with (nil, nil) put back, the test names it.

The 100% gate measures internal/cocoa on Linux, where these files are excluded by build tag, so nothing here changes what it counts. The live _darwin && integration tests are unaffected — they run with displays attached.

Companion: go-xrkit/desk#164 makes the desk safe whatever this answers.

🤖 Generated with Claude Code

liveDisplays answered (nil, nil) when CGGetActiveDisplayList counted zero,
so "I could not tell you" and "there are none" arrived as the same value.
Screens passed the second one on, and every caller believed it.

A machine running a window server has at least one display: somebody is
looking at something. A count of zero with no CGError means this process
could not see the list, not that the hardware went away.

Measured, 2026-09-08, twice in one evening on a desk somebody was wearing.
go-xrkit/desk looks its display up by name and quit with

  desk: "VITURE Beast" is not attached any more; there is  -- stopping,
  and putting back everything this changed

Note what follows "there is": nothing. That message names every attached
display and it named NONE, so the desk put the arrangement back and took a
person's screens away over an answer this package never had. An earlier
unexplained closure -- no crash report, no panic, exit status 0 -- has the
same shape.

⭐ AND THE PACKAGE ALREADY AGREED IN THE PLACES EITHER SIDE OF IT:
primaryBounds calls an empty list ErrDisplayList, and the portable layer has
ErrScreensUnsupported for a back-end that cannot enumerate. This was the one
path that answered with a fact instead of an error.

The count is FAKED in the test rather than the machine emptied, which is the
only way to reach the branch: unplugging every display from a Mac is not a
test, and a runner with one display would never take it. Proved by sabotage:
with (nil, nil) put back, the test names it.

The 100% gate measures internal/cocoa on Linux, where these files are
excluded by build tag, so nothing here changes what it counts.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@tannevaled
tannevaled merged commit 258b793 into main Sep 8, 2026
28 checks passed
@tannevaled
tannevaled deleted the an-empty-display-list-is-not-an-answer branch September 8, 2026 17:36
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