# How Mouse Navigation Implements Focus Follows Mouse in vorssaint-utils

> Discover how vorssaint-utils implements focus follows mouse using NSEvent and macOS Accessibility APIs. Learn about pointer settling and activation triggers for enhanced navigation.

- Repository: [vorssaint/vorssaint-utils](https://github.com/vorssaint/vorssaint-utils)
- Tags: internals
- Published: 2026-09-11

---

**Focus follows mouse in vorssaint-utils works by monitoring global mouse movement via `NSEvent`, waiting for the pointer to settle using a configurable delay timer, then activating the underlying window through macOS Accessibility APIs when specific guard conditions are met.**

The vorssaint-utils repository provides a robust macOS implementation of focus-follows-mouse (FFM), allowing windows to activate automatically when the cursor pauses over them. Unlike traditional click-to-focus models, this Swift-based utility uses a polling-based architecture with thread-safe state management and safety guards to prevent accidental focus stealing during gaming or drag operations. The implementation lives in `Sources/Vorssaint/Services/FocusFollowsMouse` and integrates deeply with the macOS Accessibility and WindowServer frameworks.


## Architectural Overview of the Focus Follows Mouse Service

The implementation splits responsibilities between two core files in `Sources/Vorssaint/Services/FocusFollowsMouse`:

- **[`FocusFollowsMouseService.swift`](https://github.com/vorssaint/vorssaint-utils/blob/main/FocusFollowsMouseService.swift)** – The runtime service that installs global mouse monitors, manages the evaluation timer, and orchestrates window activation.
- **[`FocusFollowsMouseSupport.swift`](https://github.com/vorssaint/vorssaint-utils/blob/main/FocusFollowsMouseSupport.swift)** – Pure logic helpers for delay calculations, window querying on background queues, and determining whether activation should occur.

The service follows a preference-driven lifecycle. When `syncWithPreferences()` is called—typically from [`SettingsView.swift`](https://github.com/vorssaint/vorssaint-utils/blob/main/SettingsView.swift) or during session changes—the service reads `focusFollowsMouseEnabled` and `focusFollowsMouseDelay` from `UserDefaults`. If the feature is enabled, the session is active, and the app holds Accessibility privileges (`AXIsProcessTrusted`), the service starts; otherwise it stops immediately.


## Step-by-Step Implementation Flow

### 1. Global Mouse Monitoring and State Recording

When active, the service installs a global event monitor using `NSEvent.addGlobalMonitorForEvents`:

```swift
// From FocusFollowsMouseService.swift
NSEvent.addGlobalMonitorForEvents(matching: [.mouseMoved, .mouseDragged]) { event in
    self.recordMovement(to: event.locationInWindow)
}

```

Every movement triggers `recordMovement(to:)`, which updates a shared `FocusFollowsMouseState` instance. This state object stores the latest pointer location, the current `systemUptime` timestamp, and a generation counter. Each new movement invalidates any pending evaluation by incrementing the generation, ensuring that continuous motion never triggers focus changes.


### 2. Delay-Based Settled Pointer Detection

After the first movement, `recordMovement` creates a `Timer` firing every **0.05 seconds** (50ms). This timer repeatedly calls `evaluateIfSettled()` until the pointer stabilizes:

```swift
// Timer initialization pattern from FocusFollowsMouseService.swift
Timer.scheduledTimer(withTimeInterval: 0.05, repeats: true) { timer in
    self.evaluateIfSettled()
}

```

The pointer is considered *settled* when the elapsed time since the last recorded movement exceeds the configured delay (default **250ms**, customizable via `focusFollowsMouseDelay`). This logic resides in `FocusFollowsMouseState.nextEvaluation`, which compares the current uptime against the last movement timestamp.


### 3. Safety Guards Before Activation

Before querying windows, `evaluateIfSettled()` enforces strict guard conditions defined in [`FocusFollowsMouseService.swift`](https://github.com/vorssaint/vorssaint-utils/blob/main/FocusFollowsMouseService.swift):

- **Accessibility Permission**: Verifies `AXIsProcessTrusted()` returns true.
- **No Input Held**: Checks `nothingIsHeldDown` to ensure no mouse buttons or modifier keys are pressed.
- **No Exclusions**: Validates the target is not blocked by `MouseAppExceptions.shared.excludesPointerTarget`.

If any guard fails, the evaluation aborts immediately, preventing focus theft during gaming sessions or drag-and-drop operations.


### 4. Window Querying and Accessibility Hit-Testing

Once the pointer settles and guards pass, `FocusFollowsMouseSupport.queryWindow` executes on a dedicated serial `DispatchQueue` named `queryQueue` to avoid blocking the main thread:

```swift
// Background window enumeration
queryQueue.async {
    let windows = WindowServerSupport.onScreenWindowInfo()
    // Find window containing point, filter by layer and ownership...
}

```

The query iterates through `WindowServerSupport.onScreenWindowInfo()` to find the window containing the cursor point. It filters out the app's own click-through windows and verifies the window belongs to a layer that participates in FFM (e.g., normal application windows, not menus or overlays).

The closure `target(at:processID:)` then performs a precise Accessibility hit-test:

1. Creates an application reference via `AXUIElementCreateApplication`
2. Calls `AXUIElementCopyElementAtPosition` to get the AX element at the cursor coordinates
3. Extracts the top-level window, verifies its role, and resolves its CG Window ID using `AXWindowResolver`


### 5. Activation Decision Logic

The `FocusFollowsMouseSupport.shouldActivate` method implements smart activation rules to minimize disruption:

- If the target app is already frontmost, activation only occurs when the target window differs from the currently focused window. This prevents games that capture the pointer from losing focus continuously.
- The service checks against `MouseAppExceptionSupport` definitions to exclude specific UI layers or applications (e.g., fullscreen video players).

### 6. Window Activation

When activation is approved, the service dispatches to the main thread and calls `WindowActivator.activate`, which sends an **AXRaise** request via the Accessibility API to bring the target window forward and make its application the active frontmost app.


## Key Design Patterns in vorssaint-utils

**Thread Discipline**

Mouse events arrive on the main thread, but the expensive window enumeration and Accessibility queries run on the serial `queryQueue`. This prevents the polling timer from stalling the UI during rapid mouse movements.

**Preference-Driven Lifecycle**

The `syncWithPreferences()` method reacts to changes from the Settings UI ([`SettingsView.swift`](https://github.com/vorssaint/vorssaint-utils/blob/main/SettingsView.swift)) and `SessionActivity` notifications. When the user disables the feature or the display sleeps, `resetMovement()` and `stop()` clear the state and invalidate the timer.

**Configurable Delay System**

The default 250ms delay prevents "jitter" from rapid focus switching. Users customize this via `DefaultsKey.focusFollowsMouseDelay`, and the `FocusFollowsMouseState` sanitizes timing calculations using `systemUptime` for monotonic clock accuracy.


## Enabling Focus Follows Mouse Programmatically

Below is a complete example for enabling the feature in your own client code:

```swift
import Vorssaint

// Enable in UserDefaults (normally controlled via SettingsView.swift UI)
UserDefaults.standard.set(true, forKey: DefaultsKey.focusFollowsMouseEnabled)
UserDefaults.standard.set(300, forKey: DefaultsKey.focusFollowsMouseDelay) // 300ms delay

// Verify Accessibility permission
guard AXIsProcessTrusted() else {
    print("Accessibility permission required")
    return
}

// Synchronize preferences to start the service
FocusFollowsMouseService.shared.syncWithPreferences()

```

**Result:** The service now monitors global mouse position. Moving the pointer over any window and pausing for 300ms will activate that window, provided it is not excluded and no mouse buttons are held. The service automatically stops if Accessibility permissions are revoked or if the session becomes inactive.


## Summary

- **Focus follows mouse** in vorssaint-utils uses `NSEvent.addGlobalMonitorForEvents` to track global mouse movement and a 50ms polling timer to detect settled pointer states.
- **Two-file architecture** separates concerns: [`FocusFollowsMouseService.swift`](https://github.com/vorssaint/vorssaint-utils/blob/main/FocusFollowsMouseService.swift) handles lifecycle and monitoring, while [`FocusFollowsMouseSupport.swift`](https://github.com/vorssaint/vorssaint-utils/blob/main/FocusFollowsMouseSupport.swift) manages window queries and activation logic.
- **Configurable delay** (default 250ms) prevents rapid focus switching; users customize this via `focusFollowsMouseDelay` in `UserDefaults`.
- **Strict safety guards** require Accessibility permissions, no held modifiers/buttons, and exclusion list validation before activating any window.
- **Thread-safe design** runs window queries on a dedicated `queryQueue` while keeping event monitoring on the main thread.
- **Smart activation** avoids stealing focus from already-frontmost applications unless the specific window changes, preventing disruption to games and fullscreen apps.


## Frequently Asked Questions

### How does vorssaint-utils prevent focus stealing during gaming?

The implementation checks `nothingIsHeldDown` to ensure no mouse buttons or modifier keys are pressed before activation. Additionally, `MouseAppExceptions.shared.excludesPointerTarget` allows specific applications (like games) to be excluded from focus-follows-mouse entirely. If the frontmost application is already active, the service only switches focus when the *window* changes, preventing pointer-captured games from losing focus during camera movements.

### What is the default delay for focus activation, and can it be changed?

The default delay is **250 milliseconds**, defined in the `FocusFollowsMouseState` logic. Users can adjust this via the `focusFollowsMouseDelay` UserDefaults key, typically through the Settings UI in [`SettingsView.swift`](https://github.com/vorssaint/vorssaint-utils/blob/main/SettingsView.swift). The `syncWithPreferences()` method reads this value and applies it immediately without requiring an app restart.

### Why does the service require Accessibility permissions?

Activating windows belonging to other applications requires the **Accessibility API**, specifically `AXUIElementCreateApplication` and `AXUIElementCopyElementAtPosition` for hit-testing, plus `AXRaise` for raising windows. The `evaluateIfSettled()` function explicitly checks `AXIsProcessTrusted()`; if permissions are missing, the service stops immediately to avoid console spam and failed assertions.

### Where is the window querying logic performed to avoid UI lag?

The expensive window enumeration occurs on a dedicated serial `DispatchQueue` named `queryQueue` inside `FocusFollowsMouseSupport.queryWindow`. This prevents the 50ms polling timer on the main thread from blocking the UI during the `WindowServerSupport.onScreenWindowInfo()` iteration and Accessibility element resolution.