Skip to content

Commit eedfd1b

Browse files
authored
Merge pull request #305 from altic-dev/212-screen-based-overlay
Fix overlay screen selection
2 parents a57a197 + 28344ba commit eedfd1b

3 files changed

Lines changed: 32 additions & 7 deletions

File tree

Sources/Fluid/Services/NotchOverlayManager.swift

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ final class NotchOverlayManager {
160160

161161
// Start monitoring active app changes (updates icon in real-time)
162162
ActiveAppMonitor.shared.startMonitoring()
163+
let targetScreen = OverlayScreenResolver.screenForCurrentPointer()
163164

164165
// Route to bottom overlay if user preference is set
165166
if SettingsStore.shared.overlayPosition == .bottom {
@@ -168,7 +169,7 @@ final class NotchOverlayManager {
168169
}
169170

170171
// Otherwise show notch overlay (original behavior)
171-
self.showNotchOverlay(audioLevelPublisher: audioLevelPublisher, mode: mode)
172+
self.showNotchOverlay(audioLevelPublisher: audioLevelPublisher, mode: mode, screen: targetScreen)
172173
}
173174

174175
/// Show bottom overlay (alternative to notch)
@@ -186,7 +187,7 @@ final class NotchOverlayManager {
186187
}
187188

188189
/// Show notch overlay (original behavior)
189-
private func showNotchOverlay(audioLevelPublisher: AnyPublisher<CGFloat, Never>, mode: OverlayMode) {
190+
private func showNotchOverlay(audioLevelPublisher: AnyPublisher<CGFloat, Never>, mode: OverlayMode, screen: NSScreen?) {
190191
// Hide bottom overlay if it was visible
191192
if self.isBottomOverlayVisible {
192193
BottomOverlayWindowController.shared.hide()
@@ -221,7 +222,11 @@ final class NotchOverlayManager {
221222

222223
// Show in expanded state
223224
Task { [weak self] in
224-
await newNotch.expand()
225+
if let screen {
226+
await newNotch.expand(on: screen)
227+
} else {
228+
await newNotch.expand()
229+
}
225230
// Only update state if we're still the active generation
226231
guard let self = self, self.generation == currentGeneration else { return }
227232
self.state = .visible
@@ -403,7 +408,11 @@ final class NotchOverlayManager {
403408

404409
self.commandOutputNotch = newNotch
405410

406-
await newNotch.expand()
411+
if let screen = OverlayScreenResolver.screenForCurrentPointer() {
412+
await newNotch.expand(on: screen)
413+
} else {
414+
await newNotch.expand()
415+
}
407416

408417
guard self.commandOutputGeneration == currentGeneration else { return }
409418
self.commandOutputState = .visible
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//
2+
// OverlayScreenResolver.swift
3+
// Fluid
4+
//
5+
6+
import AppKit
7+
8+
enum OverlayScreenResolver {
9+
static func screenForCurrentPointer() -> NSScreen? {
10+
let location = NSEvent.mouseLocation
11+
return NSScreen.screens.first { screen in
12+
screen.frame.contains(location)
13+
} ?? NSScreen.main ?? NSScreen.screens.first
14+
}
15+
}

Sources/Fluid/Views/BottomOverlayView.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ final class BottomOverlayWindowController {
3333
private var pendingResizeWorkItem: DispatchWorkItem?
3434
private var localMouseDownMonitor: Any?
3535
private var globalMouseDownMonitor: Any?
36+
private var targetScreen: NSScreen?
3637

3738
private init() {
3839
NotificationCenter.default.addObserver(forName: NSNotification.Name("OverlayOffsetChanged"), object: nil, queue: .main) { [weak self] _ in
@@ -78,7 +79,7 @@ final class BottomOverlayWindowController {
7879
self.createWindow()
7980
}
8081

81-
// Position at bottom center of main screen
82+
self.targetScreen = OverlayScreenResolver.screenForCurrentPointer()
8283
self.positionWindow()
8384

8485
// Show with animation
@@ -98,6 +99,7 @@ final class BottomOverlayWindowController {
9899
self.audioSubscription = nil
99100
self.pendingResizeWorkItem?.cancel()
100101
self.pendingResizeWorkItem = nil
102+
self.targetScreen = nil
101103
self.removeMouseDownMonitors()
102104
BottomOverlayPromptMenuController.shared.hide()
103105
BottomOverlayModeMenuController.shared.hide()
@@ -247,8 +249,7 @@ final class BottomOverlayWindowController {
247249
// Safe check for window and screen availability
248250
guard let window = window else { return }
249251

250-
// Use the screen that contains the window, or fallback to the main screen
251-
let screen = window.screen ?? NSScreen.main
252+
let screen = self.targetScreen ?? window.screen ?? OverlayScreenResolver.screenForCurrentPointer()
252253
guard let screen = screen else { return }
253254

254255
let fullFrame = screen.frame

0 commit comments

Comments
 (0)