Update standard title/tab bar when config changes

This commit is contained in:
Pete Schaffner
2024-04-05 15:19:20 +02:00
parent da9df865ef
commit 4ede25dd00
2 changed files with 54 additions and 43 deletions

View File

@ -166,15 +166,9 @@ class TerminalController: NSWindowController, NSWindowDelegate,
private func syncAppearance() {
guard let window = self.window as? TerminalWindow else { return }
// We match the appearance depending on the lightness/darkness of the
// background color. We have to do this because our titlebars in tabs inherit
// our background color for the focused tab but use the macOS theme for the
// rest of the titlebar.
if (window.titlebarTabs) {
let color = OSColor(ghostty.config.backgroundColor)
let appearance = NSAppearance(named: color.isLightColor ? .aqua : .darkAqua)
let backgroundColor = OSColor(ghostty.config.backgroundColor)
let appearance = NSAppearance(named: backgroundColor.isLightColor ? .aqua : .darkAqua)
window.appearance = appearance
}
// Set the font for the window and tab titles.
if let titleFontName = ghostty.config.windowTitleFontFamily {
@ -182,6 +176,10 @@ class TerminalController: NSWindowController, NSWindowDelegate,
} else {
window.titlebarFont = nil
}
window.backgroundColor = backgroundColor
window.titlebarColor = backgroundColor.withAlphaComponent(ghostty.config.backgroundOpacity)
window.updateToolbar()
}
/// Update all surfaces with the focus state. This ensures that libghostty has an accurate view about
@ -254,10 +252,11 @@ class TerminalController: NSWindowController, NSWindowDelegate,
window.center()
// Set the background color of the window
window.backgroundColor = NSColor(ghostty.config.backgroundColor)
let backgroundColor = NSColor(ghostty.config.backgroundColor)
window.backgroundColor = backgroundColor
// This makes sure our titlebar renders correctly when there is a transparent background
window.titlebarOpacity = ghostty.config.backgroundOpacity
window.titlebarColor = backgroundColor.withAlphaComponent(ghostty.config.backgroundOpacity)
// Handle titlebar tabs config option. Something about what we do while setting up the
// titlebar tabs interferes with the window restore process unless window.tabbingMode

View File

