Skip to content

Commit

Permalink
feat: improve thumbnails performance (closes #4)
Browse files Browse the repository at this point in the history
  • Loading branch information
Louis Pontoise committed Aug 18, 2019
1 parent 2fa3f24 commit 509e5e0
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 37 deletions.
44 changes: 30 additions & 14 deletions alt-tab-swindler/Application.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Foundation

let cellBorderWidth: CGFloat = 5
let thumbnailHeight: CGFloat = 250
let thumbnailMaxWidth = 400
let thumbnailMaxWidth: CGFloat = 400
let thumbnailEstimatedWidth: CGFloat = 140 + cellBorderWidth * 2
let textHeight: CGFloat = 20
let cellHeight = thumbnailHeight + textHeight + cellBorderWidth * 2
Expand Down Expand Up @@ -85,6 +85,7 @@ class Application: NSApplication, NSApplicationDelegate, NSWindowDelegate, NSCol
var openWindows: [OpenWindow] = []
var workItems: [DispatchWorkItem] = []
var isFirstSummon: Bool = true
var appIsBeingUsed: Bool = false

func applicationDidFinishLaunching(_ aNotification: Notification) {
ensureAccessibilityCheckboxIsChecked()
Expand All @@ -104,6 +105,12 @@ class Application: NSApplication, NSApplicationDelegate, NSWindowDelegate, NSCol
listenToGlobalKeyboardEvents(delegate: self)
}

func applicationDidBecomeActive(_ notification: Notification) {
if (!self.appIsBeingUsed) {
self.focusSelectedWindow()
}
}

func makeCollectionView() {
let layout = CollectionViewLeftFlowLayout()
layout.estimatedItemSize = NSSize(width: thumbnailEstimatedWidth, height: thumbnailHeight)
Expand Down Expand Up @@ -194,7 +201,8 @@ class Application: NSApplication, NSApplicationDelegate, NSWindowDelegate, NSCol
}

func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> NSSize {
return NSSize(width: thumbnails[indexPath.item].size.width + cellBorderWidth * 2, height: cellHeight)
let (width, height) = computeDownscaledSize(thumbnails[indexPath.item])
return NSSize(width: CGFloat(width) + cellBorderWidth * 2, height: CGFloat(height) + textHeight + cellBorderWidth * 2)
}

func cellWithStep(_ step: Int) -> Int {
Expand All @@ -215,29 +223,34 @@ class Application: NSApplication, NSApplicationDelegate, NSWindowDelegate, NSCol
self.showWindow()
}
workItems.append(workItem)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.200, execute: workItem)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2, execute: workItem)
} else {
highlightThumbnail(step)
}
}

private func showWindow() {
func showWindow() {
self.window!.makeKeyAndOrderFront(nil)
NSRunningApplication.current.activate(options: [.activateIgnoringOtherApps, .activateAllWindows])
}

func keyUpAlt() {
debugPrint("alt up")
if NSRunningApplication.current.isActive {
isFirstSummon = true
workItems.forEach({ $0.cancel() })
workItems.removeAll()
func focusSelectedWindow() {
workItems.forEach({ $0.cancel() })
workItems.removeAll()
if openWindows.count > selectedOpenWindow {
openWindows[selectedOpenWindow].focus()
}
}

func keyDownAlt() {
debugPrint("alt down")
computeOpenWindows()
selectedOpenWindow = 0
}

func keyDownAltTab() {
debugPrint("alt+tab down")
appIsBeingUsed = true
selectOtherCell(1)
}

Expand All @@ -246,9 +259,12 @@ class Application: NSApplication, NSApplicationDelegate, NSWindowDelegate, NSCol
selectOtherCell(-1)
}

func keyDownAlt() {
debugPrint("alt down")
computeOpenWindows()
selectedOpenWindow = 0
func keyUpAlt() {
debugPrint("alt up")
if appIsBeingUsed {
focusSelectedWindow()
}
appIsBeingUsed = false
isFirstSummon = true
}
}
33 changes: 10 additions & 23 deletions alt-tab-swindler/WindowManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,31 +22,18 @@ class OpenWindow {

func computeWindowThumbnail(_ cgId: CGWindowID) -> NSImage {
let windowImage = CGWindowListCreateImage(.null, .optionIncludingWindow, cgId, [.boundsIgnoreFraming, .bestResolution])
let imageRatio = CGFloat(windowImage!.width) / CGFloat(windowImage!.height)
let thumbnailWidth = Int(floor(thumbnailHeight * imageRatio))
let image = NSImage(cgImage: windowImage!, size: NSSize(width: windowImage!.width, height: windowImage!.height))
if (thumbnailWidth <= thumbnailMaxWidth) {
return resize(image, thumbnailWidth, Int(thumbnailHeight))
} else {
return resize(image, thumbnailMaxWidth, Int(floor(CGFloat(thumbnailMaxWidth) / imageRatio)))
}
return image
}

func resize(_ image: NSImage, _ w: Int, _ h: Int) -> NSImage {
let destSize = NSMakeSize(CGFloat(w), CGFloat(h))
let newImage = NSImage(size: destSize)
newImage.lockFocus()
image.draw(
in: NSMakeRect(0, 0, destSize.width, destSize.height),
from: NSMakeRect(0, 0, image.size.width, image.size.height),
operation: NSCompositingOperation.copy,
fraction: CGFloat(1),
respectFlipped: true,
hints: [NSImageRep.HintKey.interpolation: NSImageInterpolation.high.rawValue]
)
newImage.unlockFocus()
newImage.size = destSize
return NSImage(data: newImage.tiffRepresentation!)!
func computeDownscaledSize(_ image: NSImage) -> (Int, Int) {
let imageRatio = image.size.width / image.size.height
let thumbnailWidth = Int(floor(thumbnailHeight * imageRatio))
if (thumbnailWidth <= Int(thumbnailMaxWidth)) {
return (thumbnailWidth, Int(thumbnailHeight))
} else {
return (Int(thumbnailMaxWidth), Int(floor(thumbnailMaxWidth / imageRatio)))
}
}

func cgMakeshiftId(_ window: NSDictionary) -> (String, pid_t, CGWindowID, String) {
Expand Down Expand Up @@ -99,7 +86,7 @@ func AXUIElementCopyAttributeValue<T>(_ element: AXUIElement, _ attribute: Strin
}

func AXValueGetValue<T>(_ element: AXUIElement, _ attribute: String, _ target: T, _ type: AXValueType) -> T? {
if let a = AXUIElementCopyAttributeValue(element, attribute, AXValue.self) {
if let a = AXUIElementCopyAttributeValue(element, attribute, AXValue.self) {
var value = target
AXValueGetValue(a, type, &value)
return value
Expand Down

0 comments on commit 509e5e0

Please sign in to comment.