diff --git a/Sources/Panels/BrowserPanel.swift b/Sources/Panels/BrowserPanel.swift index faf39dea..dfbd8a9c 100644 --- a/Sources/Panels/BrowserPanel.swift +++ b/Sources/Panels/BrowserPanel.swift @@ -210,6 +210,17 @@ enum BrowserThemeSettings { return defaultMode } + + static func apply(_ mode: BrowserThemeMode, to webView: WKWebView) { + switch mode { + case .system: + webView.appearance = nil + case .light: + webView.appearance = NSAppearance(named: .aqua) + case .dark: + webView.appearance = NSAppearance(named: .darkAqua) + } + } } enum BrowserImportHintVariant: String, CaseIterable, Identifiable { @@ -2295,6 +2306,10 @@ final class BrowserPanel: Panel, ObservableObject { profileID == BrowserProfileStore.shared.builtInDefaultProfileID } + var currentBrowserThemeMode: BrowserThemeMode { + browserThemeMode + } + private static let portalHostAreaThreshold: CGFloat = 4 private static let portalHostReplacementAreaGainRatio: CGFloat = 1.2 @@ -2468,8 +2483,9 @@ final class BrowserPanel: Panel, ObservableObject { if #available(macOS 13.3, *) { webView.isInspectable = true } - // Match the empty-page background to the terminal theme so newly-created browsers - // don't flash white before content loads. + // Match only the unpainted/loading background so newly-created browsers don't flash + // white before content loads. Do not force page appearance or inject color-scheme CSS; + // websites must keep control of their own theme. webView.underPageBackgroundColor = GhosttyBackgroundTheme.currentColor() // Always present as Safari. webView.customUserAgent = BrowserUserAgentSettings.safariUserAgent @@ -2544,7 +2560,6 @@ final class BrowserPanel: Panel, ObservableObject { self.realignRestoredSessionHistoryToLiveCurrentIfPossible() boundHistoryStore.recordVisit(url: webView.url, title: webView.title) self.refreshFavicon(from: webView) - self.applyBrowserThemeModeIfNeeded() // Keep find-in-page open through load completion and refresh matches for the new DOM. self.restoreFindStateAfterNavigation(replaySearch: true) } @@ -4929,6 +4944,9 @@ extension BrowserPanel { func setBrowserThemeMode(_ mode: BrowserThemeMode) { browserThemeMode = mode applyBrowserThemeModeIfNeeded() + for controller in popupControllers { + controller.setBrowserThemeMode(mode) + } } func refreshAppearanceDrivenColors() { @@ -5431,63 +5449,7 @@ extension BrowserPanel { private extension BrowserPanel { func applyBrowserThemeModeIfNeeded() { - switch browserThemeMode { - case .system: - webView.appearance = nil - case .light: - webView.appearance = NSAppearance(named: .aqua) - case .dark: - webView.appearance = NSAppearance(named: .darkAqua) - } - - let script = makeBrowserThemeModeScript(mode: browserThemeMode) - webView.evaluateJavaScript(script) { _, error in - #if DEBUG - if let error { - dlog("browser.themeMode error=\(error.localizedDescription)") - } - #endif - } - } - - func makeBrowserThemeModeScript(mode: BrowserThemeMode) -> String { - let colorSchemeLiteral: String - switch mode { - case .system: - colorSchemeLiteral = "null" - case .light: - colorSchemeLiteral = "'light'" - case .dark: - colorSchemeLiteral = "'dark'" - } - - return """ - (() => { - const metaId = 'cmux-browser-theme-mode-meta'; - const colorScheme = \(colorSchemeLiteral); - const root = document.documentElement || document.body; - if (!root) return; - - let meta = document.getElementById(metaId); - if (colorScheme) { - root.style.setProperty('color-scheme', colorScheme, 'important'); - root.setAttribute('data-cmux-browser-theme', colorScheme); - if (!meta) { - meta = document.createElement('meta'); - meta.id = metaId; - meta.name = 'color-scheme'; - (document.head || root).appendChild(meta); - } - meta.setAttribute('content', colorScheme); - } else { - root.style.removeProperty('color-scheme'); - root.removeAttribute('data-cmux-browser-theme'); - if (meta) { - meta.remove(); - } - } - })(); - """ + BrowserThemeSettings.apply(browserThemeMode, to: webView) } func scheduleDeveloperToolsRestoreRetry() { diff --git a/Sources/Panels/BrowserPopupWindowController.swift b/Sources/Panels/BrowserPopupWindowController.swift index b457ba85..623a9bc9 100644 --- a/Sources/Panels/BrowserPopupWindowController.swift +++ b/Sources/Panels/BrowserPopupWindowController.swift @@ -111,6 +111,7 @@ final class BrowserPopupWindowController: NSObject, NSWindowDelegate { } webView.underPageBackgroundColor = GhosttyBackgroundTheme.currentColor() webView.customUserAgent = BrowserUserAgentSettings.safariUserAgent + BrowserThemeSettings.apply(openerPanel?.currentBrowserThemeMode ?? BrowserThemeSettings.mode(), to: webView) self.webView = webView // --- Window sizing from WKWindowFeatures --- @@ -251,6 +252,13 @@ final class BrowserPopupWindowController: NSObject, NSWindowDelegate { childPopups.removeAll { $0 === child } } + func setBrowserThemeMode(_ mode: BrowserThemeMode) { + BrowserThemeSettings.apply(mode, to: webView) + for child in childPopups { + child.setBrowserThemeMode(mode) + } + } + // MARK: - Popup lifecycle func closePopup() {