mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 16:56:09 +03:00
Merge pull request #1838 from ghostty-org/macos-terminal-style
macOS: prefer window shadowing (configurable), move blur config to window controller
This commit is contained in:
@ -513,7 +513,6 @@ ghostty_surface_config_s ghostty_surface_config_new();
|
|||||||
ghostty_surface_t ghostty_surface_new(ghostty_app_t, ghostty_surface_config_s*);
|
ghostty_surface_t ghostty_surface_new(ghostty_app_t, ghostty_surface_config_s*);
|
||||||
void ghostty_surface_free(ghostty_surface_t);
|
void ghostty_surface_free(ghostty_surface_t);
|
||||||
ghostty_app_t ghostty_surface_app(ghostty_surface_t);
|
ghostty_app_t ghostty_surface_app(ghostty_surface_t);
|
||||||
bool ghostty_surface_transparent(ghostty_surface_t);
|
|
||||||
bool ghostty_surface_needs_confirm_quit(ghostty_surface_t);
|
bool ghostty_surface_needs_confirm_quit(ghostty_surface_t);
|
||||||
void ghostty_surface_refresh(ghostty_surface_t);
|
void ghostty_surface_refresh(ghostty_surface_t);
|
||||||
void ghostty_surface_draw(ghostty_surface_t);
|
void ghostty_surface_draw(ghostty_surface_t);
|
||||||
@ -586,7 +585,7 @@ bool ghostty_inspector_metal_shutdown(ghostty_inspector_t);
|
|||||||
|
|
||||||
// APIs I'd like to get rid of eventually but are still needed for now.
|
// APIs I'd like to get rid of eventually but are still needed for now.
|
||||||
// Don't use these unless you know what you're doing.
|
// Don't use these unless you know what you're doing.
|
||||||
void ghostty_set_window_background_blur(ghostty_surface_t, void*);
|
void ghostty_set_window_background_blur(ghostty_app_t, void*);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -166,6 +166,16 @@ class TerminalController: NSWindowController, NSWindowDelegate,
|
|||||||
private func syncAppearance() {
|
private func syncAppearance() {
|
||||||
guard let window = self.window as? TerminalWindow else { return }
|
guard let window = self.window as? TerminalWindow else { return }
|
||||||
|
|
||||||
|
// If our window is not visible, then delay this. This is possible specifically
|
||||||
|
// during state restoration but probably in other scenarios as well. To delay,
|
||||||
|
// we just loop directly on the dispatch queue. We have to delay because some
|
||||||
|
// APIs such as window blur have no effect unless the window is visible.
|
||||||
|
guard window.isVisible else {
|
||||||
|
// Weak window so that if the window changes or is destroyed we aren't holding a ref
|
||||||
|
DispatchQueue.main.async { [weak self] in self?.syncAppearance() }
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Set the font for the window and tab titles.
|
// Set the font for the window and tab titles.
|
||||||
if let titleFontName = ghostty.config.windowTitleFontFamily {
|
if let titleFontName = ghostty.config.windowTitleFontFamily {
|
||||||
window.titlebarFont = NSFont(name: titleFontName, size: NSFont.systemFontSize)
|
window.titlebarFont = NSFont(name: titleFontName, size: NSFont.systemFontSize)
|
||||||
@ -173,6 +183,23 @@ class TerminalController: NSWindowController, NSWindowDelegate,
|
|||||||
window.titlebarFont = nil
|
window.titlebarFont = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we have window transparency then set it transparent. Otherwise set it opaque.
|
||||||
|
if (ghostty.config.backgroundOpacity < 1) {
|
||||||
|
window.isOpaque = false
|
||||||
|
|
||||||
|
// This is weird, but we don't use ".clear" because this creates a look that
|
||||||
|
// matches Terminal.app much more closer. This lets users transition from
|
||||||
|
// Terminal.app more easily.
|
||||||
|
window.backgroundColor = .white.withAlphaComponent(0.001)
|
||||||
|
|
||||||
|
ghostty_set_window_background_blur(ghostty.app, Unmanaged.passUnretained(window).toOpaque())
|
||||||
|
} else {
|
||||||
|
window.isOpaque = true
|
||||||
|
window.backgroundColor = .windowBackgroundColor
|
||||||
|
}
|
||||||
|
|
||||||
|
window.hasShadow = ghostty.config.macosWindowShadow
|
||||||
|
|
||||||
guard window.hasStyledTabs else { return }
|
guard window.hasStyledTabs else { return }
|
||||||
|
|
||||||
// The titlebar is always updated. We don't need to worry about opacity
|
// The titlebar is always updated. We don't need to worry about opacity
|
||||||
|
@ -236,6 +236,14 @@ extension Ghostty {
|
|||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var macosWindowShadow: Bool {
|
||||||
|
guard let config = self.config else { return false }
|
||||||
|
var v = false;
|
||||||
|
let key = "macos-window-shadow"
|
||||||
|
_ = ghostty_config_get(config, &v, key, UInt(key.count))
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
var backgroundColor: Color {
|
var backgroundColor: Color {
|
||||||
var rgb: UInt32 = 0
|
var rgb: UInt32 = 0
|
||||||
let bg_key = "background"
|
let bg_key = "background"
|
||||||
@ -268,6 +276,14 @@ extension Ghostty {
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var backgroundBlurRadius: Int {
|
||||||
|
guard let config = self.config else { return 1 }
|
||||||
|
var v: Int = 0
|
||||||
|
let key = "background-blur-radius"
|
||||||
|
_ = ghostty_config_get(config, &v, key, UInt(key.count))
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
var unfocusedSplitOpacity: Double {
|
var unfocusedSplitOpacity: Double {
|
||||||
guard let config = self.config else { return 1 }
|
guard let config = self.config else { return 1 }
|
||||||
var opacity: Double = 0.85
|
var opacity: Double = 0.85
|
||||||
|
@ -342,40 +342,6 @@ extension Ghostty {
|
|||||||
|
|
||||||
// MARK: - NSView
|
// MARK: - NSView
|
||||||
|
|
||||||
override func viewDidMoveToWindow() {
|
|
||||||
// Set our background blur if requested
|
|
||||||
setWindowBackgroundBlur(window)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This function sets the window background to blur if it is configured on the surface.
|
|
||||||
private func setWindowBackgroundBlur(_ targetWindow: NSWindow?) {
|
|
||||||
// Surface must desire transparency
|
|
||||||
guard let surface = self.surface,
|
|
||||||
ghostty_surface_transparent(surface) else { return }
|
|
||||||
|
|
||||||
// Our target should always be our own view window
|
|
||||||
guard let target = targetWindow,
|
|
||||||
let window = self.window,
|
|
||||||
target == window else { return }
|
|
||||||
|
|
||||||
// If our window is not visible, then delay this. This is possible specifically
|
|
||||||
// during state restoration but probably in other scenarios as well. To delay,
|
|
||||||
// we just loop directly on the dispatch queue.
|
|
||||||
guard window.isVisible else {
|
|
||||||
// Weak window so that if the window changes or is destroyed we aren't holding a ref
|
|
||||||
DispatchQueue.main.async { [weak self, weak window] in self?.setWindowBackgroundBlur(window) }
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the window transparency settings
|
|
||||||
window.isOpaque = false
|
|
||||||
window.hasShadow = false
|
|
||||||
window.backgroundColor = .clear
|
|
||||||
|
|
||||||
// If we have a blur, set the blur
|
|
||||||
ghostty_set_window_background_blur(surface, Unmanaged.passUnretained(window).toOpaque())
|
|
||||||
}
|
|
||||||
|
|
||||||
override func becomeFirstResponder() -> Bool {
|
override func becomeFirstResponder() -> Bool {
|
||||||
let result = super.becomeFirstResponder()
|
let result = super.becomeFirstResponder()
|
||||||
if (result) { focusDidChange(true) }
|
if (result) { focusDidChange(true) }
|
||||||
|
@ -1474,11 +1474,6 @@ pub const CAPI = struct {
|
|||||||
return surface.app;
|
return surface.app;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the surface has transparency set.
|
|
||||||
export fn ghostty_surface_transparent(surface: *Surface) bool {
|
|
||||||
return surface.app.config.@"background-opacity" < 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if the surface needs to confirm quitting.
|
/// Returns true if the surface needs to confirm quitting.
|
||||||
export fn ghostty_surface_needs_confirm_quit(surface: *Surface) bool {
|
export fn ghostty_surface_needs_confirm_quit(surface: *Surface) bool {
|
||||||
return surface.core_surface.needsConfirmQuit();
|
return surface.core_surface.needsConfirmQuit();
|
||||||
@ -1850,13 +1845,13 @@ pub const CAPI = struct {
|
|||||||
/// This uses an undocumented, non-public API because this is what
|
/// This uses an undocumented, non-public API because this is what
|
||||||
/// every terminal appears to use, including Terminal.app.
|
/// every terminal appears to use, including Terminal.app.
|
||||||
export fn ghostty_set_window_background_blur(
|
export fn ghostty_set_window_background_blur(
|
||||||
ptr: *Surface,
|
app: *App,
|
||||||
window: *anyopaque,
|
window: *anyopaque,
|
||||||
) void {
|
) void {
|
||||||
// This is only supported on macOS
|
// This is only supported on macOS
|
||||||
if (comptime builtin.target.os.tag != .macos) return;
|
if (comptime builtin.target.os.tag != .macos) return;
|
||||||
|
|
||||||
const config = ptr.app.config;
|
const config = app.config;
|
||||||
|
|
||||||
// Do nothing if we don't have background transparency enabled
|
// Do nothing if we don't have background transparency enabled
|
||||||
if (config.@"background-opacity" >= 1.0) return;
|
if (config.@"background-opacity" >= 1.0) return;
|
||||||
|
@ -368,9 +368,6 @@ palette: Palette = .{},
|
|||||||
/// The opacity level (opposite of transparency) of the background. A value of
|
/// The opacity level (opposite of transparency) of the background. A value of
|
||||||
/// 1 is fully opaque and a value of 0 is fully transparent. A value less than 0
|
/// 1 is fully opaque and a value of 0 is fully transparent. A value less than 0
|
||||||
/// or greater than 1 will be clamped to the nearest valid value.
|
/// or greater than 1 will be clamped to the nearest valid value.
|
||||||
///
|
|
||||||
/// Changing this value at runtime (and reloading config) will only affect new
|
|
||||||
/// windows, tabs, and splits.
|
|
||||||
@"background-opacity": f64 = 1.0,
|
@"background-opacity": f64 = 1.0,
|
||||||
|
|
||||||
/// A positive value enables blurring of the background when background-opacity
|
/// A positive value enables blurring of the background when background-opacity
|
||||||
@ -988,6 +985,11 @@ keybind: Keybinds = .{},
|
|||||||
/// This does not work with GLFW builds.
|
/// This does not work with GLFW builds.
|
||||||
@"macos-option-as-alt": OptionAsAlt = .false,
|
@"macos-option-as-alt": OptionAsAlt = .false,
|
||||||
|
|
||||||
|
/// Whether to enable the macOS window shadow. The default value is true.
|
||||||
|
/// With some window managers and window transparency settings, you may
|
||||||
|
/// find false more visually appealing.
|
||||||
|
@"macos-window-shadow": bool = true,
|
||||||
|
|
||||||
/// Put every surface (tab, split, window) into a dedicated Linux cgroup.
|
/// Put every surface (tab, split, window) into a dedicated Linux cgroup.
|
||||||
///
|
///
|
||||||
/// This makes it so that resource management can be done on a per-surface
|
/// This makes it so that resource management can be done on a per-surface
|
||||||
|
Reference in New Issue
Block a user