SpinWin: 透過 ScreenCaptureKit 視覺旋轉 macOS 視窗

SpinWin: 透過 ScreenCaptureKit 視覺旋轉 macOS 視窗

SpinWin 使 macOS 上的視窗能夠視覺旋轉

SpinWin 是一個 macOS 選單列工具,允許使用者以任何角度視覺旋轉或旋轉任何應用程式視窗,包括 90 度增量、任意角度或持續旋轉。由於 macOS 沒有提供旋轉其他應用程式視窗的公開 API,SpinWin 透過捕獲視窗的視覺緩衝並將其渲染在變換的疊加視窗中來實現此效果。

技術實作:透過捕獲和疊加來模擬旋轉

SpinWin 透過實作三個步驟的流程來模擬視窗旋轉,從而繞過 macOS 缺乏公開旋轉 API 的限制:

  1. 離螢幕定位:應用程式使用 Accessibility API 將選定的目標視窗移至螢幕外。視窗保持活躍並繼續渲染,使其即使對使用者不可见也能被捕獲。
  2. 持續捕獲:使用 ScreenCaptureKit (SCStreamdesktopIndependentWindow 過濾器),SpinWin 持續捕獲視窗的內容。此方法確保僅捕獲特定視窗的緩衝,防止疊加視窗出現鏡像。
  3. 圖層變換:捕獲的幀會被繪製到一個透明且無邊框的疊加視窗中。該視窗會被定位到原始視窗的位置,並使用 CALayer 變換進行旋轉。疊加視窗會自動調整大小以適應旋轉內容的邊界框,以防止裁切,並在持續旋轉時使用對角線大小的正方形。

作業需求與權限

要讓 SpinWin 正常運作,需要兩項特定的 macOS 系統權限:

  • 螢幕錄製:透過 ScreenCaptureKit 捕獲視窗內容所必需。
  • 存取輔助功能:將來源視窗移至螢幕外並在停止旋轉時恢復到原始位置所必需。

目前的技術限制

SpinWin 是一種視覺模擬,由於 macOS API 的限制,存在幾種固有的限制:

  • 非互動疊加:疊加是即時的視覺饋送;它不支援互activity。點擊和按鍵無法傳遞給隱藏的來源視窗。
  • Mission Control 與 Exposé 壓漏:因為隱藏的視窗是真實的視窗,停放在螢幕外,它在 Mission Control 和 Exposé 中仍以未旋轉的狀態可見。沒有公開 API 能在不最小化視窗的情況下將特定視窗從這些視圖中排除,而最小化會停止捕獲過程。
  • 渲染節流:某些應用程式在視窗被移至螢幕外時可能會節流渲染,這可能導致捕獲饋送的幀率下降。
  • 調整大小時的靜態佔腳:如果來源視窗在旋轉時自行調整大小,疊加會保持原始佔腳。捕獲會變成信箱樣式,直到旋轉停止並重新啟動。

專案架構

SpinWin 的程式碼基礎被組織成幾個專門的元件:

Component Responsibility
main.swift 應用程式入口點與選單列政策
AppDelegate.swift 管理選單列項目與互動邏輯
Permissions.swift 處理螢幕錄製與存取輔助功能請求
WindowPicker.swift 提供全螢幕視窗選擇與旋轉選項
RotationManager.swift 追蹤每個視窗的活躍旋轉會話
RotationSession.swift 編排隱藏-捕獲-疊加工作流程
CaptureEngine.swift 管理 ScreenCaptureKit 流與 IOSurface
OverlayWindow.swift 處理透明旋轉疊加與拖曳
AccessibilityWindowMover.swift 管理將來源視窗移至螢幕外並恢復它們

社群觀點

使用者指出,儘管此工具主要是一種新奇玩意,但它可能為特定應用程式提供實用性,例如通常允許畫布旋轉的繪圖應用程式。一位開發者指出其與早期 Linux 桌面環境中的「搖晃視窗」相似:

這讓我想起當搖晃視窗在 Linux 中是熱門話題時。當時那是純粹的樂趣,現在看起來又變得有趣了。

Sources