fix(recording): restore correct display selection after screen unlock#308
Open
pagarsky wants to merge 1 commit into
Open
fix(recording): restore correct display selection after screen unlock#308pagarsky wants to merge 1 commit into
pagarsky wants to merge 1 commit into
Conversation
When an external display sleeps between lock and unlock, SCShareableContent transiently reports only the built-in display. setupCapture, running at unlock+0.5s, would fall back to content.displays.first (built-in) even though the tracker's activeDisplayID pointed to the (currently-invisible) external — silently misclassifying capture as coming from the wrong screen until the tracker happened to publish a different id (which never happens if the cursor doesn't cross screens). Three linked changes: 1. setupCapture no longer falls back to content.displays.first when a preferred display id exists but isn't in the snapshot. Instead it persists the wanted id as requestedDisplayID and leaves cachedDisplay nil — captureScreenshot already handles that. 2. refreshDisplay likewise keeps cachedDisplay untouched when the target id is missing from the snapshot, rather than falling back to whichever display happens to be first. 3. ScreenRecorder now subscribes to NSApplication.didChangeScreenParametersNotification and calls refreshDisplay when it fires — which is what recovers the deferred selection once the external monitor finishes waking up. Also removes 'currentDisplayID != nil' from the handleActiveDisplayChange guard, since '.capturing' no longer implies a resolved display.
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.
Summary
Fixes #277.
On dual-monitor Macs, when an external display sleeps during screen lock,
SCShareableContent.displaystransiently reports only the built-in display for a couple of seconds after unlock.ScreenRecorder.setupCaptureruns inside that window (viaresumeRecording(after: 0.5)) and its fallback tocontent.displays.firstselects the built-in, even though the tracker'sactiveDisplayIDstill points at the external. OncecachedDisplay = built-in, the tracker's.removeDuplicates()swallows any republish of the same id, sohandleActiveDisplayChangeandrefreshDisplaynever re-run — capture stays on the wrong display until the cursor crosses screens for a genuine tracker id change (in the affected user's real workflow, that meant 22 minutes of misclassified capture).Fix
Three linked changes in
ScreenRecorder.swift:setupCapture: when a preferred display id exists but isn't in the current snapshot, don't fall back tocontent.displays.first. Persist the wanted id asrequestedDisplayIDand leavecachedDisplay = nil(captureScreenshotalready handles nil).refreshDisplay: same principle — if the target id isn't in the snapshot, keepcachedDisplayuntouched rather than picking a different display.NSApplication.didChangeScreenParametersNotificationinregisterForSleepAndLock()callsrefreshDisplay()when screens change. This is the recovery path: when the external monitor finishes waking up,refreshDisplayfinds the persistedrequestedDisplayIDin the fresh snapshot and restores capture to it.Also removes
currentDisplayID != nilfromhandleActiveDisplayChange's guard, since after (1).capturingno longer implies a resolved display.Test plan