# How the Vorssaint Utils App Switcher Captures and Displays Window Thumbnails

> Discover how the Vorssaint Utils app switcher uses ScreenCaptureKit to capture and display window thumbnails. Learn about its efficient thumbnail caching and SwiftUI rendering for a seamless user experience.

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

---

**The app switcher leverages ScreenCaptureKit to enumerate windows, stores 512‑pixel edge thumbnails in a 160 MiB LRU NSCache, and renders them through SwiftUI’s `SwitcherGridCard` with automatic fallback to application icons.**

The vorssaint-utils repository provides a macOS utility suite featuring an **App Switcher** that generates live window previews. Understanding how this component captures and displays window thumbnails requires examining its three‑tier architecture: window enumeration, bitmap caching, and SwiftUI rendering.

## The Thumbnail Pipeline Architecture

The implementation spans three core services that handle distinct stages of the preview lifecycle.

### Window Enumeration with ScreenCaptureKit

In [`Sources/Vorssaint/Services/Switcher/WindowEnumerator.swift`](https://github.com/vorssaint/vorssaint-utils/blob/main/Sources/Vorssaint/Services/Switcher/WindowEnumerator.swift), the **`WindowEnumerator`** class interfaces with **ScreenCaptureKit** to produce the list of capturable windows. It queries the system for all `SCWindow` objects, filters out non‑interactive or system‑level windows, and returns a lightweight `WindowItem` struct for each candidate. This enumeration runs whenever the switcher opens, ensuring the UI reflects the current window state.

### Thumbnail Capture and Caching

[`Sources/Vorssaint/Services/Switcher/WindowPreviewProvider.swift`](https://github.com/vorssaint/vorssaint-utils/blob/main/Sources/Vorssaint/Services/Switcher/WindowPreviewProvider.swift) contains the capture logic. For each `WindowItem`, the provider invokes **`SCWindow.captureThumbnail(maxEdge: 512)`** to generate a high‑resolution bitmap suitable for Retina displays. The resulting `CGImage` is wrapped in an `NSImage` and stored in an **`NSCache`** instance keyed by the window’s UUID string. The cache is configured with a **`totalCostLimit`** of **160 MiB**; each entry calculates its cost as `bytesPerRow × height`, and the cache automatically evicts the least‑recently‑used thumbnails when this budget is exceeded. If a window becomes unavailable or capture fails, the provider emits a nil value, signaling the UI to use a fallback.

### SwiftUI Rendering and Fallback Handling

The presentation layer lives in [`Sources/Vorssaint/UI/Switcher/SwitcherView.swift`](https://github.com/vorssaint/vorssaint-utils/blob/main/Sources/Vorssaint/UI/Switcher/SwitcherView.swift). The **`SwitcherView`** iterates over the window items, passing each to a **`SwitcherGridCard`**. This card inspects the cached thumbnail via the provider’s API; if present, it draws the image inside a rounded rectangle using layout constants defined in [`Sources/Vorssaint/Services/Switcher/SwitcherSupport.swift`](https://github.com/vorssaint/vorssaint-utils/blob/main/Sources/Vorssaint/Services/Switcher/SwitcherSupport.swift). When the cache returns no image, the card renders the window’s **application icon** instead, ensuring the grid remains visually consistent even for protected or minimized windows.

## Working with the Thumbnail Provider

Developers can interact with the thumbnail pipeline directly through the public APIs exposed in the switcher service layer.

### Manual Thumbnail Capture

To capture a thumbnail outside the standard provider flow, use ScreenCaptureKit directly:

```swift
import ScreenCaptureKit

func fetchThumbnail(for window: SCWindow) async -> NSImage? {
    guard let cgImage = await window.captureThumbnail(maxEdge: 512) else {
        return nil
    }
    return NSImage(cgImage: cgImage, size: .zero)
}

```

### Observing Thumbnail Updates

The `WindowPreviewProvider` exposes an **`onUpdate`** closure that fires whenever a new thumbnail enters the cache. Integrate this into a SwiftUI view as follows:

```swift
import Vorssaint

struct CustomSwitcher: View {
    @StateObject private var provider = WindowPreviewProvider()
    @State private var thumbnails: [UUID: NSImage] = [:]

    var body: some View {
        LazyVGrid(columns: [.adaptive(minimum: 200)]) {
            ForEach(provider.items) { item in
                SwitcherGridCard(item: item, image: thumbnails[item.id])
            }
        }
        .onAppear {
            provider.onUpdate = { windowID, image in
                thumbnails[windowID] = image
            }
            provider.startUpdating()
        }
    }
}

```

### Inspecting the Cache Directly

Access cached images using the window identifier as the key:

```swift
let key = window.id.uuidString as NSString
if let image = provider.thumbnailCache.object(forKey: key) {
    // Use cached NSImage
    imageView.image = image
}

```

## Key Source Files

- **[`Sources/Vorssaint/Services/Switcher/WindowEnumerator.swift`](https://github.com/vorssaint/vorssaint-utils/blob/main/Sources/Vorssaint/Services/Switcher/WindowEnumerator.swift)** – Defines the `WindowEnumerator` class that filters and lists `SCWindow` objects.
- **[`Sources/Vorssaint/Services/Switcher/WindowPreviewProvider.swift`](https://github.com/vorssaint/vorssaint-utils/blob/main/Sources/Vorssaint/Services/Switcher/WindowPreviewProvider.swift)** – Manages `SCWindow.captureThumbnail()` calls and the 160 MiB `NSCache` implementation.
- **[`Sources/Vorssaint/Services/Switcher/SwitcherSupport.swift`](https://github.com/vorssaint/vorssaint-utils/blob/main/Sources/Vorssaint/Services/Switcher/SwitcherSupport.swift)** – Contains layout constants including `maxThumbnailEdge` (512) and `thumbnailCacheByteLimit` (160 MiB).
- **[`Sources/Vorssaint/UI/Switcher/SwitcherView.swift`](https://github.com/vorssaint/vorssaint-utils/blob/main/Sources/Vorssaint/UI/Switcher/SwitcherView.swift)** – Implements the grid layout and `SwitcherGridCard` rendering logic with fallback icon support.

## Summary

- **WindowEnumerator** uses **ScreenCaptureKit** to enumerate live windows and produce `WindowItem` descriptors.
- **WindowPreviewProvider** captures 512‑pixel edge thumbnails via `SCWindow.captureThumbnail()` and stores them in a **160 MiB LRU NSCache** to balance visual quality with memory constraints.
- **SwitcherGridCard** renders cached thumbnails inside rounded rectangles, falling back to application icons when captures fail or windows are inaccessible.
- The pipeline is reactive; the provider’s `onUpdate` closure triggers SwiftUI view refreshes whenever new thumbnails arrive.

## Frequently Asked Questions

### How does the app switcher handle windows that cannot be captured?

When `SCWindow.captureThumbnail()` returns nil or throws an error, `WindowPreviewProvider` skips the cache update and signals the UI layer to display the window’s application icon instead. This ensures the switcher grid remains populated and usable even for protected, minimized, or full‑screen windows that ScreenCaptureKit cannot access.

### What is the maximum resolution of the window thumbnails?

The provider requests thumbnails with a **`maxEdge`** of **512 points**, which renders as 1024 pixels on Retina displays. This value is defined in [`SwitcherSupport.swift`](https://github.com/vorssaint/vorssaint-utils/blob/main/SwitcherSupport.swift) and provides sufficient detail for the grid view while keeping the per‑image memory footprint small enough to fit within the 160 MiB cache budget.

### How does the thumbnail cache prevent memory leaks?

The `NSCache` in [`WindowPreviewProvider.swift`](https://github.com/vorssaint/vorssaint-utils/blob/main/WindowPreviewProvider.swift) is initialized with a **`totalCostLimit`** of approximately **160 megabytes**. Each cached image reports its size in bytes as its cost; when the cumulative cost exceeds the limit, the cache automatically discards the least‑recently‑used entries. This LRU eviction policy ensures that long‑running sessions do not consume unbounded memory.

### Can the thumbnail provider be used independently of the switcher UI?

Yes, `WindowPreviewProvider` is designed as a standalone service. Any view controller or SwiftUI view can instantiate the class, assign a closure to `onUpdate`, and call `startUpdating()` to receive thumbnail updates without importing the full `SwitcherView` hierarchy, making it suitable for custom window managers or accessibility tools.