From 40cfa1abd46a4ef07855ed960650e81878c2bad8 Mon Sep 17 00:00:00 2001 From: Pete Schaffner Date: Thu, 8 Feb 2024 10:10:40 +0100 Subject: [PATCH 1/8] Add CALayer subclass for use in titlebar tabs It uses a private compositing filter to match what the sytem does to color unselected tabs in the window's tab bar (specifically with a light appearance). --- macos/Ghostty.xcodeproj/project.pbxproj | 16 ++++++++++++++++ .../Sources/App/macOS/Ghostty-Bridging-Header.h | 5 +++++ .../Helpers/PlusDarkerBlendingModeLayer.h | 4 ++++ .../Helpers/PlusDarkerBlendingModeLayer.m | 9 +++++++++ 4 files changed, 34 insertions(+) create mode 100644 macos/Sources/App/macOS/Ghostty-Bridging-Header.h create mode 100644 macos/Sources/Helpers/PlusDarkerBlendingModeLayer.h create mode 100644 macos/Sources/Helpers/PlusDarkerBlendingModeLayer.m diff --git a/macos/Ghostty.xcodeproj/project.pbxproj b/macos/Ghostty.xcodeproj/project.pbxproj index d0942cad2..286fe5c87 100644 --- a/macos/Ghostty.xcodeproj/project.pbxproj +++ b/macos/Ghostty.xcodeproj/project.pbxproj @@ -69,6 +69,7 @@ C159E81D2B66A06B00FDFE9C /* OSColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C159E81C2B66A06B00FDFE9C /* OSColor+Extension.swift */; }; C159E89D2B69A2EF00FDFE9C /* OSColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C159E81C2B66A06B00FDFE9C /* OSColor+Extension.swift */; }; C1F26EA72B738B9900404083 /* NSView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1F26EA62B738B9900404083 /* NSView+Extension.swift */; }; + C1F26EB22B743B7700404083 /* PlusDarkerBlendingModeLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = C1F26EB12B743B7700404083 /* PlusDarkerBlendingModeLayer.m */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -130,6 +131,9 @@ AEF9CE232B6AD07A0017E195 /* TerminalToolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalToolbar.swift; sourceTree = ""; }; C159E81C2B66A06B00FDFE9C /* OSColor+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OSColor+Extension.swift"; sourceTree = ""; }; C1F26EA62B738B9900404083 /* NSView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSView+Extension.swift"; sourceTree = ""; }; + C1F26EB02B743B7700404083 /* Ghostty-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Ghostty-Bridging-Header.h"; sourceTree = ""; }; + C1F26EB12B743B7700404083 /* PlusDarkerBlendingModeLayer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PlusDarkerBlendingModeLayer.m; sourceTree = ""; }; + C1F26EB32B743C9300404083 /* PlusDarkerBlendingModeLayer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PlusDarkerBlendingModeLayer.h; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -196,6 +200,8 @@ A59FB5D02AE0DEA7009128F3 /* MetalView.swift */, C159E81C2B66A06B00FDFE9C /* OSColor+Extension.swift */, C1F26EA62B738B9900404083 /* NSView+Extension.swift */, + C1F26EB32B743C9300404083 /* PlusDarkerBlendingModeLayer.h */, + C1F26EB12B743B7700404083 /* PlusDarkerBlendingModeLayer.m */, A5CEAFDA29B8005900646FDA /* SplitView */, ); path = Helpers; @@ -235,6 +241,7 @@ A5FEB2FF2ABB69450068369E /* main.swift */, A53426342A7DA53D00EBB7A2 /* AppDelegate.swift */, 857F63802A5E64F200CA4815 /* MainMenu.xib */, + C1F26EB02B743B7700404083 /* Ghostty-Bridging-Header.h */, ); path = macOS; sourceTree = ""; @@ -406,6 +413,7 @@ TargetAttributes = { A5B30530299BEAAA0047F10C = { CreatedOnToolsVersion = 14.2; + LastSwiftMigration = 1510; }; A5D4499C2B53AE7B000F5B83 = { CreatedOnToolsVersion = 15.2; @@ -496,6 +504,7 @@ A55685E029A03A9F004303CE /* AppError.swift in Sources */, A535B9DA299C569B0017E2E4 /* ErrorView.swift in Sources */, A51BFC202B2FB64F00E92F16 /* AboutController.swift in Sources */, + C1F26EB22B743B7700404083 /* PlusDarkerBlendingModeLayer.m in Sources */, A5CEAFFF29C2410700646FDA /* Backport.swift in Sources */, A5E112952AF73E8A00C6E0C2 /* ClipboardConfirmationController.swift in Sources */, 8503D7C72A549C66006CFF3D /* FullScreenHandler.swift in Sources */, @@ -586,6 +595,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = GhosttyReleaseLocal.entitlements; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; CODE_SIGN_STYLE = Automatic; @@ -612,6 +622,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.mitchellh.ghostty; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = "Sources/App/macOS/Ghostty-Bridging-Header.h"; SWIFT_VERSION = 5.0; }; name = ReleaseLocal; @@ -735,6 +746,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = GhosttyDebug.entitlements; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; CODE_SIGN_STYLE = Automatic; @@ -760,6 +772,8 @@ PRODUCT_BUNDLE_IDENTIFIER = com.mitchellh.ghostty; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = "Sources/App/macOS/Ghostty-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; }; name = Debug; @@ -770,6 +784,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Ghostty.entitlements; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; CODE_SIGN_STYLE = Automatic; @@ -796,6 +811,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.mitchellh.ghostty; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = "Sources/App/macOS/Ghostty-Bridging-Header.h"; SWIFT_VERSION = 5.0; }; name = Release; diff --git a/macos/Sources/App/macOS/Ghostty-Bridging-Header.h b/macos/Sources/App/macOS/Ghostty-Bridging-Header.h new file mode 100644 index 000000000..44aaa3ff6 --- /dev/null +++ b/macos/Sources/App/macOS/Ghostty-Bridging-Header.h @@ -0,0 +1,5 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + +#import "PlusDarkerBlendingModeLayer.h" diff --git a/macos/Sources/Helpers/PlusDarkerBlendingModeLayer.h b/macos/Sources/Helpers/PlusDarkerBlendingModeLayer.h new file mode 100644 index 000000000..e3d0c5f8e --- /dev/null +++ b/macos/Sources/Helpers/PlusDarkerBlendingModeLayer.h @@ -0,0 +1,4 @@ +#import + +@interface PlusDarkerBlendingModeLayer: CALayer +@end diff --git a/macos/Sources/Helpers/PlusDarkerBlendingModeLayer.m b/macos/Sources/Helpers/PlusDarkerBlendingModeLayer.m new file mode 100644 index 000000000..2ec6933e5 --- /dev/null +++ b/macos/Sources/Helpers/PlusDarkerBlendingModeLayer.m @@ -0,0 +1,9 @@ +#import "PlusDarkerBlendingModeLayer.h" + +@implementation PlusDarkerBlendingModeLayer + +// A private compositing filter ("plus darker") that is used in titlebar +// tab bars to create the effect of recessed, unselected tabs. +- (id)compositingFilter { return @"plusD"; } + +@end From 33a8368a6855f71c650d3964c6b02026dd17a8a7 Mon Sep 17 00:00:00 2001 From: Pete Schaffner Date: Thu, 8 Feb 2024 10:14:15 +0100 Subject: [PATCH 2/8] Make unselected tabs blend better with background color This enables the standard effect created by a sytem tab bar, which ensures unselected tabs blend with the window's/titlebar's background color. This also ensures the `windowButtonsBackdrop` view matches the color of the adjacent tab (be it selected or not). --- .../Features/Terminal/TerminalWindow.swift | 93 +++++++++++++++---- 1 file changed, 75 insertions(+), 18 deletions(-) diff --git a/macos/Sources/Features/Terminal/TerminalWindow.swift b/macos/Sources/Features/Terminal/TerminalWindow.swift index 457b3bd08..c0b90afbd 100644 --- a/macos/Sources/Features/Terminal/TerminalWindow.swift +++ b/macos/Sources/Features/Terminal/TerminalWindow.swift @@ -27,7 +27,7 @@ class TerminalWindow: NSWindow { } } - private var windowButtonsBackdrop: NSView? = nil + private var windowButtonsBackdrop: WindowButtonsBackdropView? = nil private var windowDragHandle: WindowDragView? = nil private var storedTitlebarBackgroundColor: CGColor? = nil @@ -51,9 +51,21 @@ class TerminalWindow: NSWindow { /// This is called by titlebarTabs changing so that we can setup the rest of our window private func changedTitlebarTabs(to newValue: Bool) { - self.titlebarAppearsTransparent = newValue - if (newValue) { + // By hiding the visual effect view, we allow the window's (or titlebar's in this case) + // background color to show through. If we were to set `titlebarAppearsTransparent` to true + // the selected tab would look fine, but the unselected ones and new tab button backgrounds + // would be an opaque color. When the titlebar isn't transparent, however, the system applies + // a compositing effect to the unselected tab backgrounds, which makes them blend with the + // titlebar's/window's background. + if let titlebarContainer = contentView?.superview?.subviews.first(where: { + $0.className == "NSTitlebarContainerView" + }), let effectView = titlebarContainer.descendants(withClassName: "NSVisualEffectView").first { + effectView.isHidden = true + } + + self.titlebarSeparatorStyle = .none + // We use the toolbar to anchor our tab bar positions in the titlebar, // so we make sure it's the right size/position, and exists. self.toolbarStyle = .unifiedCompact @@ -180,7 +192,20 @@ class TerminalWindow: NSWindow { self.markHierarchyForLayout(accessoryView) } } - + + // This is called when we open, close, switch, and reorder tabs, at which point we determine if the + // first tab in the tab bar is selected. If it is, we make the `windowButtonsBackdrop` color the same + // as that of the active tab (i.e. the titlebar's background color), otherwise we make it the same + // color as the background of unselected tabs. + override func update() { + super.update() + if let index = windowController?.window?.tabbedWindows?.firstIndex(of: self) { + let firstTabIsSelected = index == 0 + + windowButtonsBackdrop?.isHighlighted = firstTabIsSelected + } + } + private func addWindowButtonsBackdrop(titlebarView: NSView, toolbarView: NSView) { // If we already made the view, just make sure it's unhidden and correctly placed as a subview. if let view = windowButtonsBackdrop { @@ -188,32 +213,22 @@ class TerminalWindow: NSWindow { view.isHidden = false titlebarView.addSubview(view) view.leftAnchor.constraint(equalTo: toolbarView.leftAnchor).isActive = true - view.rightAnchor.constraint(equalTo: toolbarView.leftAnchor, constant: 80).isActive = true + view.rightAnchor.constraint(equalTo: toolbarView.leftAnchor, constant: 78).isActive = true view.topAnchor.constraint(equalTo: toolbarView.topAnchor).isActive = true view.heightAnchor.constraint(equalTo: toolbarView.heightAnchor).isActive = true return } - let view = NSView() + let view = WindowButtonsBackdropView(backgroundColor: storedTitlebarBackgroundColor ?? NSColor.windowBackgroundColor.cgColor) view.identifier = NSUserInterfaceItemIdentifier("_windowButtonsBackdrop") titlebarView.addSubview(view) view.translatesAutoresizingMaskIntoConstraints = false view.leftAnchor.constraint(equalTo: toolbarView.leftAnchor).isActive = true - view.rightAnchor.constraint(equalTo: toolbarView.leftAnchor, constant: 80).isActive = true + view.rightAnchor.constraint(equalTo: toolbarView.leftAnchor, constant: 78).isActive = true view.topAnchor.constraint(equalTo: toolbarView.topAnchor).isActive = true view.heightAnchor.constraint(equalTo: toolbarView.heightAnchor).isActive = true - view.wantsLayer = true - - // This is jank but this makes the background color for light themes on the button - // backdrop look MUCH better. I couldn't figure out a perfect color to use that works - // for both so we just check the appearance. - if effectiveAppearance.name == .aqua { - view.layer?.backgroundColor = CGColor(genericGrayGamma2_2Gray: 0.95, alpha: 1) - } else { - view.layer?.backgroundColor = CGColor(genericGrayGamma2_2Gray: 0.0, alpha: 0.45) - } - + windowButtonsBackdrop = view } @@ -283,3 +298,45 @@ fileprivate class WindowDragView: NSView { addCursorRect(bounds, cursor: .openHand) } } + +// A view that matches the color of selected and unselected tabs in the adjacent tab bar. +fileprivate class WindowButtonsBackdropView: NSView { + private let overlayLayer = PlusDarkerBlendingModeLayer() + private let backgroundColor: CGColor + private let isLightTheme: Bool + + var isHighlighted: Bool = true { + didSet { + if isLightTheme { + overlayLayer.isHidden = isHighlighted + layer?.backgroundColor = backgroundColor + } else { + overlayLayer.isHidden = true + layer?.backgroundColor = isHighlighted ? backgroundColor : CGColor(genericGrayGamma2_2Gray: 0.0, alpha: 0.45) + } + + } + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + init(backgroundColor: CGColor) { + self.backgroundColor = backgroundColor + self.isLightTheme = NSColor(cgColor: backgroundColor)!.isLightColor + + super.init(frame: .zero) + + + wantsLayer = true + + overlayLayer.frame = layer!.bounds + overlayLayer.autoresizingMask = [.layerWidthSizable, .layerHeightSizable] + overlayLayer.backgroundColor = CGColor(genericGrayGamma2_2Gray: 0.95, alpha: 1) + + layer?.addSublayer(overlayLayer) + + isHighlighted = true + } +} From 8831c601a4c803c58b4b255791e4ba3cdc0cbc15 Mon Sep 17 00:00:00 2001 From: Pete Schaffner Date: Thu, 8 Feb 2024 16:38:07 +0100 Subject: [PATCH 3/8] Use draw rect to do the "plus darker" blending This is a lot simpler and doesn't require adding Obj-C into the mix. --- macos/Ghostty.xcodeproj/project.pbxproj | 11 ------ .../App/macOS/Ghostty-Bridging-Header.h | 5 --- .../Features/Terminal/TerminalWindow.swift | 37 +++++++++---------- .../Helpers/PlusDarkerBlendingModeLayer.h | 4 -- .../Helpers/PlusDarkerBlendingModeLayer.m | 9 ----- 5 files changed, 17 insertions(+), 49 deletions(-) delete mode 100644 macos/Sources/App/macOS/Ghostty-Bridging-Header.h delete mode 100644 macos/Sources/Helpers/PlusDarkerBlendingModeLayer.h delete mode 100644 macos/Sources/Helpers/PlusDarkerBlendingModeLayer.m diff --git a/macos/Ghostty.xcodeproj/project.pbxproj b/macos/Ghostty.xcodeproj/project.pbxproj index 286fe5c87..b7e0134c8 100644 --- a/macos/Ghostty.xcodeproj/project.pbxproj +++ b/macos/Ghostty.xcodeproj/project.pbxproj @@ -69,7 +69,6 @@ C159E81D2B66A06B00FDFE9C /* OSColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C159E81C2B66A06B00FDFE9C /* OSColor+Extension.swift */; }; C159E89D2B69A2EF00FDFE9C /* OSColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C159E81C2B66A06B00FDFE9C /* OSColor+Extension.swift */; }; C1F26EA72B738B9900404083 /* NSView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1F26EA62B738B9900404083 /* NSView+Extension.swift */; }; - C1F26EB22B743B7700404083 /* PlusDarkerBlendingModeLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = C1F26EB12B743B7700404083 /* PlusDarkerBlendingModeLayer.m */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -131,9 +130,6 @@ AEF9CE232B6AD07A0017E195 /* TerminalToolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalToolbar.swift; sourceTree = ""; }; C159E81C2B66A06B00FDFE9C /* OSColor+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OSColor+Extension.swift"; sourceTree = ""; }; C1F26EA62B738B9900404083 /* NSView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSView+Extension.swift"; sourceTree = ""; }; - C1F26EB02B743B7700404083 /* Ghostty-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Ghostty-Bridging-Header.h"; sourceTree = ""; }; - C1F26EB12B743B7700404083 /* PlusDarkerBlendingModeLayer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PlusDarkerBlendingModeLayer.m; sourceTree = ""; }; - C1F26EB32B743C9300404083 /* PlusDarkerBlendingModeLayer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PlusDarkerBlendingModeLayer.h; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -200,8 +196,6 @@ A59FB5D02AE0DEA7009128F3 /* MetalView.swift */, C159E81C2B66A06B00FDFE9C /* OSColor+Extension.swift */, C1F26EA62B738B9900404083 /* NSView+Extension.swift */, - C1F26EB32B743C9300404083 /* PlusDarkerBlendingModeLayer.h */, - C1F26EB12B743B7700404083 /* PlusDarkerBlendingModeLayer.m */, A5CEAFDA29B8005900646FDA /* SplitView */, ); path = Helpers; @@ -241,7 +235,6 @@ A5FEB2FF2ABB69450068369E /* main.swift */, A53426342A7DA53D00EBB7A2 /* AppDelegate.swift */, 857F63802A5E64F200CA4815 /* MainMenu.xib */, - C1F26EB02B743B7700404083 /* Ghostty-Bridging-Header.h */, ); path = macOS; sourceTree = ""; @@ -504,7 +497,6 @@ A55685E029A03A9F004303CE /* AppError.swift in Sources */, A535B9DA299C569B0017E2E4 /* ErrorView.swift in Sources */, A51BFC202B2FB64F00E92F16 /* AboutController.swift in Sources */, - C1F26EB22B743B7700404083 /* PlusDarkerBlendingModeLayer.m in Sources */, A5CEAFFF29C2410700646FDA /* Backport.swift in Sources */, A5E112952AF73E8A00C6E0C2 /* ClipboardConfirmationController.swift in Sources */, 8503D7C72A549C66006CFF3D /* FullScreenHandler.swift in Sources */, @@ -622,7 +614,6 @@ PRODUCT_BUNDLE_IDENTIFIER = com.mitchellh.ghostty; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_OBJC_BRIDGING_HEADER = "Sources/App/macOS/Ghostty-Bridging-Header.h"; SWIFT_VERSION = 5.0; }; name = ReleaseLocal; @@ -772,7 +763,6 @@ PRODUCT_BUNDLE_IDENTIFIER = com.mitchellh.ghostty; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_OBJC_BRIDGING_HEADER = "Sources/App/macOS/Ghostty-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; }; @@ -811,7 +801,6 @@ PRODUCT_BUNDLE_IDENTIFIER = com.mitchellh.ghostty; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_OBJC_BRIDGING_HEADER = "Sources/App/macOS/Ghostty-Bridging-Header.h"; SWIFT_VERSION = 5.0; }; name = Release; diff --git a/macos/Sources/App/macOS/Ghostty-Bridging-Header.h b/macos/Sources/App/macOS/Ghostty-Bridging-Header.h deleted file mode 100644 index 44aaa3ff6..000000000 --- a/macos/Sources/App/macOS/Ghostty-Bridging-Header.h +++ /dev/null @@ -1,5 +0,0 @@ -// -// Use this file to import your target's public headers that you would like to expose to Swift. -// - -#import "PlusDarkerBlendingModeLayer.h" diff --git a/macos/Sources/Features/Terminal/TerminalWindow.swift b/macos/Sources/Features/Terminal/TerminalWindow.swift index c0b90afbd..de0749f27 100644 --- a/macos/Sources/Features/Terminal/TerminalWindow.swift +++ b/macos/Sources/Features/Terminal/TerminalWindow.swift @@ -301,20 +301,12 @@ fileprivate class WindowDragView: NSView { // A view that matches the color of selected and unselected tabs in the adjacent tab bar. fileprivate class WindowButtonsBackdropView: NSView { - private let overlayLayer = PlusDarkerBlendingModeLayer() - private let backgroundColor: CGColor + private let backgroundColor: NSColor private let isLightTheme: Bool var isHighlighted: Bool = true { didSet { - if isLightTheme { - overlayLayer.isHidden = isHighlighted - layer?.backgroundColor = backgroundColor - } else { - overlayLayer.isHidden = true - layer?.backgroundColor = isHighlighted ? backgroundColor : CGColor(genericGrayGamma2_2Gray: 0.0, alpha: 0.45) - } - + setNeedsDisplay(self.bounds) } } @@ -323,20 +315,25 @@ fileprivate class WindowButtonsBackdropView: NSView { } init(backgroundColor: CGColor) { - self.backgroundColor = backgroundColor + self.backgroundColor = NSColor(cgColor: backgroundColor)! self.isLightTheme = NSColor(cgColor: backgroundColor)!.isLightColor super.init(frame: .zero) + } + override func draw(_ dirtyRect: NSRect) { + if isLightTheme { + backgroundColor.setFill() + bounds.fill() - wantsLayer = true - - overlayLayer.frame = layer!.bounds - overlayLayer.autoresizingMask = [.layerWidthSizable, .layerHeightSizable] - overlayLayer.backgroundColor = CGColor(genericGrayGamma2_2Gray: 0.95, alpha: 1) - - layer?.addSublayer(overlayLayer) - - isHighlighted = true + if !isHighlighted { + let overlayColor = NSColor(cgColor: CGColor(genericGrayGamma2_2Gray: 0.95, alpha: 1))! + overlayColor.setFill() + bounds.fill(using: .plusDarker) + } + } else { + (isHighlighted ? backgroundColor : NSColor(cgColor: CGColor(genericGrayGamma2_2Gray: 0.0, alpha: 0.45))!).setFill() + bounds.fill() + } } } diff --git a/macos/Sources/Helpers/PlusDarkerBlendingModeLayer.h b/macos/Sources/Helpers/PlusDarkerBlendingModeLayer.h deleted file mode 100644 index e3d0c5f8e..000000000 --- a/macos/Sources/Helpers/PlusDarkerBlendingModeLayer.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface PlusDarkerBlendingModeLayer: CALayer -@end diff --git a/macos/Sources/Helpers/PlusDarkerBlendingModeLayer.m b/macos/Sources/Helpers/PlusDarkerBlendingModeLayer.m deleted file mode 100644 index 2ec6933e5..000000000 --- a/macos/Sources/Helpers/PlusDarkerBlendingModeLayer.m +++ /dev/null @@ -1,9 +0,0 @@ -#import "PlusDarkerBlendingModeLayer.h" - -@implementation PlusDarkerBlendingModeLayer - -// A private compositing filter ("plus darker") that is used in titlebar -// tab bars to create the effect of recessed, unselected tabs. -- (id)compositingFilter { return @"plusD"; } - -@end From 95c8541efd2c1f0a58a10a491e673d5f42cfa4b6 Mon Sep 17 00:00:00 2001 From: Pete Schaffner Date: Thu, 8 Feb 2024 17:46:16 +0100 Subject: [PATCH 4/8] Color the new tab button image appropriately --- .../Features/Terminal/TerminalWindow.swift | 68 +++++++++++++------ macos/Sources/Helpers/NSView+Extension.swift | 13 ++++ 2 files changed, 62 insertions(+), 19 deletions(-) diff --git a/macos/Sources/Features/Terminal/TerminalWindow.swift b/macos/Sources/Features/Terminal/TerminalWindow.swift index de0749f27..25bf5a523 100644 --- a/macos/Sources/Features/Terminal/TerminalWindow.swift +++ b/macos/Sources/Features/Terminal/TerminalWindow.swift @@ -34,21 +34,6 @@ class TerminalWindow: NSWindow { // The tab bar controller ID from macOS static private let TabBarController = NSUserInterfaceItemIdentifier("_tabBarController") - // Look through the titlebar's view hierarchy and hide any of the internal - // views used to create a separator between the title/toolbar and unselected - // tabs in the tab bar. - override func updateConstraintsIfNeeded() { - super.updateConstraintsIfNeeded() - - guard let titlebarContainer = contentView?.superview?.subviews.first(where: { - $0.className == "NSTitlebarContainerView" - }) else { return } - - for v in titlebarContainer.descendants(withClassName: "NSTitlebarSeparatorView") { - v.isHidden = true - } - } - /// This is called by titlebarTabs changing so that we can setup the rest of our window private func changedTitlebarTabs(to newValue: Bool) { if (newValue) { @@ -193,17 +178,62 @@ class TerminalWindow: NSWindow { } } - // This is called when we open, close, switch, and reorder tabs, at which point we determine if the - // first tab in the tab bar is selected. If it is, we make the `windowButtonsBackdrop` color the same - // as that of the active tab (i.e. the titlebar's background color), otherwise we make it the same - // color as the background of unselected tabs. override func update() { super.update() + + // This is called when we open, close, switch, and reorder tabs, at which point we determine if the + // first tab in the tab bar is selected. If it is, we make the `windowButtonsBackdrop` color the same + // as that of the active tab (i.e. the titlebar's background color), otherwise we make it the same + // color as the background of unselected tabs. if let index = windowController?.window?.tabbedWindows?.firstIndex(of: self) { let firstTabIsSelected = index == 0 windowButtonsBackdrop?.isHighlighted = firstTabIsSelected } + + guard let titlebarContainer = contentView?.superview?.subviews.first(where: { + $0.className == "NSTitlebarContainerView" + }) else { return } + + // Look through the titlebar's view hierarchy and hide any of the internal + // views used to create a separator between the title/toolbar and unselected + // tabs in the tab bar. + for v in titlebarContainer.descendants(withClassName: "NSTitlebarSeparatorView") { + v.isHidden = true + } + + // 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 newTabButton: NSButton = titlebarContainer.firstDescendant(withClassName: "NSTabBarNewTabButton") as? NSButton else { return } + guard let newTabButtonImageView: NSImageView = newTabButton.subviews.first(where: { + $0 as? NSImageView != nil + }) as? NSImageView else { return } + guard let newTabButtonImage = newTabButtonImageView.image, + let storedTitlebarBackgroundColor, + let titlebarBackgroundColor = NSColor(cgColor: storedTitlebarBackgroundColor) else { return } + + let isLightTheme = titlebarBackgroundColor.isLightColor + + let newImage = NSImage(size: newTabButtonImage.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() + + newTabButtonImage.draw(in: rect, from: .zero, operation: .destinationAtop, fraction: 1.0) + + return true + } + + newTabButtonImageView.image = newImage } private func addWindowButtonsBackdrop(titlebarView: NSView, toolbarView: NSView) { diff --git a/macos/Sources/Helpers/NSView+Extension.swift b/macos/Sources/Helpers/NSView+Extension.swift index 8612c0417..1fcaea380 100644 --- a/macos/Sources/Helpers/NSView+Extension.swift +++ b/macos/Sources/Helpers/NSView+Extension.swift @@ -1,6 +1,19 @@ import AppKit extension NSView { + /// Recursively finds and returns the first descendant view that has the given class name. + func firstDescendant(withClassName name: String) -> NSView? { + for subview in subviews { + if String(describing: type(of: subview)) == name { + return subview + } else if let found = subview.firstDescendant(withClassName: name) { + return found + } + } + + return nil + } + /// Recursively finds and returns descendant views that have the given class name. func descendants(withClassName name: String) -> [NSView] { var result = [NSView]() From 7e945a52f15df81edebbb4797f7fe0c2b371a45c Mon Sep 17 00:00:00 2001 From: Pete Schaffner Date: Thu, 8 Feb 2024 18:16:17 +0100 Subject: [PATCH 5/8] Move separator hiding back into `updateConstraintsIfNeeded` I moved this into `update` when doing the tab bar background coloring but the separators would still show briefly. --- .../Features/Terminal/TerminalWindow.swift | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/macos/Sources/Features/Terminal/TerminalWindow.swift b/macos/Sources/Features/Terminal/TerminalWindow.swift index 25bf5a523..e3362300c 100644 --- a/macos/Sources/Features/Terminal/TerminalWindow.swift +++ b/macos/Sources/Features/Terminal/TerminalWindow.swift @@ -34,6 +34,21 @@ class TerminalWindow: NSWindow { // The tab bar controller ID from macOS static private let TabBarController = NSUserInterfaceItemIdentifier("_tabBarController") + // Look through the titlebar's view hierarchy and hide any of the internal + // views used to create a separator between the title/toolbar and unselected + // tabs in the tab bar. + override func updateConstraintsIfNeeded() { + super.updateConstraintsIfNeeded() + + guard let titlebarContainer = contentView?.superview?.subviews.first(where: { + $0.className == "NSTitlebarContainerView" + }) else { return } + + for v in titlebarContainer.descendants(withClassName: "NSTitlebarSeparatorView") { + v.isHidden = true + } + } + /// This is called by titlebarTabs changing so that we can setup the rest of our window private func changedTitlebarTabs(to newValue: Bool) { if (newValue) { @@ -195,13 +210,6 @@ class TerminalWindow: NSWindow { $0.className == "NSTitlebarContainerView" }) else { return } - // Look through the titlebar's view hierarchy and hide any of the internal - // views used to create a separator between the title/toolbar and unselected - // tabs in the tab bar. - for v in titlebarContainer.descendants(withClassName: "NSTitlebarSeparatorView") { - v.isHidden = true - } - // 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. // From 20ed0999409ca693cd815031dc3f37c3a4fe17f9 Mon Sep 17 00:00:00 2001 From: Pete Schaffner Date: Fri, 9 Feb 2024 00:06:40 +0100 Subject: [PATCH 6/8] Cache new tab button image to improve performance --- .../Features/Terminal/TerminalWindow.swift | 49 +++++++++++-------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/macos/Sources/Features/Terminal/TerminalWindow.swift b/macos/Sources/Features/Terminal/TerminalWindow.swift index e3362300c..d42a72de5 100644 --- a/macos/Sources/Features/Terminal/TerminalWindow.swift +++ b/macos/Sources/Features/Terminal/TerminalWindow.swift @@ -30,7 +30,8 @@ class TerminalWindow: NSWindow { private var windowButtonsBackdrop: WindowButtonsBackdropView? = nil private var windowDragHandle: WindowDragView? = nil private var storedTitlebarBackgroundColor: CGColor? = nil - + private var newTabButtonImage: NSImage? = nil + // The tab bar controller ID from macOS static private let TabBarController = NSUserInterfaceItemIdentifier("_tabBarController") @@ -76,7 +77,11 @@ class TerminalWindow: NSWindow { // Set a custom background on the titlebar - this is required for when // titlebar tabs is used in conjunction with a transparent background. self.restoreTitlebarBackground() - + + // 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 + // 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. DispatchQueue.main.async { @@ -206,42 +211,46 @@ class TerminalWindow: NSWindow { windowButtonsBackdrop?.isHighlighted = firstTabIsSelected } - guard let titlebarContainer = contentView?.superview?.subviews.first(where: { - $0.className == "NSTitlebarContainerView" - }) else { return } - // 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 } guard let newTabButton: NSButton = titlebarContainer.firstDescendant(withClassName: "NSTabBarNewTabButton") as? NSButton else { return } guard let newTabButtonImageView: NSImageView = newTabButton.subviews.first(where: { $0 as? NSImageView != nil }) as? NSImageView else { return } - guard let newTabButtonImage = newTabButtonImageView.image, - let storedTitlebarBackgroundColor, - let titlebarBackgroundColor = NSColor(cgColor: storedTitlebarBackgroundColor) else { return } - let isLightTheme = titlebarBackgroundColor.isLightColor + if newTabButtonImage == nil { + guard let image = newTabButtonImageView.image, + let storedTitlebarBackgroundColor, + let titlebarBackgroundColor = NSColor(cgColor: storedTitlebarBackgroundColor) else { return } - let newImage = NSImage(size: newTabButtonImage.size, flipped: false) { rect in - NSGraphicsContext.saveGraphicsState() + let isLightTheme = titlebarBackgroundColor.isLightColor - titlebarBackgroundColor.darken(by: isLightTheme ? 0.1 : 0.5).setFill() - rect.fill() + let newImage = NSImage(size: image.size, flipped: false) { rect in + NSGraphicsContext.saveGraphicsState() - NSColor.secondaryLabelColor.setFill() - rect.fill(using: titlebarBackgroundColor.isLightColor ? .plusDarker : .plusLighter) + titlebarBackgroundColor.darken(by: isLightTheme ? 0.1 : 0.5).setFill() + rect.fill() - NSGraphicsContext.restoreGraphicsState() + NSColor.secondaryLabelColor.setFill() + rect.fill(using: titlebarBackgroundColor.isLightColor ? .plusDarker : .plusLighter) - newTabButtonImage.draw(in: rect, from: .zero, operation: .destinationAtop, fraction: 1.0) + NSGraphicsContext.restoreGraphicsState() - return true + image.draw(in: rect, from: .zero, operation: .destinationAtop, fraction: 1.0) + + return true + } + + newTabButtonImage = newImage } - newTabButtonImageView.image = newImage + newTabButtonImageView.image = newTabButtonImage } private func addWindowButtonsBackdrop(titlebarView: NSView, toolbarView: NSView) { From 77e82b4d2a26ebedd86802d6e0e7166b9ef5e5be Mon Sep 17 00:00:00 2001 From: Pete Schaffner Date: Fri, 9 Feb 2024 22:46:49 +0100 Subject: [PATCH 7/8] Improve window buttons backdrop with window opacity --- macos/Ghostty.xcodeproj/project.pbxproj | 11 +++++++ .../App/macOS/Ghostty-Bridging-Header.h | 5 +++ .../Features/Terminal/TerminalWindow.swift | 31 +++++++++---------- ...erminalWindowButtonsBackdropOverlayLayer.h | 4 +++ ...erminalWindowButtonsBackdropOverlayLayer.m | 9 ++++++ 5 files changed, 43 insertions(+), 17 deletions(-) create mode 100644 macos/Sources/App/macOS/Ghostty-Bridging-Header.h create mode 100644 macos/Sources/Features/Terminal/TerminalWindowButtonsBackdropOverlayLayer.h create mode 100644 macos/Sources/Features/Terminal/TerminalWindowButtonsBackdropOverlayLayer.m diff --git a/macos/Ghostty.xcodeproj/project.pbxproj b/macos/Ghostty.xcodeproj/project.pbxproj index b7e0134c8..583313b92 100644 --- a/macos/Ghostty.xcodeproj/project.pbxproj +++ b/macos/Ghostty.xcodeproj/project.pbxproj @@ -69,6 +69,7 @@ C159E81D2B66A06B00FDFE9C /* OSColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C159E81C2B66A06B00FDFE9C /* OSColor+Extension.swift */; }; C159E89D2B69A2EF00FDFE9C /* OSColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C159E81C2B66A06B00FDFE9C /* OSColor+Extension.swift */; }; C1F26EA72B738B9900404083 /* NSView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1F26EA62B738B9900404083 /* NSView+Extension.swift */; }; + C1F26EE92B76CBFC00404083 /* TerminalWindowButtonsBackdropOverlayLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = C1F26EE82B76CBFC00404083 /* TerminalWindowButtonsBackdropOverlayLayer.m */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -130,6 +131,9 @@ AEF9CE232B6AD07A0017E195 /* TerminalToolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalToolbar.swift; sourceTree = ""; }; C159E81C2B66A06B00FDFE9C /* OSColor+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OSColor+Extension.swift"; sourceTree = ""; }; C1F26EA62B738B9900404083 /* NSView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSView+Extension.swift"; sourceTree = ""; }; + C1F26EE72B76CBFC00404083 /* TerminalWindowButtonsBackdropOverlayLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TerminalWindowButtonsBackdropOverlayLayer.h; sourceTree = ""; }; + C1F26EE82B76CBFC00404083 /* TerminalWindowButtonsBackdropOverlayLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TerminalWindowButtonsBackdropOverlayLayer.m; sourceTree = ""; }; + C1F26EEA2B76CC2400404083 /* Ghostty-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Ghostty-Bridging-Header.h"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -235,6 +239,7 @@ A5FEB2FF2ABB69450068369E /* main.swift */, A53426342A7DA53D00EBB7A2 /* AppDelegate.swift */, 857F63802A5E64F200CA4815 /* MainMenu.xib */, + C1F26EEA2B76CC2400404083 /* Ghostty-Bridging-Header.h */, ); path = macOS; sourceTree = ""; @@ -286,6 +291,8 @@ A5D0AF3A2B36A1DE00D21823 /* TerminalRestorable.swift */, A596309D2AEE1D6C00D64628 /* TerminalView.swift */, A51B78462AF4B58B00F3EDB9 /* TerminalWindow.swift */, + C1F26EE72B76CBFC00404083 /* TerminalWindowButtonsBackdropOverlayLayer.h */, + C1F26EE82B76CBFC00404083 /* TerminalWindowButtonsBackdropOverlayLayer.m */, AEF9CE232B6AD07A0017E195 /* TerminalToolbar.swift */, A535B9D9299C569B0017E2E4 /* ErrorView.swift */, ); @@ -477,6 +484,7 @@ A56D58892ACDE6CA00508D2C /* ServiceProvider.swift in Sources */, A51BFC222B2FB6B400E92F16 /* AboutView.swift in Sources */, A5278A9B2AA05B2600CD3039 /* Ghostty.Input.swift in Sources */, + C1F26EE92B76CBFC00404083 /* TerminalWindowButtonsBackdropOverlayLayer.m in Sources */, A59630972AEE163600D64628 /* HostingWindow.swift in Sources */, A59630A02AEF6AEB00D64628 /* TerminalManager.swift in Sources */, A51BFC2B2B30F6BE00E92F16 /* UpdateDelegate.swift in Sources */, @@ -614,6 +622,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.mitchellh.ghostty; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = "Sources/App/macOS/Ghostty-Bridging-Header.h"; SWIFT_VERSION = 5.0; }; name = ReleaseLocal; @@ -763,6 +772,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.mitchellh.ghostty; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = "Sources/App/macOS/Ghostty-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; }; @@ -801,6 +811,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.mitchellh.ghostty; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OBJC_BRIDGING_HEADER = "Sources/App/macOS/Ghostty-Bridging-Header.h"; SWIFT_VERSION = 5.0; }; name = Release; diff --git a/macos/Sources/App/macOS/Ghostty-Bridging-Header.h b/macos/Sources/App/macOS/Ghostty-Bridging-Header.h new file mode 100644 index 000000000..0b15a518e --- /dev/null +++ b/macos/Sources/App/macOS/Ghostty-Bridging-Header.h @@ -0,0 +1,5 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + +#import "TerminalWindowButtonsBackdropOverlayLayer.h" diff --git a/macos/Sources/Features/Terminal/TerminalWindow.swift b/macos/Sources/Features/Terminal/TerminalWindow.swift index d42a72de5..4cb75bd99 100644 --- a/macos/Sources/Features/Terminal/TerminalWindow.swift +++ b/macos/Sources/Features/Terminal/TerminalWindow.swift @@ -348,12 +348,18 @@ fileprivate class WindowDragView: NSView { // A view that matches the color of selected and unselected tabs in the adjacent tab bar. fileprivate class WindowButtonsBackdropView: NSView { - private let backgroundColor: NSColor + private let overlayLayer = TerminalWindowButtonsBackdropOverlayLayer() private let isLightTheme: Bool var isHighlighted: Bool = true { didSet { - setNeedsDisplay(self.bounds) + if isLightTheme { + overlayLayer.isHidden = isHighlighted + layer?.backgroundColor = .clear + } else { + overlayLayer.isHidden = true + layer?.backgroundColor = isHighlighted ? .clear : CGColor(genericGrayGamma2_2Gray: 0.0, alpha: 0.45) + } } } @@ -362,25 +368,16 @@ fileprivate class WindowButtonsBackdropView: NSView { } init(backgroundColor: CGColor) { - self.backgroundColor = NSColor(cgColor: backgroundColor)! self.isLightTheme = NSColor(cgColor: backgroundColor)!.isLightColor super.init(frame: .zero) - } - override func draw(_ dirtyRect: NSRect) { - if isLightTheme { - backgroundColor.setFill() - bounds.fill() + wantsLayer = true - if !isHighlighted { - let overlayColor = NSColor(cgColor: CGColor(genericGrayGamma2_2Gray: 0.95, alpha: 1))! - overlayColor.setFill() - bounds.fill(using: .plusDarker) - } - } else { - (isHighlighted ? backgroundColor : NSColor(cgColor: CGColor(genericGrayGamma2_2Gray: 0.0, alpha: 0.45))!).setFill() - bounds.fill() - } + overlayLayer.frame = layer!.bounds + overlayLayer.autoresizingMask = [.layerWidthSizable, .layerHeightSizable] + overlayLayer.backgroundColor = CGColor(genericGrayGamma2_2Gray: 0.95, alpha: 1) + + layer?.addSublayer(overlayLayer) } } diff --git a/macos/Sources/Features/Terminal/TerminalWindowButtonsBackdropOverlayLayer.h b/macos/Sources/Features/Terminal/TerminalWindowButtonsBackdropOverlayLayer.h new file mode 100644 index 000000000..2f5d0169a --- /dev/null +++ b/macos/Sources/Features/Terminal/TerminalWindowButtonsBackdropOverlayLayer.h @@ -0,0 +1,4 @@ +#import + +@interface TerminalWindowButtonsBackdropOverlayLayer: CALayer +@end diff --git a/macos/Sources/Features/Terminal/TerminalWindowButtonsBackdropOverlayLayer.m b/macos/Sources/Features/Terminal/TerminalWindowButtonsBackdropOverlayLayer.m new file mode 100644 index 000000000..9ce1250ec --- /dev/null +++ b/macos/Sources/Features/Terminal/TerminalWindowButtonsBackdropOverlayLayer.m @@ -0,0 +1,9 @@ +#import "TerminalWindowButtonsBackdropOverlayLayer.h" + +@implementation TerminalWindowButtonsBackdropOverlayLayer + +// A private compositing filter ("plus darker") that is used in titlebar +// tab bars to create the effect of recessed, unselected tabs. +- (id)compositingFilter { return @"plusD"; } + +@end From 0e482b8519fe7ca55c75b43eef514694568dd51f Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 10 Feb 2024 07:52:02 -0800 Subject: [PATCH 8/8] macos: nitpicks --- macos/Ghostty.xcodeproj/project.pbxproj | 10 +++++----- macos/Sources/App/macOS/Ghostty-Bridging-Header.h | 5 ----- macos/Sources/App/macOS/ghostty-bridging-header.h | 3 +++ macos/Sources/Features/Terminal/TerminalWindow.swift | 4 +--- 4 files changed, 9 insertions(+), 13 deletions(-) delete mode 100644 macos/Sources/App/macOS/Ghostty-Bridging-Header.h create mode 100644 macos/Sources/App/macOS/ghostty-bridging-header.h diff --git a/macos/Ghostty.xcodeproj/project.pbxproj b/macos/Ghostty.xcodeproj/project.pbxproj index 583313b92..b33d9b472 100644 --- a/macos/Ghostty.xcodeproj/project.pbxproj +++ b/macos/Ghostty.xcodeproj/project.pbxproj @@ -133,7 +133,7 @@ C1F26EA62B738B9900404083 /* NSView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSView+Extension.swift"; sourceTree = ""; }; C1F26EE72B76CBFC00404083 /* TerminalWindowButtonsBackdropOverlayLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TerminalWindowButtonsBackdropOverlayLayer.h; sourceTree = ""; }; C1F26EE82B76CBFC00404083 /* TerminalWindowButtonsBackdropOverlayLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TerminalWindowButtonsBackdropOverlayLayer.m; sourceTree = ""; }; - C1F26EEA2B76CC2400404083 /* Ghostty-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Ghostty-Bridging-Header.h"; sourceTree = ""; }; + C1F26EEA2B76CC2400404083 /* ghostty-bridging-header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ghostty-bridging-header.h"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -239,7 +239,7 @@ A5FEB2FF2ABB69450068369E /* main.swift */, A53426342A7DA53D00EBB7A2 /* AppDelegate.swift */, 857F63802A5E64F200CA4815 /* MainMenu.xib */, - C1F26EEA2B76CC2400404083 /* Ghostty-Bridging-Header.h */, + C1F26EEA2B76CC2400404083 /* ghostty-bridging-header.h */, ); path = macOS; sourceTree = ""; @@ -622,7 +622,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.mitchellh.ghostty; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_OBJC_BRIDGING_HEADER = "Sources/App/macOS/Ghostty-Bridging-Header.h"; + SWIFT_OBJC_BRIDGING_HEADER = "Sources/App/macOS/ghostty-bridging-header.h"; SWIFT_VERSION = 5.0; }; name = ReleaseLocal; @@ -772,7 +772,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.mitchellh.ghostty; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_OBJC_BRIDGING_HEADER = "Sources/App/macOS/Ghostty-Bridging-Header.h"; + SWIFT_OBJC_BRIDGING_HEADER = "Sources/App/macOS/ghostty-bridging-header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; }; @@ -811,7 +811,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.mitchellh.ghostty; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_OBJC_BRIDGING_HEADER = "Sources/App/macOS/Ghostty-Bridging-Header.h"; + SWIFT_OBJC_BRIDGING_HEADER = "Sources/App/macOS/ghostty-bridging-header.h"; SWIFT_VERSION = 5.0; }; name = Release; diff --git a/macos/Sources/App/macOS/Ghostty-Bridging-Header.h b/macos/Sources/App/macOS/Ghostty-Bridging-Header.h deleted file mode 100644 index 0b15a518e..000000000 --- a/macos/Sources/App/macOS/Ghostty-Bridging-Header.h +++ /dev/null @@ -1,5 +0,0 @@ -// -// Use this file to import your target's public headers that you would like to expose to Swift. -// - -#import "TerminalWindowButtonsBackdropOverlayLayer.h" diff --git a/macos/Sources/App/macOS/ghostty-bridging-header.h b/macos/Sources/App/macOS/ghostty-bridging-header.h new file mode 100644 index 000000000..6d2ccfaf3 --- /dev/null +++ b/macos/Sources/App/macOS/ghostty-bridging-header.h @@ -0,0 +1,3 @@ +// C imports here are exposed to Swift. + +#import "TerminalWindowButtonsBackdropOverlayLayer.h" diff --git a/macos/Sources/Features/Terminal/TerminalWindow.swift b/macos/Sources/Features/Terminal/TerminalWindow.swift index 4cb75bd99..f3f9bd4ed 100644 --- a/macos/Sources/Features/Terminal/TerminalWindow.swift +++ b/macos/Sources/Features/Terminal/TerminalWindow.swift @@ -206,9 +206,7 @@ class TerminalWindow: NSWindow { // as that of the active tab (i.e. the titlebar's background color), otherwise we make it the same // color as the background of unselected tabs. if let index = windowController?.window?.tabbedWindows?.firstIndex(of: self) { - let firstTabIsSelected = index == 0 - - windowButtonsBackdrop?.isHighlighted = firstTabIsSelected + windowButtonsBackdrop?.isHighlighted = index == 0 } // Color the new tab button's image to match the color of the tab title/keyboard shortcut labels,