### Install SwipeAeroSpace with Homebrew Source: https://github.com/mediosz/swipeaerospace/blob/main/Readme.md Use this command to install the SwipeAeroSpace application via Homebrew. ```bash brew install --cask mediosz/tap/swipeaerospace ``` -------------------------------- ### Install SwipeAerospace via Homebrew Source: https://context7.com/mediosz/swipeaerospace/llms.txt Use this command to install the released version of SwipeAerospace using Homebrew Cask. ```bash # Install released version via Homebrew: brew install --cask mediosz/tap/swipeaerospace ``` -------------------------------- ### OverlayPanelController.show() Source: https://context7.com/mediosz/swipeaerospace/llms.txt Creates and displays a borderless, floating NSPanel that hosts the WorkspaceOverlayView. This method installs event monitors to dismiss the panel and revert the focused workspace upon Escape key press or an outside click. Hovering over a workspace card provides a live preview, and clicking selects it permanently. ```APIDOC ## `OverlayPanelController.show(workspaces:focusedMonitorId:onSelect:onPreview:onRevert:)` ### Description Creates a borderless, floating `NSPanel` hosting `WorkspaceOverlayView`. Installs both local and global `NSEvent` monitors so Escape or an outside click dismisses the panel and reverts the focused workspace. Hovering a card on the focused monitor live-previews that workspace; clicking selects it permanently. ### Method `show(workspaces:focusedMonitorId:onSelect:onPreview:onRevert:)` ### Parameters - **workspaces** ([WorkspaceInfo]) - An array of `WorkspaceInfo` objects representing the workspaces to display. - **focusedMonitorId** (String) - The ID of the currently focused monitor. - **onSelect** ((WorkspaceInfo) -> Void) - A closure to execute when a workspace is selected. - **onPreview** ((WorkspaceInfo) -> Void) - A closure to execute for live previewing a workspace. - **onRevert** (() -> Void) - A closure to execute to revert to the original workspace. ### Request Example ```swift overlayController.show( workspaces: [ WorkspaceInfo(id: "1", windows: [WindowInfo(id: "1-0", appName: "Xcode", windowTitle: "MyApp")], isFocused: true, monitorId: "1", monitorName: "Built-in Retina Display"), WorkspaceInfo(id: "2", windows: [], isFocused: false, monitorId: "1", monitorName: "Built-in Retina Display"), ], focusedMonitorId: "1", onSelect: { ws in /* aerospace workspace */ }, onPreview: { ws in /* aerospace workspace (live preview) */ }, onRevert: { /* aerospace workspace */ } ) ``` ### Dismiss Programmatically ```swift overlayController.dismiss() ``` ### Update Panel ```swift // update(workspaces:) replaces cards in-place while the panel is open: overlayController.update(workspaces: enrichedWorkspaces) ``` ``` -------------------------------- ### Start SwipeManager: Register Event Tap and Connect Socket Source: https://context7.com/mediosz/swipeaerospace/llms.txt Initiates the SwipeManager by creating a CGEventTap for gesture events and establishing a connection to the AeroSpace Unix domain socket. This should be called once at application launch. Ensure Accessibility permissions are granted, otherwise, an error will be logged and the tap will not be enabled. ```swift let manager = SwipeManager() manager.start() // Internally runs: // CGEvent.tapCreate(tap: .cghidEventTap, place: .headInsertEventTap, ...) // connectSocket() → /tmp/bobko.aerospace-.sock ``` -------------------------------- ### Connect/Reconnect to AeroSpace IPC Socket Source: https://context7.com/mediosz/swipeaerospace/llms.txt Establishes or re-establishes a connection to the AeroSpace Unix domain socket. The `reconnect: true` parameter forces a new connection. This is automatically called by `start()` and `runCommand` on socket errors. ```swift Button("Reconnect") { swipeManager.connectSocket(reconnect: true) } // Socket path used internally: let socket_path = "/tmp/bobko.aerospace-\(NSUserName()).sock" // Socket family: .unix, type: .stream, proto: .unix ``` -------------------------------- ### SwipeManager.connectSocket(reconnect:) Source: https://context7.com/mediosz/swipeaerospace/llms.txt Establishes or re-establishes a connection to the AeroSpace IPC socket. The `reconnect` parameter forces a new connection if one already exists. This is called automatically by `start()` and can be manually triggered. ```APIDOC ## SwipeManager.connectSocket(reconnect:) ### Description Opens a Unix-domain stream socket to `/tmp/bobko.aerospace-.sock`. Passing `reconnect: true` forces a fresh connection. Called automatically by `start()` and re-invoked transparently by `runCommand` on socket errors. ### Method `connectSocket(reconnect: Bool)` ### Parameters #### Path Parameters - `reconnect` (Bool) - Optional - Forces a fresh connection even if one already exists. ### Usage ```swift // Manual reconnect from SettingsView Button("Reconnect") { swipeManager.connectSocket(reconnect: true) } ``` ### Internals - Socket path: `/tmp/bobko.aerospace-\(NSUserName()).sock` - Socket family: `.unix`, type: `.stream`, proto: `.unix` ``` -------------------------------- ### SwipeManager.start() Source: https://context7.com/mediosz/swipeaerospace/llms.txt Registers a global trackpad event tap and connects to the AeroSpace Unix socket. This method should be called once at application launch to enable gesture recognition and communication. ```APIDOC ## SwipeManager.start() ### Description Installs a `CGEventTap` for gesture events and connects to the AeroSpace Unix socket. Must be called once at app launch. If Accessibility permission is missing, an error is logged and the tap is not enabled. ### Method `start()` ### Usage ```swift let manager = SwipeManager() manager.start() ``` ### Internals - `CGEvent.tapCreate(tap: .cghidEventTap, place: .headInsertEventTap, ...)` - `connectSocket()` to `/tmp/bobko.aerospace-.sock` ``` -------------------------------- ### Build and Export App with xcodebuild Source: https://github.com/mediosz/swipeaerospace/blob/main/Readme.md This command-line tool can be used to build and export the SwipeAeroSpace application from source. ```bash xcodebuild ``` -------------------------------- ### Manage Launch at Login with LaunchAtLogin Source: https://context7.com/mediosz/swipeaerospace/llms.txt Enables or disables the application's automatic launch at login using the ServiceManagement framework. Includes a SwiftUI toggle for easy integration into settings views and a check for whether the app was launched by the system. ```swift // Check status print(LaunchAtLogin.isEnabled) // true / false // Enable / disable programmatically LaunchAtLogin.isEnabled = true LaunchAtLogin.isEnabled = false // SwiftUI toggle (used in SettingsView): LaunchAtLogin.Toggle { Text("Launch at Login") } // Detect if the app was opened by the system at login // (must be checked in applicationDidFinishLaunching) if LaunchAtLogin.wasLaunchedAtLogin { print("Started automatically at login") } ``` -------------------------------- ### Build SwipeAerospace from Source (Xcode CLI) Source: https://context7.com/mediosz/swipeaerospace/llms.txt Use the Xcode command-line tools to build the SwipeAerospace application from source. The output application will be located in the specified derived data path. ```bash # Build from source with Xcode CLI: xcodebuild -scheme SwipeAeroSpace \ -configuration Release \ -derivedDataPath build \ -destination "generic/platform=macOS" # App output: build/Build/Products/Release/SwipeAeroSpace.app ``` -------------------------------- ### LaunchAtLogin Source: https://context7.com/mediosz/swipeaerospace/llms.txt Manages the application's launch at login behavior by wrapping the ServiceManagement framework. It allows checking the current status, enabling/disabling the feature programmatically, and detecting if the app was launched automatically at login. ```APIDOC ## `LaunchAtLogin` — Enable/disable automatic app launch at login ### Description Wraps `SMAppService.mainApp` (ServiceManagement framework) to register or unregister the app as a login item. Includes a ready-made `LaunchAtLogin.Toggle` SwiftUI view. ### Check Status ```swift // Check status print(LaunchAtLogin.isEnabled) // true / false ``` ### Enable/Disable Programmatically ```swift // Enable / disable programmatically LaunchAtLogin.isEnabled = true LaunchAtLogin.isEnabled = false ``` ### SwiftUI Toggle ```swift // SwiftUI toggle (used in SettingsView): LaunchAtLogin.Toggle { Text("Launch at Login") } ``` ### Detect Launch at Login ```swift // Detect if the app was opened by the system at login // (must be checked in applicationDidFinishLaunching) if LaunchAtLogin.wasLaunchedAtLogin { print("Started automatically at login") } ``` ``` -------------------------------- ### Show Workspace Overview Overlay Source: https://context7.com/mediosz/swipeaerospace/llms.txt Triggers the display of a workspace overview panel. This operation is executed on a background queue, with UI updates dispatched to the main thread. It involves multiple socket calls for fetching workspace and window details. ```swift // Triggered by 3-finger swipe-up (default) or menu-bar button swipeManager.showWorkspaceOverview() // Phase 1 socket calls (fast): // aerospace list-workspaces --focused // aerospace list-workspaces --focused --format %{monitor-id} // aerospace list-monitors --format %{monitor-id}|%{monitor-name} // aerospace list-workspaces --monitor all --empty no --format %{workspace}|%{monitor-id} // Phase 2 per-workspace (enriches cards): // aerospace list-windows --workspace --format %{app-name}|%{window-title} ``` -------------------------------- ### SwipeManager.nextWorkspace() / SwipeManager.prevWorkspace() Source: https://context7.com/mediosz/swipeaerospace/llms.txt Public methods to programmatically navigate to the next or previous workspace. These methods are also exposed as menu-bar actions for keyboard-driven navigation. ```APIDOC ## SwipeManager.nextWorkspace() / SwipeManager.prevWorkspace() ### Description Public methods that invoke `switchWorkspace(direction:)` and log errors. Also exposed as menu-bar buttons for keyboard-driven navigation without a trackpad gesture. ### Methods - `nextWorkspace()` - `prevWorkspace()` ### Usage ```swift // Menu-bar actions Button("Next Workspace") { swipeManager.nextWorkspace() } Button("Prev Workspace") { swipeManager.prevWorkspace() } ``` ### Internals - Calls `switchWorkspace(direction:)`. - May involve `aerospace list-workspaces` and `aerospace workspace` commands. ``` -------------------------------- ### Display Workspace Picker Panel Source: https://context7.com/mediosz/swipeaerospace/llms.txt Shows a floating panel for selecting workspaces. The panel can be dismissed by pressing Escape or clicking outside. Hovering over a workspace card provides a live preview, and clicking selects it. ```swift overlayController.show( workspaces: [ WorkspaceInfo(id: "1", windows: [WindowInfo(id: "1-0", appName: "Xcode", windowTitle: "MyApp")], isFocused: true, monitorId: "1", monitorName: "Built-in Retina Display"), WorkspaceInfo(id: "2", windows: [], isFocused: false, monitorId: "1", monitorName: "Built-in Retina Display"), ], focusedMonitorId: "1", onSelect: { ws in /* aerospace workspace */ }, onPreview: { ws in /* aerospace workspace (live preview) */ }, onRevert: { /* aerospace workspace */ } ) // Dismiss programmatically: overlayController.dismiss() // update(workspaces:) replaces cards in-place while the panel is open: overlayController.update(workspaces: enrichedWorkspaces) ``` -------------------------------- ### Generate Homebrew Cask File (Python) Source: https://context7.com/mediosz/swipeaerospace/llms.txt Run this Python script to generate a new Homebrew cask file after publishing a GitHub release. Ensure you have the correct build version. ```python # Generate a new cask file after publishing a GitHub release (Python): python3 scripts/build-brew-cask.py --build-version 0.3.0 # Output: swipeaerospace.rb (ready to commit to the Homebrew tap) ``` -------------------------------- ### Generate Homebrew Cask File (Bash) Source: https://context7.com/mediosz/swipeaerospace/llms.txt This bash script provides equivalent functionality to the Python script for generating a Homebrew cask file. It requires explicit specification of the zip URI. ```bash # Shell equivalent with explicit zip URL: bash scripts/build-brew-cask.sh \ --build-version 0.3.0 \ --zip-uri https://github.com/MediosZ/SwipeAeroSpace/releases/download/0.3.0/SwipeAeroSpace.zip ``` -------------------------------- ### checkAccessibilityPermissions() Source: https://context7.com/mediosz/swipeaerospace/llms.txt Ensures Accessibility access is granted at startup. If the application lacks the necessary permissions, this function resets the Accessibility TCC entry and terminates the app, prompting the user to re-grant permission upon the next launch. ```APIDOC ## `checkAccessibilityPermissions()` — Enforce Accessibility access at startup ### Description Called in `SwipeAeroSpaceApp.init()`. If the process is not trusted, it resets the Accessibility TCC entry via `/usr/bin/tccutil reset Accessibility club.mediosz.SwipeAeroSpace` and terminates the app, forcing the user to re-grant permission on the next launch. ### Usage ```swift // Runs automatically on every launch: checkAccessibilityPermissions() ``` ### Internal Process ```swift // Internally: // AXIsProcessTrustedWithOptions([kAXTrustedCheckOptionPrompt: true]) // If NOT trusted → // Process.run("/usr/bin/tccutil", ["reset", "Accessibility", "club.mediosz.SwipeAeroSpace"]) // NSApplication.shared.terminate(nil) ``` ``` -------------------------------- ### Programmatic Workspace Navigation Source: https://context7.com/mediosz/swipeaerospace/llms.txt Provides public methods for switching to the next or previous workspace, which internally call `switchWorkspace(direction:)`. These methods are also exposed as menu-bar buttons for keyboard-based navigation. ```swift // Menu-bar actions Button("Next Workspace") { swipeManager.nextWorkspace() } Button("Prev Workspace") { swipeManager.prevWorkspace() } // switchWorkspace internally: // 1. aerospace list-workspaces --monitor mouse --visible → e.g. "2" // 2. aerospace workspace 2 → focus that monitor // 3. aerospace workspace next [--wrap-around] [--stdin] → switch // When skipEmpty == true, also runs: // aerospace list-workspaces --monitor focused --empty no → list passed via stdin ``` -------------------------------- ### SwipeManager.showWorkspaceOverview() Source: https://context7.com/mediosz/swipeaerospace/llms.txt Displays a floating workspace overlay panel that lists all non-empty workspaces with their associated app windows. This method is executed on a background queue and dispatches UI updates to the main thread. It uses a two-phase approach for efficiency: first showing workspace names, then enriching cards with window details. ```APIDOC ## `SwipeManager.showWorkspaceOverview()` ### Description Presents a glass-morphism panel centered on the current screen listing all non-empty workspaces with their app windows. Executed on a background `DispatchQueue`; UI updates are dispatched to the main thread. Uses a two-phase approach: shows workspace names immediately (3 socket calls), then enriches cards with window details (1 call per workspace). ### Method `showWorkspaceOverview()` ### Usage ```swift // Triggered by 3-finger swipe-up (default) or menu-bar button swipeManager.showWorkspaceOverview() ``` ### Internal Socket Calls #### Phase 1 (fast): - `aerospace list-workspaces --focused` - `aerospace list-workspaces --focused --format %{monitor-id}` - `aerospace list-monitors --format %{monitor-id}|%{monitor-name}` - `aerospace list-workspaces --monitor all --empty no --format %{workspace}|%{monitor-id}` #### Phase 2 (per-workspace, enriches cards): - `aerospace list-windows --workspace --format %{app-name}|%{window-title}` ``` -------------------------------- ### runCommand(args:stdin:retry:) Source: https://context7.com/mediosz/swipeaerospace/llms.txt Sends a JSON-encoded command to the AeroSpace daemon via the Unix socket and receives a response. It handles command encoding, sending, receiving, and decoding, with automatic reconnection and retry logic. ```APIDOC ## runCommand(args:stdin:retry:) ### Description Private method that encodes a `ClientRequest` as JSON, writes it to the socket, waits for a `ServerAnswer` response, and returns `Result`. On a socket error, it automatically reconnects and retries once (`retry: true` stops recursion). ### Method `runCommand(args: [String], stdin: String, retry: Bool = true) -> Result` ### Parameters #### Path Parameters - `args` ([String]) - Required - The command arguments to send to AeroSpace. - `stdin` (String) - Required - Standard input for the command. - `retry` (Bool) - Optional - Whether to retry the command on socket error. Defaults to true. ### Request Example ```json { "command": "", "args": ["workspace", "next"], "stdin": "", "windowId": null, "workspace": null } ``` ### Response Example ```json { "exitCode": 0, "stdout": "", "stderr": "", "serverVersionAndHash": "0.16.0-..." } ``` ### Usage Example ```swift let result = runCommand(args: ["workspace", "next"], stdin: "") switch result { case .success(let stdout): print("Switched: \(stdout)") case .failure(.SocketError(let msg)): print("Socket error: \(msg)") case .failure(.CommandFail(let msg)): print("AeroSpace error: \(msg)") case .failure(.Unknown(let msg)): print("Unknown error: \(msg)") } ``` ``` -------------------------------- ### AppStorage Settings Keys Source: https://context7.com/mediosz/swipeaerospace/llms.txt Provides access to configurable settings for swipe behavior, stored in UserDefaults. These keys control sensitivity, finger count, swipe direction, wrapping, skipping empty workspaces, multi-swipe behavior, and overview gesture configuration. ```APIDOC ## `AppStorage` settings keys ### Description All settings are stored in `UserDefaults` under the following keys and are read live by `SwipeManager` during gesture processing. ### Configurable Settings | Key | Type | Default | Description | |---------------|--------|---------|-----------------------------------------------------------------------------| | `threshold` | Double | 1.0 | Sensitivity multiplier; internal = value * 0.05 | | `fingers` | String | "Three" | Finger count for horizontal swipe ("Three" | "Four") | | `natrual` | Bool | true | Natural (true) or inverted swipe direction | | `wrap` | Bool | false | Wrap around from last workspace to first | | `skip-empty` | Bool | false | Skip workspaces with no windows | | `multiSwipe` | Bool | true | Fire workspace switches live during the gesture | | `maxSteps` | Int | 5 | Max workspaces to jump in a single multi-swipe (2–9) | | `swipeUpOverview` | Bool | true | Enable 3/4-finger swipe-up workspace overview | | `swipeUpFingers` | String | "Three" | Finger count for vertical overview swipe | ### Programmatic Read/Write Example ```swift // Programmatic read/write example: UserDefaults.standard.set(2.0, forKey: "threshold") // more sensitive UserDefaults.standard.set(true, forKey: "wrap") // wrap around UserDefaults.standard.set("Four", forKey: "fingers") // require 4 fingers ``` ``` -------------------------------- ### Enforce Accessibility Permissions Source: https://context7.com/mediosz/swipeaerospace/llms.txt Ensures Accessibility access is granted at application startup. If access is not trusted, it resets the Accessibility TCC entry and terminates the app, prompting the user to re-grant permission on the next launch. ```swift // Runs automatically on every launch: checkAccessibilityPermissions() // Internally: // AXIsProcessTrustedWithOptions([kAXTrustedCheckOptionPrompt: true]) // If NOT trusted → // Process.run("/usr/bin/tccutil", ["reset", "Accessibility", "club.mediosz.SwipeAeroSpace"]) // NSApplication.shared.terminate(nil) ``` -------------------------------- ### Configure Swipe Behavior with AppStorage Source: https://context7.com/mediosz/swipeaerospace/llms.txt Allows programmatic reading and writing of swipe gesture sensitivity and behavior settings stored in UserDefaults. These settings are read live by the SwipeManager. ```swift // Key Type Default Description // "threshold" Double 1.0 Sensitivity multiplier; internal = value * 0.05 // "fingers" String "Three" Finger count for horizontal swipe ("Three" | "Four") // "natrual" Bool true Natural (true) or inverted swipe direction // "wrap" Bool false Wrap around from last workspace to first // "skip-empty" Bool false Skip workspaces with no windows // "multiSwipe" Bool true Fire workspace switches live during the gesture // "maxSteps" Int 5 Max workspaces to jump in a single multi-swipe (2–9) // "swipeUpOverview" Bool true Enable 3/4-finger swipe-up workspace overview // "swipeUpFingers" String "Three" Finger count for vertical overview swipe // Programmatic read/write example: UserDefaults.standard.set(2.0, forKey: "threshold") // more sensitive UserDefaults.standard.set(true, forKey: "wrap") // wrap around UserDefaults.standard.set("Four", forKey: "fingers") // require 4 fingers ``` -------------------------------- ### Send Command to AeroSpace and Receive Response Source: https://context7.com/mediosz/swipeaerospace/llms.txt Sends a JSON-encoded `ClientRequest` to the AeroSpace daemon via the Unix socket and processes the `ServerAnswer` response. It handles potential socket errors by attempting to reconnect and retry once. Errors are returned as a `Result`. ```swift // Internal usage — send "workspace next" to AeroSpace let result = runCommand(args: ["workspace", "next"], stdin: "") switch result { case .success(let stdout): print("Switched: \(stdout)") case .failure(.SocketError(let msg)): print("Socket error: \(msg)") case .failure(.CommandFail(let msg)): print("AeroSpace error: \(msg)") case .failure(.Unknown(let msg)): print("Unknown error: \(msg)") } // ClientRequest JSON sent over the socket: // { "command": "", "args": ["workspace", "next"], // "stdin": "", "windowId": null, "workspace": null } // ServerAnswer JSON received: // { "exitCode": 0, "stdout": "", "stderr": "", // "serverVersionAndHash": "0.16.0-..." } ``` -------------------------------- ### SwipeManager.stop() Source: https://context7.com/mediosz/swipeaerospace/llms.txt Tears down the connection to the AeroSpace Unix socket. This method is called when the application is quitting to ensure a clean shutdown. ```APIDOC ## SwipeManager.stop() ### Description Closes the AeroSpace Unix socket connection. This is paired with the "Quit" menu-bar button and called before `NSApplication.shared.terminate(nil)`. ### Method `stop()` ### Usage ```swift // In response to the "Quit" menu-bar button swipeManager.stop() // closes Socket NSApplication.shared.terminate(nil) ``` ``` -------------------------------- ### Remove Quarantine Attribute from App Source: https://github.com/mediosz/swipeaerospace/blob/main/Readme.md Execute this command in the terminal to remove the quarantine attribute from the SwipeAeroSpace application, allowing it to open. ```bash xattr -d com.apple.quarantine /path/to/SwipeAeroSpace.app ``` -------------------------------- ### Stop SwipeManager: Close Socket on Quit Source: https://context7.com/mediosz/swipeaerospace/llms.txt Closes the Unix domain socket connection to the AeroSpace daemon. This function is typically called before terminating the application, often triggered by a 'Quit' menu-bar item. ```swift Button("Quit") { swipeManager.stop() // closes Socket NSApplication.shared.terminate(nil) }.keyboardShortcut("q") ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.