diff --git a/alt-tab-macos/logic/Applications.swift b/alt-tab-macos/logic/Applications.swift index 7b570979..3f91bc44 100644 --- a/alt-tab-macos/logic/Applications.swift +++ b/alt-tab-macos/logic/Applications.swift @@ -13,11 +13,17 @@ class Applications { NSWorkspace.shared.addObserver(Applications.appsObserver, forKeyPath: "runningApplications", options: [.old, .new], context: nil) } - static func reviewRunningApplicationsWindows() { + static func addInitialRunningApplicationsWindows() { + let windows = Spaces.windowsInSpaces(Spaces.otherSpaces()).filter { window in + return Windows.list.first(where: { $0.cgWindowId == window }) == nil + } + CGSAddWindowsToSpaces(cgsMainConnectionId, windows as NSArray, [Spaces.currentSpaceId]) for app in list { guard app.runningApplication.isFinishedLaunching else { continue } app.observeNewWindows() } + Windows.sortByLevel() + CGSRemoveWindowsFromSpaces(cgsMainConnectionId, windows as NSArray, [Spaces.currentSpaceId]) } static func addRunningApplications(_ runningApps: [NSRunningApplication]) { diff --git a/alt-tab-macos/logic/Spaces.swift b/alt-tab-macos/logic/Spaces.swift index 61a7ace3..38a4c2e7 100644 --- a/alt-tab-macos/logic/Spaces.swift +++ b/alt-tab-macos/logic/Spaces.swift @@ -10,10 +10,6 @@ class Spaces { static func observeSpaceChanges() { NSWorkspace.shared.notificationCenter.addObserver(forName: NSWorkspace.activeSpaceDidChangeNotification, object: nil, queue: nil, using: { _ in updateCurrentSpace() - guard visitedSpaces[Spaces.currentSpaceId] == nil else { return } - visitedSpaces[Spaces.currentSpaceId] = true - // when visiting a space for the first time, we review windows that we could not gather before the visit, from the other space - Applications.reviewRunningApplicationsWindows() }) } @@ -23,17 +19,16 @@ class Spaces { debugPrint("current space", Spaces.currentSpaceId) } - static func updateInitialSpace() { - updateCurrentSpace() - visitedSpaces[Spaces.currentSpaceId] = true - } - static func allIdsAndIndexes() -> [(CGSSpaceID, SpaceIndex)] { return (CGSCopyManagedDisplaySpaces(cgsMainConnectionId) as! [NSDictionary]) .map { return $0["Spaces"] }.joined().enumerated() .map { (($0.element as! NSDictionary)["id64"]! as! CGSSpaceID, $0.offset + 1) } } + static func otherSpaces() -> [CGSSpaceID] { + return allIdsAndIndexes().filter { $0.0 != Spaces.currentSpaceId }.map { $0.0 } + } + static func windowsInSpaces(_ spaceIds: [CGSSpaceID]) -> [CGWindowID] { var set_tags = UInt64(0) var clear_tags = UInt64(0) diff --git a/alt-tab-macos/logic/Window.swift b/alt-tab-macos/logic/Window.swift index 07603ea6..2bca10ba 100644 --- a/alt-tab-macos/logic/Window.swift +++ b/alt-tab-macos/logic/Window.swift @@ -8,6 +8,7 @@ class Window { var icon: NSImage? var isHidden: Bool var isMinimized: Bool + var isOnAllSpaces: Bool var spaceId: CGSSpaceID? var spaceIndex: SpaceIndex? var axUiElement: AXUIElement @@ -24,6 +25,7 @@ class Window { self.isMinimized = axUiElement.isMinimized() self.spaceId = Spaces.currentSpaceId self.spaceIndex = Spaces.currentSpaceIndex + self.isOnAllSpaces = false self.title = Window.bestEffortTitle(axUiElement, cgWindowId, application) debugPrint("Adding window: " + title, application.runningApplication.bundleIdentifier, Spaces.currentSpaceId, Spaces.currentSpaceIndex) observeEvents() diff --git a/alt-tab-macos/logic/Windows.swift b/alt-tab-macos/logic/Windows.swift index 97a0b7fb..7ed1b99a 100644 --- a/alt-tab-macos/logic/Windows.swift +++ b/alt-tab-macos/logic/Windows.swift @@ -28,9 +28,16 @@ class Windows { static func updateSpaces() { let spacesMap = Spaces.allIdsAndIndexes() for window in list { - guard let spaceId = (CGSCopySpacesForWindows(cgsMainConnectionId, CGSSpaceMask.all.rawValue, [window.cgWindowId] as CFArray) as! [CGSSpaceID]).first else { continue } - window.spaceId = spaceId - window.spaceIndex = spacesMap.first { $0.0 == spaceId }!.1 + let spaceIds = CGSCopySpacesForWindows(cgsMainConnectionId, CGSSpaceMask.all.rawValue, [window.cgWindowId] as CFArray) as! [CGSSpaceID] + guard spaceIds.count > 0 else { continue } + if spaceIds.count > 1 { + window.spaceId = Spaces.currentSpaceId + window.spaceIndex = Spaces.currentSpaceIndex + window.isOnAllSpaces = true + continue + } + window.spaceId = spaceIds.first! + window.spaceIndex = spacesMap.first { $0.0 == spaceIds.first! }!.1 } } diff --git a/alt-tab-macos/ui/App.swift b/alt-tab-macos/ui/App.swift index 4f13c776..11fe8f68 100644 --- a/alt-tab-macos/ui/App.swift +++ b/alt-tab-macos/ui/App.swift @@ -27,11 +27,12 @@ class App: NSApplication, NSApplicationDelegate, NSWindowDelegate { Preferences.loadFromDiskAndUpdateValues() statusItem = StatusItem.make(self) initPreferencesDependentComponents() - Spaces.updateInitialSpace() + Spaces.updateCurrentSpace() + Spaces.updateIsSingleSpace() Applications.addInitialRunningApplications() Applications.observeRunningApplications() Spaces.observeSpaceChanges() - Windows.sortByLevel() + Applications.addInitialRunningApplicationsWindows() Keyboard.listenToGlobalEvents(self) } diff --git a/alt-tab-macos/ui/Cell.swift b/alt-tab-macos/ui/Cell.swift index 30f826cd..31e7bb5d 100644 --- a/alt-tab-macos/ui/Cell.swift +++ b/alt-tab-macos/ui/Cell.swift @@ -55,7 +55,11 @@ class Cell: NSCollectionViewItem { minimizedIcon.isHidden = !window!.isMinimized spaceIcon.isHidden = element.spaceIndex == nil || Spaces.isSingleSpace || Preferences.hideSpaceNumberLabels if !spaceIcon.isHidden { - spaceIcon.setNumber(UInt32(element.spaceIndex!)) + if element.isOnAllSpaces { + spaceIcon.setStar() + } else { + spaceIcon.setNumber(UInt32(element.spaceIndex!)) + } } let fontIconWidth = CGFloat([minimizedIcon, hiddenIcon, spaceIcon].filter { !$0.isHidden }.count) * (Preferences.fontIconSize + Preferences.interItemPadding) label.textContainer!.size.width = thumbnail.frame.width - Preferences.iconSize! - Preferences.interItemPadding - fontIconWidth diff --git a/alt-tab-macos/ui/FontIcon.swift b/alt-tab-macos/ui/FontIcon.swift index 13497fe4..be4a9e0b 100644 --- a/alt-tab-macos/ui/FontIcon.swift +++ b/alt-tab-macos/ui/FontIcon.swift @@ -7,6 +7,7 @@ class FontIcon: CellTitle { static let sfSymbolCircledDotSign = "􀍷" static let sfSymbolCircledNumber0 = "􀀸" static let sfSymbolCircledNumber10 = "􀓵" + static let sfSymbolCircledStart = "􀕬" required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") @@ -28,6 +29,10 @@ class FontIcon: CellTitle { string = String(UnicodeScalar(baseCharacter.unicodeScalars.first!.value + offset)!) } + func setStar() { + string = FontIcon.sfSymbolCircledStart + } + private func baseCharacterAndOffset(_ number: UInt32) -> (String, UInt32) { if number <= 9 { // numbers alternate between empty and full circles; we skip the full circles