From 1bcec0d49fdbe4682157961636f4c9fdd3ad2ca4 Mon Sep 17 00:00:00 2001 From: Pete Schaffner Date: Sun, 11 Feb 2024 00:55:33 +0100 Subject: [PATCH] Make new tab button images vibrant This makes them blend better with the background in windows with transparency. --- .../Features/Terminal/TerminalWindow.swift | 48 ++++++++----------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/macos/Sources/Features/Terminal/TerminalWindow.swift b/macos/Sources/Features/Terminal/TerminalWindow.swift index b6d0bbc02..395a1bd8d 100644 --- a/macos/Sources/Features/Terminal/TerminalWindow.swift +++ b/macos/Sources/Features/Terminal/TerminalWindow.swift @@ -30,7 +30,7 @@ class TerminalWindow: NSWindow { private var windowButtonsBackdrop: WindowButtonsBackdropView? = nil private var windowDragHandle: WindowDragView? = nil private var storedTitlebarBackgroundColor: CGColor? = nil - private var newTabButtonImage: NSImage? = nil + private var newTabButtonImageLayer: VibrantLayer? = nil // The tab bar controller ID from macOS static private let TabBarController = NSUserInterfaceItemIdentifier("_tabBarController") @@ -84,7 +84,7 @@ class TerminalWindow: NSWindow { // Reset the new tab button image so that we are sure to generate a fresh // one, tinted appropriately for the given theme. - self.newTabButtonImage = nil + self.newTabButtonImageLayer = nil // We have to wait before setting the titleVisibility or else it prevents // the window from hiding the tab bar when we get down to a single tab. @@ -215,9 +215,6 @@ class TerminalWindow: NSWindow { // Color the new tab button's image to match the color of the tab title/keyboard shortcut labels, // just as it does in the stock tab bar. - // - // One issue I haven't been able to fix is that their tint is made grey when the window isn't key, - // which doesn't look great and is made worse by the fact that the tab label colors don't change. guard let titlebarContainer = contentView?.superview?.subviews.first(where: { $0.className == "NSTitlebarContainerView" }) else { return } @@ -225,34 +222,31 @@ class TerminalWindow: NSWindow { guard let newTabButtonImageView: NSImageView = newTabButton.subviews.first(where: { $0 as? NSImageView != nil }) as? NSImageView else { return } + guard let newTabButtonImage = newTabButtonImageView.image else { return } + guard let storedTitlebarBackgroundColor, let isLightTheme = NSColor(cgColor: storedTitlebarBackgroundColor)?.isLightColor else { return } - if newTabButtonImage == nil { - guard let image = newTabButtonImageView.image, - let storedTitlebarBackgroundColor, - let titlebarBackgroundColor = NSColor(cgColor: storedTitlebarBackgroundColor) else { return } - - let isLightTheme = titlebarBackgroundColor.isLightColor - - let newImage = NSImage(size: image.size, flipped: false) { rect in - NSGraphicsContext.saveGraphicsState() - - titlebarBackgroundColor.darken(by: isLightTheme ? 0.1 : 0.5).setFill() - rect.fill() - - NSColor.secondaryLabelColor.setFill() - rect.fill(using: titlebarBackgroundColor.isLightColor ? .plusDarker : .plusLighter) - - NSGraphicsContext.restoreGraphicsState() - - image.draw(in: rect, from: .zero, operation: .destinationAtop, fraction: 1.0) - + if newTabButtonImageLayer == nil { + let fillColor: NSColor = isLightTheme ? .black.withAlphaComponent(0.85) : .white.withAlphaComponent(0.85) + let newImage = NSImage(size: newTabButtonImage.size, flipped: false) { rect in + newTabButtonImage.draw(in: rect) + fillColor.setFill() + rect.fill(using: .sourceAtop) return true } + let imageLayer = VibrantLayer(forAppearance: isLightTheme ? .light : .dark)! + imageLayer.frame = NSRect(origin: NSPoint(x: newTabButton.bounds.midX - newTabButtonImage.size.width/2, y: newTabButton.bounds.midY - newTabButtonImage.size.height/2), size: newTabButtonImage.size) + imageLayer.contentsGravity = .resizeAspect + imageLayer.contents = newImage + imageLayer.opacity = 0.5 - newTabButtonImage = newImage + newTabButtonImageLayer = imageLayer } - newTabButtonImageView.image = newTabButtonImage + newTabButtonImageView.layer?.addSublayer(newTabButtonImageLayer!) + newTabButtonImageView.image = nil + // When we nil out the original image, the image view's frame resizes and repositions + // slightly, so we need to reset it to make sure our new image doesn't shift quickly. + newTabButtonImageView.frame = newTabButton.bounds } private func addWindowButtonsBackdrop(titlebarView: NSView, toolbarView: NSView) {