Back to Alt Tab Macos

WindowCaptureEvents — Specs

src/events/WindowCaptureEventsSpecs.md

11.4.43.0 KB
Original Source

WindowCaptureEvents — Specs

Summary

One-shot window screenshots for thumbnails and Preview. macOS 26+ captures through ScreenCaptureKit (WindowCaptureScreenshots); older versions capture through the private CGSHWCaptureWindowList (WindowCaptureScreenshotsPrivateApi), because SCK is unreliable there (macOS 14 crashes inside Apple's code, macOS 15 leaks).

SCK API selection (macOS 26+)

Two public one-shot APIs exist, each broken differently:

  • captureSampleBuffer returns a zero-copy IOSurface, but Apple implements each call by creating and destroying a capture stream. On some machines that churn leaks WindowServer memory until macOS force-logs-out the session (#5786). Each call also emits WindowServer Creating sharing context events and Screenshots via streams are inefficient warnings.
  • captureScreenshot (new in macOS 26) creates no per-call stream (zero of the above events), but:
    • it fails with SCStreamError -3811 for a fullscreen window whose Space is not frontmost (it succeeds when that Space is frontmost, and for minimized, other-Space, partially-offscreen, and tabbed windows);
    • it returns a copied CGImage instead of an IOSurface, which measurably slows full-resolution captures of large windows (relevant to Preview; at thumbnail sizes it is slightly faster than captureSampleBuffer).

Routing: captureScreenshot for every window, except fullscreen windows and, when any shortcut's effective settings enable preview-selected-window, all windows (full-resolution path) — those use captureSampleBuffer.

Edge cases

  • Stale fullscreen state: isFullscreen is snapshotted on the main thread when the burst is built, so a window mid-transition can be routed to captureScreenshot and fail with -3811. Deliberately no fallback/retry: the thumbnail keeps its previous contents and the next refresh re-routes. A fallback would silently reintroduce stream churn and hide new failure modes.
  • Preview is burst-wide, not per-window: background captures aren't tied to a shortcut, so if any shortcut slot enables preview, every capture in the burst is full-resolution and uses captureSampleBuffer (Preferences.anyShortcutUsesPreview).
  • Privacy attribution cost is API-independent: both APIs flip replayd's screen-capture attribution (~4 updateScreenCaptureDidStart events per capture) and cost systemstatusd the same CPU (measured within 2%). Switching APIs fixes the WindowServer leak, not the per-capture attribution overhead.

Measurements (2026-07-11, macOS 26.5.1, M-series, 29-window payload, 10 switcher cycles per run)

per run (~355 captures)captureSampleBuffercaptureScreenshot
WindowServer sharing contexts / warnings~355 / ~3550 / 0
capture latency mean (thumbnail sizes)706 ms644 ms
capture latency mean (full-res, ≤5.2 MP)709 ms664 ms
replayd CPU2.0 s1.8 s
systemstatusd CPU4.8 s4.7 s
failures0only fullscreen-on-inactive-Space, always -3811