diff --git a/src/logic/Applications.swift b/src/logic/Applications.swift index 8328db25..ce8da858 100644 --- a/src/logic/Applications.swift +++ b/src/logic/Applications.swift @@ -66,21 +66,38 @@ class Applications { } static func refreshBadges() { - let group = DispatchGroup() - retryAxCallUntilTimeout(group) { - if let dockPid = (Applications.list.first { $0.runningApplication.bundleIdentifier == "com.apple.dock" }?.pid), + if !App.app.appIsBeingUsed || Preferences.hideAppBadges { return } + retryAxCallUntilTimeout { + if let dockPid = (list.first { $0.runningApplication.bundleIdentifier == "com.apple.dock" }?.pid), let axList = (try AXUIElementCreateApplication(dockPid).children()?.first { try $0.role() == "AXList" }), let axAppDockItem = (try axList.children()?.filter { try $0.subrole() == "AXApplicationDockItem" && ($0.appIsRunning() ?? false) }) { - try Applications.list.forEach { app in - if app.runningApplication.activationPolicy == .regular, - let bundleId = app.runningApplication.bundleIdentifier, - let url = NSWorkspace.shared.urlForApplication(withBundleIdentifier: bundleId) { - app.dockLabel = try axAppDockItem.first { try $0.attribute(kAXURLAttribute, URL.self) == url }?.attribute(kAXStatusLabelAttribute, String.self) - } + let axAppDockItemUrlAndLabel = try axAppDockItem.map { try ($0.attribute(kAXURLAttribute, URL.self), $0.attribute(kAXStatusLabelAttribute, String.self)) } + DispatchQueue.main.async { + refreshBadges_(axAppDockItemUrlAndLabel) + } + } + } + } + + static func refreshBadges_(_ items: [(URL?, String?)], _ currentIndex: Int = 0) { + Windows.list.enumerated().forEach { (i, window) in + let view = ThumbnailsView.recycledViews[i] + if let app = (Applications.list.first { window.application.pid == $0.pid }) { + if App.app.appIsBeingUsed, + app.runningApplication.activationPolicy == .regular, + let bundleId = app.runningApplication.bundleIdentifier, + let url = NSWorkspace.shared.urlForApplication(withBundleIdentifier: bundleId), + let matchingItem = (items.first { $0.0 == url }), + let label = matchingItem.1, + let labelInt = Int(label) { + app.dockLabel = label + view.updateDockLabelIcon(labelInt) + } else { + app.dockLabel = nil + assignIfDifferent(&view.dockLabelIcon.isHidden, true) } } } - _ = group.wait(wallTimeout: .now() + .seconds(1)) } private static func isActualApplication(_ app: NSRunningApplication) -> Bool { diff --git a/src/logic/Windows.swift b/src/logic/Windows.swift index af1f125b..7e5368e9 100644 --- a/src/logic/Windows.swift +++ b/src/logic/Windows.swift @@ -153,8 +153,7 @@ class Windows { } static func refreshThumbnailsAsync(_ screen: NSScreen, _ currentIndex: Int = criticalFirstThumbnails) { - guard App.app.appIsBeingUsed else { return } - if Preferences.hideThumbnails { return } + if !App.app.appIsBeingUsed || Preferences.hideThumbnails { return } BackgroundWork.mainQueueConcurrentWorkQueue.async { if currentIndex < list.count { let window = list[currentIndex] diff --git a/src/ui/App.swift b/src/ui/App.swift index 7d62aa3c..c75d2014 100644 --- a/src/ui/App.swift +++ b/src/ui/App.swift @@ -264,5 +264,7 @@ class App: AppCenterApplication, NSApplicationDelegate { thumbnailsPanel.show() guard appIsBeingUsed else { return } Windows.refreshThumbnailsAsync(screen) + guard appIsBeingUsed else { return } + Applications.refreshBadges() } } diff --git a/src/ui/main-window/ThumbnailView.swift b/src/ui/main-window/ThumbnailView.swift index 906cf727..d28187cd 100644 --- a/src/ui/main-window/ThumbnailView.swift +++ b/src/ui/main-window/ThumbnailView.swift @@ -135,16 +135,7 @@ class ThumbnailView: NSStackView { spaceIcon.setNumber(element.spaceIndex, false) } } - assignIfDifferent(&dockLabelIcon.isHidden, element.dockLabel == nil || Preferences.hideAppBadges || Preferences.iconSize == 0) - if !dockLabelIcon.isHidden, let dockLabel = element.dockLabel { - let view = dockLabelIcon.subviews[1] as! ThumbnailFontIconView - if dockLabel > 30 { - view.setFilledStar() - } else { - view.setNumber(dockLabel, true) - } - dockLabelIcon.setFrameOrigin(NSPoint(x: appIcon.frame.maxX - dockLabelIcon.fittingSize.width - 1, y: appIcon.frame.maxY - dockLabelIcon.fittingSize.height + 4)) - } + updateDockLabelIcon(element.dockLabel) assignIfDifferent(&frame.size.width, max((Preferences.hideThumbnails ? hStackView.fittingSize.width : thumbnail.frame.size.width) + Preferences.intraCellPadding * 2, ThumbnailView.widthMin(screen)).rounded()) assignIfDifferent(&frame.size.height, newHeight) let fontIconWidth = CGFloat([fullscreenIcon, minimizedIcon, hiddenIcon, spaceIcon].filter { !$0.isHidden }.count) * (Preferences.fontHeight + Preferences.intraCellPadding) @@ -170,6 +161,19 @@ class ThumbnailView: NSStackView { } } + func updateDockLabelIcon(_ dockLabel: Int?) { + assignIfDifferent(&dockLabelIcon.isHidden, dockLabel == nil || Preferences.hideAppBadges || Preferences.iconSize == 0) + if !dockLabelIcon.isHidden, let dockLabel = dockLabel { + let view = dockLabelIcon.subviews[1] as! ThumbnailFontIconView + if dockLabel > 30 { + view.setFilledStar() + } else { + view.setNumber(dockLabel, true) + } + dockLabelIcon.setFrameOrigin(NSPoint(x: appIcon.frame.maxX - dockLabelIcon.fittingSize.width - 1, y: appIcon.frame.maxY - dockLabelIcon.fittingSize.height + 4)) + } + } + private func observeDragAndDrop() { // NSImageView instances are registered to drag-and-drop by default thumbnail.unregisterDraggedTypes()