SpinWin: Visually Rotating macOS Windows via ScreenCaptureKit
SpinWin: Visually Rotating macOS Windows via ScreenCaptureKit
SpinWin is a macOS menu bar utility that allows users to visually rotate or spin any application window by arbitrary angles, 90-degree increments, or continuous motion. Because macOS provides no public API to rotate another application's window, SpinWin implements a visual simulation using a combination of screen capture and overlay rendering.
Technical Implementation: Simulating Window Rotation
SpinWin achieves the effect of window rotation without requiring private SkyLight calls or disabling System Integrity Protection (SIP). The process follows a three-step pipeline:
- Window Hiding: The app uses the Accessibility API to move the target window off-screen. The window remains active and continues to render, allowing it to be captured even while invisible to the user.
- Content Capture: Using
ScreenCaptureKit, specificallySCStreamwith adesktopIndependentWindowfilter, SpinWin captures the buffer of the hidden window continuously. This ensures that the overlay does not mirror itself, as only the source window's content is captured. - Overlay Rendering: The captured frames are drawn into a transparent, borderless overlay window. This overlay is positioned where the original window was located and is rotated using a
CALayertransform. The overlay is sized to the rotated content's bounding box to prevent clipping, using a diagonal-sized square for continuous spinning.
Usage and Configuration
SpinWin operates as a menu bar application. Users can initiate a rotation by left-clicking the menu bar icon and selecting a rotation mode from the options bar: a preset angle, a specific spin speed and direction, or free rotation. After selecting the mode, the user clicks the window they wish to rotate.
The overlay can be repositioned by dragging it, and free rotation can be adjusted via a handle on the overlay. Pressing the Esc key restores the original window to its position and stops the rotation.
System Permissions
To function, SpinWin requires two specific macOS permissions:
- Screen Recording: Necessary to capture the contents of the target window.
- Accessibility: Required to move the source window off-screen and restore it to its original position.
Current Technical Limitations
While SpinWin provides a visual simulation of rotation, it introduces several functional trade-offs:
- Non-Interactive Overlays: The overlay is a live visual feed; it is not an interactive window. Clicks and keystrokes cannot be passed through to the hidden source window.
- Mission Control and Exposé Leak: Because the hidden window is still a real window parked off-screen, it appears unrotated in Mission Control or Exposé. There is no public API to exclude a specific window from these system views without minimizing it, which would stop the capture stream.
- Rendering Throttling: Some applications may throttle their rendering speed when they are moved off-screen, which can result in a lower frame rate for the captured feed.
- Static Footprint: If a window resizes itself while rotated, the capture remains letterboxed to the original size. The user must stop the rotation and restart it to update the window's footprint.
Project Architecture
The SpinWin codebase is organized into several specialized components:
| Component | Responsibility |
|---|---|
main.swift |
Application entry point and menu bar policy |
AppDelegate.swift |
Manages the menu bar item and interaction logic |
Permissions.swift |
Handles requests for Screen Recording and Accessibility permissions |
WindowPicker.swift |
Provides the full-screen window selection interface |
RotationManager.swift |
Tracks active rotation sessions per window |
RotationSession.swift |
Orchestrates the hide-capture-overlay workflow |
CaptureEngine.swift |
Manages the ScreenCaptureKit stream and IOSurface frames |
OverlayWindow.swift |
Handles the transparent rotating overlay and drag functionality |
AccessibilityWindowMover.swift |
Manages moving windows off-screen and restoring them |