macos: assign unique UUID per surface, store in app state

This commit is contained in:
Mitchell Hashimoto
2023-12-26 14:24:05 -08:00
parent 10a1a94b5d
commit a321ef515d
3 changed files with 16 additions and 7 deletions

View File

@ -52,7 +52,7 @@ class TerminalController: NSWindowController, NSWindowDelegate,
// Initialize our initial surface. // Initialize our initial surface.
guard let ghostty_app = ghostty.app else { preconditionFailure("app must be loaded") } 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 // Setup our notifications for behaviors
let center = NotificationCenter.default let center = NotificationCenter.default

View File

@ -121,9 +121,9 @@ extension Ghostty {
weak var parent: SplitNode.Container? weak var parent: SplitNode.Container?
/// Initialize a new leaf which creates a new terminal surface. /// 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.app = app
self.surface = SurfaceView(app, baseConfig) self.surface = SurfaceView(app, baseConfig: baseConfig, uuid: uuid)
} }
// MARK: - Hashable // MARK: - Hashable
@ -143,6 +143,7 @@ extension Ghostty {
enum CodingKeys: String, CodingKey { enum CodingKeys: String, CodingKey {
case pwd case pwd
case uuid
} }
required convenience init(from decoder: Decoder) throws { required convenience init(from decoder: Decoder) throws {
@ -154,15 +155,17 @@ extension Ghostty {
} }
let container = try decoder.container(keyedBy: CodingKeys.self) let container = try decoder.container(keyedBy: CodingKeys.self)
let uuid = NSUUID(uuidString: try container.decode(String.self, forKey: .uuid))
var config = SurfaceConfiguration() var config = SurfaceConfiguration()
config.workingDirectory = try container.decode(String?.self, forKey: .pwd) 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 { func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(surface.pwd, forKey: .pwd) 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. // state since this is a new split.
self.topLeft = .leaf(from) self.topLeft = .leaf(from)
let bottomRight: Leaf = .init(app, baseConfig) let bottomRight: Leaf = .init(app, baseConfig: baseConfig)
self.bottomRight = .leaf(bottomRight) self.bottomRight = .leaf(bottomRight)
from.parent = self from.parent = self

View File

@ -25,7 +25,7 @@ extension Ghostty {
@StateObject private var surfaceView: SurfaceView @StateObject private var surfaceView: SurfaceView
init(_ app: ghostty_app_t, @ViewBuilder content: @escaping ((SurfaceView) -> Content)) { init(_ app: ghostty_app_t, @ViewBuilder content: @escaping ((SurfaceView) -> Content)) {
_surfaceView = StateObject(wrappedValue: SurfaceView(app, nil)) _surfaceView = StateObject(wrappedValue: SurfaceView(app))
self.content = content self.content = content
} }
@ -259,8 +259,13 @@ extension Ghostty {
} }
} }
// MARK: - Surface View
/// The NSView implementation for a terminal surface. /// The NSView implementation for a terminal surface.
class SurfaceView: NSView, NSTextInputClient, ObservableObject { 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 // 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 // changed with escape codes. This is public because the callbacks go
// to the app level and it is set from there. // to the app level and it is set from there.
@ -342,8 +347,9 @@ extension Ghostty {
case pendingHidden case pendingHidden
} }
init(_ app: ghostty_app_t, _ baseConfig: SurfaceConfiguration?) { init(_ app: ghostty_app_t, baseConfig: SurfaceConfiguration? = nil, uuid: NSUUID? = nil) {
self.markedText = NSMutableAttributedString() self.markedText = NSMutableAttributedString()
self.uuid = uuid ?? .init()
// Initialize with some default frame size. The important thing is that this // 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 // is non-zero so that our layer bounds are non-zero so that our renderer