diff --git a/lib/osx/advanced-scene-switcher-osx.mm b/lib/osx/advanced-scene-switcher-osx.mm index 7fb81e9a..27d5a898 100644 --- a/lib/osx/advanced-scene-switcher-osx.mm +++ b/lib/osx/advanced-scene-switcher-osx.mm @@ -6,6 +6,7 @@ #import #include #include +#include #include #include #include @@ -140,13 +141,44 @@ std::vector GetWindows(const WindowQueryOptions &options) NSArray *screens = [NSScreen screens]; CFArrayRef cfApps = CGWindowListCopyWindowInfo( - kCGWindowListOptionOnScreenOnly, kCGNullWindowID); + kCGWindowListExcludeDesktopElements, kCGNullWindowID); NSMutableArray *apps = (__bridge NSMutableArray *)cfApps; + // Pre-compute which PIDs own at least one fullscreen-sized window. + // A fullscreen app reports a small chrome/title bar window first and + // its full-size content window second; checking only the first + // window's bounds gives a false negative. + std::set fullscreenPIDs; + if (options.fullscreen) { + for (NSDictionary *app in apps) { + int layer = [[app objectForKey:@"kCGWindowLayer"] + intValue]; + if (layer != 0) { + continue; + } + for (NSScreen *screen in screens) { + if (isWindowFullscreenOnScreen(app, + screen)) { + int pid = [[app objectForKey: + @"kCGWindowOwnerPID"] + intValue]; + fullscreenPIDs.insert(pid); + break; + } + } + } + } + // Track titles already added to avoid duplicates (name + owner) std::vector seen; for (NSDictionary *app in apps) { + int layer = + [[app objectForKey:@"kCGWindowLayer"] intValue]; + if (layer != 0) { + continue; + } + std::string name = nsStringToStdString( [app objectForKey:@"kCGWindowName"]); std::string owner = nsStringToStdString( @@ -193,16 +225,11 @@ std::vector GetWindows(const WindowQueryOptions &options) } if (options.fullscreen) { - for (NSScreen *screen in screens) { - if (isWindowOriginOnScreen( - app, screen, - true) && - isWindowFullscreenOnScreen( - app, screen)) { - info.fullscreen = true; - break; - } - } + int pid = [[app objectForKey: + @"kCGWindowOwnerPID"] + intValue]; + info.fullscreen = + fullscreenPIDs.count(pid) > 0; } if (options.maximized) {