### Full StashManager Usage Example Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/stash-manager.md Demonstrates the complete lifecycle of using StashManager, from starting and stashing windows to revealing, hiding, unstashing, and shutting down. ```swift let stashManager = StashManager.shared // Start the manager stashManager.start() // Stash a window to the right edge let window = try? Window(pid: targetPID) if let window { await stashManager.stash(window: window, to: .right, animated: true) } // Reveal the stashed window await stashManager.revealWindow(id: window.cgWindowID, animated: true) // Hide it again await stashManager.hideWindow(id: window.cgWindowID, animated: true) // Unstash (remove from stash system) await stashManager.unstash(windowID: window.cgWindowID, animated: true) // Check if an action should be intercepted let action = WindowAction(.rightHalf) if stashManager.shouldInterceptAction(action) { // StashManager handles this } else { // LoopManager handles this } // Clean up stashManager.shutdown() ``` -------------------------------- ### start() Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/stash-manager.md Starts the stash manager and restores previously stashed windows. It asynchronously calls store.restore() and prepares mouse movement monitoring. ```APIDOC ## start() ### Description Starts the stash manager and restores previously stashed windows. ### Behavior - Asynchronously calls store.restore() to reload stashed windows - Prepares mouse movement monitoring (not started until windows are stashed) ``` -------------------------------- ### InstallState Enumeration Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/types.md Represents the progress and outcome of the update installation process. Use this to provide feedback to the user during installation. ```swift enum InstallState: String, Codable { case ready case downloading case extracting case installing case complete case failed(String) } ``` -------------------------------- ### Example ResizeContext Initialization Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/resize-context.md Demonstrates how to create a ResizeContext with specific window, screen, action, and mouse position. ```swift let context = ResizeContext( window: targetWindow, screen: NSScreen.main, action: WindowAction(.rightHalf), initialMousePosition: NSEvent.mouseLocation ) ``` -------------------------------- ### Example Usage Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/stash-manager.md Illustrates common StashManager operations such as starting, stashing, revealing, hiding, unstashing, and shutting down. ```APIDOC ## Example Usage ```swift let stashManager = StashManager.shared // Start the manager stashManager.start() // Stash a window to the right edge let window = try? Window(pid: targetPID) if let window { await stashManager.stash(window: window, to: .right, animated: true) } // Reveal the stashed window await stashManager.revealWindow(id: window.cgWindowID, animated: true) // Hide it again await stashManager.hideWindow(id: window.cgWindowID, animated: true) // Unstash (remove from stash system) await stashManager.unstash(windowID: window.cgWindowID, animated: true) // Check if an action should be intercepted let action = WindowAction(.rightHalf) if stashManager.shouldInterceptAction(action) { // StashManager handles this } else { // LoopManager handles this } // Clean up stashManager.shutdown() ``` ``` -------------------------------- ### start() Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/keybind-trigger.md Starts monitoring keyboard events for trigger key presses and releases. This method initializes the event tap and begins listening for key events until the stop() method is called. ```APIDOC ## start() ### Description Starts monitoring keyboard events. Initializes the event tap for keyboard monitoring, starts listening for key press/release events, and sets up the trigger delay timer if needed. Monitoring continues until `stop()` is called. ### Method func start() ### Behavior - Initializes event tap for keyboard monitoring - Starts listening for key press/release events - Sets up trigger delay timer if needed - Monitoring continues until stop() is called ``` -------------------------------- ### ResizeContext Usage Example Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/resize-context.md Demonstrates a typical workflow for resizing a window using ResizeContext, including refreshing state, setting actions, getting target frames, and applying frames, with an example for creating an undo context. ```swift // Typical flow when Loop opens let context = ResizeContext( window: targetWindow, screen: targetScreen, action: .init(.noSelection), initialMousePosition: NSEvent.mouseLocation ) // Fetch current window state from Accessibility framework await context.refreshResolvedState() // User selects an action (e.g., right half) context.setAction(to: WindowAction(.rightHalf), parent: nil) // Get computed frame let targetFrame = context.getTargetFrame() print("Window should resize to: \(targetFrame.raw)") // Apply the frame to window try await window.setFrame(targetFrame.raw) // For undo, create derived context with previous action let previousAction = ... let undoContext = context.derivedContext(action: previousAction, bounds: context.bounds) let undoFrame = undoContext.getTargetFrame() // Apply undo frame try await window.setFrame(undoFrame.raw) ``` -------------------------------- ### Download and Install Update Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/updater.md Downloads and installs the available update. This process includes downloading the package, verifying its integrity, extracting, and installing it. It updates the install state throughout the process and can throw errors for download, checksum, or installation failures. The progress bar is updated during the download phase. ```swift func downloadAndInstallUpdate() async throws ``` ```swift do { try await Updater.shared.downloadAndInstallUpdate() print("Update installed, relaunch Loop to apply") } catch { print("Update failed: \(error)") } ``` -------------------------------- ### Install Loop via Homebrew Source: https://github.com/mrkai77/loop/blob/develop/README.md Use this command to install the Loop application using the Homebrew package manager. ```bash brew install loop ``` -------------------------------- ### downloadAndInstallUpdate() Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/updater.md Downloads and installs the available update. This method progresses through states like downloading, extracting, and installing, validating the package integrity and updating the application version upon successful completion. It also provides progress updates and can throw errors related to download, checksum, or installation failures. ```APIDOC ## downloadAndInstallUpdate() ### Description Downloads and installs the available update. This method sets the `installState` to `downloading`, fetches the package from `manifest.downloadURL`, validates it using checksum verification, then sets the state to `extracting` and `installing` before finally setting it to `complete` and updating the application version. Progress is reported via the `progressBar` and can be observed via `@Published`. ### Method `async throws` ### Parameters None ### Throws - `UpdateDownloadError`: For download or network failures. - `ChecksumMismatchError`: If the package integrity check fails. - `InstallationError`: If the installation process fails. ### Request Example ```swift do { try await Updater.shared.downloadAndInstallUpdate() print("Update installed, relaunch Loop to apply") } catch { print("Update failed: \(error)") } ``` ### Response Updates internal state (`installState`, application version). No direct return value upon success. ``` -------------------------------- ### Start Loop Manager Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/loop-manager.md Starts all event monitors and accessibility permission monitoring. This method is called during app startup. ```swift func start() ``` -------------------------------- ### Accessing and Starting LoopManager Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/loop-manager.md Demonstrates how to access the shared LoopManager instance and start its monitoring services. This is the primary entry point for using LoopManager. ```swift // Access singleton let manager = LoopManager.shared // Start monitoring manager.start() ``` -------------------------------- ### InstallState Enum Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/updater.md Represents the different stages of the update installation process. Monitor this enum to track the progress and status of an update installation. ```swift enum InstallState: String, Codable { case ready // Ready to start download/install case downloading // Download in progress case extracting // Package extraction in progress case installing // Installation in progress case complete // Installation completed case failed(String) // Installation failed with error } ``` -------------------------------- ### WindowAction Example Usage Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/window-action.md Demonstrates how to create and use WindowAction instances, including standard actions, actions with keyboard bindings, custom actions, and cycles of actions. Also shows how to access the properties of a WindowAction. ```swift // Create a standard action let topHalf = WindowAction(.topHalf) // Create an action with keyboard binding let rightQuarter = WindowAction(.rightQuarter, keybind: [.kVK_ANSI_Right, .kVK_RightControl]) // Create a custom action: 500px wide, anchored to top-left, in pixels let customFrame = WindowAction( .custom, keybind: [.kVK_ANSI_C], name: "500px Sidebar", unit: .pixels, anchor: .topLeft, width: 500, height: 600, positionMode: .generic, sizeMode: .custom ) // Create a cycle with three sizing options let sizeCycle = WindowAction( "Size Cycle", cycle: [ WindowAction(.rightThird), WindowAction(.rightHalf), WindowAction(.rightTwoThirds) ], keybind: [.kVK_ANSI_Right, .kVK_RightShift] ) // Access properties print(topHalf.direction) // .topHalf print(rightQuarter.keybind) // {.kVK_ANSI_Right, .kVK_RightControl} print(customFrame.width) // 500.0 print(sizeCycle.cycle?.count) // 3 ``` -------------------------------- ### Swift: Configure and Start Middle-Click Trigger Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/middle-click-trigger.md This snippet shows how to create, configure, and start the MiddleClickTrigger. It includes setting up callbacks for opening and closing Loop, checking if Loop is already open, and enabling the trigger via application defaults. Optional delay settings are also demonstrated. ```swift // Create and configure middle-click trigger let trigger = MiddleClickTrigger( openCallback: { action in print("Opening Loop via middle-click") }, closeCallback: { forceClose in print("Closing Loop (force: \(forceClose))") }, checkIfLoopOpen: { LoopManager.shared.isLoopActive } ) // Enable in defaults Defaults[.middleClickTriggersLoop] = true // Optional: enable delay Defaults[.triggerDelay] = 0.2 Defaults[.enableTriggerDelayOnMiddleClick] = true // Start monitoring trigger.start() // Later... trigger.stop() ``` -------------------------------- ### Displaying Changelog Information Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/updater.md Provides an example of how to access and display the changelog sections from the `updateManifest`. It also shows how to toggle the expansion state of changelog sections. ```swift // Access changelog sections if let manifest = updater.updateManifest { for section in manifest.changelog { print("## \(section.title)") for item in section.items { print("- \(item)") } } } // Toggle section expansion updater.expandedChangelogSections.toggle(section.id) ``` -------------------------------- ### Basic Window Manipulation and Information Retrieval Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/window.md Demonstrates how to get the frontmost window, check its resizability, resize, move, and retrieve its title and app name. Also shows how to focus the window. ```swift // Get the frontmost window let frontmostApp = NSWorkspace.shared.frontmostApplication! let window = try Window(pid: frontmostApp.processIdentifier) // Check window capabilities if !window.isResizable { print("Window cannot be resized") return } // Resize window let newFrame = CGRect(x: 0, y: 0, width: 960, height: 1080) try await window.setFrame(newFrame) // Move window try await window.setPosition(CGPoint(x: 500, y: 300)) // Get window info print("Window: \(window.title ?? \"Untitled\")") print("App: \(window.appName ?? \"Unknown\")") print("Minimizable: \(window.isMinimizable)") // Focus window try window.makeKeyAndOrderFront() ``` -------------------------------- ### Open Loop with Starting Action Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/loop-manager.md Opens Loop and prepares to execute a window action. This is an internal method called by event monitors. It validates permissions, determines the target window, and sets up visual indicators. ```swift private func openLoop(startingAction: WindowAction) async ``` -------------------------------- ### Managing Icon Settings Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/configuration.md Shows how to retrieve the current icon setting and how to change the app icon. Also includes examples for tracking usage and modifying icon-related preferences. ```swift // Check current icon let icon = Defaults[.currentIcon] // Change icon Defaults[.currentIcon] = "AppIcon-Dark" // Track usage Defaults[.timesLooped] += 1 ``` -------------------------------- ### Enable and Set Uniform Padding Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/configuration.md Example of enabling window padding and setting uniform padding values. This involves enabling the padding feature and then assigning a configured PaddingConfiguration object. ```swift // Enable padding Defaults[.enablePadding] = true // Set uniform padding var padding = PaddingConfiguration.zero padding.window = 10 // 10px between windows padding.top = 20 padding.bottom = 20 padding.right = 20 padding.left = 20 Defaults[.padding] = padding ``` -------------------------------- ### Get Apps With Windows Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/window-utility.md Returns a list of all running applications that currently have on-screen windows. This is useful for identifying active applications. ```swift static func getAppsWithWindows() -> [NSRunningApplication] ``` -------------------------------- ### Set Trigger Key Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/configuration.md Configures the trigger key for Loop. This example demonstrates setting the trigger to the Control key. ```swift // Set trigger to Control key Defaults[.triggerKey] = [.kVK_Control] ``` -------------------------------- ### List Available Loop Commands Source: https://github.com/mrkai77/loop/blob/develop/README.md Execute these shell commands to get a list of all available commands, window actions, or custom keybinds supported by Loop. ```bash open "loop://list/all" # List all commands open "loop://list/actions" # List window actions open "loop://list/keybinds" # List custom keybinds ``` -------------------------------- ### relaunchAfterUpdate() Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/updater.md Relaunches the application after an update has been successfully installed. This method waits for the user to close the application, then terminates the current process and launches a new instance of the updated application. ```APIDOC ## relaunchAfterUpdate() ### Description Relaunches the application after an update has been installed. This method waits for the user to close the application, then terminates the current process and launches a new instance of the updated application. ### Method `async` ### Parameters None ### Request Example ```swift await Updater.shared.relaunchAfterUpdate() ``` ### Response No direct return value. Restarts the application. ``` -------------------------------- ### Update State Properties Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/updater.md Observe the current state of the update process, including availability, installation progress, download progress, and release notes. ```swift @Published var updateState: UpdateAvailability { get } ``` ```swift @Published var installState: InstallState { get } ``` ```swift @Published var progressBar: Double { get } ``` ```swift @Published var changelog: [ChangelogSection] { get } ``` ```swift @Published var expandedChangelogSections: Set { get set } ``` ```swift @Published var updateManifest: UpdateManifest? { get } ``` -------------------------------- ### Relaunch After Update Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/updater.md Relaunches the application after an update has been successfully installed. This function waits for the user to close the application before terminating and restarting it with the new version. ```swift func relaunchAfterUpdate() async ``` -------------------------------- ### PreviewStartingPosition Enumeration Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/types.md Specifies the starting position for preview window animations. Options include the screen center, radial menu, or the action's center point. ```swift enum PreviewStartingPosition: String, CaseIterable, Identifiable, Codable { case screenCenter = "screenCenter" case radialMenu = "radialMenu" case actionCenter = "actionCenter" } ``` -------------------------------- ### App Startup with Permission Check Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/accessibility-manager.md Handles accessibility permission checks during application launch. If permissions are not granted, it prompts the user with an alert and terminates the app; otherwise, it starts the main Loop manager. ```swift func applicationDidFinishLaunching(_ notification: Notification) { // Check permissions if !AccessibilityManager.shared.isGranted { // Request permissions if !AccessibilityManager.requestAccess() { // User denied let alert = NSAlert() alert.messageText = "Accessibility Required" alert.informativeText = "Loop cannot function without accessibility permissions." alert.addButton(withTitle: "OK") alert.runModal() NSApp.terminate(nil) return } } // Start main app LoopManager.shared.start() } ``` -------------------------------- ### Swift Function with Comprehensive Comments Source: https://github.com/mrkai77/loop/blob/develop/CONTRIBUTING.md Example of a Swift function that includes detailed documentation comments explaining its purpose, parameters, and return value. This adheres to the project's documentation standards. ```swift /// Determines if two colors are similar based on a threshold. /// - Parameters: /// - color: The color to compare with the receiver. /// - threshold: The maximum allowed difference between color components. /// - Returns: A Boolean value indicating whether the two colors are similar. func isSimilar(to color: NSColor, threshold: CGFloat = 0.1) -> Bool { // Convert both colors to the RGB color space for comparison. guard let color1 = usingColorSpace(.deviceRGB), let color2 = color.usingColorSpace(.deviceRGB) else { return false } // Compare the red, green, and blue components of both colors. return abs(color1.redComponent - color2.redComponent) < threshold && abs(color1.greenComponent - color2.greenComponent) < threshold && abs(color1.blueComponent - color2.blueComponent) < threshold } ``` -------------------------------- ### Get Windows for a Specific Screen Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/window-utility.md Returns an array of all visible windows on a given screen, sorted from front to back. If nil is provided for the screen, it queries all screens. ```swift static func getWindowList(for screen: NSScreen?) -> [Window] ``` -------------------------------- ### MiddleClickTrigger.start() Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/middle-click-trigger.md Starts the middle-click event monitoring. This method initializes a passive event monitor that listens for middle-mouse-click events (specifically NSEventTypeOtherMouseDown with button 2) and continues until the stop() method is called. ```APIDOC ## start() ### Description Starts monitoring middle-click events. ### Behavior - Initializes passive event monitor for middle-click events - Listens for NSEventTypeOtherMouseDown events (middle button = 2) - Monitoring continues until stop() is called ``` -------------------------------- ### Swift: Get Target Frame Example Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/resize-context.md Retrieves the computed target frame for the current action. If the frame requires recomputation, it calculates and caches the result. The example shows how to access the raw, normalized, and padded frame values. ```swift func getTargetFrame() -> ComputedFrame ``` -------------------------------- ### Configuring Accent Color Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/configuration.md Provides examples for setting a custom accent color and enabling gradient effects for the accent color. This includes setting the accent color mode and specifying gradient colors. ```swift // Set custom accent color Defaults[.accentColorMode] = .custom Defaults[.customAccentColor] = Color.red // Enable gradient Defaults[.useGradient] = true Defaults[.gradientColor] = Color.orange ``` -------------------------------- ### Accessing and Observing Configuration Settings Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/configuration.md Demonstrates how to read, write, and observe changes to configuration settings using the Defaults package. Ensure the Defaults package is imported. ```swift import Defaults // Read a setting let currentTriggerKey = Defaults[.triggerKey] // Write a setting Defaults[.triggerKey] = [.kVK_Control] // Observe changes Task { for await value in Defaults.updates(.enablePadding) { print("Padding enabled:", value) } } ``` -------------------------------- ### Basic Window Actions Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/window-action-engine.md Demonstrates how to apply basic window actions like hiding, resizing to the right half, and focusing to the right. It also shows how to access the newly targeted window after an action. ```swift // Quick action: hide window let result = try await WindowActionEngine.shared.apply( WindowAction(.hide), window: window, screen: screen ) // Resize: right half let result = try await WindowActionEngine.shared.apply( WindowAction(.rightHalf), window: window, screen: screen ) // Focus: focus window to the right let result = try await WindowActionEngine.shared.apply( WindowAction(.focusRight), window: currentWindow, screen: screen ) if let newWindow = result.newTargetWindow { print("Focused window:", newWindow.title ?? "Unknown") } ``` -------------------------------- ### Read and Write Settings with Defaults Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/README.md Demonstrates how to read, write, and observe changes to application settings using the Defaults package. ```swift import Defaults // Read setting let enabled = Defaults[.enablePadding] // Write setting Defaults[.enablePadding] = true // Observe changes Task { for await value in Defaults.updates(.enablePadding) { print("Padding enabled:", value) } } ``` -------------------------------- ### Create and Apply Basic Padding Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/padding-configuration.md Demonstrates how to create a PaddingConfiguration with specific margins and apply it to screen bounds. This snippet shows setting window, external bar, and edge paddings, storing the configuration in Defaults, and then applying it to a screen's frame. ```swift // Create padding: 10px between windows, 20px from screen edges let padding = PaddingConfiguration( window: 10, externalBar: 0, top: 20, bottom: 20, right: 20, left: 20, configureScreenPadding: true ) // Store in Defaults Defaults[.padding] = padding Defaults[.enablePadding] = true // Apply to screen bounds let screen = NSScreen.main! let bounds = screen.cgSafeScreenFrame let paddedBounds = padding.applyToBounds(bounds, screen: screen) // paddedBounds is now 40px smaller on each side (20px padding per side) ``` -------------------------------- ### Start MiddleClickTrigger Monitoring Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/middle-click-trigger.md Starts the monitoring of middle-mouse-click events. This method initializes an event monitor that listens for middle-click events (NSEventTypeOtherMouseDown with button 2) and continues until stop() is called. ```swift func start() ``` -------------------------------- ### Apply Window Action (Simple) Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/window-action-engine.md Use this simplified apply method for basic URL commands or drag snap operations when resize context tracking is not needed. It creates an internal ResizeContext and fetches the current window state before routing to the full apply method. ```swift func apply( _ action: WindowAction, window: Window?, screen: NSScreen ) async throws -> Result ``` ```swift let result = try await WindowActionEngine.shared.apply( WindowAction(.rightHalf), window: targetWindow, screen: NSScreen.main! ) if result.success { print("Window resized successfully") } ``` -------------------------------- ### Updater API Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/MANIFEST.txt Handles update checking and installation, changelog management, and auto-update functionality. ```APIDOC ## updater.md ### Description Manages the update process, including checking for updates, installation, changelog management, and auto-update features. ### Topics Covered - Update checking and installation - Changelog management - Auto-update functionality ``` -------------------------------- ### Get Window Level Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/window-utility.md Retrieves the window's layer/level in the window manager. Returns nil if the level cannot be determined. ```swift static func getWindowLevel(_ window: Window?) -> CGWindowLevel? ``` -------------------------------- ### makeKeyAndOrderFront() Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/window.md Brings the window to the foreground and makes it the key (focused) window. ```APIDOC ## makeKeyAndOrderFront() ### Description Brings the window to the foreground and makes it key (focused). ### Method Swift Function ### Throws Any error from AXUIElement performAction or Accessibility calls ``` -------------------------------- ### Update State Properties Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/updater.md Exposes the current state of the update process, including availability, installation progress, and download progress. ```APIDOC ## Update State Properties ### Description These properties provide read-only access to the current state of the update process, including availability, installation progress, and download progress. ### Properties - **updateState** (UpdateAvailability) - Current update availability state. - **installState** (InstallState) - Current installation progress state. - **progressBar** (Double) - Download/install progress (0.0-1.0). - **changelog** ([ChangelogSection]) - Release notes for the available update. - **updateManifest** (UpdateManifest?) - Full manifest of the available update. ``` -------------------------------- ### Create and Configure Keybind Trigger Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/keybind-trigger.md This Swift code demonstrates how to initialize and configure a KeybindTrigger. It shows adding window actions with specific keybinds and storing them in user defaults. The trigger is then set up with callbacks for opening and closing Loop, and a check for Loop's active state. ```swift let cache = WindowActionCache() var keybinds: [WindowAction] = [] // Add some keybinds keybinds.append(WindowAction(.rightHalf, keybind: [.kVK_ANSI_Right])) keybinds.append(WindowAction(.maximize, keybind: [.kVK_ANSI_M])) // Store in defaults Defaults[.keybinds] = keybinds // Create trigger let trigger = KeybindTrigger( windowActionCache: cache, openCallback: { action in print("Opening Loop with action: \(action.direction)") }, closeCallback: { forceClose in print("Closing Loop (force: \(forceClose))") }, checkIfLoopOpen: { LoopManager.shared.isLoopActive } ) // Start monitoring trigger.start() // Later... trigger.stop() ``` -------------------------------- ### Stop MiddleClickTrigger Monitoring Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/middle-click-trigger.md Stops the monitoring of middle-mouse-click events by removing the event monitor. The trigger can be restarted later using the start() method. ```swift func stop() ``` -------------------------------- ### Basic Update Checking Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/updater.md Demonstrates how to fetch the latest update information and check the current update state using the `Updater` singleton. ```swift let updater = Updater.shared // Check for updates await updater.fetchLatestInfo() // Check status switch updater.updateState { case .available: print("Update available: \(updater.updateManifest?.version ?? "unknown")") case .checking: print("Checking for updates...") case .unavailable: print("No update available") case .error(let error): print("Update check failed: \(error)") } ``` -------------------------------- ### Get Screen by Index Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/window-utility.md Retrieves a specific screen from the list of available screens using its index. Returns nil if the provided index is out of bounds. ```swift static func getScreenAtIndex(_ index: Int) -> NSScreen? ``` -------------------------------- ### fromWindowInfo(_:) Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/window.md Creates a Window object from a dictionary containing window information, typically obtained from `CGWindowListCopyWindowInfo`. This method includes filtering for invisible or invalid windows and uses CGWindowBounds for matching. ```APIDOC ## fromWindowInfo(_:) ### Description Creates a Window from a dictionary returned by `CGWindowListCopyWindowInfo`. ### Parameters #### Path Parameters - **windowInfo** ([String: AnyObject]) - Required - Window info dict with keys like kCGWindowNumber, kCGWindowBounds, etc. ### Throws Same as init(element:), plus WindowError.filteredOutFromWindowInfo ### Filtering - Skips invisible windows (alpha <= 0.01) - Skips windows with invalid layers - Uses CGWindowBounds to match window against AX elements ### Example ```swift if let windowList = CGWindowListCopyWindowInfo([.optionIncludingWindow], cgWindowID) as? [[String: AnyObject]] { for windowInfo in windowList { if let window = try? Window.fromWindowInfo(windowInfo) { // Process window } } } ``` ``` -------------------------------- ### Get Target Window Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/README.md Retrieves the target window based on user configuration, which can be either the window under the cursor or the frontmost application's window. ```swift // Based on configuration (cursor or frontmost) if let window = WindowUtility.userDefinedTargetWindow() { // Use this window } // Or explicitly if let cursorWindow = WindowUtility.getWindowUnderCursor() { // Window under cursor } ``` -------------------------------- ### Loop Manager API Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/MANIFEST.txt Provides access to the central orchestrator for Loop sessions, including event monitoring setup and action execution lifecycle. ```APIDOC ## loop-manager.md ### Description Central orchestrator for Loop sessions. Manages event monitoring setup and the action execution lifecycle. ### Topics Covered - Event monitoring setup - Action execution lifecycle ``` -------------------------------- ### Window Operations Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/window.md Demonstrates common operations such as creating, resizing, moving, and focusing windows. ```APIDOC ## Window Operations ### Description Examples of how to use the Window API for various tasks. ### Usage Example ```swift // Get the frontmost window let frontmostApp = NSWorkspace.shared.frontmostApplication! let window = try Window(pid: frontmostApp.processIdentifier) // Check window capabilities if !window.isResizable { print("Window cannot be resized") return } // Resize window let newFrame = CGRect(x: 0, y: 0, width: 960, height: 1080) try await window.setFrame(newFrame) // Move window try await window.setPosition(CGPoint(x: 500, y: 300)) // Get window info print("Window: \(window.title ?? \"Untitled\")") print("App: \(window.appName ?? \"Unknown\")") print("Minimizable: \(window.isMinimizable)") // Focus window try window.makeKeyAndOrderFront() ``` ``` -------------------------------- ### Simple Apply Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/window-action-engine.md Applies a window action without explicit resize context tracking. This is suitable for basic commands like URL commands or drag snapping. ```APIDOC ## apply(_:window:screen:) ### Description Simplified apply for callers that don't need resize context tracking. ### Method `apply(_:window:screen:)` ### Parameters #### Path Parameters - **action** (WindowAction) - Required - Action to apply - **window** (Window?) - Optional - Target window (can be nil for some actions) - **screen** (NSScreen) - Required - Screen to perform action on ### Returns `Result` — Success/failure and any window changes ### Throws `CancellationError` if action is cancelled by a new action on the same window ### Behavior - Creates an internal ResizeContext - Calls refreshResolvedState() to fetch current window state - Routes to full apply(context:) ### Example ```swift let result = try await WindowActionEngine.shared.apply( WindowAction(.rightHalf), window: targetWindow, screen: NSScreen.main! ) if result.success { print("Window resized successfully") } ``` ``` -------------------------------- ### Request Accessibility Permissions Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/accessibility-manager.md Requests accessibility permissions from the user. If granted, it starts the main Loop manager; otherwise, it prints an error and terminates the application. ```swift // Ask user for permissions if AccessibilityManager.requestAccess() { // Start window management LoopManager.shared.start() } else { // Show error and quit print("Cannot continue without accessibility permissions") NSApp.terminate(nil) } ``` -------------------------------- ### Exclude Application from Loop Management Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/configuration.md Add the bundle URL of an application to the 'excludedApps' default to prevent Loop from managing it. This example shows how to exclude Zoom. ```swift // Exclude Zoom from Loop management let zoomURL = URL(fileURLWithPath: "/Applications/Zoom.app") var excluded = Defaults[.excludedApps] excluded.append(zoomURL) Defaults[.excludedApps] = excluded ``` -------------------------------- ### Execute a Window Action Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/README.md Applies a specified window action to resize or reposition a window on the screen. Ensure the `WindowActionEngine` is initialized and the target window and screen are valid. ```swift let window = try Window(pid: frontmostApp.processIdentifier) let screen = NSScreen.main! let result = try await WindowActionEngine.shared.apply( WindowAction(.rightHalf), window: window, screen: screen ) if result.success { print("Window resized to right half") } ``` -------------------------------- ### Swift Function with Minimal Comments (Not Accepted) Source: https://github.com/mrkai77/loop/blob/develop/CONTRIBUTING.md Example of a Swift function with insufficient comments, which will not be accepted for submission. Contributions must include comprehensive documentation. ```swift // Compares to another and returns a boolean func isSimilar(to color: NSColor, threshold: CGFloat = 0.1) -> Bool { ... } ``` -------------------------------- ### Configure Window Padding Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/README.md Sets up custom padding values for window margins and inner spacing. Ensure `Defaults[.enablePadding]` is set to `true` to activate these settings. ```swift // Create padding configuration var padding = PaddingConfiguration.zero padding.window = 10 // Inner padding between windows padding.top = 20 padding.bottom = 20 padding.right = 20 padding.left = 20 // Store Defaults[.enablePadding] = true Defaults[.padding] = padding ``` -------------------------------- ### Get Screen for Point Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/window-utility.md Identifies and returns the screen that contains a given point in screen coordinates. Returns nil if the point does not fall within any screen. ```swift static func getScreen(for point: CGPoint) -> NSScreen? ``` -------------------------------- ### Context-Tracked Grow/Shrink Operations Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/window-action-engine.md Illustrates using a ResizeContext for sequential grow and shrink operations on a window. The context preserves the sides to adjust across multiple calls. ```swift var context = ResizeContext(window: window, screen: screen) // First grow right context.setAction(to: WindowAction(.growRight), parent: nil) try await WindowActionEngine.shared.apply(context: context) // Second grow right — keeps right edge adjusting context.setAction(to: WindowAction(.growRight), parent: nil) try await WindowActionEngine.shared.apply(context: context) // Now shrink from left context.setAction(to: WindowAction(.shrinkLeft), parent: nil) try await WindowActionEngine.shared.apply(context: context) // sidesToAdjust is preserved across calls within same context ``` -------------------------------- ### Enabling Automatic Updates Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/updater.md Configures the `Updater` to automatically check for, download, verify, and install updates when the application is not in use. No manual user action is required after enabling. ```swift // Enable automatic updates Defaults[.automaticallyUpdate] = true // Updater will now: // 1. Check for updates periodically // 2. When available and Loop is not in use: // - Download automatically // - Verify checksum // - Extract and install // - Relaunch with new version // User has no manual action needed ``` -------------------------------- ### Initialize Resize Context Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/README.md Create a ResizeContext to track the state during a window resize operation. This includes the target window, screen, the action being performed, and the initial mouse position. ```swift let context = ResizeContext( window: targetWindow, screen: NSScreen.main, action: WindowAction(.rightHalf), initialMousePosition: NSEvent.mouseLocation ) // Get the computed target frame let targetFrame = context.getTargetFrame() // Apply to window try await window.setFrame(targetFrame.raw) ``` -------------------------------- ### Creating a KeybindTrigger Instance Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/keybind-trigger.md Instantiate KeybindTrigger, providing necessary dependencies and callback closures for opening, closing, and checking loop status. Callbacks are executed on the event tap thread. ```swift let keybindTrigger = KeybindTrigger( windowActionCache: windowActionCache, openCallback: { [weak self] action in Task { await self?.openLoop(startingAction: action) } }, closeCallback: { [weak self] forceClose in Task { await self?.closeLoop(forceClose: forceClose) } }, checkIfLoopOpen: { [weak self] in self?.isLoopActiveAtomic ?? false } ) ``` -------------------------------- ### MiddleClickTrigger.stop() Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/middle-click-trigger.md Stops the middle-click event monitoring. This method removes the event monitor, ceasing the listening for mouse events. The monitoring can be restarted by calling the start() method again. ```APIDOC ## stop() ### Description Stops monitoring middle-click events. ### Behavior - Removes event monitor - Stops listening for mouse events - Can be restarted with start() ``` -------------------------------- ### Handle Quick Window Actions Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/window-action-engine.md This private method processes quick actions that do not require full resize logic, such as hide, minimize, or fullscreen. It returns a Result if the action is a quick action, otherwise returns nil to indicate that resize logic is needed. ```swift private func handleQuickAction( _ action: WindowAction, window: Window? ) -> Result? ``` -------------------------------- ### Context-Tracked Apply Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/window-action-engine.md Applies a window action with explicit resize context tracking. The context should be updated before calling this function, and is used for Loop operations. ```APIDOC ## apply(context:) ### Description Applies a window action with explicit resize context tracking. The context should be updated before calling this function. ### Method `apply(context:)` ### Parameters #### Path Parameters - **context** (ResizeContext) - Required - Context containing tracking state and target window ### Returns `Result` — Success/failure and any window changes ### Throws `CancellationError` if a new action is applied to the same window ### Behavior - Extracts window ID from context - Cancels any existing action on this window - Creates a Task for this action - Awaits task completion - Cleans up task from tracking dictionary - Tracks grow/shrink edge state in context.sidesToAdjust across calls ### Example ```swift var context = ResizeContext(window: window, screen: screen) context.setAction(to: WindowAction(.rightHalf), parent: nil) let result = try await WindowActionEngine.shared.apply(context: context) if result.success { print("Action applied, new frame:", context.getTargetFrame()) } // Can change action and apply again without recreating context context.setAction(to: WindowAction(.larger), parent: nil) let result2 = try await WindowActionEngine.shared.apply(context: context) ``` ``` -------------------------------- ### minimize() Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/window.md Minimizes the window to the dock. ```APIDOC ## minimize() ### Description Minimizes the window to the dock. ### Method Swift Function ### Throws Any error from AXUIElement performAction ``` -------------------------------- ### Get Stashed Window Visible Padding Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/stash-manager.md Retrieves the number of pixels of a stashed window that remain visible at the screen edge. This value can be configured through user defaults. ```swift var stashedWindowVisiblePadding: CGFloat { get } ``` -------------------------------- ### Filter Windows by Manipulability and Screen Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/window-utility.md Demonstrates filtering all on-screen windows to find those that can be manipulated and retrieving windows specifically on the main screen. ```swift // Get all windows except excluded let allWindows = WindowUtility.getAllOnScreenWindows() let manageable = allWindows.filter { window in WindowUtility.canManipulate(window) } // Get windows on specific screen let screen = NSScreen.main! let windowsOnMain = WindowUtility.getWindowList(for: screen) ``` -------------------------------- ### Get Window from CGWindowID Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/window-utility.md Retrieves a Window object using its Core Graphics window identifier. Returns nil if the window ID does not correspond to a valid, accessible window. ```swift static func getWindowFromCGWindowID(_ windowID: CGWindowID) -> Window? ``` -------------------------------- ### Window Action Engine API Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/MANIFEST.txt Serves as the unified entry point for action execution, handling focus navigation and quick actions. ```APIDOC ## window-action-engine.md ### Description The unified entry point for executing window actions, managing focus navigation and handling quick actions. ### Topics Covered - Unified action execution entry point - Focus navigation - Quick actions handling ``` -------------------------------- ### Get Window Under Cursor Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/window-utility.md Returns the window located at the current mouse cursor position. Returns nil if no window is found at the cursor's location or if an error occurs. ```swift static func getWindowUnderCursor() -> Window? if let cursorWindow = WindowUtility.getWindowUnderCursor() { print("Window under cursor: \(cursorWindow.title ?? \"Unknown\")") } ``` -------------------------------- ### Get Raw Accessibility Permission Status Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/accessibility-manager.md A private method to determine if the app currently has accessibility permissions by checking AXIsProcessTrusted(). Use the `isGranted` property for the current state. ```swift private static func getStatus() -> Bool ``` -------------------------------- ### getWindowList(for:) Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/window-utility.md Retrieves a list of all visible windows present on a specified screen. If no screen is provided (nil), it queries all screens. The windows are returned in order from front to back. ```APIDOC ## getWindowList(for:) ### Description Returns all visible windows on a specific screen, sorted from front to back. If `nil` is passed for the screen, it will return windows from all screens. ### Parameters #### Path Parameters - **screen** (NSScreen?) - Optional - Screen to query (nil = all screens) ### Returns `[Window]` — Windows on screen, sorted front to back ``` -------------------------------- ### Enable Automatic Updates Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/updater.md Enables automatic updates by setting the `automaticallyUpdate` default to true. When enabled, the updater will automatically download and install updates when the application is not active and all windows are hidden. ```swift Defaults[.automaticallyUpdate] = true ``` -------------------------------- ### Initialize ResizeContext Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/resize-context.md Creates a new ResizeContext instance with optional initialization parameters for window manipulation. ```swift init( window: Window? = nil, initialFrame: CGRect? = nil, screen: NSScreen? = nil, bounds: CGRect? = nil, padding: PaddingConfiguration? = nil, action: WindowAction = .init(.noSelection), parentAction: WindowAction? = nil, initialMousePosition: CGPoint = .zero ) ``` -------------------------------- ### stash(window:to:animated:) Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/stash-manager.md Stashes a window, hiding it at a screen edge with a peek indicator. It calculates positions, detects overlaps, animates if configured, updates the store, and starts monitoring. ```APIDOC ## stash(window:to:animated:) ### Description Stashes a window (hides it at a screen edge with peek indicator). ### Parameters #### Path Parameters - **window** (Window) - Required - Window to stash - **direction** (StashDirection) - Required - Edge to stash to (.left, .right, .top, .bottom) - **animated** (Bool) - Required - Whether to animate the stash transition ### Behavior - Calculates target stashed frame at specified edge - Detects overlapping stashed windows on same edge and adjusts position - Animates if configured and animated=true - Updates stash store - Starts mouse movement monitoring **Related:** `StashDirection` — Specifies which screen edge to stash to ``` -------------------------------- ### Stash Window Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/stash-manager.md Stashes a window, hiding it at a screen edge with a peek indicator. Calculates target frame, detects overlaps, animates if configured, updates store, and starts monitoring. ```swift func stash(window: Window, to direction: StashDirection, animated: Bool) async ``` -------------------------------- ### WindowActionEngine Singleton Instance Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/window-action-engine.md Provides the singleton instance of the WindowActionEngine. This is the primary way to access the engine's functionality. ```swift static let shared = WindowActionEngine() ``` -------------------------------- ### Bring Window to Front Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/window.md Brings the window to the foreground and makes it the key (focused) window. This ensures the window is active and interactive. ```swift func makeKeyAndOrderFront() throws ``` -------------------------------- ### Add Custom Keybind for Right Half Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/configuration.md Example of adding a custom keybind to trigger the right half window action. This involves defining a WindowAction and appending it to the existing keybinds. ```swift // Add custom keybind for right half let rightHalf = WindowAction(.rightHalf, keybind: [.kVK_ANSI_Right]) var keybinds = Defaults[.keybinds] keybinds.append(rightHalf) Defaults[.keybinds] = keybinds ``` -------------------------------- ### Window(element:pid:nsRunningApplication:) Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/window.md Creates a Window object from an accessibility element. It can optionally take a process ID and a running application instance, fetching them from the element if not provided. This constructor includes error handling for specific window types and states. ```APIDOC ## Window(element:pid:nsRunningApplication:) ### Description Creates a Window from an accessibility element. It can optionally fetch the process ID and running application instance if not provided. ### Parameters #### Path Parameters - **element** (AXUIElement) - Required - Accessibility element representing a window - **pid** (pid_t?) - Optional - Process ID (fetched from element if nil) - **nsRunningApplication** (NSRunningApplication?) - Optional - Running app instance (created if nil) ### Throws - **WindowError.sheetWindow**: Element is a sheet window - **WindowError.blockedBundleID**: App is in blocked list (PIP, widgets, etc.) - **WindowError.cannotGetWindow**: Could not get window from app - **WindowError.invalidWindowLevel**: Window level outside manageable range ### Example ```swift let app = AXUIElementCreateApplication(pid) if let window: AXUIElement = try app.getValue(.focusedWindow) { let windowObj = try Window(element: window, pid: pid) } ``` ``` -------------------------------- ### Get All On-Screen Windows Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/window-utility.md Returns an array of all visible windows currently displayed on the screen. This method excludes system windows and windows that are invisible or outside the manageable level range. ```swift static func getAllOnScreenWindows() -> [Window] ``` -------------------------------- ### Swift: Using Derived Context for Undo Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/resize-context.md Demonstrates how to create a derived context for undo operations and then retrieve the target frame for that undo context. This allows for simulating previous states or actions. ```swift let undoContext = currentContext.derivedContext( action: recordedAction, bounds: currentContext.bounds ) let undoFrame = undoContext.getTargetFrame() ``` -------------------------------- ### Monitor Accessibility Permission Changes Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/README.md Continuously monitors the status of accessibility permissions and starts or stops window management features accordingly. This ensures the application behaves correctly when permissions change. ```swift Task { for await isGranted in AccessibilityManager.shared.stream(initial: true) { if isGranted { // Start window management LoopManager.shared.start() } else { // Disable features LoopManager.shared.shutdown() } } } ``` -------------------------------- ### Apply Window Action (Context-Tracked) Source: https://github.com/mrkai77/loop/blob/develop/_autodocs/api-reference/window-action-engine.md This method applies a window action with explicit resize context tracking, suitable for Loop operations. Ensure the context is updated before calling. It handles window ID extraction, action cancellation, task creation, and cleanup, while tracking edge states across calls. ```swift @concurrent func apply(context: ResizeContext) async throws -> Result ``` ```swift var context = ResizeContext(window: window, screen: screen) context.setAction(to: WindowAction(.rightHalf), parent: nil) let result = try await WindowActionEngine.shared.apply(context: context) if result.success { print("Action applied, new frame:", context.getTargetFrame()) } // Can change action and apply again without recreating context context.setAction(to: WindowAction(.larger), parent: nil) let result2 = try await WindowActionEngine.shared.apply(context: context) ```