feat: display quickly even with many open windows (closes #171)
BREAKING CHANGE: the window thumbnails are now updated *after* the UI is shown. AltTab will first display its window, with the first 3 thumbnails up-to-date, then asynchronously update the rest of the thumbnails one-by-one. This improves the experience of users with lots of windows open.
This commit is contained in:
1 parent
2bc09e64b2
commit
da16a0b8f9
4 files changed
+34
-5
No files matched your search
@@ -41,7 +41,7 @@ extension NSView {
|
||||
}
|
||||
}
|
||||
|
||||
extension Array {
|
||||
extension Collection {
|
||||
// forEach with each iteration run concurrently on the global queue
|
||||
func forEachAsync(fn: @escaping (Element) -> Void) {
|
||||
let group = DispatchGroup()
|
||||
|
||||
@@ -42,6 +42,7 @@ class Window {
|
||||
self.position = position
|
||||
self.title = bestEffortTitle(axTitle)
|
||||
self.isTabbed = false
|
||||
refreshThumbnail()
|
||||
debugPrint("Adding window", cgWindowId, title ?? "nil", application.runningApplication.bundleIdentifier ?? "nil")
|
||||
observeEvents()
|
||||
}
|
||||
|
||||
+27
-1
@@ -5,6 +5,8 @@ class Windows {
|
||||
static var list = [Window]()
|
||||
static var previousFocusedWindowIndex = Int(0)
|
||||
static var focusedWindowIndex = Int(0)
|
||||
// the first few thumbnails are the most commonly looked at; we pay special attention to them
|
||||
static let criticalFirstThumbnails = 3
|
||||
|
||||
static func updateFocusedWindowIndex(_ newIndex: Int) {
|
||||
previousFocusedWindowIndex = focusedWindowIndex
|
||||
@@ -84,11 +86,35 @@ class Windows {
|
||||
Windows.list = sortedTuples.map { $0.1 }
|
||||
}
|
||||
|
||||
static func refreshAllThumbnails() {
|
||||
static func refreshFirstFewThumbnailsSync() {
|
||||
list.filter { $0.shouldShowTheUser }
|
||||
.prefix(criticalFirstThumbnails)
|
||||
.forEachAsync { window in window.refreshThumbnail() }
|
||||
}
|
||||
|
||||
static func refreshThumbnailsAsync(_ screen: NSScreen, _ currentIndex: Int = criticalFirstThumbnails) {
|
||||
guard App.app.appIsBeingUsed else { return }
|
||||
BackgroundWork.mainQueueConcurrentWorkQueue.async {
|
||||
if currentIndex < list.count {
|
||||
let window = list[currentIndex]
|
||||
if window.shouldShowTheUser {
|
||||
window.refreshThumbnail()
|
||||
DispatchQueue.main.async {
|
||||
let view = ThumbnailsView.recycledViews[currentIndex]
|
||||
if view.thumbnail.image != window.thumbnail {
|
||||
view.thumbnail.image = window.thumbnail
|
||||
let (thumbnailWidth, thumbnailHeight) = ThumbnailView.thumbnailSize(window.thumbnail, screen)
|
||||
let thumbnailSize = NSSize(width: thumbnailWidth.rounded(), height: thumbnailHeight.rounded())
|
||||
view.thumbnail.image?.size = thumbnailSize
|
||||
view.thumbnail.frame.size = thumbnailSize
|
||||
}
|
||||
}
|
||||
}
|
||||
refreshThumbnailsAsync(screen, currentIndex + 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static func refreshWhichWindowsToShowTheUser(_ screen: NSScreen) {
|
||||
Windows.list.forEach { (window: Window) in
|
||||
refreshIfWindowShouldBeShownToTheUser(window, screen)
|
||||
|
||||
+5
-3
@@ -228,21 +228,23 @@ class App: AppCenterApplication, NSApplicationDelegate {
|
||||
Windows.updateFocusedWindowIndex(0)
|
||||
Windows.cycleFocusedWindowIndex(1)
|
||||
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Preferences.windowDisplayDelay) { () -> () in
|
||||
self.rebuildUi()
|
||||
self.rebuildUi(screen)
|
||||
}
|
||||
} else {
|
||||
cycleSelection(.leading)
|
||||
}
|
||||
}
|
||||
|
||||
func rebuildUi() {
|
||||
func rebuildUi(_ screen: NSScreen = Screen.preferred()) {
|
||||
guard appIsBeingUsed else { return }
|
||||
Windows.refreshAllThumbnails()
|
||||
Windows.refreshFirstFewThumbnailsSync()
|
||||
guard appIsBeingUsed else { return }
|
||||
Applications.refreshBadges()
|
||||
guard appIsBeingUsed else { return }
|
||||
refreshOpenUi()
|
||||
guard appIsBeingUsed else { return }
|
||||
thumbnailsPanel.show()
|
||||
guard appIsBeingUsed else { return }
|
||||
Windows.refreshThumbnailsAsync(screen)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user