Show HN: SpinWin – 一款可以在 macOS 菜单栏通过视觉效果旋转或翻转任意窗口的应用
Show HN: SpinWin – A macOS menu bar app to visually rotate or spin any window

原始链接: https://github.com/alokdhir/spinwin

SpinWin 是一款 macOS 菜单栏实用工具,它通过创建视觉“伪装”而非直接修改系统窗口来模拟窗口旋转。由于 macOS 缺乏公开的窗口旋转 API,SpinWin 利用辅助功能(Accessibility)API 将原始窗口隐藏到屏幕外,同时通过 ScreenCaptureKit 实时捕获其画面。 捕获的内容随后会被渲染在一个透明、无边框的覆盖窗口中,该窗口的位置与原窗口完全重合。通过对该覆盖层应用 `CALayer` 变换,用户可以实现旋转、翻转或将窗口设定为任意角度。 **核心注意事项:** * **功能性:** 覆盖窗口为非交互式实时画面;点击和按键操作无法传递至底层窗口。 * **局限性:** 由于源窗口保持活动状态但被隐藏,它在调度中心(Mission Control)或 Exposé 中可能仍以原始方向显示。此外,某些应用在后台运行时可能会降低性能或在自动调整大小时出现问题。 * **使用方法:** 需要授予“屏幕录制”和“辅助功能”权限。用户可通过简洁的菜单控制旋转,包括预设选项、持续旋转或手动调节。 SpinWin 提供已公证的应用版本,也可通过 Swift 从源码构建。

抱歉。
相关文章

原文

A macOS menubar utility that visually rotates a selected window by any angle (90° increments, arbitrary angles, or a continuous spin).

SpinWin flipping a terminal window upside down

macOS has no public API to rotate another app's window. Real rotation would require private SkyLight calls (CGSSetWindowTransform) with System Integrity Protection disabled — not worth it.

Instead, SpinWin fakes it:

  1. Hide the selected window off-screen via the Accessibility API. It keeps rendering there, so it can still be captured.
  2. Capture its contents continuously with ScreenCaptureKit (SCStream + desktopIndependentWindow filter) — this grabs only that window's buffer, so the overlay never mirrors itself.
  3. Draw the frames in a transparent, borderless overlay window placed where the original was, rotated with a CALayer transform.

Because it's a layer transform, any angle works — the overlay is sized to the rotated content's bounding box so nothing clips, and a diagonal-sized square is used while spinning.

The easiest way to get SpinWin is the latest release — the download is signed with a Developer ID and notarized by Apple, so it launches without Gatekeeper warnings. Or build it yourself:

./scripts/build-app.sh          # builds SpinWin.app (release)
open SpinWin.app              # grant Screen Recording + Accessibility

For quick iteration during development:

swift build && swift run SpinWin

Left-click the menubar icon to start: choose a rotation in the bottom options bar (a preset angle, a spin speed + direction, or free rotation), then click the window you want. Drag the overlay to reposition it; drag its handle to rotate freely. Press Esc on the overlay to stop and restore the window.

Right-click (or Control-click) the icon for the menu: active rotations (with per-window angle/spin controls), Stop all, and Quit.

  • Screen Recording — to capture the window contents.
  • Accessibility — to move the source window off-screen and restore it.
  • The overlay is a live picture, not interactive. You can drag and rotate it, but clicks and keystrokes are not sent to the real window underneath.
  • Mission Control / Exposé leak. The hidden window is parked off-screen but still a real window, so Exposé shows it unrotated. There is no public API to exclude another app's window from Mission Control, and minimizing it would stop the capture.
  • Some apps throttle rendering of off-screen windows, which can slow the feed.
  • A window that resizes itself while rotated keeps its original footprint. You can't drag-resize the hidden window, but an app can still resize it on its own (a video player adapting to a new track, a terminal responding to an escape sequence). The capture is letterboxed into the original size until you stop and rotate it again.
File Role
main.swift App entry point (accessory/menubar policy)
AppDelegate.swift Menubar item; left-click rotates, right-click opens menu
Permissions.swift Requests Screen Recording + Accessibility at launch
WindowPicker.swift Full-screen window picker + rotation options bar
RotationManager.swift Tracks one rotation session per window
RotationSession.swift Orchestrates hide → capture → overlay per window
CaptureEngine.swift ScreenCaptureKit stream → IOSurface frames
OverlayWindow.swift Transparent rotating/spinning overlay, drag
AccessibilityWindowMover.swift Move source window off-screen + restore
ActivationChoice.swift Initial rotation choice (angle/spin/free)
SpinDirection.swift Clockwise/counterclockwise spin option
MenuBarIcon.swift Draws the menubar icon
联系我们 contact @ memedata.com