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:

  1. 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.
  2. Content Capture: Using ScreenCaptureKit, specifically SCStream with a desktopIndependentWindow filter, 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.
  3. 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 CALayer transform. 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

Sources