From 23bbd6498f4fbd1987f198af57eb2e785f6310ad Mon Sep 17 00:00:00 2001 From: Louis Pontoise Date: Sat, 18 Sep 2021 21:59:11 +0900 Subject: [PATCH] fix: "show on active screen" could show the wrong screen (closes #1129) --- src/logic/NSScreen.swift | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/logic/NSScreen.swift b/src/logic/NSScreen.swift index f51b056e..a0c780ff 100644 --- a/src/logic/NSScreen.swift +++ b/src/logic/NSScreen.swift @@ -14,13 +14,31 @@ extension NSScreen { } static func preferred() -> NSScreen { + preferred_() ?? NSScreen.screens.first! + } + + static func preferred_() -> NSScreen? { switch Preferences.showOnScreen { - case .includingMouse: return withMouse() ?? NSScreen.main! // .main as fall-back - case .active: return NSScreen.main! // macOS bug: this will return screens[0] if the main screen shows a fullscreen app - case .includingMenubar: return NSScreen.screens.first! + case .includingMouse: return withMouse() + case .active: return NSScreen.active() + case .includingMenubar: return NSScreen.screens.first } } + // NSScreen.main docs are incorrect. It stopped returning the screen with the key window in macOS 10.9 + // see https://stackoverflow.com/a/56268826/2249756 + // There are a few cases where .main doesn't return the screen with the key window: + // * if the active screen shows a fullscreen app, it always returns screens[0] + // * if NSScreen.screensHaveSeparateSpaces == false, and key window is on another screen than screens[0], it still returns screens[0] + // we find the screen with the key window ourselves manually + static func active() -> NSScreen? { + if let app = Applications.list.first { $0.pid == NSWorkspace.shared.frontmostApplication?.processIdentifier }, + let focusedWindow = app.focusedWindow { + return NSScreen.screens.first { focusedWindow.isOnScreen($0) } + } + return nil + } + static func withMouse() -> NSScreen? { return NSScreen.screens.first { NSMouseInRect(NSEvent.mouseLocation, $0.frame, false) } }