feat(Zoom): Live Zoom mode — real-time screen magnification#32
Conversation
All APIs used (ScreenCaptureKit, SCScreenshotManager, CGPreflightScreenCaptureAccess) are available since macOS 13+. Allows contributors on current macOS to build and run.
Unsigned builds fail with -10825 on macOS. Contributors must set their own team ID in project.yml for a valid code signature.
Implements Live Zoom using ScreenCaptureKit SCStream for continuous 60fps frame capture with pan/zoom controls. - New hotkey: ⌃⇧1 (Control+Shift+1) activates Live Zoom - Real-time screen content updates (videos, terminals keep playing) - Mouse movement pans, scroll wheel/arrow keys zoom in/out - Click enters Draw mode (freezes current frame) - Escape/right-click exits - Own overlay window excluded from capture to prevent infinite mirror - Zero-copy rendering via IOSurface for GPU-backed display New files: - LiveZoomWindowController.swift — SCStream lifecycle and window management - LiveZoomView.swift — CALayer-based rendering with ZoomMath integration Modified: - AppDelegate: toggleLiveZoomMode() with Draw mode transition - HotkeyManager: Live Zoom hotkey registration (ID 3) - Settings: liveZoomHotkeyKeyCode/Modifiers with ⌃⇧1 default - README: Feature coverage updated
There was a problem hiding this comment.
Pull request overview
Adds a new “Live Zoom” overlay mode to ZoomacIt, implementing real-time magnification by streaming screen frames via ScreenCaptureKit and rendering them in an overlay with pan/zoom controls.
Changes:
- Introduces
LiveZoomWindowController+LiveZoomViewto manageSCStreamcapture and render frames viaCALayer.contents(IOSurface-backed). - Adds a new global hotkey (⌃⇧1) and persists its keycode/modifiers in
Settings. - Lowers the macOS deployment target to 15.0 and updates project/docs (README + design plan).
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| src/ZoomacIt/Overlay/LiveZoomWindowController.swift | New controller to start/stop SCStream, exclude app windows, and feed frames to the view. |
| src/ZoomacIt/Overlay/LiveZoomView.swift | New view to display live frames and implement pan/zoom + exit/enter-draw inputs. |
| src/ZoomacIt/Models/Settings.swift | Adds persisted defaults/getters for the Live Zoom hotkey. |
| src/ZoomacIt/Core/HotkeyManager.swift | Registers/unregisters the new Live Zoom hotkey and routes callbacks. |
| src/ZoomacIt/App/AppDelegate.swift | Wires the new hotkey to a Live Zoom mode toggle and coordinates mode transitions. |
| src/ZoomacIt.xcodeproj/project.pbxproj | Adds new source files to the project and lowers deployment target to macOS 15.0. |
| src/project.yml | Lowers deployment target to macOS 15.0 for xcodegen generation. |
| README.md | Marks Live Zoom as complete and adds contributor build/signing guidance. |
| design/LiveZoom-implementation-plan.md | Adds an implementation plan/design note for Live Zoom. |
- Move SCStream output to dedicated serial queue to avoid starving UI event handling at 60fps (dispatch only layer update to main) - Set showsCursor=false to prevent double cursor (captured + system) - Replace fragile 50ms sleep with retry loop for window exclusion - Clamp initial zoomLevel to min/max range - Add Live Zoom hotkey keys to resetToDefaults() - Assign liveZoomController before showLiveZoom() so onShowFailed can properly clear the reference
|
Addressed Copilot review feedback in commit 7e74ebd:
|
Merge order noteThese 4 PRs are now fully independent (each branched from main), but they all add to the same shared files (Settings.swift, HotkeyManager.swift, AppDelegate.swift, StatusBarController.swift). When merging sequentially, you'll hit additive conflicts that are trivial to resolve (just keep both sides). Recommended merge order (least conflicts):
I've verified all 4 build independently and combine correctly. Happy to squash them into a single PR if you'd prefer a cleaner merge. |
- Clear zoomSourceForDrawReturn before dismissing Draw mode when entering Live Zoom, preventing brief Still Zoom restoration Also adds SettingsTests for Live Zoom hotkey: - testDefaultLiveZoomHotkey (⌃⇧1) - testLiveZoomHotkeyRoundTrip - testLiveZoomHotkeyIndependentOfOtherHotkeys - testLiveZoomHotkeyResetToDefaults All 148 tests pass.
|
The deployment target of 15.0 is a minimum — it still builds and runs perfectly on macOS 26. This just allows users on older macOS versions to use the app too. |
@yusufk The deployment target controls what builds, but what I really care about is the support guarantee of the released app. My only test environment is macOS 26, so I can verify that the app behaves to spec on 26, but I have no way to test 15 through 25. This app leans heavily on version-sensitive APIs, and these areas have changed behavior across macOS releases before. So "the API exists since macOS 13" doesn't fully reassure me that it works correctly on every version in between. That said, I don't think we have to choose between "revert to 26" and "guarantee 15–26." I'd be fine keeping the target at 15 as long as we clearly separate the build floor from the support scope — i.e. document in the README that the minimum build target is macOS 15, but the app is tested and officially supported on macOS 26 only, with earlier versions working possibly but not guaranteed. That way contributors on current macOS can still build and run, and I'm not on the hook for versions I can't test. Would you be okay with that approach? |
|
Hi, Thanks for the feedback and I understand the concern. I also agree with the approach and will adjust the readme when I get a moment. Just a note though, Apple went straight from MacOS 15 to 26, with 15 still likely being the most prominent version out in the market. Thanks |
|
Done — updated the README to clarify: minimum build target is macOS 15, but officially supported on macOS 26 only. See commit 470cbef. |
Add Live Zoom feature documentation to the VitePress docs site: - Add Live Zoom hotkey and feature description to usage pages (EN/JA) - Add Live Zoom section to zoom usage pages with controls and comparison table vs Still Zoom (EN/JA) - Update index page Zoom feature description Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Thanks, I've updated the README and docs(include Japanese version) to reflect your changes. |
…ure, reuse CIContext
|
Addressed all three review comments in commit 1546d17:
|
…Zoom, ⌃7 DemoType)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Fixed minor issues. |
Summary
Implements Live Zoom using ScreenCaptureKit's
SCStreamfor continuous 60fps frame capture with real-time pan/zoom controls.Changes
Technical Details
LiveZoomWindowControllermanages SCStream lifecycle and overlay windowLiveZoomViewrenders frames viaCALayer.contentswithZoomMathcontentsRectOverlayWindow,ZoomMath, andSettingsinfrastructureAlso included
Testing