macos: rename TerminalSurfaceView to TerminalSurface

This commit is contained in:
Mitchell Hashimoto
2023-03-05 13:18:19 -08:00
parent b1a7baf394
commit b1d57cd500
4 changed files with 75 additions and 16 deletions

View File

@ -7,7 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
A507573E299FF33C009D7DC7 /* TerminalSurfaceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A507573D299FF33C009D7DC7 /* TerminalSurfaceView.swift */; };
A507573E299FF33C009D7DC7 /* TerminalSurface.swift in Sources */ = {isa = PBXBuildFile; fileRef = A507573D299FF33C009D7DC7 /* TerminalSurface.swift */; };
A518502429A197C700E4CC4F /* TerminalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A518502329A197C700E4CC4F /* TerminalView.swift */; };
A518502629A1A45100E4CC4F /* WindowTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = A518502529A1A45100E4CC4F /* WindowTracker.swift */; };
A535B9DA299C569B0017E2E4 /* ErrorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A535B9D9299C569B0017E2E4 /* ErrorView.swift */; };
@ -19,7 +19,7 @@
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
A507573D299FF33C009D7DC7 /* TerminalSurfaceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalSurfaceView.swift; sourceTree = "<group>"; };
A507573D299FF33C009D7DC7 /* TerminalSurface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalSurface.swift; sourceTree = "<group>"; };
A518502329A197C700E4CC4F /* TerminalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalView.swift; sourceTree = "<group>"; };
A518502529A1A45100E4CC4F /* WindowTracker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowTracker.swift; sourceTree = "<group>"; };
A535B9D9299C569B0017E2E4 /* ErrorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorView.swift; sourceTree = "<group>"; };
@ -53,7 +53,7 @@
A55685DF29A03A9F004303CE /* AppError.swift */,
A59444F629A2ED5200725BBA /* SettingsView.swift */,
A518502329A197C700E4CC4F /* TerminalView.swift */,
A507573D299FF33C009D7DC7 /* TerminalSurfaceView.swift */,
A507573D299FF33C009D7DC7 /* TerminalSurface.swift */,
A518502529A1A45100E4CC4F /* WindowTracker.swift */,
);
path = Sources;
@ -166,7 +166,7 @@
A518502629A1A45100E4CC4F /* WindowTracker.swift in Sources */,
A518502429A197C700E4CC4F /* TerminalView.swift in Sources */,
A55685E029A03A9F004303CE /* AppError.swift in Sources */,
A507573E299FF33C009D7DC7 /* TerminalSurfaceView.swift in Sources */,
A507573E299FF33C009D7DC7 /* TerminalSurface.swift in Sources */,
A535B9DA299C569B0017E2E4 /* ErrorView.swift in Sources */,
A5B30535299BEAAA0047F10C /* GhosttyApp.swift in Sources */,
);

View File

