fix: load app badges asynchronously to avoid system lag (closes #563)
This commit is contained in:
1 parent
4fea9431cd
commit
29eff03e70
4 files changed
+44
-22
No files matched your search
@@ -66,21 +66,38 @@ class Applications {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static func refreshBadges() {
|
static func refreshBadges() {
|
||||||
let group = DispatchGroup()
|
if !App.app.appIsBeingUsed || Preferences.hideAppBadges { return }
|
||||||
retryAxCallUntilTimeout(group) {
|
retryAxCallUntilTimeout {
|
||||||
if let dockPid = (Applications.list.first { $0.runningApplication.bundleIdentifier == "com.apple.dock" }?.pid),
|
if let dockPid = (list.first { $0.runningApplication.bundleIdentifier == "com.apple.dock" }?.pid),
|
||||||
let axList = (try AXUIElementCreateApplication(dockPid).children()?.first { try $0.role() == "AXList" }),
|
let axList = (try AXUIElementCreateApplication(dockPid).children()?.first { try $0.role() == "AXList" }),
|
||||||
let axAppDockItem = (try axList.children()?.filter { try $0.subrole() == "AXApplicationDockItem" && ($0.appIsRunning() ?? false) }) {
|
let axAppDockItem = (try axList.children()?.filter { try $0.subrole() == "AXApplicationDockItem" && ($0.appIsRunning() ?? false) }) {
|
||||||
try Applications.list.forEach { app in
|
let axAppDockItemUrlAndLabel = try axAppDockItem.map { try ($0.attribute(kAXURLAttribute, URL.self), $0.attribute(kAXStatusLabelAttribute, String.self)) }
|
||||||
if app.runningApplication.activationPolicy == .regular,
|
DispatchQueue.main.async {
|
||||||
let bundleId = app.runningApplication.bundleIdentifier,
|
refreshBadges_(axAppDockItemUrlAndLabel)
|
||||||
let url = NSWorkspace.shared.urlForApplication(withBundleIdentifier: bundleId) {
|
}
|
||||||
app.dockLabel = try axAppDockItem.first { try $0.attribute(kAXURLAttribute, URL.self) == url }?.attribute(kAXStatusLabelAttribute, String.self)
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
private static func isActualApplication(_ app: NSRunningApplication) -> Bool {
|
||||||
|
|||||||
@@ -153,8 +153,7 @@ class Windows {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static func refreshThumbnailsAsync(_ screen: NSScreen, _ currentIndex: Int = criticalFirstThumbnails) {
|
static func refreshThumbnailsAsync(_ screen: NSScreen, _ currentIndex: Int = criticalFirstThumbnails) {
|
||||||
guard App.app.appIsBeingUsed else { return }
|
if !App.app.appIsBeingUsed || Preferences.hideThumbnails { return }
|
||||||
if Preferences.hideThumbnails { return }
|
|
||||||
BackgroundWork.mainQueueConcurrentWorkQueue.async {
|
BackgroundWork.mainQueueConcurrentWorkQueue.async {
|
||||||
if currentIndex < list.count {
|
if currentIndex < list.count {
|
||||||
let window = list[currentIndex]
|
let window = list[currentIndex]
|
||||||
|
|||||||
@@ -264,5 +264,7 @@ class App: AppCenterApplication, NSApplicationDelegate {
|
|||||||
thumbnailsPanel.show()
|
thumbnailsPanel.show()
|
||||||
guard appIsBeingUsed else { return }
|
guard appIsBeingUsed else { return }
|
||||||
Windows.refreshThumbnailsAsync(screen)
|
Windows.refreshThumbnailsAsync(screen)
|
||||||
|
guard appIsBeingUsed else { return }
|
||||||
|
Applications.refreshBadges()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -135,16 +135,7 @@ class ThumbnailView: NSStackView {
|
|||||||
spaceIcon.setNumber(element.spaceIndex, false)
|
spaceIcon.setNumber(element.spaceIndex, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assignIfDifferent(&dockLabelIcon.isHidden, element.dockLabel == nil || Preferences.hideAppBadges || Preferences.iconSize == 0)
|
updateDockLabelIcon(element.dockLabel)
|
||||||
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))
|
|
||||||
}
|
|
||||||
assignIfDifferent(&frame.size.width, max((Preferences.hideThumbnails ? hStackView.fittingSize.width : thumbnail.frame.size.width) + Preferences.intraCellPadding * 2, ThumbnailView.widthMin(screen)).rounded())
|
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)
|
assignIfDifferent(&frame.size.height, newHeight)
|
||||||
let fontIconWidth = CGFloat([fullscreenIcon, minimizedIcon, hiddenIcon, spaceIcon].filter { !$0.isHidden }.count) * (Preferences.fontHeight + Preferences.intraCellPadding)
|
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() {
|
private func observeDragAndDrop() {
|
||||||
// NSImageView instances are registered to drag-and-drop by default
|
// NSImageView instances are registered to drag-and-drop by default
|
||||||
thumbnail.unregisterDraggedTypes()
|
thumbnail.unregisterDraggedTypes()
|
||||||
|
|||||||
Reference in new issue
Block a user