From 9d6b9d78d86f3df33c87ff3f785561964f6987b0 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 22 Dec 2024 19:31:06 -0800 Subject: [PATCH] macos: set NSAppearance on windowDidLoad Fixes #3072 Previously, when `window-theme = auto`, the appearance was delayed enough on the DispatchQueue that the window was already visible. This would result in the window appearing with the wrong appearance before switching to the correct one. For annoying reasons, we can't set the NSApplication.shared.appearance in `applicationDidFinishLaunching` because it results in a deadlock with AppKit. This commit moves to set the `NSWindow.appearance` in `windowDidLoad` (and any config sync) to ensure that the appearance is set before the window is visible. This is probably the right solution anyways because this allows windows with different background colors to each have their own distinct appearance. --- macos/Sources/App/macOS/AppDelegate.swift | 19 +-------------- .../Terminal/TerminalController.swift | 3 +++ .../Sources/Ghostty/SurfaceView_AppKit.swift | 3 +++ .../Helpers/NSAppearance+Extension.swift | 23 +++++++++++++++++++ 4 files changed, 30 insertions(+), 18 deletions(-) diff --git a/macos/Sources/App/macOS/AppDelegate.swift b/macos/Sources/App/macOS/AppDelegate.swift index b38a019f0..7b0ff6fc2 100644 --- a/macos/Sources/App/macOS/AppDelegate.swift +++ b/macos/Sources/App/macOS/AppDelegate.swift @@ -546,24 +546,7 @@ class AppDelegate: NSObject, /// Sync the appearance of our app with the theme specified in the config. private func syncAppearance(config: Ghostty.Config) { - guard let theme = config.windowTheme else { return } - switch (theme) { - case "dark": - let appearance = NSAppearance(named: .darkAqua) - NSApplication.shared.appearance = appearance - - case "light": - let appearance = NSAppearance(named: .aqua) - NSApplication.shared.appearance = appearance - - case "auto": - let color = OSColor(config.backgroundColor) - let appearance = NSAppearance(named: color.isLightColor ? .aqua : .darkAqua) - NSApplication.shared.appearance = appearance - - default: - NSApplication.shared.appearance = nil - } + NSApplication.shared.appearance = .init(ghosttyConfig: config) } //MARK: - Restorable State diff --git a/macos/Sources/Features/Terminal/TerminalController.swift b/macos/Sources/Features/Terminal/TerminalController.swift index 67e7259f3..7fd1802dc 100644 --- a/macos/Sources/Features/Terminal/TerminalController.swift +++ b/macos/Sources/Features/Terminal/TerminalController.swift @@ -201,6 +201,9 @@ class TerminalController: BaseTerminalController { private func syncAppearance(_ surfaceConfig: Ghostty.SurfaceView.DerivedConfig) { guard let window = self.window as? TerminalWindow else { return } + // Set our explicit appearance if we need to based on the configuration. + window.appearance = surfaceConfig.windowAppearance + // If our window is not visible, then we do nothing. Some things such as blurring // have no effect if the window is not visible. Ultimately, we'll have this called // at some point when a surface becomes focused. diff --git a/macos/Sources/Ghostty/SurfaceView_AppKit.swift b/macos/Sources/Ghostty/SurfaceView_AppKit.swift index d06ab36eb..14f2a43c8 100644 --- a/macos/Sources/Ghostty/SurfaceView_AppKit.swift +++ b/macos/Sources/Ghostty/SurfaceView_AppKit.swift @@ -1097,12 +1097,14 @@ extension Ghostty { let backgroundOpacity: Double let macosWindowShadow: Bool let windowTitleFontFamily: String? + let windowAppearance: NSAppearance? init() { self.backgroundColor = Color(NSColor.windowBackgroundColor) self.backgroundOpacity = 1 self.macosWindowShadow = true self.windowTitleFontFamily = nil + self.windowAppearance = nil } init(_ config: Ghostty.Config) { @@ -1110,6 +1112,7 @@ extension Ghostty { self.backgroundOpacity = config.backgroundOpacity self.macosWindowShadow = config.macosWindowShadow self.windowTitleFontFamily = config.windowTitleFontFamily + self.windowAppearance = .init(ghosttyConfig: config) } } } diff --git a/macos/Sources/Helpers/NSAppearance+Extension.swift b/macos/Sources/Helpers/NSAppearance+Extension.swift index 336125574..28edb1a35 100644 --- a/macos/Sources/Helpers/NSAppearance+Extension.swift +++ b/macos/Sources/Helpers/NSAppearance+Extension.swift @@ -5,4 +5,27 @@ extension NSAppearance { var isDark: Bool { return name.rawValue.lowercased().contains("dark") } + + /// Initialize a desired NSAppearance for the Ghostty configuration. + convenience init?(ghosttyConfig config: Ghostty.Config) { + guard let theme = config.windowTheme else { return nil } + switch (theme) { + case "dark": + self.init(named: .darkAqua) + + case "light": + self.init(named: .aqua) + + case "auto": + let color = OSColor(config.backgroundColor) + if color.isLightColor { + self.init(named: .aqua) + } else { + self.init(named: .darkAqua) + } + + default: + return nil + } + } }