mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
feat: add macos-window-shadow
optionally enable the window shadow (and border) like Terminal.app
This commit is contained in:
@ -71,8 +71,8 @@ class TerminalController: NSWindowController, NSWindowDelegate,
|
||||
super.init(window: nil)
|
||||
|
||||
// Initialize our initial surface.
|
||||
guard let ghostty_app = ghostty.app else { preconditionFailure("app must be loaded") }
|
||||
self.surfaceTree = tree ?? .leaf(.init(ghostty_app, baseConfig: base))
|
||||
guard ghostty.app != nil else { preconditionFailure("app must be loaded") }
|
||||
self.surfaceTree = tree ?? .leaf(.init(ghostty, baseConfig: base))
|
||||
|
||||
// Setup our notifications for behaviors
|
||||
let center = NotificationCenter.default
|
||||
|
@ -236,6 +236,14 @@ extension Ghostty {
|
||||
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 rgb: UInt32 = 0
|
||||
let bg_key = "background"
|
||||
|
@ -168,13 +168,13 @@ extension Ghostty {
|
||||
}
|
||||
|
||||
class Leaf: ObservableObject, Equatable, Hashable, Codable {
|
||||
let app: ghostty_app_t
|
||||
let app: Ghostty.App
|
||||
@Published var surface: SurfaceView
|
||||
|
||||
weak var parent: SplitNode.Container?
|
||||
|
||||
/// Initialize a new leaf which creates a new terminal surface.
|
||||
init(_ app: ghostty_app_t, baseConfig: SurfaceConfiguration? = nil, uuid: UUID? = nil) {
|
||||
init(_ app: Ghostty.App, baseConfig: SurfaceConfiguration? = nil, uuid: UUID? = nil) {
|
||||
self.app = app
|
||||
self.surface = SurfaceView(app, baseConfig: baseConfig, uuid: uuid)
|
||||
}
|
||||
@ -182,14 +182,14 @@ extension Ghostty {
|
||||
// MARK: - Hashable
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
hasher.combine(app)
|
||||
hasher.combine(app.app)
|
||||
hasher.combine(surface)
|
||||
}
|
||||
|
||||
// MARK: - Equatable
|
||||
|
||||
static func == (lhs: Leaf, rhs: Leaf) -> Bool {
|
||||
return lhs.app == rhs.app && lhs.surface === rhs.surface
|
||||
return lhs.app.app == rhs.app.app && lhs.surface === rhs.surface
|
||||
}
|
||||
|
||||
// MARK: - Codable
|
||||
@ -203,7 +203,7 @@ extension Ghostty {
|
||||
// Decoding uses the global Ghostty app
|
||||
guard let del = NSApplication.shared.delegate,
|
||||
let appDel = del as? AppDelegate,
|
||||
let app = appDel.ghostty.app else {
|
||||
appDel.ghostty.app != nil else {
|
||||
throw TerminalRestoreError.delegateInvalid
|
||||
}
|
||||
|
||||
@ -212,7 +212,7 @@ extension Ghostty {
|
||||
var config = SurfaceConfiguration()
|
||||
config.workingDirectory = try container.decode(String?.self, forKey: .pwd)
|
||||
|
||||
self.init(app, baseConfig: config, uuid: uuid)
|
||||
self.init(appDel.ghostty, baseConfig: config, uuid: uuid)
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
@ -223,7 +223,7 @@ extension Ghostty {
|
||||
}
|
||||
|
||||
class Container: ObservableObject, Equatable, Hashable, Codable {
|
||||
let app: ghostty_app_t
|
||||
let app: Ghostty.App
|
||||
let direction: SplitViewDirection
|
||||
|
||||
@Published var topLeft: SplitNode
|
||||
@ -335,7 +335,7 @@ extension Ghostty {
|
||||
// MARK: - Hashable
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
hasher.combine(app)
|
||||
hasher.combine(app.app)
|
||||
hasher.combine(direction)
|
||||
hasher.combine(topLeft)
|
||||
hasher.combine(bottomRight)
|
||||
@ -344,7 +344,7 @@ extension Ghostty {
|
||||
// MARK: - Equatable
|
||||
|
||||
static func == (lhs: Container, rhs: Container) -> Bool {
|
||||
return lhs.app == rhs.app &&
|
||||
return lhs.app.app == rhs.app.app &&
|
||||
lhs.direction == rhs.direction &&
|
||||
lhs.topLeft == rhs.topLeft &&
|
||||
lhs.bottomRight == rhs.bottomRight
|
||||
@ -363,12 +363,12 @@ extension Ghostty {
|
||||
// Decoding uses the global Ghostty app
|
||||
guard let del = NSApplication.shared.delegate,
|
||||
let appDel = del as? AppDelegate,
|
||||
let app = appDel.ghostty.app else {
|
||||
appDel.ghostty.app != nil else {
|
||||
throw TerminalRestoreError.delegateInvalid
|
||||
}
|
||||
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.app = app
|
||||
self.app = appDel.ghostty
|
||||
self.direction = try container.decode(SplitViewDirection.self, forKey: .direction)
|
||||
self.split = try container.decode(CGFloat.self, forKey: .split)
|
||||
self.topLeft = try container.decode(SplitNode.self, forKey: .topLeft)
|
||||
|
@ -9,8 +9,8 @@ extension Ghostty {
|
||||
@FocusedValue(\.ghosttySurfaceTitle) private var surfaceTitle: String?
|
||||
|
||||
var body: some View {
|
||||
if let app = self.ghostty.app {
|
||||
SurfaceForApp(app) { surfaceView in
|
||||
if self.ghostty.app != nil {
|
||||
SurfaceForApp(self.ghostty) { surfaceView in
|
||||
SurfaceWrapper(surfaceView: surfaceView)
|
||||
}
|
||||
.navigationTitle(surfaceTitle ?? "Ghostty")
|
||||
@ -24,7 +24,7 @@ extension Ghostty {
|
||||
|
||||
@StateObject private var surfaceView: SurfaceView
|
||||
|
||||
init(_ app: ghostty_app_t, @ViewBuilder content: @escaping ((SurfaceView) -> Content)) {
|
||||
init(_ app: Ghostty.App, @ViewBuilder content: @escaping ((SurfaceView) -> Content)) {
|
||||
_surfaceView = StateObject(wrappedValue: SurfaceView(app))
|
||||
self.content = content
|
||||
}
|
||||
|
@ -85,6 +85,8 @@ extension Ghostty {
|
||||
// I don't think we need this but this lets us know we should redraw our layer
|
||||
// so we'll use that to tell ghostty to refresh.
|
||||
override var wantsUpdateLayer: Bool { return true }
|
||||
|
||||
private let app: Ghostty.App
|
||||
|
||||
// State machine for mouse cursor visibility because every call to
|
||||
// NSCursor.hide/unhide must be balanced.
|
||||
@ -95,9 +97,10 @@ extension Ghostty {
|
||||
case pendingHidden
|
||||
}
|
||||
|
||||
init(_ app: ghostty_app_t, baseConfig: SurfaceConfiguration? = nil, uuid: UUID? = nil) {
|
||||
init(_ app: Ghostty.App, baseConfig: SurfaceConfiguration? = nil, uuid: UUID? = nil) {
|
||||
self.markedText = NSMutableAttributedString()
|
||||
self.uuid = uuid ?? .init()
|
||||
self.app = app
|
||||
|
||||
// Initialize with some default frame size. The important thing is that this
|
||||
// is non-zero so that our layer bounds are non-zero so that our renderer
|
||||
@ -121,7 +124,7 @@ extension Ghostty {
|
||||
// Setup our surface. This will also initialize all the terminal IO.
|
||||
let surface_cfg = baseConfig ?? SurfaceConfiguration()
|
||||
var surface_cfg_c = surface_cfg.ghosttyConfig(view: self)
|
||||
guard let surface = ghostty_surface_new(app, &surface_cfg_c) else {
|
||||
guard let surface = ghostty_surface_new(app.app, &surface_cfg_c) else {
|
||||
self.error = AppError.surfaceCreateError
|
||||
return
|
||||
}
|
||||
@ -369,8 +372,16 @@ extension Ghostty {
|
||||
|
||||
// Set the window transparency settings
|
||||
window.isOpaque = false
|
||||
window.hasShadow = false
|
||||
window.backgroundColor = .clear
|
||||
|
||||
if app.config.macosWindowShadow {
|
||||
window.hasShadow = true
|
||||
// NOTE(haze): I have no idea why this works, but it does. This emulates the
|
||||
// aesthetic of `Terminal.app`.
|
||||
window.backgroundColor = .white.withAlphaComponent(0.001)
|
||||
} else {
|
||||
window.hasShadow = false
|
||||
window.backgroundColor = .clear
|
||||
}
|
||||
|
||||
// If we have a blur, set the blur
|
||||
ghostty_set_window_background_blur(surface, Unmanaged.passUnretained(window).toOpaque())
|
||||
|
@ -976,6 +976,9 @@ keybind: Keybinds = .{},
|
||||
/// This option only applies to new windows when changed.
|
||||
@"macos-titlebar-tabs": bool = false,
|
||||
|
||||
/// If `true`, render the drop shadow behind the macOS window.
|
||||
@"macos-window-shadow": bool = true,
|
||||
|
||||
/// If `true`, the *Option* key will be treated as *Alt*. This makes terminal
|
||||
/// sequences expecting *Alt* to work properly, but will break Unicode input
|
||||
/// sequences on macOS if you use them via the *Alt* key. You may set this to
|
||||
|
Reference in New Issue
Block a user