diff --git a/macos/Sources/Features/Terminal/TerminalController.swift b/macos/Sources/Features/Terminal/TerminalController.swift index e2ba359ad..906f78ee2 100644 --- a/macos/Sources/Features/Terminal/TerminalController.swift +++ b/macos/Sources/Features/Terminal/TerminalController.swift @@ -52,7 +52,7 @@ class TerminalController: NSWindowController, NSWindowDelegate, // Initialize our initial surface. guard let ghostty_app = ghostty.app else { preconditionFailure("app must be loaded") } - self.surfaceTree = .leaf(.init(ghostty_app, base)) + self.surfaceTree = .leaf(.init(ghostty_app, baseConfig: base)) // Setup our notifications for behaviors let center = NotificationCenter.default diff --git a/macos/Sources/Ghostty/Ghostty.SplitNode.swift b/macos/Sources/Ghostty/Ghostty.SplitNode.swift index 35240b5fa..4e87feda0 100644 --- a/macos/Sources/Ghostty/Ghostty.SplitNode.swift +++ b/macos/Sources/Ghostty/Ghostty.SplitNode.swift @@ -121,9 +121,9 @@ extension Ghostty { weak var parent: SplitNode.Container? /// Initialize a new leaf which creates a new terminal surface. - init(_ app: ghostty_app_t, _ baseConfig: SurfaceConfiguration?) { + init(_ app: ghostty_app_t, baseConfig: SurfaceConfiguration? = nil, uuid: NSUUID? = nil) { self.app = app - self.surface = SurfaceView(app, baseConfig) + self.surface = SurfaceView(app, baseConfig: baseConfig, uuid: uuid) } // MARK: - Hashable @@ -143,6 +143,7 @@ extension Ghostty { enum CodingKeys: String, CodingKey { case pwd + case uuid } required convenience init(from decoder: Decoder) throws { @@ -154,15 +155,17 @@ extension Ghostty { } let container = try decoder.container(keyedBy: CodingKeys.self) + let uuid = NSUUID(uuidString: try container.decode(String.self, forKey: .uuid)) var config = SurfaceConfiguration() config.workingDirectory = try container.decode(String?.self, forKey: .pwd) - self.init(app, config) + self.init(app, baseConfig: config, uuid: uuid) } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(surface.pwd, forKey: .pwd) + try container.encode(surface.uuid.uuidString, forKey: .uuid) } } @@ -190,7 +193,7 @@ extension Ghostty { // state since this is a new split. self.topLeft = .leaf(from) - let bottomRight: Leaf = .init(app, baseConfig) + let bottomRight: Leaf = .init(app, baseConfig: baseConfig) self.bottomRight = .leaf(bottomRight) from.parent = self diff --git a/macos/Sources/Ghostty/SurfaceView.swift b/macos/Sources/Ghostty/SurfaceView.swift index 6ad8122a6..b53c42c94 100644 --- a/macos/Sources/Ghostty/SurfaceView.swift +++ b/macos/Sources/Ghostty/SurfaceView.swift @@ -25,7 +25,7 @@ extension Ghostty { @StateObject private var surfaceView: SurfaceView init(_ app: ghostty_app_t, @ViewBuilder content: @escaping ((SurfaceView) -> Content)) { - _surfaceView = StateObject(wrappedValue: SurfaceView(app, nil)) + _surfaceView = StateObject(wrappedValue: SurfaceView(app)) self.content = content } @@ -259,8 +259,13 @@ extension Ghostty { } } + // MARK: - Surface View + /// The NSView implementation for a terminal surface. class SurfaceView: NSView, NSTextInputClient, ObservableObject { + /// Unique ID per surface + let uuid: NSUUID + // The current title of the surface as defined by the pty. This can be // changed with escape codes. This is public because the callbacks go // to the app level and it is set from there. @@ -342,8 +347,9 @@ extension Ghostty { case pendingHidden } - init(_ app: ghostty_app_t, _ baseConfig: SurfaceConfiguration?) { + init(_ app: ghostty_app_t, baseConfig: SurfaceConfiguration? = nil, uuid: NSUUID? = nil) { self.markedText = NSMutableAttributedString() + self.uuid = uuid ?? .init() // 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