mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
macos: fix state handling of terminal surface in split
This commit is contained in:
@ -49,52 +49,70 @@ struct TerminalSplittableView: View {
|
|||||||
case BottomRight
|
case BottomRight
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The stored state between invocations.
|
||||||
|
class ViewState: ObservableObject {
|
||||||
|
/// The direction of the split currently
|
||||||
|
@Published var direction: Direction = .none
|
||||||
|
|
||||||
|
/// The top or left view. This is always set.
|
||||||
|
@Published var topLeft: TerminalSurfaceView
|
||||||
|
|
||||||
|
/// The bottom or right view. This can be nil if the direction == .none.
|
||||||
|
@Published var bottomRight: TerminalSurfaceView? = nil
|
||||||
|
|
||||||
|
/// Initialize the view state for the first time. This will create our topLeft view from new.
|
||||||
|
init(_ app: ghostty_app_t) {
|
||||||
|
self.topLeft = TerminalSurfaceView(app)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initialize the view state using an existing top left. This is usually used when a split happens and
|
||||||
|
/// the child view inherits the top left.
|
||||||
|
init(topLeft: TerminalSurfaceView) {
|
||||||
|
self.topLeft = topLeft
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let app: ghostty_app_t
|
||||||
|
@StateObject private var state: ViewState
|
||||||
@FocusState private var focusedSide: Side?
|
@FocusState private var focusedSide: Side?
|
||||||
|
|
||||||
let app: ghostty_app_t;
|
|
||||||
|
|
||||||
@State private var topLeft: TerminalSurfaceView
|
|
||||||
|
|
||||||
/// The bottom or right surface. This is private because in a splittable view it is only possible that we set
|
|
||||||
/// this, because it is triggered from a split event.
|
|
||||||
@State private var bottomRight: TerminalSurfaceView? = nil
|
|
||||||
|
|
||||||
/// Direction of the current split. If this is "nil" then the terminal is not currently split at all.
|
|
||||||
@State private var splitDirection: Direction = .none
|
|
||||||
|
|
||||||
init(_ app: ghostty_app_t) {
|
init(_ app: ghostty_app_t) {
|
||||||
self.app = app
|
self.app = app
|
||||||
_topLeft = State(wrappedValue: TerminalSurfaceView(app))
|
_state = StateObject(wrappedValue: ViewState(app))
|
||||||
}
|
}
|
||||||
|
|
||||||
init(_ app: ghostty_app_t, topLeft: TerminalSurfaceView) {
|
init(_ app: ghostty_app_t, topLeft: TerminalSurfaceView) {
|
||||||
self.app = app
|
self.app = app
|
||||||
_topLeft = State(wrappedValue: topLeft)
|
_state = StateObject(wrappedValue: ViewState(topLeft: topLeft))
|
||||||
}
|
}
|
||||||
|
|
||||||
func split(to: Direction) {
|
func split(to: Direction) {
|
||||||
assert(to != .none)
|
assert(to != .none)
|
||||||
assert(splitDirection == .none)
|
assert(state.direction == .none)
|
||||||
splitDirection = to
|
|
||||||
bottomRight = TerminalSurfaceView(app)
|
// Make the split the desired value
|
||||||
|
state.direction = to
|
||||||
|
|
||||||
|
// Create the new split which always goes to the bottom right.
|
||||||
|
state.bottomRight = TerminalSurfaceView(app)
|
||||||
}
|
}
|
||||||
|
|
||||||
func closeTopLeft() {
|
func closeTopLeft() {
|
||||||
assert(splitDirection != .none)
|
assert(state.direction != .none)
|
||||||
assert(bottomRight != nil)
|
assert(state.bottomRight != nil)
|
||||||
topLeft = bottomRight!
|
state.topLeft = state.bottomRight!
|
||||||
splitDirection = .none
|
state.direction = .none
|
||||||
}
|
}
|
||||||
|
|
||||||
func closeBottomRight() {
|
func closeBottomRight() {
|
||||||
assert(splitDirection != .none)
|
assert(state.direction != .none)
|
||||||
assert(bottomRight != nil)
|
assert(state.bottomRight != nil)
|
||||||
bottomRight = nil
|
state.bottomRight = nil
|
||||||
splitDirection = .none
|
state.direction = .none
|
||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
switch (splitDirection) {
|
switch (state.direction) {
|
||||||
case .none:
|
case .none:
|
||||||
VStack {
|
VStack {
|
||||||
HStack {
|
HStack {
|
||||||
@ -102,7 +120,7 @@ struct TerminalSplittableView: View {
|
|||||||
Button("Split Vertical") { split(to: .vertical) }
|
Button("Split Vertical") { split(to: .vertical) }
|
||||||
}
|
}
|
||||||
|
|
||||||
TerminalView(surface: topLeft)
|
TerminalView(surface: state.topLeft)
|
||||||
.focused($focusedSide, equals: .TopLeft)
|
.focused($focusedSide, equals: .TopLeft)
|
||||||
}
|
}
|
||||||
case .horizontal:
|
case .horizontal:
|
||||||
@ -113,9 +131,9 @@ struct TerminalSplittableView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
HSplitView {
|
HSplitView {
|
||||||
TerminalSplittableView(app, topLeft: topLeft)
|
TerminalSplittableView(app, topLeft: state.topLeft)
|
||||||
.focused($focusedSide, equals: .TopLeft)
|
.focused($focusedSide, equals: .TopLeft)
|
||||||
TerminalSplittableView(app, topLeft: bottomRight!)
|
TerminalSplittableView(app, topLeft: state.bottomRight!)
|
||||||
.focused($focusedSide, equals: .BottomRight)
|
.focused($focusedSide, equals: .BottomRight)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -127,9 +145,9 @@ struct TerminalSplittableView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
VSplitView {
|
VSplitView {
|
||||||
TerminalSplittableView(app, topLeft: topLeft)
|
TerminalSplittableView(app, topLeft: state.topLeft)
|
||||||
.focused($focusedSide, equals: .TopLeft)
|
.focused($focusedSide, equals: .TopLeft)
|
||||||
TerminalSplittableView(app, topLeft: bottomRight!)
|
TerminalSplittableView(app, topLeft: state.bottomRight!)
|
||||||
.focused($focusedSide, equals: .BottomRight)
|
.focused($focusedSide, equals: .BottomRight)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,6 @@ class WindowObserver: ObservableObject {
|
|||||||
object: window,
|
object: window,
|
||||||
queue: .main
|
queue: .main
|
||||||
) { (n) in
|
) { (n) in
|
||||||
print("KEY WINDOW YES")
|
|
||||||
self.isKeyWindow = true
|
self.isKeyWindow = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,7 +67,6 @@ class WindowObserver: ObservableObject {
|
|||||||
object: window,
|
object: window,
|
||||||
queue: .main
|
queue: .main
|
||||||
) { (n) in
|
) { (n) in
|
||||||
print("KEY WINDOW RESIGN")
|
|
||||||
self.isKeyWindow = false
|
self.isKeyWindow = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user