fix: restore cursor and SCStream capture after display sleep/wake#42
Open
cwy433-png wants to merge 1 commit into
Open
fix: restore cursor and SCStream capture after display sleep/wake#42cwy433-png wants to merge 1 commit into
cwy433-png wants to merge 1 commit into
Conversation
|
@cwy433-png is attempting to deploy a commit to the tranvuongquocdat's projects Team on Vercel. A member of the Team first needs to authorize it. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
After the Mac's displays sleep and wake again, the mouse cursor is no longer
visible on the tablet even though the pointer has actually moved onto the
virtual display (clicks still land). The cursor stays lost for the rest of
the session.
Root cause (two stacked issues, confirmed via /tmp/sidescreen.log)
SCStreamErrorDomain -3815("no displays or windows to capture"). Thestream-error delegate then silently switches capture to the
CGDisplayStreamfallback — and the session stays on the fallbackforever, even after wake.
properties: nil, andkCGDisplayStreamShowCursordefaults to false, so the fallback nevercomposites the cursor at all.
Net effect: any sleep/wake cycle permanently drops the session onto a
capture path that cannot show the pointer.
Fix
ScreenCaptureregistersNSWorkspace.screensDidWakeNotification/didWakeNotificationobservers while a capture is active (removed instopStreaming(), with a defensivedeinitbackstop). A full system wakefires both notifications, so they are coalesced into a single restart.
retry SCStream via the existing
restartStream()path (which re-entersthe fallback on its own if SCStream still cannot start). The
wake-triggered restart does not consume the frame monitor's one-shot
stall-recovery budget.
CGDisplayStreamfallback now setsCGDisplayStream.showCursor, sothe pointer remains visible even while the fallback is in use.
One file changed (
MacHost/Sources/ScreenCapture.swift), no newdependencies, no private API.
Testing
M1 MacBook Air, macOS 15.7.5 (24G624), Android tablet over USB, HEVC,
1280x800 HiDPI. Each scenario was verified twice (before final cleanup and
on the final patch):
Log-verified sequence on every cycle:
SCStream stopped with error … -3815→CGDisplayStream fallback started(cursor now still visible thanks to showCursor) → wake →
Wake restart: leaving CGDisplayStream fallback, retrying SCStream→First frame received from SCStream (restart).Also verified: repeated sleep/wake cycles do not stack observers or
restarts, and stopping the server unregisters the observers.
Notes — approaches tried and rejected (for reviewer context)
CGSSetCursorScale, the programmatic"shake to locate"): rejected. Manual testing showed the enlarged cursor is
visible on the tablet but the pointer disappears again the moment the
scale returns to normal, so a transient nudge cannot fix the steady state.
Dropping it also avoids introducing a new private API.
CGDisplayHideCursor/CGDisplayShowCursortoggle after wake: wasimplemented behind a debug switch during testing and turned out to be
unnecessary once the fallback/showCursor issue was fixed; removed from the
final patch.
fix) is not sufficient — by the time the machine wakes, capture has
already degraded to the cursor-less fallback, and a session that ever
falls back for other reasons would still lose the pointer.
displays after wake (e.g. BetterDisplay discussions #999 / #2770). That
may still exist independently on some macOS versions, but in SideScreen's
case the dominant cause was the two issues above: on macOS 15.7.5 the
restarted SCStream composites the cursor correctly after every wake.