diff --git a/src/api-wrappers/HelperExtensions.swift b/src/api-wrappers/HelperExtensions.swift index f7db63d2..c5e93a44 100644 --- a/src/api-wrappers/HelperExtensions.swift +++ b/src/api-wrappers/HelperExtensions.swift @@ -199,6 +199,17 @@ extension DispatchQoS { } } +extension NSImageView { + func setSize(_ size: NSSize) { + frame.size = size + // TODO: NSImageView does some internal magic, and ends up with constraints. We need to add our own to force its size + // We can't update .image.size because we share the image between multiple NSImageViews + // I wish there was a better way to only set the frame.size + addOrUpdateConstraint(widthAnchor, size.width) + addOrUpdateConstraint(heightAnchor, size.height) + } +} + extension NSImage { // NSImage(named) caches/reuses NSImage objects; we force separate instances of images by using copy() static func initCopy(_ name: String) -> NSImage { diff --git a/src/logic/Window.swift b/src/logic/Window.swift index 4619b57d..2d775490 100644 --- a/src/logic/Window.swift +++ b/src/logic/Window.swift @@ -7,6 +7,7 @@ class Window { var creationOrder = Int.zero var title: String! var thumbnail: NSImage? + var thumbnailFullSize: NSSize? var icon: NSImage? { get { application.icon } } var shouldShowTheUser = true var isTabbed: Bool = false @@ -98,6 +99,7 @@ class Window { func refreshThumbnail(_ screenshot: NSImage?) { thumbnail = screenshot + thumbnailFullSize = screenshot?.size if App.app.appIsBeingUsed && shouldShowTheUser { if let index = (Windows.list.firstIndex { $0.cgWindowId == cgWindowId }) { let view = ThumbnailsView.recycledViews[index] @@ -111,9 +113,9 @@ class Window { } } - func getPreview() -> NSImage? { - if let cgImage = cgWindowId?.screenshot(true) { - return NSImage.fromCgImage(cgImage) + func getPreview() -> (NSImage, NSSize)? { + if let thumbnail = thumbnail, let thumbnailFullSize = thumbnailFullSize { + return (thumbnail, thumbnailFullSize) } return nil } diff --git a/src/logic/Windows.swift b/src/logic/Windows.swift index 32b3b7c3..e30e4ebb 100644 --- a/src/logic/Windows.swift +++ b/src/logic/Windows.swift @@ -153,14 +153,14 @@ class Windows { App.app.appIsBeingUsed && App.app.thumbnailsPanel.isKeyWindow, let window = focusedWindow(), let id = window.cgWindowId, - let preview = window.getPreview(), + let (preview, previewSize) = window.getPreview(), let position = window.position, let size = window.size else { App.app.previewPanel.orderOut(nil) return } - App.app.previewPanel.show(id, preview, position, size) + App.app.previewPanel.show(id, preview, previewSize, position, size) } static func voiceOverWindow(_ windowIndex: Int = focusedWindowIndex) { diff --git a/src/ui/App.swift b/src/ui/App.swift index a89c746c..8ffee2f2 100644 --- a/src/ui/App.swift +++ b/src/ui/App.swift @@ -252,7 +252,7 @@ class App: AppCenterApplication, NSApplicationDelegate { func refreshOpenUi(_ windowsToScreenshot: [Window], skipUpdatesBeforeShowing: Bool = false, onlyUpdateScreenshots: Bool = false) { if !Appearance.hideThumbnails && !windowsToScreenshot.isEmpty { - Windows.refreshThumbnails(windowsToScreenshot, false, onlyUpdateScreenshots) + Windows.refreshThumbnails(windowsToScreenshot, true, onlyUpdateScreenshots) return } guard appIsBeingUsed else { return } diff --git a/src/ui/main-window/PreviewPanel.swift b/src/ui/main-window/PreviewPanel.swift index 4d7b1397..ddd9b30a 100644 --- a/src/ui/main-window/PreviewPanel.swift +++ b/src/ui/main-window/PreviewPanel.swift @@ -25,9 +25,10 @@ class PreviewPanel: NSPanel { setAccessibilitySubrole(.unknown) } - func show(_ id: CGWindowID, _ preview: NSImage, _ position: CGPoint, _ size: CGSize) { + func show(_ id: CGWindowID, _ preview: NSImage, _ previewSize: NSSize, _ position: CGPoint, _ size: CGSize) { if id != currentId { previewView.image = preview + previewView.image!.size = previewSize var frame = NSRect(origin: position, size: size) // Flip Y coordinate from Quartz (0,0 at bottom-left) to Cocoa coordinates (0,0 at top-left) // Always use the primary screen as reference since all coordinates are relative to it diff --git a/src/ui/main-window/ThumbnailView.swift b/src/ui/main-window/ThumbnailView.swift index 7cdd8520..49cc4da5 100644 --- a/src/ui/main-window/ThumbnailView.swift +++ b/src/ui/main-window/ThumbnailView.swift @@ -159,11 +159,14 @@ class ThumbnailView: FlippedView { private func setupSharedSubiews() { let shadow = ThumbnailView.makeShadow(Appearance.imageShadowColor) + thumbnail.imageScaling = .scaleProportionallyUpOrDown thumbnail.shadow = shadow windowlessIcon.translatesAutoresizingMaskIntoConstraints = false + windowlessIcon.imageScaling = .scaleProportionallyUpOrDown windowlessIcon.toolTip = ThumbnailView.noOpenWindowToolTip windowlessIcon.shadow = shadow appIcon.translatesAutoresizingMaskIntoConstraints = false + appIcon.imageScaling = .scaleProportionallyUpOrDown appIcon.shadow = shadow appIcon.setSubviewAbove(dockLabelIcon) label.fixHeight() @@ -340,8 +343,8 @@ class ThumbnailView: FlippedView { if appIconChanged || dockLabelChanged { setAccessibilityHelp(getAccessibilityHelp(element.application.runningApplication.localizedName, element.dockLabel)) } - if element.isWindowlessApp { - windowlessIcon.image = appIcon.image!.copy() as? NSImage + if element.isWindowlessApp && windowlessIcon.image != element.icon { + windowlessIcon.image = element.icon } windowControlIcons.forEach { $0.window_ = element } showOrHideWindowControls(false) @@ -353,19 +356,16 @@ class ThumbnailView: FlippedView { if Preferences.appearanceStyle == .thumbnails { if !thumbnail.isHidden { let thumbnailSize = ThumbnailView.thumbnailSize(thumbnail.image, screen, false) - thumbnail.image?.size = thumbnailSize - thumbnail.frame.size = thumbnailSize + thumbnail.setSize(thumbnailSize) } if !windowlessIcon.isHidden { let windowlessIconSize = ThumbnailView.thumbnailSize(windowlessIcon.image, screen, true) - windowlessIcon.image!.size = windowlessIconSize - windowlessIcon.frame.size = windowlessIconSize + windowlessIcon.setSize(windowlessIconSize) } } setFrameWidthHeight(screen, newHeight) let appIconSize = ThumbnailView.iconSize(screen) - appIcon.image?.size = appIconSize - appIcon.frame.size = appIconSize + appIcon.setSize(appIconSize) if Preferences.appearanceStyle == .appIcons { vStackView.frame.size = NSSize(width: frame.width, height: appIcon.frame.height + Appearance.edgeInsetsSize * 2) hStackView.frame.size = NSSize(width: appIcon.frame.width, height: appIcon.frame.height)