macOS: only show the update overlay if window doesn't support it

This commit is contained in:
Mitchell Hashimoto
2025-10-08 13:54:58 -07:00
parent 81e3ff90a3
commit f975ac8019
7 changed files with 73 additions and 12 deletions

View File

@@ -49,6 +49,9 @@ class BaseTerminalController: NSWindowController,
/// This can be set to show/hide the command palette. /// This can be set to show/hide the command palette.
@Published var commandPaletteIsShowing: Bool = false @Published var commandPaletteIsShowing: Bool = false
/// Set if the terminal view should show the update overlay.
@Published var updateOverlayIsVisible: Bool = false
/// Whether the terminal surface should focus when the mouse is over it. /// Whether the terminal surface should focus when the mouse is over it.
var focusFollowsMouse: Bool { var focusFollowsMouse: Bool {
self.derivedConfig.focusFollowsMouse self.derivedConfig.focusFollowsMouse
@@ -818,7 +821,18 @@ class BaseTerminalController: NSWindowController,
} }
} }
func fullscreenDidChange() {} func fullscreenDidChange() {
guard let fullscreenStyle else { return }
// When we enter fullscreen, we want to show the update overlay so that it
// is easily visible. For native fullscreen this is visible by showing the
// menubar but we don't want to rely on that.
if fullscreenStyle.isFullscreen {
updateOverlayIsVisible = true
} else {
updateOverlayIsVisible = defaultUpdateOverlayVisibility()
}
}
// MARK: Clipboard Confirmation // MARK: Clipboard Confirmation
@@ -900,6 +914,28 @@ class BaseTerminalController: NSWindowController,
fullscreenStyle = NativeFullscreen(window) fullscreenStyle = NativeFullscreen(window)
fullscreenStyle?.delegate = self fullscreenStyle?.delegate = self
} }
// Set our update overlay state
updateOverlayIsVisible = defaultUpdateOverlayVisibility()
}
func defaultUpdateOverlayVisibility() -> Bool {
guard let window else { return true }
// No titlebar we always show the update overlay because it can't support
// updates in the titlebar
guard window.styleMask.contains(.titled) else {
return true
}
// If it's a non terminal window we can't trust it has an update accessory,
// so we always want to show the overlay.
guard let window = window as? TerminalWindow else {
return true
}
// Show the overlay if the window isn't.
return !window.supportsUpdateAccessory
} }
// MARK: NSWindowDelegate // MARK: NSWindowDelegate

View File

@@ -31,6 +31,9 @@ protocol TerminalViewModel: ObservableObject {
/// The command palette state. /// The command palette state.
var commandPaletteIsShowing: Bool { get set } var commandPaletteIsShowing: Bool { get set }
/// The update overlay should be visible.
var updateOverlayIsVisible: Bool { get }
} }
/// The main terminal view. This terminal view supports splits. /// The main terminal view. This terminal view supports splits.
@@ -111,11 +114,13 @@ struct TerminalView<ViewModel: TerminalViewModel>: View {
} }
// Show update information above all else. // Show update information above all else.
if viewModel.updateOverlayIsVisible {
UpdateOverlay() UpdateOverlay()
} }
} }
} }
} }
}
fileprivate struct UpdateOverlay: View { fileprivate struct UpdateOverlay: View {
var body: some View { var body: some View {

View File

@@ -1,6 +1,9 @@
import AppKit import AppKit
class HiddenTitlebarTerminalWindow: TerminalWindow { class HiddenTitlebarTerminalWindow: TerminalWindow {
// No titlebar, we don't support accessories.
override var supportsUpdateAccessory: Bool { false }
override func awakeFromNib() { override func awakeFromNib() {
super.awakeFromNib() super.awakeFromNib()

View File

@@ -21,6 +21,13 @@ class TerminalWindow: NSWindow {
/// The configuration derived from the Ghostty config so we don't need to rely on references. /// The configuration derived from the Ghostty config so we don't need to rely on references.
private(set) var derivedConfig: DerivedConfig = .init() private(set) var derivedConfig: DerivedConfig = .init()
/// Whether this window supports the update accessory. If this is false, then views within this
/// window should determine how to show update notifications.
var supportsUpdateAccessory: Bool {
// Native window supports it.
true
}
/// Gets the terminal controller from the window controller. /// Gets the terminal controller from the window controller.
var terminalController: TerminalController? { var terminalController: TerminalController? {
windowController as? TerminalController windowController as? TerminalController
@@ -90,6 +97,7 @@ class TerminalWindow: NSWindow {
resetZoomAccessory.view.translatesAutoresizingMaskIntoConstraints = false resetZoomAccessory.view.translatesAutoresizingMaskIntoConstraints = false
// Create update notification accessory // Create update notification accessory
if supportsUpdateAccessory {
updateAccessory.layoutAttribute = .right updateAccessory.layoutAttribute = .right
updateAccessory.view = NSHostingView(rootView: UpdateAccessoryView( updateAccessory.view = NSHostingView(rootView: UpdateAccessoryView(
viewModel: viewModel, viewModel: viewModel,
@@ -99,6 +107,7 @@ class TerminalWindow: NSWindow {
addTitlebarAccessoryViewController(updateAccessory) addTitlebarAccessoryViewController(updateAccessory)
updateAccessory.view.translatesAutoresizingMaskIntoConstraints = false updateAccessory.view.translatesAutoresizingMaskIntoConstraints = false
} }
}
// Setup the accessory view for tabs that shows our keyboard shortcuts, // Setup the accessory view for tabs that shows our keyboard shortcuts,
// zoomed state, etc. Note I tried to use SwiftUI here but ran into issues // zoomed state, etc. Note I tried to use SwiftUI here but ran into issues

View File

@@ -9,6 +9,10 @@ class TitlebarTabsTahoeTerminalWindow: TransparentTitlebarTerminalWindow, NSTool
/// The view model for SwiftUI views /// The view model for SwiftUI views
private var viewModel = ViewModel() private var viewModel = ViewModel()
/// Titlebar tabs can't support the update accessory because of the way we layout
/// the native tabs back into the menu bar.
override var supportsUpdateAccessory: Bool { false }
deinit { deinit {
tabBarObserver = nil tabBarObserver = nil
} }

View File

@@ -2,6 +2,10 @@ import Cocoa
/// Titlebar tabs for macOS 13 to 15. /// Titlebar tabs for macOS 13 to 15.
class TitlebarTabsVenturaTerminalWindow: TerminalWindow { class TitlebarTabsVenturaTerminalWindow: TerminalWindow {
/// Titlebar tabs can't support the update accessory because of the way we layout
/// the native tabs back into the menu bar.
override var supportsUpdateAccessory: Bool { false }
/// This is used to determine if certain elements should be drawn light or dark and should /// This is used to determine if certain elements should be drawn light or dark and should
/// be updated whenever the window background color or surrounding elements changes. /// be updated whenever the window background color or surrounding elements changes.
fileprivate var isLightTheme: Bool = false fileprivate var isLightTheme: Bool = false