mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 16:56:09 +03:00
Merge pull request #1437 from mitchellh/theme-auto
config: add window-theme = auto for automatic choosing based on bg color
This commit is contained in:
@ -377,6 +377,11 @@ class AppDelegate: NSObject,
|
||||
// Config could change window appearance
|
||||
syncAppearance()
|
||||
|
||||
// Update all of our windows
|
||||
terminalManager.windows.forEach { window in
|
||||
window.controller.configDidReload()
|
||||
}
|
||||
|
||||
// If we have configuration errors, we need to show them.
|
||||
let c = ConfigurationErrorsController.sharedInstance
|
||||
c.errors = state.config.errors
|
||||
@ -399,6 +404,11 @@ class AppDelegate: NSObject,
|
||||
let appearance = NSAppearance(named: .aqua)
|
||||
NSApplication.shared.appearance = appearance
|
||||
|
||||
case "auto":
|
||||
let color = OSColor(ghostty.config.backgroundColor)
|
||||
let appearance = NSAppearance(named: color.isLightColor ? .aqua : .darkAqua)
|
||||
NSApplication.shared.appearance = appearance
|
||||
|
||||
default:
|
||||
NSApplication.shared.appearance = nil
|
||||
}
|
||||
|
@ -105,6 +105,10 @@ class TerminalController: NSWindowController, NSWindowDelegate,
|
||||
|
||||
//MARK: - Methods
|
||||
|
||||
func configDidReload() {
|
||||
syncAppearance()
|
||||
}
|
||||
|
||||
/// Update the accessory view of each tab according to the keyboard
|
||||
/// shortcut that activates it (if any). This is called when the key window
|
||||
/// changes and when a window is closed.
|
||||
@ -151,6 +155,20 @@ class TerminalController: NSWindowController, NSWindowDelegate,
|
||||
self.relabelTabs()
|
||||
}
|
||||
|
||||
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)
|
||||
window.appearance = appearance
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: - NSWindowController
|
||||
|
||||
override func windowWillLoad() {
|
||||
@ -214,6 +232,7 @@ class TerminalController: NSWindowController, NSWindowDelegate,
|
||||
if (ghostty.config.macosTitlebarTabs) {
|
||||
window.tabbingMode = .preferred
|
||||
window.titlebarTabs = true
|
||||
syncAppearance()
|
||||
DispatchQueue.main.async {
|
||||
window.tabbingMode = .automatic
|
||||
}
|
||||
|
@ -59,16 +59,6 @@ class TerminalWindow: NSWindow {
|
||||
}) {
|
||||
toolbarTitleView.isHidden = true
|
||||
}
|
||||
|
||||
// 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 let appDelegate = NSApp.delegate as? AppDelegate {
|
||||
let color = OSColor(appDelegate.ghostty.config.backgroundColor)
|
||||
let appearance = NSAppearance(named: color.isLightColor ? .aqua : .darkAqua)
|
||||
self.appearance = appearance
|
||||
}
|
||||
} else {
|
||||
// "expanded" places the toolbar below the titlebar, so setting this style and
|
||||
// removing the toolbar ensures that the titlebar will be the default height.
|
||||
|
@ -133,6 +133,14 @@ pub fn init(core_app: *CoreApp, opts: Options) !App {
|
||||
c.adw_style_manager_set_color_scheme(
|
||||
style_manager,
|
||||
switch (config.@"window-theme") {
|
||||
.auto => auto: {
|
||||
const lum = config.background.toTerminalRGB().perceivedLuminance();
|
||||
break :auto if (lum > 0.5)
|
||||
c.ADW_COLOR_SCHEME_PREFER_LIGHT
|
||||
else
|
||||
c.ADW_COLOR_SCHEME_PREFER_DARK;
|
||||
},
|
||||
|
||||
.system => c.ADW_COLOR_SCHEME_PREFER_LIGHT,
|
||||
.dark => c.ADW_COLOR_SCHEME_FORCE_DARK,
|
||||
.light => c.ADW_COLOR_SCHEME_FORCE_LIGHT,
|
||||
|
@ -600,9 +600,13 @@ keybind: Keybinds = .{},
|
||||
/// borders.
|
||||
@"window-decoration": bool = true,
|
||||
|
||||
/// The theme to use for the windows. The default is `system` which means that
|
||||
/// whatever the system theme is will be used. This can also be set to `light`
|
||||
/// or `dark` to force a specific theme regardless of the system settings.
|
||||
/// The theme to use for the windows. Valid values:
|
||||
///
|
||||
/// * `auto` - Determine the theme based on the configured terminal
|
||||
/// background color.
|
||||
/// * `system` - Use the system theme.
|
||||
/// * `light` - Use the light theme regardless of system theme.
|
||||
/// * `dark` - Use the dark theme regardless of system theme.
|
||||
///
|
||||
/// On macOS, if `macos-titlebar-tabs` is set, the window theme will be
|
||||
/// automatically set based on the luminosity of the terminal background color.
|
||||
@ -610,7 +614,7 @@ keybind: Keybinds = .{},
|
||||
/// non-terminal windows within Ghostty.
|
||||
///
|
||||
/// This is currently only supported on macOS and Linux.
|
||||
@"window-theme": WindowTheme = .system,
|
||||
@"window-theme": WindowTheme = .auto,
|
||||
|
||||
/// The colorspace to use for the terminal window. The default is `srgb` but
|
||||
/// this can also be set to `display-p3` to use the Display P3 colorspace.
|
||||
@ -3342,6 +3346,7 @@ pub const OSCColorReportFormat = enum {
|
||||
|
||||
/// The default window theme.
|
||||
pub const WindowTheme = enum {
|
||||
auto,
|
||||
system,
|
||||
light,
|
||||
dark,
|
||||
|
@ -144,6 +144,17 @@ pub const RGB = struct {
|
||||
return std.math.pow(f64, (normalized + 0.055) / 1.055, 2.4);
|
||||
}
|
||||
|
||||
/// Calculates "perceived luminance" which is better for determining
|
||||
/// light vs dark.
|
||||
///
|
||||
/// Source: https://www.w3.org/TR/AERT/#color-contrast
|
||||
pub fn perceivedLuminance(self: RGB) f64 {
|
||||
const r_f64: f64 = @floatFromInt(self.r);
|
||||
const g_f64: f64 = @floatFromInt(self.g);
|
||||
const b_f64: f64 = @floatFromInt(self.b);
|
||||
return 0.299 * (r_f64 / 255) + 0.587 * (g_f64 / 255) + 0.114 * (b_f64 / 255);
|
||||
}
|
||||
|
||||
test "size" {
|
||||
try std.testing.expectEqual(@as(usize, 24), @bitSizeOf(RGB));
|
||||
try std.testing.expectEqual(@as(usize, 3), @sizeOf(RGB));
|
||||
|
Reference in New Issue
Block a user