@ -4,14 +4,14 @@ class TerminalWindow: NSWindow {
@objc dynamic var surfaceIsZoomed: Bool = false
@objc dynamic var keyEquivalent: String = ""
var titlebarOpacity: CGFloat = 1 {
lazy var titlebarColor: NSColor = backgroundColor {
didSet {
guard let titlebarContainer = contentView?.superview?.subviews.first(where: {
$0.className == "NSTitlebarContainerView"
}) else { return }
titlebarContainer.wantsLayer = true
titlebarContainer.layer?.backgroundColor = backgroundColor.withAlphaComponent(titlebarOpacity).cgColor
titlebarContainer.layer?.backgroundColor = titlebarColor.cgColor
}
}
@ -182,6 +182,12 @@ class TerminalWindow: NSWindow {
// MARK: -
func updateToolbar() {
newTabButtonImageLayer = nil
effectViewIsHidden = false
}
private var newTabButtonImage: NSImage? = nil
private var newTabButtonImageLayer: VibrantLayer? = nil
// Since we are coloring the new tab button's image, it doesn't respond to the
@ -209,7 +215,12 @@ 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 }
if newTabButtonImage == nil {
newTabButtonImage = newTabButtonImageView.image
}
guard let newTabButtonImage else { return }
let isLightTheme = backgroundColor.isLightColor
@ -242,8 +253,6 @@ class TerminalWindow: NSWindow {
backgroundColor.luminance < 0.05
}
lazy var backgroundColorWithOpacity: NSColor = backgroundColor.withAlphaComponent(titlebarOpacity)
private func updateTabsForVeryDarkBackgrounds() {
guard hasVeryDarkBackground else { return }
@ -255,13 +264,15 @@ class TerminalWindow: NSWindow {
guard let activeTabBackgroundView = titlebarContainer.firstDescendant(withClassName: "NSTabButton")?.superview?.subviews.last?.firstDescendant(withID: "_backgroundView")
else { return }
activeTabBackgroundView.layer?.backgroundColor = backgroundColorWithOpacity.cgColor
titlebarContainer.layer?.backgroundColor = backgroundColorWithOpacity.highlight(withLevel: 0.14)?.cgColor
activeTabBackgroundView.layer?.backgroundColor = titlebarColor.cgColor
titlebarContainer.layer?.backgroundColor = titlebarColor.highlight(withLevel: 0.14)?.cgColor
} else {
titlebarContainer.layer?.backgroundColor = backgroundColorWithOpacity.cgColor
titlebarContainer.layer?.backgroundColor = titlebarColor.cgColor
}
}
// MARK: - Split zooming
private func updateResetZoomTitlebarButtonVisibility() {
guard let tabGroup, let resetZoomTitlebarAccessoryViewController else { return }
@ -282,24 +293,6 @@ class TerminalWindow: NSWindow {
}
}
// We have to regenerate a toolbar when the titlebar tabs setting changes since our
// custom toolbar conditionally generates the items based on this setting. I tried to
// invalidate the toolbar items and force a refresh, but as far as I can tell that
// isn't possible.
private func generateToolbar() {
let terminalToolbar = TerminalToolbar(identifier: "Toolbar")
toolbar = terminalToolbar
toolbarStyle = .unifiedCompact
if let resetZoomItem = terminalToolbar.items.first(where: { $0.itemIdentifier == .resetZoom }) {
resetZoomItem.view = resetZoomToolbarButton
resetZoomItem.view!.removeConstraints(resetZoomItem.view!.constraints)
resetZoomItem.view!.widthAnchor.constraint(equalToConstant: 22).isActive = true
resetZoomItem.view!.heightAnchor.constraint(equalToConstant: 20).isActive = true
}
updateResetZoomTitlebarButtonVisibility()
}
private func generateResetZoomButton() -> NSButton {
let button = NSButton()
button.target = nil
@ -356,6 +349,24 @@ class TerminalWindow: NSWindow {
}
}
// We have to regenerate a toolbar when the titlebar tabs setting changes since our
// custom toolbar conditionally generates the items based on this setting. I tried to
// invalidate the toolbar items and force a refresh, but as far as I can tell that
// isn't possible.
func generateToolbar() {
let terminalToolbar = TerminalToolbar(identifier: "Toolbar")
toolbar = terminalToolbar
toolbarStyle = .unifiedCompact
if let resetZoomItem = terminalToolbar.items.first(where: { $0.itemIdentifier == .resetZoom }) {
resetZoomItem.view = resetZoomToolbarButton
resetZoomItem.view!.removeConstraints(resetZoomItem.view!.constraints)
resetZoomItem.view!.widthAnchor.constraint(equalToConstant: 22).isActive = true
resetZoomItem.view!.heightAnchor.constraint(equalToConstant: 20).isActive = true
}
updateResetZoomTitlebarButtonVisibility()
}
// Find the NSTextField responsible for displaying the titlebar's title.
private var titlebarTextField: NSTextField? {
guard let titlebarContainer = contentView?.superview?.subviews
@ -382,14 +393,15 @@ 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()
hideTitleBarSeparators()
}
// For titlebar tabs, we want to hide the separator view so that we get rid
// of an aesthetically unpleasing shadow.
private func hideTitleBarSeparators() {
guard titlebarTabs else { return }
guard let titlebarContainer = contentView?.superview?.subviews.first(where: {
@ -589,7 +601,7 @@ fileprivate class WindowButtonsBackdropView: NSView {
layer?.backgroundColor = .clear
} else {
let systemOverlayColor = NSColor(cgColor: CGColor(genericGrayGamma2_2Gray: 0.0, alpha: 0.45))!
let titlebarBackgroundColor = terminalWindow.backgroundColorWithOpacity.blended(withFraction: 1, of: systemOverlayColor)
let titlebarBackgroundColor = terminalWindow.titlebarColor.blended(withFraction: 1, of: systemOverlayColor)
let highlightedColor = terminalWindow.hasVeryDarkBackground ? terminalWindow.backgroundColor : .clear
let backgroundColor = terminalWindow.hasVeryDarkBackground ? titlebarBackgroundColor : systemOverlayColor