diff --git a/src/api-wrappers/HelperExtensions.swift b/src/api-wrappers/HelperExtensions.swift index 7840d5f4..6704256b 100644 --- a/src/api-wrappers/HelperExtensions.swift +++ b/src/api-wrappers/HelperExtensions.swift @@ -97,18 +97,6 @@ extension NSControl { } } -extension NSImage { - // copy and resize an image using high quality interpolation - func resizedCopy(_ width: CGFloat, _ height: CGFloat) -> NSImage { - let img = NSImage(size: CGSize(width: width, height: height)) - img.lockFocus() - NSGraphicsContext.current?.imageInterpolation = .high - draw(in: NSMakeRect(0, 0, width, height), from: NSMakeRect(0, 0, size.width, size.height), operation: .copy, fraction: 1) - img.unlockFocus() - return img - } -} - // only assign if different; useful for performance func assignIfDifferent(_ a: UnsafeMutablePointer, _ b: T) { if a.pointee != b { @@ -149,9 +137,25 @@ extension NSViewController { } extension NSImage { - static func initTemplate(_ name: String) -> NSImage { - let image = NSImage(named: name)! + // NSImage(named) caches/reuses NSImage objects; we force separate instances of images by using copy() + static func initCopy(_ name: String) -> NSImage { + return NSImage(named: name)!.copy() as! NSImage + } + + static func initTemplateCopy(_ name: String) -> NSImage { + let image = initCopy(name) image.isTemplate = true return image } + + // copy and resize an image using high quality interpolation + static func initResizedCopy(_ name: String, _ width: CGFloat, _ height: CGFloat) -> NSImage { + let original = initCopy(name) + let img = NSImage(size: CGSize(width: width, height: height)) + img.lockFocus() + NSGraphicsContext.current?.imageInterpolation = .high + original.draw(in: NSMakeRect(0, 0, width, height), from: NSMakeRect(0, 0, original.size.width, original.size.height), operation: .copy, fraction: 1) + img.unlockFocus() + return img + } } diff --git a/src/ui/FeedbackWindow.swift b/src/ui/FeedbackWindow.swift index f22077cf..ac3c3c86 100644 --- a/src/ui/FeedbackWindow.swift +++ b/src/ui/FeedbackWindow.swift @@ -26,7 +26,7 @@ class FeedbackWindow: NSWindow { } private func setupView() { - let appIcon = NSImageView(image: NSImage(named: "app-icon")!.resizedCopy(80, 80)) + let appIcon = NSImageView(image: NSImage.initResizedCopy("app-icon", 80, 80)) appIcon.imageScaling = .scaleNone let appText = StackView([ BoldLabel(NSLocalizedString("Share improvement ideas, or report bugs", comment: "")), diff --git a/src/ui/Menubar.swift b/src/ui/Menubar.swift index e4d23583..d66db50c 100644 --- a/src/ui/Menubar.swift +++ b/src/ui/Menubar.swift @@ -4,8 +4,7 @@ class Menubar { static var statusItem: NSStatusItem! static func initialize() { - statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) - statusItem.button!.imageScaling = .scaleProportionallyUpOrDown + statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength) statusItem.menu = NSMenu() statusItem.menu!.addItem( withTitle: NSLocalizedString("Show", comment: "Menubar option"), @@ -43,9 +42,9 @@ class Menubar { let i = imageIndexFromPreference() let image = NSImage(named: "menubar-icon-" + i)! image.isTemplate = i == "3" ? false : true - statusItem.button!.appearance = i == "3" ? NSAppearance(named: .aqua) : nil statusItem.button!.image = image statusItem.isVisible = true + statusItem.button!.imageScaling = .scaleProportionallyUpOrDown } static private func imageIndexFromPreference() -> String { diff --git a/src/ui/permission-window/PermissionView.swift b/src/ui/permission-window/PermissionView.swift index 1bdd9200..24008e2f 100644 --- a/src/ui/permission-window/PermissionView.swift +++ b/src/ui/permission-window/PermissionView.swift @@ -10,7 +10,7 @@ class PermissionView: StackView { var isPermissionGranted = false convenience init(_ iconName: String, _ title: String, _ justification: String, _ buttonText: String, _ buttonUrl: String, _ checkFunction: @escaping () -> Bool) { - let icon = NSImageView(image: NSImage(named: iconName)!) + let icon = NSImageView(image: NSImage.initCopy(iconName)) icon.translatesAutoresizingMaskIntoConstraints = false icon.fit() let title = BoldLabel(title) diff --git a/src/ui/permission-window/PermissionsWindow.swift b/src/ui/permission-window/PermissionsWindow.swift index 79bcfdda..5be0eb91 100644 --- a/src/ui/permission-window/PermissionsWindow.swift +++ b/src/ui/permission-window/PermissionsWindow.swift @@ -33,7 +33,7 @@ class PermissionsWindow: NSWindow, NSWindowDelegate { } private func setupView() { - let appIcon = NSImageView(image: NSImage(named: "app-icon")!.resizedCopy(80, 80)) + let appIcon = NSImageView(image: NSImage.initResizedCopy("app-icon", 80, 80)) appIcon.imageScaling = .scaleNone let appText = TitleLabel(NSLocalizedString("AltTab needs some permissions", comment: "")) appText.preferredMaxLayoutWidth = 380 diff --git a/src/ui/preferences-window/tabs/AboutTab.swift b/src/ui/preferences-window/tabs/AboutTab.swift index fb421707..c1576e22 100644 --- a/src/ui/preferences-window/tabs/AboutTab.swift +++ b/src/ui/preferences-window/tabs/AboutTab.swift @@ -4,10 +4,10 @@ import Preferences class AboutTab: NSViewController, PreferencePane { let preferencePaneIdentifier = PreferencePane.Identifier("About") let preferencePaneTitle = NSLocalizedString("About", comment: "") - let toolbarItemIcon = NSImage.initTemplate("about") + let toolbarItemIcon = NSImage.initTemplateCopy("about") override func loadView() { - let appIcon = NSImageView(image: NSImage(named: "app-icon")!.resizedCopy(256, 256)) + let appIcon = NSImageView(image: NSImage.initResizedCopy("app-icon", 256, 256)) appIcon.imageScaling = .scaleNone let appText = StackView([ BoldLabel(App.name), diff --git a/src/ui/preferences-window/tabs/AcknowledgmentsTab.swift b/src/ui/preferences-window/tabs/AcknowledgmentsTab.swift index a01e862d..4a09020c 100644 --- a/src/ui/preferences-window/tabs/AcknowledgmentsTab.swift +++ b/src/ui/preferences-window/tabs/AcknowledgmentsTab.swift @@ -7,7 +7,7 @@ class AcknowledgmentsTab: NSViewController, PreferencePane { static let maxTabHeight = CGFloat(450) let preferencePaneIdentifier = PreferencePane.Identifier("Acknowledgments") let preferencePaneTitle = NSLocalizedString("Acknowledgments", comment: "") - let toolbarItemIcon = NSImage.initTemplate("acknowledgments") + let toolbarItemIcon = NSImage.initTemplateCopy("acknowledgments") override func loadView() { let textViews: [TextField] = ["Contributors", "Acknowledgments"].map { diff --git a/src/ui/preferences-window/tabs/AppearanceTab.swift b/src/ui/preferences-window/tabs/AppearanceTab.swift index ff2ac202..4e064c10 100644 --- a/src/ui/preferences-window/tabs/AppearanceTab.swift +++ b/src/ui/preferences-window/tabs/AppearanceTab.swift @@ -4,7 +4,7 @@ import Preferences class AppearanceTab: NSViewController, PreferencePane { let preferencePaneIdentifier = PreferencePane.Identifier("Appearance") let preferencePaneTitle = NSLocalizedString("Appearance", comment: "") - let toolbarItemIcon = NSImage.initTemplate("appearance") + let toolbarItemIcon = NSImage.initTemplateCopy("appearance") override func loadView() { let grid = GridView([ diff --git a/src/ui/preferences-window/tabs/BlacklistsTab.swift b/src/ui/preferences-window/tabs/BlacklistsTab.swift index 781fee99..6b791d86 100644 --- a/src/ui/preferences-window/tabs/BlacklistsTab.swift +++ b/src/ui/preferences-window/tabs/BlacklistsTab.swift @@ -5,7 +5,7 @@ import Preferences class BlacklistsTab: NSViewController, PreferencePane { let preferencePaneIdentifier = PreferencePane.Identifier("Blacklists") let preferencePaneTitle = NSLocalizedString("Blacklists", comment: "") - let toolbarItemIcon = NSImage.initTemplate("blacklists") + let toolbarItemIcon = NSImage.initTemplateCopy("blacklists") override func loadView() { let dontShowBlacklistLabel = NSTextField(labelWithString: NSLocalizedString("Don’t show windows from these apps", comment: "")) diff --git a/src/ui/preferences-window/tabs/ControlsTab.swift b/src/ui/preferences-window/tabs/ControlsTab.swift index 0e73993b..1cbd776f 100644 --- a/src/ui/preferences-window/tabs/ControlsTab.swift +++ b/src/ui/preferences-window/tabs/ControlsTab.swift @@ -5,7 +5,7 @@ import Preferences class ControlsTab: NSViewController, PreferencePane { let preferencePaneIdentifier = PreferencePane.Identifier("Controls") let preferencePaneTitle = NSLocalizedString("Controls", comment: "") - let toolbarItemIcon = NSImage.initTemplate("controls") + let toolbarItemIcon = NSImage.initTemplateCopy("controls") static var nextWindowShortcut: [NSControl]! static var shortcuts = [String: Shortcut]() diff --git a/src/ui/preferences-window/tabs/GeneralTab.swift b/src/ui/preferences-window/tabs/GeneralTab.swift index e937d29e..c4781584 100644 --- a/src/ui/preferences-window/tabs/GeneralTab.swift +++ b/src/ui/preferences-window/tabs/GeneralTab.swift @@ -4,15 +4,15 @@ import Preferences class GeneralTab: NSViewController, PreferencePane { let preferencePaneIdentifier = PreferencePane.Identifier("General") let preferencePaneTitle = NSLocalizedString("General", comment: "") - let toolbarItemIcon = NSImage.initTemplate("general") + let toolbarItemIcon = NSImage.initTemplateCopy("general") override func loadView() { let startAtLogin = LabelAndControl.makeLabelWithCheckbox(NSLocalizedString("Start at login:", comment: ""), "startAtLogin", extraAction: startAtLoginCallback) let menubarIcon = LabelAndControl.makeLabelWithDropdown(NSLocalizedString("Menubar icon:", comment: ""), "menubarIcon", MenubarIconPreference.allCases, extraAction: Menubar.menubarIconCallback) let menubarIconDropdown = menubarIcon[1] as! NSPopUpButton for i in 0...2 { - let image = NSImage(named: "menubar-icon-" + String(i + 1))! - image.isTemplate = i == 2 ? false : true + let image = NSImage.initCopy("menubar-icon-" + String(i + 1)) + image.isTemplate = false menubarIconDropdown.item(at: i)!.image = image } menubarIconDropdown.item(at: 3)!.image = NSImage(size: NSSize(width: 1, height: menubarIconDropdown.item(at: 0)!.image!.size.height)) diff --git a/src/ui/preferences-window/tabs/PoliciesTab.swift b/src/ui/preferences-window/tabs/PoliciesTab.swift index f75756a4..26a59522 100644 --- a/src/ui/preferences-window/tabs/PoliciesTab.swift +++ b/src/ui/preferences-window/tabs/PoliciesTab.swift @@ -5,7 +5,7 @@ import Preferences class PoliciesTab: NSViewController, PreferencePane { let preferencePaneIdentifier = PreferencePane.Identifier("Policies") let preferencePaneTitle = NSLocalizedString("Policies", comment: "") - let toolbarItemIcon = NSImage.initTemplate("policies") + let toolbarItemIcon = NSImage.initTemplateCopy("policies") static var updateButtons: [NSButton]! static var crashButtons: [NSButton]!