@ -21,7 +21,7 @@ struct GhosttyApp: App {
case .error:
ErrorView()
case .ready:
TerminalView(app: ghostty.app!)
TerminalSplittableView(app: ghostty.app!)
.modifier(WindowObservationModifier())
}
}.commands {
@ -160,7 +160,7 @@ class GhosttyState: ObservableObject {
}
static func setTitle(_ userdata: UnsafeMutableRawPointer?, title: UnsafePointer<CChar>?) {
let surfaceView = Unmanaged<TerminalSurfaceView_Real>.fromOpaque(userdata!).takeUnretainedValue()
let surfaceView = Unmanaged<TerminalSurfaceView>.fromOpaque(userdata!).takeUnretainedValue()
guard let titleStr = String(cString: title!, encoding: .utf8) else { return }
DispatchQueue.main.async {
surfaceView.title = titleStr
@ -169,7 +169,7 @@ class GhosttyState: ObservableObject {
/// Returns the GhosttyState from the given userdata value.
static func appState(fromSurface userdata: UnsafeMutableRawPointer?) -> GhosttyState? {
let surfaceView = Unmanaged<TerminalSurfaceView_Real>.fromOpaque(userdata!).takeUnretainedValue()
let surfaceView = Unmanaged<TerminalSurfaceView>.fromOpaque(userdata!).takeUnretainedValue()
guard let surface = surfaceView.surface else { return nil }
guard let app = ghostty_surface_app(surface) else { return nil }
guard let app_ud = ghostty_app_userdata(app) else { return nil }

View File

@ -9,7 +9,7 @@ import GhosttyKit
/// We just wrap an AppKit NSView here at the moment so that we can behave as low level as possible
/// since that is what the Metal renderer in Ghostty expects. In the future, it may make more sense to
/// wrap an MTKView and use that, but for legacy reasons we didn't do that to begin with.
struct TerminalSurfaceView: NSViewRepresentable {
struct TerminalSurface: NSViewRepresentable {
static let logger = Logger(
subsystem: Bundle.main.bundleIdentifier!,
category: String(describing: TerminalSurfaceView.self)
@ -34,16 +34,16 @@ struct TerminalSurfaceView: NSViewRepresentable {
/// set the appropriate title of the window/tab/split/etc. if they care.
@Binding var title: String
@StateObject private var state: TerminalSurfaceView_Real
@StateObject private var state: TerminalSurfaceView
init(_ app: ghostty_app_t, hasFocus: Bool, size: CGSize, title: Binding<String>) {
self._state = StateObject(wrappedValue: TerminalSurfaceView_Real(app))
self._state = StateObject(wrappedValue: TerminalSurfaceView(app))
self._title = title
self.hasFocus = hasFocus
self.size = size
}
func makeNSView(context: Context) -> TerminalSurfaceView_Real {
func makeNSView(context: Context) -> TerminalSurfaceView {
// We need the view as part of the state to be created previously because
// the view is sent to the Ghostty API so that it can manipulate it
// directly since we draw on a render thread.
@ -51,7 +51,7 @@ struct TerminalSurfaceView: NSViewRepresentable {
return state;
}
func updateNSView(_ view: TerminalSurfaceView_Real, context: Context) {
func updateNSView(_ view: TerminalSurfaceView, context: Context) {
state.delegate = context.coordinator
state.focusDidChange(hasFocus)
state.sizeDidChange(size)
@ -62,9 +62,9 @@ struct TerminalSurfaceView: NSViewRepresentable {
}
class Coordinator : TerminalSurfaceDelegate {
let view: TerminalSurfaceView
let view: TerminalSurface
init(_ view: TerminalSurfaceView) {
init(_ view: TerminalSurface) {
self.view = view
}
@ -80,7 +80,7 @@ protocol TerminalSurfaceDelegate: AnyObject {
}
/// The actual NSView implementation for the terminal surface.
class TerminalSurfaceView_Real: NSView, NSTextInputClient, ObservableObject {
class TerminalSurfaceView: NSView, NSTextInputClient, ObservableObject {
weak var delegate: TerminalSurfaceDelegate?
// The current title of the surface as defined by the pty. This can be

View File

@ -16,9 +16,68 @@ struct TerminalView: View {
// is up to date. See TerminalSurfaceView for why we don't use the NSView
// resize callback.
GeometryReader { geo in
TerminalSurfaceView(app, hasFocus: hasFocus, size: geo.size, title: $title)
TerminalSurface(app, hasFocus: hasFocus, size: geo.size, title: $title)
.focused($surfaceFocus)
.navigationTitle(title)
}
}
}
/// A spittable terminal view is one where the terminal allows for "splits" (vertical and horizontal) within the
/// view. The terminal starts in the unsplit state (a plain ol' TerminalView) but responds to changes to the
/// split direction by splitting the terminal.
struct TerminalSplittableView: View {
enum Direction {
case none
case vertical
case horizontal
}
enum Side: Hashable {
case TopLeft
case BottomRight
}
@FocusState private var focusedSide: Side?
let app: ghostty_app_t
/// Direction of the current split. If this is "nil" then the terminal is not currently split at all.
@State var splitDirection: Direction = .none
var body: some View {
switch (splitDirection) {
case .none:
VStack {
HStack {
Button("Split Horizontal") { splitDirection = .horizontal }
Button("Split Vertical") { splitDirection = .vertical }
}
TerminalView(app: app)
.focused($focusedSide, equals: .TopLeft)
}
case .horizontal:
VStack {
HStack {
Button("Close Left") { splitDirection = .none }
Button("Close Right") { splitDirection = .none }
}
HSplitView {
TerminalSplittableView(app: app)
.focused($focusedSide, equals: .TopLeft)
TerminalSplittableView(app: app)
.focused($focusedSide, equals: .BottomRight)
}
}
case .vertical:
VSplitView {
TerminalSplittableView(app: app)
.focused($focusedSide, equals: .TopLeft)
TerminalSplittableView(app: app)
.focused($focusedSide, equals: .BottomRight)
}
}
}
}