zed/crates/gpui_macos
Lysastriel 71b3b9b887
gpui_macos: Guard start_display_link against nil screens (#60419)
# Objective

Prevent a macOS crash in GPUI when AppKit temporarily reports that a
visible window has no associated `NSScreen` during display
reconfiguration.

The crash can happen on this path:

```text
NSScreen::deviceDescription
gpui_macos:🪟:display_id_for_screen
gpui_macos:🪟:MacWindowState::start_display_link
gpui_macos:🪟:window_did_change_screen
```

`start_display_link` checked the window occlusion state before creating
a display link, but it still assumed `NSWindow.screen()` was non-null.
During display changes, sleep/wake, lid close/open, or monitor
reconfiguration, AppKit can transiently return `nil` for `screen`, and
passing that into `NSScreen::deviceDescription` aborts with a null
pointer dereference.

I observed this on macOS 26.5 after the system entered a rare display
state: once in that state, running GPUI applications would crash
immediately after wake. I have not identified the exact OS/display
condition that triggers it, so the full wake/reconfiguration scenario is
not deterministic, but the crash report consistently points to
`NSWindow.screen()` being `nil` when `start_display_link` tries to
create a display link.

## Solution

Make `display_id_for_screen` explicitly handle a null `NSScreen` by
returning `None`.

Callers now handle that case by either:

- returning early from `start_display_link`, because there is no valid
display id to create a display link for yet
- skipping a null screen while iterating `NSScreen::screens`

The normal non-null screen path is unchanged.

This keeps the nil-screen guard at the FFI boundary where
`NSScreen::deviceDescription` is called.

## Testing

Tested on macOS 26.5.

Commands run:

```bash
cargo fmt --check -p gpui_macos
cargo test -p gpui_macos display_id_for_screen_returns_none_for_null_screen
cargo check -p gpui_macos
```

Added a unit test covering the new boundary behavior:
`window::tests::display_id_for_screen_returns_none_for_null_screen`

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

---

Release Notes:

- Fixed a macOS crash that could occur when display configuration
changes while a GPUI window is temporarily not associated with a screen.
2026-07-07 09:02:29 +00:00
..
src gpui_macos: Guard start_display_link against nil screens (#60419) 2026-07-07 09:02:29 +00:00
build.rs Use dispatch2 crate (#50171) 2026-02-28 02:54:15 +00:00
Cargo.toml Remove gpui's dependency on async-process (#59358) 2026-06-16 13:47:55 +00:00
LICENSE-APACHE