mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
macos: restore focused split on app restore
This commit is contained in:
@ -6,9 +6,11 @@ class TerminalRestorableState: Codable {
|
||||
static let versionKey = "version"
|
||||
static let version: Int = 1
|
||||
|
||||
let focusedSurface: String?
|
||||
let surfaceTree: Ghostty.SplitNode?
|
||||
|
||||
init(from controller: TerminalController) {
|
||||
self.focusedSurface = controller.focusedSurface?.uuid.uuidString
|
||||
self.surfaceTree = controller.surfaceTree
|
||||
}
|
||||
|
||||
@ -25,6 +27,7 @@ class TerminalRestorableState: Codable {
|
||||
}
|
||||
|
||||
self.surfaceTree = v.value.surfaceTree
|
||||
self.focusedSurface = v.value.focusedSurface
|
||||
}
|
||||
|
||||
func encode(with coder: NSCoder) {
|
||||
@ -86,7 +89,31 @@ class TerminalWindowRestoration: NSObject, NSWindowRestoration {
|
||||
|
||||
// Setup our restored state on the controller
|
||||
c.surfaceTree = state.surfaceTree
|
||||
if let focusedStr = state.focusedSurface,
|
||||
let focusedUUID = UUID(uuidString: focusedStr),
|
||||
let view = c.surfaceTree?.findUUID(uuid: focusedUUID) {
|
||||
c.focusedSurface = view
|
||||
restoreFocus(to: view, inWindow: window)
|
||||
}
|
||||
|
||||
completionHandler(window, nil)
|
||||
}
|
||||
|
||||
/// This restores the focus state of the surfaceview within the given window. When restoring,
|
||||
/// the view isn't immediately attached to the window since we have to wait for SwiftUI to
|
||||
/// catch up. Therefore, we sit in an async loop waiting for the attachment to happen.
|
||||
private static func restoreFocus(to: Ghostty.SurfaceView, inWindow: NSWindow) {
|
||||
DispatchQueue.main.async {
|
||||
// If the view is not attached to a window yet then we repeat.
|
||||
guard let viewWindow = to.window else {
|
||||
restoreFocus(to: to, inWindow: inWindow)
|
||||
return
|
||||
}
|
||||
|
||||
// If the view is attached to some other window, we give up
|
||||
guard viewWindow == inWindow else { return }
|
||||
|
||||
inWindow.makeFirstResponder(to)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -101,6 +101,22 @@ extension Ghostty {
|
||||
}
|
||||
}
|
||||
|
||||
/// Find a surface view by UUID.
|
||||
func findUUID(uuid: UUID) -> SurfaceView? {
|
||||
switch (self) {
|
||||
case .leaf(let leaf):
|
||||
if (leaf.surface.uuid == uuid) {
|
||||
return leaf.surface
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
case .split(let container):
|
||||
return container.topLeft.findUUID(uuid: uuid) ??
|
||||
container.bottomRight.findUUID(uuid: uuid)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Equatable
|
||||
|
||||
static func == (lhs: SplitNode, rhs: SplitNode) -> Bool {
|
||||
@ -121,7 +137,7 @@ extension Ghostty {
|
||||
weak var parent: SplitNode.Container?
|
||||
|
||||
/// Initialize a new leaf which creates a new terminal surface.
|
||||
init(_ app: ghostty_app_t, baseConfig: SurfaceConfiguration? = nil, uuid: NSUUID? = nil) {
|
||||
init(_ app: ghostty_app_t, baseConfig: SurfaceConfiguration? = nil, uuid: UUID? = nil) {
|
||||
self.app = app
|
||||
self.surface = SurfaceView(app, baseConfig: baseConfig, uuid: uuid)
|
||||
}
|
||||
@ -155,7 +171,7 @@ extension Ghostty {
|
||||
}
|
||||
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
let uuid = NSUUID(uuidString: try container.decode(String.self, forKey: .uuid))
|
||||
let uuid = UUID(uuidString: try container.decode(String.self, forKey: .uuid))
|
||||
var config = SurfaceConfiguration()
|
||||
config.workingDirectory = try container.decode(String?.self, forKey: .pwd)
|
||||
|
||||
|
@ -264,7 +264,7 @@ extension Ghostty {
|
||||
/// The NSView implementation for a terminal surface.
|
||||
class SurfaceView: NSView, NSTextInputClient, ObservableObject {
|
||||
/// Unique ID per surface
|
||||
let uuid: NSUUID
|
||||
let uuid: UUID
|
||||
|
||||
// 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
|
||||
@ -347,7 +347,7 @@ extension Ghostty {
|
||||
case pendingHidden
|
||||
}
|
||||
|
||||
init(_ app: ghostty_app_t, baseConfig: SurfaceConfiguration? = nil, uuid: NSUUID? = nil) {
|
||||
init(_ app: ghostty_app_t, baseConfig: SurfaceConfiguration? = nil, uuid: UUID? = nil) {
|
||||
self.markedText = NSMutableAttributedString()
|
||||
self.uuid = uuid ?? .init()
|
||||
|
||||
|
Reference in New Issue
Block a user