mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-10-17 15:21:50 +00:00
macos: rename surfaceTree2 to surfaceTree
This commit is contained in:
@@ -741,7 +741,7 @@ class AppDelegate: NSObject,
|
|||||||
|
|
||||||
func findSurface(forUUID uuid: UUID) -> Ghostty.SurfaceView? {
|
func findSurface(forUUID uuid: UUID) -> Ghostty.SurfaceView? {
|
||||||
for c in terminalManager.windows {
|
for c in terminalManager.windows {
|
||||||
for view in c.controller.surfaceTree2 {
|
for view in c.controller.surfaceTree {
|
||||||
if view.uuid == uuid {
|
if view.uuid == uuid {
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
@@ -30,11 +30,11 @@ class QuickTerminalController: BaseTerminalController {
|
|||||||
init(_ ghostty: Ghostty.App,
|
init(_ ghostty: Ghostty.App,
|
||||||
position: QuickTerminalPosition = .top,
|
position: QuickTerminalPosition = .top,
|
||||||
baseConfig base: Ghostty.SurfaceConfiguration? = nil,
|
baseConfig base: Ghostty.SurfaceConfiguration? = nil,
|
||||||
surfaceTree2 tree2: SplitTree<Ghostty.SurfaceView>? = nil
|
surfaceTree tree: SplitTree<Ghostty.SurfaceView>? = nil
|
||||||
) {
|
) {
|
||||||
self.position = position
|
self.position = position
|
||||||
self.derivedConfig = DerivedConfig(ghostty.config)
|
self.derivedConfig = DerivedConfig(ghostty.config)
|
||||||
super.init(ghostty, baseConfig: base, surfaceTree2: tree2)
|
super.init(ghostty, baseConfig: base, surfaceTree: tree)
|
||||||
|
|
||||||
// Setup our notifications for behaviors
|
// Setup our notifications for behaviors
|
||||||
let center = NotificationCenter.default
|
let center = NotificationCenter.default
|
||||||
@@ -236,10 +236,10 @@ class QuickTerminalController: BaseTerminalController {
|
|||||||
// If our surface tree is empty then we initialize a new terminal. The surface
|
// If our surface tree is empty then we initialize a new terminal. The surface
|
||||||
// tree can be empty if for example we run "exit" in the terminal and force
|
// tree can be empty if for example we run "exit" in the terminal and force
|
||||||
// animate out.
|
// animate out.
|
||||||
if surfaceTree2.isEmpty,
|
if surfaceTree.isEmpty,
|
||||||
let ghostty_app = ghostty.app {
|
let ghostty_app = ghostty.app {
|
||||||
let view = Ghostty.SurfaceView(ghostty_app, baseConfig: nil)
|
let view = Ghostty.SurfaceView(ghostty_app, baseConfig: nil)
|
||||||
surfaceTree2 = SplitTree(view: view)
|
surfaceTree = SplitTree(view: view)
|
||||||
focusedSurface = view
|
focusedSurface = view
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -42,8 +42,8 @@ class BaseTerminalController: NSWindowController,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The tree of splits within this terminal window.
|
/// The tree of splits within this terminal window.
|
||||||
@Published var surfaceTree2: SplitTree<Ghostty.SurfaceView> = .init() {
|
@Published var surfaceTree: SplitTree<Ghostty.SurfaceView> = .init() {
|
||||||
didSet { surfaceTreeDidChange(from: oldValue, to: surfaceTree2) }
|
didSet { surfaceTreeDidChange(from: oldValue, to: surfaceTree) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This can be set to show/hide the command palette.
|
/// This can be set to show/hide the command palette.
|
||||||
@@ -86,7 +86,7 @@ class BaseTerminalController: NSWindowController,
|
|||||||
|
|
||||||
init(_ ghostty: Ghostty.App,
|
init(_ ghostty: Ghostty.App,
|
||||||
baseConfig base: Ghostty.SurfaceConfiguration? = nil,
|
baseConfig base: Ghostty.SurfaceConfiguration? = nil,
|
||||||
surfaceTree2 tree2: SplitTree<Ghostty.SurfaceView>? = nil
|
surfaceTree tree: SplitTree<Ghostty.SurfaceView>? = nil
|
||||||
) {
|
) {
|
||||||
self.ghostty = ghostty
|
self.ghostty = ghostty
|
||||||
self.derivedConfig = DerivedConfig(ghostty.config)
|
self.derivedConfig = DerivedConfig(ghostty.config)
|
||||||
@@ -95,7 +95,7 @@ class BaseTerminalController: NSWindowController,
|
|||||||
|
|
||||||
// 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.surfaceTree2 = tree2 ?? .init(view: Ghostty.SurfaceView(ghostty_app, baseConfig: base))
|
self.surfaceTree = tree ?? .init(view: Ghostty.SurfaceView(ghostty_app, baseConfig: base))
|
||||||
|
|
||||||
// Setup our notifications for behaviors
|
// Setup our notifications for behaviors
|
||||||
let center = NotificationCenter.default
|
let center = NotificationCenter.default
|
||||||
@@ -167,7 +167,7 @@ class BaseTerminalController: NSWindowController,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when the surfaceTree2 variable changed.
|
/// Called when the surfaceTree variable changed.
|
||||||
///
|
///
|
||||||
/// Subclasses should call super first.
|
/// Subclasses should call super first.
|
||||||
func surfaceTreeDidChange(from: SplitTree<Ghostty.SurfaceView>, to: SplitTree<Ghostty.SurfaceView>) {
|
func surfaceTreeDidChange(from: SplitTree<Ghostty.SurfaceView>, to: SplitTree<Ghostty.SurfaceView>) {
|
||||||
@@ -180,7 +180,7 @@ class BaseTerminalController: NSWindowController,
|
|||||||
/// Update all surfaces with the focus state. This ensures that libghostty has an accurate view about
|
/// Update all surfaces with the focus state. This ensures that libghostty has an accurate view about
|
||||||
/// what surface is focused. This must be called whenever a surface OR window changes focus.
|
/// what surface is focused. This must be called whenever a surface OR window changes focus.
|
||||||
func syncFocusToSurfaceTree() {
|
func syncFocusToSurfaceTree() {
|
||||||
for surfaceView in surfaceTree2 {
|
for surfaceView in surfaceTree {
|
||||||
// Our focus state requires that this window is key and our currently
|
// Our focus state requires that this window is key and our currently
|
||||||
// focused surface is the surface in this view.
|
// focused surface is the surface in this view.
|
||||||
let focused: Bool = (window?.isKeyWindow ?? false) &&
|
let focused: Bool = (window?.isKeyWindow ?? false) &&
|
||||||
@@ -296,21 +296,21 @@ class BaseTerminalController: NSWindowController,
|
|||||||
|
|
||||||
@objc private func ghosttyCommandPaletteDidToggle(_ notification: Notification) {
|
@objc private func ghosttyCommandPaletteDidToggle(_ notification: Notification) {
|
||||||
guard let surfaceView = notification.object as? Ghostty.SurfaceView else { return }
|
guard let surfaceView = notification.object as? Ghostty.SurfaceView else { return }
|
||||||
guard surfaceTree2.contains(surfaceView) else { return }
|
guard surfaceTree.contains(surfaceView) else { return }
|
||||||
toggleCommandPalette(nil)
|
toggleCommandPalette(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func ghosttyMaximizeDidToggle(_ notification: Notification) {
|
@objc private func ghosttyMaximizeDidToggle(_ notification: Notification) {
|
||||||
guard let window else { return }
|
guard let window else { return }
|
||||||
guard let surfaceView = notification.object as? Ghostty.SurfaceView else { return }
|
guard let surfaceView = notification.object as? Ghostty.SurfaceView else { return }
|
||||||
guard surfaceTree2.contains(surfaceView) else { return }
|
guard surfaceTree.contains(surfaceView) else { return }
|
||||||
window.zoom(nil)
|
window.zoom(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func ghosttyDidCloseSurface(_ notification: Notification) {
|
@objc private func ghosttyDidCloseSurface(_ notification: Notification) {
|
||||||
// The target must be within our tree
|
// The target must be within our tree
|
||||||
guard let target = notification.object as? Ghostty.SurfaceView else { return }
|
guard let target = notification.object as? Ghostty.SurfaceView else { return }
|
||||||
guard let node = surfaceTree2.root?.node(view: target) else { return }
|
guard let node = surfaceTree.root?.node(view: target) else { return }
|
||||||
|
|
||||||
// TODO: fix focus
|
// TODO: fix focus
|
||||||
|
|
||||||
@@ -323,7 +323,7 @@ class BaseTerminalController: NSWindowController,
|
|||||||
|
|
||||||
// If the child process is not alive, then we exit immediately
|
// If the child process is not alive, then we exit immediately
|
||||||
guard processAlive else {
|
guard processAlive else {
|
||||||
surfaceTree2 = surfaceTree2.remove(node)
|
surfaceTree = surfaceTree.remove(node)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,7 +337,7 @@ class BaseTerminalController: NSWindowController,
|
|||||||
informativeText: "The terminal still has a running process. If you close the terminal the process will be killed."
|
informativeText: "The terminal still has a running process. If you close the terminal the process will be killed."
|
||||||
) { [weak self] in
|
) { [weak self] in
|
||||||
if let self {
|
if let self {
|
||||||
self.surfaceTree2 = self.surfaceTree2.remove(node)
|
self.surfaceTree = self.surfaceTree.remove(node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -345,7 +345,7 @@ class BaseTerminalController: NSWindowController,
|
|||||||
@objc private func ghosttyDidNewSplit(_ notification: Notification) {
|
@objc private func ghosttyDidNewSplit(_ notification: Notification) {
|
||||||
// The target must be within our tree
|
// The target must be within our tree
|
||||||
guard let oldView = notification.object as? Ghostty.SurfaceView else { return }
|
guard let oldView = notification.object as? Ghostty.SurfaceView else { return }
|
||||||
guard surfaceTree2.root?.node(view: oldView) != nil else { return }
|
guard surfaceTree.root?.node(view: oldView) != nil else { return }
|
||||||
|
|
||||||
// Notification must contain our base config
|
// Notification must contain our base config
|
||||||
let configAny = notification.userInfo?[Ghostty.Notification.NewSurfaceConfigKey]
|
let configAny = notification.userInfo?[Ghostty.Notification.NewSurfaceConfigKey]
|
||||||
@@ -369,7 +369,7 @@ class BaseTerminalController: NSWindowController,
|
|||||||
|
|
||||||
// Do the split
|
// Do the split
|
||||||
do {
|
do {
|
||||||
surfaceTree2 = try surfaceTree2.insert(view: newView, at: oldView, direction: splitDirection)
|
surfaceTree = try surfaceTree.insert(view: newView, at: oldView, direction: splitDirection)
|
||||||
} catch {
|
} catch {
|
||||||
// If splitting fails for any reason (it should not), then we just log
|
// If splitting fails for any reason (it should not), then we just log
|
||||||
// and return. The new view we created will be deinitialized and its
|
// and return. The new view we created will be deinitialized and its
|
||||||
@@ -386,16 +386,16 @@ class BaseTerminalController: NSWindowController,
|
|||||||
guard let target = notification.object as? Ghostty.SurfaceView else { return }
|
guard let target = notification.object as? Ghostty.SurfaceView else { return }
|
||||||
|
|
||||||
// Check if target surface is in current controller's tree
|
// Check if target surface is in current controller's tree
|
||||||
guard surfaceTree2.contains(target) else { return }
|
guard surfaceTree.contains(target) else { return }
|
||||||
|
|
||||||
// Equalize the splits
|
// Equalize the splits
|
||||||
surfaceTree2 = surfaceTree2.equalize()
|
surfaceTree = surfaceTree.equalize()
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func ghosttyDidFocusSplit(_ notification: Notification) {
|
@objc private func ghosttyDidFocusSplit(_ notification: Notification) {
|
||||||
// The target must be within our tree
|
// The target must be within our tree
|
||||||
guard let target = notification.object as? Ghostty.SurfaceView else { return }
|
guard let target = notification.object as? Ghostty.SurfaceView else { return }
|
||||||
guard surfaceTree2.root?.node(view: target) != nil else { return }
|
guard surfaceTree.root?.node(view: target) != nil else { return }
|
||||||
|
|
||||||
// Get the direction from the notification
|
// Get the direction from the notification
|
||||||
guard let directionAny = notification.userInfo?[Ghostty.Notification.SplitDirectionKey] else { return }
|
guard let directionAny = notification.userInfo?[Ghostty.Notification.SplitDirectionKey] else { return }
|
||||||
@@ -413,10 +413,10 @@ class BaseTerminalController: NSWindowController,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find the node for the target surface
|
// Find the node for the target surface
|
||||||
guard let targetNode = surfaceTree2.root?.node(view: target) else { return }
|
guard let targetNode = surfaceTree.root?.node(view: target) else { return }
|
||||||
|
|
||||||
// Find the next surface to focus
|
// Find the next surface to focus
|
||||||
guard let nextSurface = surfaceTree2.focusTarget(for: focusDirection, from: targetNode) else {
|
guard let nextSurface = surfaceTree.focusTarget(for: focusDirection, from: targetNode) else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -427,15 +427,15 @@ class BaseTerminalController: NSWindowController,
|
|||||||
@objc private func ghosttyDidToggleSplitZoom(_ notification: Notification) {
|
@objc private func ghosttyDidToggleSplitZoom(_ notification: Notification) {
|
||||||
// The target must be within our tree
|
// The target must be within our tree
|
||||||
guard let target = notification.object as? Ghostty.SurfaceView else { return }
|
guard let target = notification.object as? Ghostty.SurfaceView else { return }
|
||||||
guard let targetNode = surfaceTree2.root?.node(view: target) else { return }
|
guard let targetNode = surfaceTree.root?.node(view: target) else { return }
|
||||||
|
|
||||||
// Toggle the zoomed state
|
// Toggle the zoomed state
|
||||||
if surfaceTree2.zoomed == targetNode {
|
if surfaceTree.zoomed == targetNode {
|
||||||
// Already zoomed, unzoom it
|
// Already zoomed, unzoom it
|
||||||
surfaceTree2 = SplitTree(root: surfaceTree2.root, zoomed: nil)
|
surfaceTree = SplitTree(root: surfaceTree.root, zoomed: nil)
|
||||||
} else {
|
} else {
|
||||||
// Not zoomed or different node zoomed, zoom this node
|
// Not zoomed or different node zoomed, zoom this node
|
||||||
surfaceTree2 = SplitTree(root: surfaceTree2.root, zoomed: targetNode)
|
surfaceTree = SplitTree(root: surfaceTree.root, zoomed: targetNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure focus stays on the target surface. We lose focus when we do
|
// Ensure focus stays on the target surface. We lose focus when we do
|
||||||
@@ -458,8 +458,7 @@ class BaseTerminalController: NSWindowController,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func localEventFlagsChanged(_ event: NSEvent) -> NSEvent? {
|
private func localEventFlagsChanged(_ event: NSEvent) -> NSEvent? {
|
||||||
// Also update surfaceTree2
|
var surfaces: [Ghostty.SurfaceView] = surfaceTree.map { $0 }
|
||||||
var surfaces: [Ghostty.SurfaceView] = surfaceTree2.map { $0 }
|
|
||||||
|
|
||||||
// If we're the main window receiving key input, then we want to avoid
|
// If we're the main window receiving key input, then we want to avoid
|
||||||
// calling this on our focused surface because that'll trigger a double
|
// calling this on our focused surface because that'll trigger a double
|
||||||
@@ -489,7 +488,7 @@ class BaseTerminalController: NSWindowController,
|
|||||||
// want to care if the surface is in the tree so we don't listen to titles of
|
// want to care if the surface is in the tree so we don't listen to titles of
|
||||||
// closed surfaces.
|
// closed surfaces.
|
||||||
if let titleSurface = focusedSurface ?? lastFocusedSurface,
|
if let titleSurface = focusedSurface ?? lastFocusedSurface,
|
||||||
surfaceTree2.contains(titleSurface) {
|
surfaceTree.contains(titleSurface) {
|
||||||
// If we have a surface, we want to listen for title changes.
|
// If we have a surface, we want to listen for title changes.
|
||||||
titleSurface.$title
|
titleSurface.$title
|
||||||
.sink { [weak self] in self?.titleDidChange(to: $0) }
|
.sink { [weak self] in self?.titleDidChange(to: $0) }
|
||||||
@@ -527,7 +526,7 @@ class BaseTerminalController: NSWindowController,
|
|||||||
func splitDidResize(node: SplitTree<Ghostty.SurfaceView>.Node, to newRatio: Double) {
|
func splitDidResize(node: SplitTree<Ghostty.SurfaceView>.Node, to newRatio: Double) {
|
||||||
let resizedNode = node.resize(to: newRatio)
|
let resizedNode = node.resize(to: newRatio)
|
||||||
do {
|
do {
|
||||||
surfaceTree2 = try surfaceTree2.replace(node: node, with: resizedNode)
|
surfaceTree = try surfaceTree.replace(node: node, with: resizedNode)
|
||||||
} catch {
|
} catch {
|
||||||
// TODO: log
|
// TODO: log
|
||||||
return
|
return
|
||||||
@@ -687,13 +686,13 @@ class BaseTerminalController: NSWindowController,
|
|||||||
guard let window = self.window else { return true }
|
guard let window = self.window else { return true }
|
||||||
|
|
||||||
// If we have no surfaces, close.
|
// If we have no surfaces, close.
|
||||||
if surfaceTree2.isEmpty { return true }
|
if surfaceTree.isEmpty { return true }
|
||||||
|
|
||||||
// If we already have an alert, continue with it
|
// If we already have an alert, continue with it
|
||||||
guard alert == nil else { return false }
|
guard alert == nil else { return false }
|
||||||
|
|
||||||
// If our surfaces don't require confirmation, close.
|
// If our surfaces don't require confirmation, close.
|
||||||
if !surfaceTree2.contains(where: { $0.needsConfirmQuit }) { return true }
|
if !surfaceTree.contains(where: { $0.needsConfirmQuit }) { return true }
|
||||||
|
|
||||||
// We require confirmation, so show an alert as long as we aren't already.
|
// We require confirmation, so show an alert as long as we aren't already.
|
||||||
confirmClose(
|
confirmClose(
|
||||||
@@ -729,7 +728,7 @@ class BaseTerminalController: NSWindowController,
|
|||||||
|
|
||||||
func windowDidChangeOcclusionState(_ notification: Notification) {
|
func windowDidChangeOcclusionState(_ notification: Notification) {
|
||||||
let visible = self.window?.occlusionState.contains(.visible) ?? false
|
let visible = self.window?.occlusionState.contains(.visible) ?? false
|
||||||
for view in surfaceTree2 {
|
for view in surfaceTree {
|
||||||
if let surface = view.surface {
|
if let surface = view.surface {
|
||||||
ghostty_surface_set_occlusion(surface, visible)
|
ghostty_surface_set_occlusion(surface, visible)
|
||||||
}
|
}
|
||||||
|
@@ -32,8 +32,7 @@ class TerminalController: BaseTerminalController {
|
|||||||
|
|
||||||
init(_ ghostty: Ghostty.App,
|
init(_ ghostty: Ghostty.App,
|
||||||
withBaseConfig base: Ghostty.SurfaceConfiguration? = nil,
|
withBaseConfig base: Ghostty.SurfaceConfiguration? = nil,
|
||||||
withSurfaceTree tree: Ghostty.SplitNode? = nil,
|
withSurfaceTree tree: SplitTree<Ghostty.SurfaceView>? = nil
|
||||||
withSurfaceTree2 tree2: SplitTree<Ghostty.SurfaceView>? = nil
|
|
||||||
) {
|
) {
|
||||||
// The window we manage is not restorable if we've specified a command
|
// The window we manage is not restorable if we've specified a command
|
||||||
// to execute. We do this because the restored window is meaningless at the
|
// to execute. We do this because the restored window is meaningless at the
|
||||||
@@ -45,7 +44,7 @@ class TerminalController: BaseTerminalController {
|
|||||||
// Setup our initial derived config based on the current app config
|
// Setup our initial derived config based on the current app config
|
||||||
self.derivedConfig = DerivedConfig(ghostty.config)
|
self.derivedConfig = DerivedConfig(ghostty.config)
|
||||||
|
|
||||||
super.init(ghostty, baseConfig: base, surfaceTree2: tree2)
|
super.init(ghostty, baseConfig: base, surfaceTree: tree)
|
||||||
|
|
||||||
// Setup our notifications for behaviors
|
// Setup our notifications for behaviors
|
||||||
let center = NotificationCenter.default
|
let center = NotificationCenter.default
|
||||||
@@ -154,7 +153,7 @@ class TerminalController: BaseTerminalController {
|
|||||||
// If we have no surfaces in our window (is that possible?) then we update
|
// If we have no surfaces in our window (is that possible?) then we update
|
||||||
// our window appearance based on the root config. If we have surfaces, we
|
// our window appearance based on the root config. If we have surfaces, we
|
||||||
// don't call this because the TODO
|
// don't call this because the TODO
|
||||||
if surfaceTree2.isEmpty {
|
if surfaceTree.isEmpty {
|
||||||
syncAppearance(.init(config))
|
syncAppearance(.init(config))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,7 +163,7 @@ class TerminalController: BaseTerminalController {
|
|||||||
// This is a surface-level config update. If we have the surface, we
|
// This is a surface-level config update. If we have the surface, we
|
||||||
// update our appearance based on it.
|
// update our appearance based on it.
|
||||||
guard let surfaceView = notification.object as? Ghostty.SurfaceView else { return }
|
guard let surfaceView = notification.object as? Ghostty.SurfaceView else { return }
|
||||||
guard surfaceTree2.contains(surfaceView) else { return }
|
guard surfaceTree.contains(surfaceView) else { return }
|
||||||
|
|
||||||
// We can't use surfaceView.derivedConfig because it may not be updated
|
// We can't use surfaceView.derivedConfig because it may not be updated
|
||||||
// yet since it also responds to notifications.
|
// yet since it also responds to notifications.
|
||||||
@@ -239,7 +238,7 @@ class TerminalController: BaseTerminalController {
|
|||||||
window.isLightTheme = OSColor(surfaceConfig.backgroundColor).isLightColor
|
window.isLightTheme = OSColor(surfaceConfig.backgroundColor).isLightColor
|
||||||
|
|
||||||
// Sync our zoom state for splits
|
// Sync our zoom state for splits
|
||||||
window.surfaceIsZoomed = surfaceTree2.zoomed != nil
|
window.surfaceIsZoomed = surfaceTree.zoomed != nil
|
||||||
|
|
||||||
// If our window is not visible, then we do nothing. Some things such as blurring
|
// If our window is not visible, then we do nothing. Some things such as blurring
|
||||||
// have no effect if the window is not visible. Ultimately, we'll have this called
|
// have no effect if the window is not visible. Ultimately, we'll have this called
|
||||||
@@ -282,9 +281,9 @@ class TerminalController: BaseTerminalController {
|
|||||||
// If it does, we match the focused surface. If it doesn't, we use the app
|
// If it does, we match the focused surface. If it doesn't, we use the app
|
||||||
// configuration.
|
// configuration.
|
||||||
let backgroundColor: OSColor
|
let backgroundColor: OSColor
|
||||||
if !surfaceTree2.isEmpty {
|
if !surfaceTree.isEmpty {
|
||||||
if let focusedSurface = focusedSurface,
|
if let focusedSurface = focusedSurface,
|
||||||
let treeRoot = surfaceTree2.root,
|
let treeRoot = surfaceTree.root,
|
||||||
let focusedNode = treeRoot.node(view: focusedSurface),
|
let focusedNode = treeRoot.node(view: focusedSurface),
|
||||||
treeRoot.spatial().doesBorder(side: .up, from: focusedNode) {
|
treeRoot.spatial().doesBorder(side: .up, from: focusedNode) {
|
||||||
// Similar to above, an alpha component of "0" causes compositor issues, so
|
// Similar to above, an alpha component of "0" causes compositor issues, so
|
||||||
@@ -293,7 +292,7 @@ class TerminalController: BaseTerminalController {
|
|||||||
} else {
|
} else {
|
||||||
// We don't have a focused surface or our surface doesn't border the
|
// We don't have a focused surface or our surface doesn't border the
|
||||||
// top. We choose to match the color of the top-left most surface.
|
// top. We choose to match the color of the top-left most surface.
|
||||||
let topLeftSurface = surfaceTree2.root?.leftmostLeaf()
|
let topLeftSurface = surfaceTree.root?.leftmostLeaf()
|
||||||
backgroundColor = OSColor(topLeftSurface?.backgroundColor ?? derivedConfig.backgroundColor)
|
backgroundColor = OSColor(topLeftSurface?.backgroundColor ?? derivedConfig.backgroundColor)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -456,7 +455,7 @@ class TerminalController: BaseTerminalController {
|
|||||||
|
|
||||||
// If we have only a single surface (no splits) and there is a default size then
|
// If we have only a single surface (no splits) and there is a default size then
|
||||||
// we should resize to that default size.
|
// we should resize to that default size.
|
||||||
if case let .leaf(view) = surfaceTree2.root {
|
if case let .leaf(view) = surfaceTree.root {
|
||||||
// If this is our first surface then our focused surface will be nil
|
// If this is our first surface then our focused surface will be nil
|
||||||
// so we force the focused surface to the leaf.
|
// so we force the focused surface to the leaf.
|
||||||
focusedSurface = view
|
focusedSurface = view
|
||||||
@@ -604,7 +603,7 @@ class TerminalController: BaseTerminalController {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if surfaceTree2.contains(where: { $0.needsConfirmQuit }) {
|
if surfaceTree.contains(where: { $0.needsConfirmQuit }) {
|
||||||
confirmClose(
|
confirmClose(
|
||||||
messageText: "Close Tab?",
|
messageText: "Close Tab?",
|
||||||
informativeText: "The terminal still has a running process. If you close the tab the process will be killed."
|
informativeText: "The terminal still has a running process. If you close the tab the process will be killed."
|
||||||
@@ -641,7 +640,7 @@ class TerminalController: BaseTerminalController {
|
|||||||
guard let controller = tabWindow.windowController as? TerminalController else {
|
guard let controller = tabWindow.windowController as? TerminalController else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return controller.surfaceTree2.contains(where: { $0.needsConfirmQuit })
|
return controller.surfaceTree.contains(where: { $0.needsConfirmQuit })
|
||||||
}
|
}
|
||||||
|
|
||||||
// If none need confirmation then we can just close all the windows.
|
// If none need confirmation then we can just close all the windows.
|
||||||
@@ -819,19 +818,19 @@ class TerminalController: BaseTerminalController {
|
|||||||
|
|
||||||
@objc private func onCloseTab(notification: SwiftUI.Notification) {
|
@objc private func onCloseTab(notification: SwiftUI.Notification) {
|
||||||
guard let target = notification.object as? Ghostty.SurfaceView else { return }
|
guard let target = notification.object as? Ghostty.SurfaceView else { return }
|
||||||
guard surfaceTree2.contains(target) else { return }
|
guard surfaceTree.contains(target) else { return }
|
||||||
closeTab(self)
|
closeTab(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func onCloseWindow(notification: SwiftUI.Notification) {
|
@objc private func onCloseWindow(notification: SwiftUI.Notification) {
|
||||||
guard let target = notification.object as? Ghostty.SurfaceView else { return }
|
guard let target = notification.object as? Ghostty.SurfaceView else { return }
|
||||||
guard surfaceTree2.contains(target) else { return }
|
guard surfaceTree.contains(target) else { return }
|
||||||
closeWindow(self)
|
closeWindow(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func onResetWindowSize(notification: SwiftUI.Notification) {
|
@objc private func onResetWindowSize(notification: SwiftUI.Notification) {
|
||||||
guard let target = notification.object as? Ghostty.SurfaceView else { return }
|
guard let target = notification.object as? Ghostty.SurfaceView else { return }
|
||||||
guard surfaceTree2.contains(target) else { return }
|
guard surfaceTree.contains(target) else { return }
|
||||||
returnToDefaultSize(nil)
|
returnToDefaultSize(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -197,9 +197,9 @@ class TerminalManager {
|
|||||||
|
|
||||||
/// Creates a window controller, adds it to our managed list, and returns it.
|
/// Creates a window controller, adds it to our managed list, and returns it.
|
||||||
func createWindow(withBaseConfig base: Ghostty.SurfaceConfiguration? = nil,
|
func createWindow(withBaseConfig base: Ghostty.SurfaceConfiguration? = nil,
|
||||||
withSurfaceTree2 tree2: SplitTree<Ghostty.SurfaceView>? = nil) -> TerminalController {
|
withSurfaceTree tree: SplitTree<Ghostty.SurfaceView>? = nil) -> TerminalController {
|
||||||
// Initialize our controller to load the window
|
// Initialize our controller to load the window
|
||||||
let c = TerminalController(ghostty, withBaseConfig: base, withSurfaceTree2: tree2)
|
let c = TerminalController(ghostty, withBaseConfig: base, withSurfaceTree: tree)
|
||||||
|
|
||||||
// Create a listener for when the window is closed so we can remove it.
|
// Create a listener for when the window is closed so we can remove it.
|
||||||
let pubClose = NotificationCenter.default.publisher(
|
let pubClose = NotificationCenter.default.publisher(
|
||||||
@@ -268,7 +268,7 @@ class TerminalManager {
|
|||||||
func closeAllWindows() {
|
func closeAllWindows() {
|
||||||
var needsConfirm: Bool = false
|
var needsConfirm: Bool = false
|
||||||
for w in self.windows {
|
for w in self.windows {
|
||||||
if w.controller.surfaceTree2.contains(where: { $0.needsConfirmQuit }) {
|
if w.controller.surfaceTree.contains(where: { $0.needsConfirmQuit }) {
|
||||||
needsConfirm = true
|
needsConfirm = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@@ -7,11 +7,11 @@ class TerminalRestorableState: Codable {
|
|||||||
static let version: Int = 3
|
static let version: Int = 3
|
||||||
|
|
||||||
let focusedSurface: String?
|
let focusedSurface: String?
|
||||||
let surfaceTree2: SplitTree<Ghostty.SurfaceView>
|
let surfaceTree: SplitTree<Ghostty.SurfaceView>
|
||||||
|
|
||||||
init(from controller: TerminalController) {
|
init(from controller: TerminalController) {
|
||||||
self.focusedSurface = controller.focusedSurface?.uuid.uuidString
|
self.focusedSurface = controller.focusedSurface?.uuid.uuidString
|
||||||
self.surfaceTree2 = controller.surfaceTree2
|
self.surfaceTree = controller.surfaceTree
|
||||||
}
|
}
|
||||||
|
|
||||||
init?(coder aDecoder: NSCoder) {
|
init?(coder aDecoder: NSCoder) {
|
||||||
@@ -26,7 +26,7 @@ class TerminalRestorableState: Codable {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
self.surfaceTree2 = v.value.surfaceTree2
|
self.surfaceTree = v.value.surfaceTree
|
||||||
self.focusedSurface = v.value.focusedSurface
|
self.focusedSurface = v.value.focusedSurface
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,7 +84,7 @@ class TerminalWindowRestoration: NSObject, NSWindowRestoration {
|
|||||||
// createWindow so that AppKit can place the window wherever it should
|
// createWindow so that AppKit can place the window wherever it should
|
||||||
// be.
|
// be.
|
||||||
let c = appDelegate.terminalManager.createWindow(
|
let c = appDelegate.terminalManager.createWindow(
|
||||||
withSurfaceTree2: state.surfaceTree2
|
withSurfaceTree: state.surfaceTree
|
||||||
)
|
)
|
||||||
guard let window = c.window else {
|
guard let window = c.window else {
|
||||||
completionHandler(nil, TerminalRestoreError.windowDidNotLoad)
|
completionHandler(nil, TerminalRestoreError.windowDidNotLoad)
|
||||||
@@ -92,10 +92,10 @@ class TerminalWindowRestoration: NSObject, NSWindowRestoration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Setup our restored state on the controller
|
// Setup our restored state on the controller
|
||||||
// Find the focused surface in surfaceTree2
|
// Find the focused surface in surfaceTree
|
||||||
if let focusedStr = state.focusedSurface {
|
if let focusedStr = state.focusedSurface {
|
||||||
var foundView: Ghostty.SurfaceView?
|
var foundView: Ghostty.SurfaceView?
|
||||||
for view in c.surfaceTree2 {
|
for view in c.surfaceTree {
|
||||||
if view.uuid.uuidString == focusedStr {
|
if view.uuid.uuidString == focusedStr {
|
||||||
foundView = view
|
foundView = view
|
||||||
break
|
break
|
||||||
|
@@ -27,7 +27,7 @@ protocol TerminalViewDelegate: AnyObject {
|
|||||||
protocol TerminalViewModel: ObservableObject {
|
protocol TerminalViewModel: ObservableObject {
|
||||||
/// The tree of terminal surfaces (splits) within the view. This is mutated by TerminalView
|
/// The tree of terminal surfaces (splits) within the view. This is mutated by TerminalView
|
||||||
/// and children. This should be @Published.
|
/// and children. This should be @Published.
|
||||||
var surfaceTree2: SplitTree<Ghostty.SurfaceView> { get set }
|
var surfaceTree: SplitTree<Ghostty.SurfaceView> { get set }
|
||||||
|
|
||||||
/// The command palette state.
|
/// The command palette state.
|
||||||
var commandPaletteIsShowing: Bool { get set }
|
var commandPaletteIsShowing: Bool { get set }
|
||||||
@@ -77,7 +77,7 @@ struct TerminalView<ViewModel: TerminalViewModel>: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TerminalSplitTreeView(
|
TerminalSplitTreeView(
|
||||||
tree: viewModel.surfaceTree2,
|
tree: viewModel.surfaceTree,
|
||||||
onResize: { delegate?.splitDidResize(node: $0, to: $1) })
|
onResize: { delegate?.splitDidResize(node: $0, to: $1) })
|
||||||
.environmentObject(ghostty)
|
.environmentObject(ghostty)
|
||||||
.focused($focused)
|
.focused($focused)
|
||||||
|
@@ -921,7 +921,7 @@ extension Ghostty {
|
|||||||
// we should only be returning true if we actually performed the action,
|
// we should only be returning true if we actually performed the action,
|
||||||
// but this handles the most common case of caring about goto_split performability
|
// but this handles the most common case of caring about goto_split performability
|
||||||
// which is the no-split case.
|
// which is the no-split case.
|
||||||
guard controller.surfaceTree2.isSplit else { return false }
|
guard controller.surfaceTree.isSplit else { return false }
|
||||||
|
|
||||||
NotificationCenter.default.post(
|
NotificationCenter.default.post(
|
||||||
name: Notification.ghosttyFocusSplit,
|
name: Notification.ghosttyFocusSplit,
|
||||||
|
Reference in New Issue
Block a user