Skip to content

Commit

Permalink
fix: load app badges asynchronously to avoid system lag (closes #563)
Browse files Browse the repository at this point in the history
  • Loading branch information
lwouis committed Sep 8, 2020
1 parent 4fea943 commit 29eff03
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 22 deletions.
37 changes: 27 additions & 10 deletions src/logic/Applications.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
3 changes: 1 addition & 2 deletions src/logic/Windows.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
2 changes: 2 additions & 0 deletions src/ui/App.swift
Original file line number Diff line number Diff line change
Expand Up @@ -264,5 +264,7 @@ class App: AppCenterApplication, NSApplicationDelegate {
thumbnailsPanel.show()
guard appIsBeingUsed else { return }
Windows.refreshThumbnailsAsync(screen)
guard appIsBeingUsed else { return }
Applications.refreshBadges()
}
}
24 changes: 14 additions & 10 deletions src/ui/main-window/ThumbnailView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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()
Expand Down

0 comments on commit 29eff03

Please sign in to comment.