# How FluidVoice Handles Overlay Positioning Around the MacBook Notch

> Discover how FluidVoice's NotchOverlayManager intelligently positions overlays around the MacBook notch using NSScreen auxiliary areas for optimal UI presentation.

- Repository: [ALTIC/FluidVoice](https://github.com/altic-dev/FluidVoice)
- Tags: how-to-guide
- Published: 2026-07-03

---

**FluidVoice uses `NotchOverlayManager` to detect hardware notch support via `NSScreen` auxiliary areas, dynamically selecting between expanded, compact, or bottom overlay presentations based on user preferences and screen capabilities.**

The open-source macOS application FluidVoice (altic-dev/FluidVoice) positions its recording interface around the MacBook's display notch using a specialized manager that detects hardware capabilities and respects user-defined preferences. Understanding this architecture reveals how modern Swift apps can integrate with Apple's notch hardware while providing fallback options for non-notched displays.

## MacBook Notch Detection and Screen Capability

FluidVoice determines whether the current display supports a hardware notch by inspecting system-provided screen properties in [`Sources/Fluid/Services/NotchOverlayManager.swift`](https://github.com/altic-dev/FluidVoice/blob/main/Sources/Fluid/Services/NotchOverlayManager.swift). The manager evaluates the `NSScreen` auxiliary top areas that exist only on notched MacBook displays.

### Detecting Hardware Notch Support

The `supportsCompactPresentation(on:)` method checks for non-nil `auxiliaryTopLeftArea` and `auxiliaryTopRightArea` properties. These values are present exclusively on MacBook models with a display notch, allowing the app to distinguish between notched and standard screens at runtime.

```swift
private func supportsCompactPresentation(on screen: NSScreen) -> Bool {
    // A screen with a hardware notch reports non-nil auxiliaryTopLeft/Right areas.
    screen.auxiliaryTopLeftArea?.width != nil && screen.auxiliaryTopRightArea?.width != nil
}

```

## NotchOverlayManager Architecture and Positioning

The `NotchOverlayManager` class serves as the central coordinator for all overlay positioning. When a recording session begins, the `show(audioLevelPublisher:mode:)` method evaluates the current configuration and delegates to the appropriate presentation path.

### Dynamic Presentation Policy Selection

The manager selects between three distinct presentation strategies based on the return value of `supportsCompactPresentation(on:)` and the user's `notchPresentationMode` setting. This logic is encapsulated in `refreshNotchPresentationPolicy()` (lines 55-82 of [`NotchOverlayManager.swift`](https://github.com/altic-dev/FluidVoice/blob/main/NotchOverlayManager.swift)), which sets `usesCompactPresentation` to `false` for standard mode or `true` for minimal mode when notch support is detected.

```swift
// Simplified flow from lines 60-70 and 200-207
func showInternal() {
    if SettingsStore.shared.overlayPosition == .bottom {
        showBottomOverlay()
        return
    }
    
    let screen = preferredPresentationScreen()
    if supportsCompactPresentation(on: screen) {
        refreshNotchPresentationPolicy()
        // Policy determines expanded vs. compact view hierarchy
    }
}

```

### Creating the Dynamic Notch

When presenting in the notch area, the manager initializes a `DynamicNotch` from the third-party DynamicNotchKit library. It injects the appropriate SwiftUI view hierarchy based on the selected policy:

```swift
let newNotch = DynamicNotch(
    hoverBehavior: [], style: .auto
) {
    NotchExpandedView(audioPublisher: audioLevelPublisher)   // full UI
} compactLeading: {
    NotchCompactLeadingView()                               // small icon
} compactTrailing: {
    NotchCompactTrailingView(audioPublisher: audioLevelPublisher)
} compactBottom: {
    NotchCompactBottomView()
}

```

## Standard vs. Compact Notch Presentation Modes

FluidVoice offers two distinct visual presentations for the notch area, controlled via `SettingsStore.shared.notchPresentationMode`.

### Standard Expanded Presentation

When `notchPresentationMode` equals `.standard` and the screen supports a notch, the app displays the full `NotchExpandedView` defined in [`Sources/Fluid/Views/NotchContentViews.swift`](https://github.com/altic-dev/FluidVoice/blob/main/Sources/Fluid/Views/NotchContentViews.swift). This view includes the waveform visualization, prompt selector, and streaming preview, filling the width of the notch area.

### Compact Minimal Presentation

Setting `notchPresentationMode` to `.minimal` triggers a compact policy. In this mode, the manager renders only `NotchCompactLeadingView` (status icon) and `NotchCompactTrailingView` (mini waveform), minimizing menu bar obstruction while maintaining quick access to recording controls.

## Bottom Overlay Positioning Fallback

For users who prefer the interface away from the menu bar or on non-notched displays, FluidVoice provides a bottom positioning option.

### Routing to Bottom Overlay

When `SettingsStore.shared.overlayPosition` is set to `.bottom`, the `showInternal()` method routes directly to `showBottomOverlay()` (lines 200-207). This bypasses notch detection and instead utilizes [`BottomOverlayView.swift`](https://github.com/altic-dev/FluidVoice/blob/main/BottomOverlayView.swift) to render a floating bar at the bottom of the screen.

```swift
// From SettingsStore or user toggle
SettingsStore.shared.overlayPosition = .bottom

// Subsequent show() calls route here:
private func showBottomOverlay() {
    // Initializes BottomOverlayWindowController with BottomOverlayView
}

```

## Configuring Notch Settings via SettingsStore

User preferences persist through [`SettingsStore.swift`](https://github.com/altic-dev/FluidVoice/blob/main/SettingsStore.swift) in [`Sources/Fluid/Persistence/SettingsStore.swift`](https://github.com/altic-dev/FluidVoice/blob/main/Sources/Fluid/Persistence/SettingsStore.swift). The `notchPresentationMode` property bridges the Settings UI and the overlay manager.

```swift
var notchPresentationMode: NotchPresentationMode {
    get {
        guard let raw = defaults.string(forKey: Keys.notchPresentationMode),
              let mode = NotchPresentationMode(rawValue: raw) else { return .standard }
        return mode
    }
    set {
        defaults.set(newValue.rawValue, forKey: Keys.notchPresentationMode)
    }
}

```

The [`SettingsView.swift`](https://github.com/altic-dev/FluidVoice/blob/main/SettingsView.swift) file provides the Picker interface (lines 1367-1374) allowing users to toggle between "Regular notch" (`.standard`) and "Compact notch" (`.minimal`), writing the selection to `UserDefaults` via the `SettingsStore` keys.

## Summary

- **`NotchOverlayManager`** detects hardware notch support by checking `NSScreen.auxiliaryTopLeftArea` and `auxiliaryTopRightArea` in [`Sources/Fluid/Services/NotchOverlayManager.swift`](https://github.com/altic-dev/FluidVoice/blob/main/Sources/Fluid/Services/NotchOverlayManager.swift).
- **Presentation policies** include `.standard` (expanded UI with full controls), `.minimal` (compact icon and waveform), and bottom overlay positioning.
- **Dynamic selection** occurs at runtime based on the screen containing the mouse pointer, determined by `preferredPresentationScreen()`, and current `SettingsStore` values.
- **Bottom fallback** activates when `overlayPosition` is set to `.bottom`, using [`BottomOverlayView.swift`](https://github.com/altic-dev/FluidVoice/blob/main/BottomOverlayView.swift) instead of the notch overlay.
- **View hierarchy** is managed through [`NotchContentViews.swift`](https://github.com/altic-dev/FluidVoice/blob/main/NotchContentViews.swift) for notch content and `DynamicNotchKit` for the system-level notch window integration.

## Frequently Asked Questions

### How does FluidVoice detect if my MacBook has a display notch?

FluidVoice checks `NSScreen.auxiliaryTopLeftArea?.width` and `auxiliaryTopRightArea?.width` in the `supportsCompactPresentation(on:)` method within [`NotchOverlayManager.swift`](https://github.com/altic-dev/FluidVoice/blob/main/NotchOverlayManager.swift). These properties return non-nil values only on MacBook models with a hardware notch, allowing the app to adapt its UI dynamically based on actual display capabilities.

### What is the difference between standard and compact notch presentation?

**Standard** mode displays the full `NotchExpandedView` with the waveform, prompt selector, and streaming preview filling the notch width. **Compact** mode (`.minimal`) renders only `NotchCompactLeadingView` and `NotchCompactTrailingView`, showing a small status icon and mini waveform that minimize obstruction of the menu bar while keeping recording controls accessible.

### Can I move the overlay away from the notch to the bottom of the screen?

Yes. Setting `SettingsStore.shared.overlayPosition = .bottom` causes `NotchOverlayManager` to route calls to `showBottomOverlay()` instead of the notch overlay. This utilizes [`BottomOverlayView.swift`](https://github.com/altic-dev/FluidVoice/blob/main/BottomOverlayView.swift) to display the interface as a floating bar at the bottom of the screen, useful for non-notched displays or user preference.

### Which file controls the overlay positioning logic?

The primary logic resides in [`Sources/Fluid/Services/NotchOverlayManager.swift`](https://github.com/altic-dev/FluidVoice/blob/main/Sources/Fluid/Services/NotchOverlayManager.swift), which coordinates between [`SettingsStore.swift`](https://github.com/altic-dev/FluidVoice/blob/main/SettingsStore.swift) (user preferences), the DynamicNotchKit library (notch window rendering), and the view files in `Sources/Fluid/Views/` including [`NotchContentViews.swift`](https://github.com/altic-dev/FluidVoice/blob/main/NotchContentViews.swift) and [`BottomOverlayView.swift`](https://github.com/altic-dev/FluidVoice/blob/main/BottomOverlayView.swift).