Context
Highlight clicks (setup window → More options → Capture details) currently sets SCStreamConfiguration.showMouseClicks, so ScreenCaptureKit draws its own click indicator into screen.mov. It can't be styled, and it can't be turned off after recording.
Instead, record click events and draw them at export, like the camera bubble. That way the style can be chosen, and changed, after recording.
Where to look
- The current flag:
highlightClicks in Sources/Snapcap/App/RecorderSettings.swift → AppModel.runStart() → RecordingSession.Configuration.showsClicks → ScreenCaptureOptions.showsClicks in Sources/SnapcapCore/Capture/ScreenCapture.swift.
CaptureTarget.globalFrame and AppModel.bubbleDragged(to:): how a global AppKit point becomes a normalized 0…1, top-left-origin position.
RecordingSession.recordCameraMove and CameraOverlay.moves: the precedent for timed events in project.json.
Sources/SnapcapCore/Render/FrameComposer.swift and OverlayChrome.swift: drawing and caching.
Sources/SnapcapCore/Render/OverlayCompositor.swift: composer time is compositionTime + timeOffset.
Sources/Snapcap/Views/EditorView.swift (PlayerStage): the live preview.
Proposal
- While recording, observe
.leftMouseDown and .rightMouseDown with NSEvent.addGlobalMonitorForEvents. Global mouse monitors don't need Accessibility permission. Convert each click to a normalized position inside globalFrame, and ignore clicks outside it. For window captures, positions are relative to the window's frame at the start of recording; handling a window that moves can come later.
- Store something like
"clicks": { "style": "ring", "color": {…}, "size": 1, "events": [{ "time": 4.1, "x": 0.42, "y": 0.63, "button": "left" }] }, with lenient decoding and a fingerprint entry.
- Offer styles such as an expanding ring that fades, a spotlight that dims everything but a circle, and a dot. Animate over about 0.45 s with the same easing as camera moves.
- Draw clicks relative to the fitted screen rectangle in
FrameComposer, not the whole canvas. They're the same today, but won't be once backgrounds or 1:1 and 9:16 exports land.
- When rendered clicks are on, set
showsClicks = false so indicators aren't doubled.
Acceptance criteria
Context
Highlight clicks (setup window → More options → Capture details) currently sets
SCStreamConfiguration.showMouseClicks, so ScreenCaptureKit draws its own click indicator intoscreen.mov. It can't be styled, and it can't be turned off after recording.Instead, record click events and draw them at export, like the camera bubble. That way the style can be chosen, and changed, after recording.
Where to look
highlightClicksinSources/Snapcap/App/RecorderSettings.swift→AppModel.runStart()→RecordingSession.Configuration.showsClicks→ScreenCaptureOptions.showsClicksinSources/SnapcapCore/Capture/ScreenCapture.swift.CaptureTarget.globalFrameandAppModel.bubbleDragged(to:): how a global AppKit point becomes a normalized 0…1, top-left-origin position.RecordingSession.recordCameraMoveandCameraOverlay.moves: the precedent for timed events inproject.json.Sources/SnapcapCore/Render/FrameComposer.swiftandOverlayChrome.swift: drawing and caching.Sources/SnapcapCore/Render/OverlayCompositor.swift: composer time iscompositionTime + timeOffset.Sources/Snapcap/Views/EditorView.swift(PlayerStage): the live preview.Proposal
.leftMouseDownand.rightMouseDownwithNSEvent.addGlobalMonitorForEvents. Global mouse monitors don't need Accessibility permission. Convert each click to a normalized position insideglobalFrame, and ignore clicks outside it. For window captures, positions are relative to the window's frame at the start of recording; handling a window that moves can come later."clicks": { "style": "ring", "color": {…}, "size": 1, "events": [{ "time": 4.1, "x": 0.42, "y": 0.63, "button": "left" }] }, with lenient decoding and a fingerprint entry.FrameComposer, not the whole canvas. They're the same today, but won't be once backgrounds or 1:1 and 9:16 exports land.showsClicks = falseso indicators aren't doubled.Acceptance criteria
project.jsonwith recording time and normalized position, and older projects still open.