mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-19 10:16:12 +03:00
macos: rename TerminalSurfaceView to TerminalSurface
This commit is contained in:
@ -7,7 +7,7 @@
|
|||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* 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 */; };
|
A518502429A197C700E4CC4F /* TerminalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A518502329A197C700E4CC4F /* TerminalView.swift */; };
|
||||||
A518502629A1A45100E4CC4F /* WindowTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = A518502529A1A45100E4CC4F /* WindowTracker.swift */; };
|
A518502629A1A45100E4CC4F /* WindowTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = A518502529A1A45100E4CC4F /* WindowTracker.swift */; };
|
||||||
A535B9DA299C569B0017E2E4 /* ErrorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A535B9D9299C569B0017E2E4 /* ErrorView.swift */; };
|
A535B9DA299C569B0017E2E4 /* ErrorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A535B9D9299C569B0017E2E4 /* ErrorView.swift */; };
|
||||||
@ -19,7 +19,7 @@
|
|||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXFileReference 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>"; };
|
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>"; };
|
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>"; };
|
A535B9D9299C569B0017E2E4 /* ErrorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorView.swift; sourceTree = "<group>"; };
|
||||||
@ -53,7 +53,7 @@
|
|||||||
A55685DF29A03A9F004303CE /* AppError.swift */,
|
A55685DF29A03A9F004303CE /* AppError.swift */,
|
||||||
A59444F629A2ED5200725BBA /* SettingsView.swift */,
|
A59444F629A2ED5200725BBA /* SettingsView.swift */,
|
||||||
A518502329A197C700E4CC4F /* TerminalView.swift */,
|
A518502329A197C700E4CC4F /* TerminalView.swift */,
|
||||||
A507573D299FF33C009D7DC7 /* TerminalSurfaceView.swift */,
|
A507573D299FF33C009D7DC7 /* TerminalSurface.swift */,
|
||||||
A518502529A1A45100E4CC4F /* WindowTracker.swift */,
|
A518502529A1A45100E4CC4F /* WindowTracker.swift */,
|
||||||
);
|
);
|
||||||
path = Sources;
|
path = Sources;
|
||||||
@ -166,7 +166,7 @@
|
|||||||
A518502629A1A45100E4CC4F /* WindowTracker.swift in Sources */,
|
A518502629A1A45100E4CC4F /* WindowTracker.swift in Sources */,
|
||||||
A518502429A197C700E4CC4F /* TerminalView.swift in Sources */,
|
A518502429A197C700E4CC4F /* TerminalView.swift in Sources */,
|
||||||
A55685E029A03A9F004303CE /* AppError.swift in Sources */,
|
A55685E029A03A9F004303CE /* AppError.swift in Sources */,
|
||||||
A507573E299FF33C009D7DC7 /* TerminalSurfaceView.swift in Sources */,
|
A507573E299FF33C009D7DC7 /* TerminalSurface.swift in Sources */,
|
||||||
A535B9DA299C569B0017E2E4 /* ErrorView.swift in Sources */,
|
A535B9DA299C569B0017E2E4 /* ErrorView.swift in Sources */,
|
||||||
A5B30535299BEAAA0047F10C /* GhosttyApp.swift in Sources */,
|
A5B30535299BEAAA0047F10C /* GhosttyApp.swift in Sources */,
|
||||||
);
|
);
|
||||||
|
@ -21,7 +21,7 @@ struct GhosttyApp: App {
|
|||||||
case .error:
|
case .error:
|
||||||
ErrorView()
|
ErrorView()
|
||||||
case .ready:
|
case .ready:
|
||||||
TerminalView(app: ghostty.app!)
|
TerminalSplittableView(app: ghostty.app!)
|
||||||
.modifier(WindowObservationModifier())
|
.modifier(WindowObservationModifier())
|
||||||
}
|
}
|
||||||
}.commands {
|
}.commands {
|
||||||
@ -160,7 +160,7 @@ class GhosttyState: ObservableObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static func setTitle(_ userdata: UnsafeMutableRawPointer?, title: UnsafePointer<CChar>?) {
|
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 }
|
guard let titleStr = String(cString: title!, encoding: .utf8) else { return }
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
surfaceView.title = titleStr
|
surfaceView.title = titleStr
|
||||||
@ -169,7 +169,7 @@ class GhosttyState: ObservableObject {
|
|||||||
|
|
||||||
/// Returns the GhosttyState from the given userdata value.
|
/// Returns the GhosttyState from the given userdata value.
|
||||||
static func appState(fromSurface userdata: UnsafeMutableRawPointer?) -> GhosttyState? {
|
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 surface = surfaceView.surface else { return nil }
|
||||||
guard let app = ghostty_surface_app(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 }
|
guard let app_ud = ghostty_app_userdata(app) else { return nil }
|
||||||
|
@ -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
|
/// 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
|
/// 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.
|
/// 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(
|
static let logger = Logger(
|
||||||
subsystem: Bundle.main.bundleIdentifier!,
|
subsystem: Bundle.main.bundleIdentifier!,
|
||||||
category: String(describing: TerminalSurfaceView.self)
|
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.
|
/// set the appropriate title of the window/tab/split/etc. if they care.
|
||||||
@Binding var title: String
|
@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>) {
|
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._title = title
|
||||||
self.hasFocus = hasFocus
|
self.hasFocus = hasFocus
|
||||||
self.size = size
|
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
|
// 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
|
// the view is sent to the Ghostty API so that it can manipulate it
|
||||||
// directly since we draw on a render thread.
|
// directly since we draw on a render thread.
|
||||||
@ -51,7 +51,7 @@ struct TerminalSurfaceView: NSViewRepresentable {
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateNSView(_ view: TerminalSurfaceView_Real, context: Context) {
|
func updateNSView(_ view: TerminalSurfaceView, context: Context) {
|
||||||
state.delegate = context.coordinator
|
state.delegate = context.coordinator
|
||||||
state.focusDidChange(hasFocus)
|
state.focusDidChange(hasFocus)
|
||||||
state.sizeDidChange(size)
|
state.sizeDidChange(size)
|
||||||
@ -62,9 +62,9 @@ struct TerminalSurfaceView: NSViewRepresentable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Coordinator : TerminalSurfaceDelegate {
|
class Coordinator : TerminalSurfaceDelegate {
|
||||||
let view: TerminalSurfaceView
|
let view: TerminalSurface
|
||||||
|
|
||||||
init(_ view: TerminalSurfaceView) {
|
init(_ view: TerminalSurface) {
|
||||||
self.view = view
|
self.view = view
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,7 +80,7 @@ protocol TerminalSurfaceDelegate: AnyObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The actual NSView implementation for the terminal surface.
|
/// The actual NSView implementation for the terminal surface.
|
||||||
class TerminalSurfaceView_Real: NSView, NSTextInputClient, ObservableObject {
|
class TerminalSurfaceView: NSView, NSTextInputClient, ObservableObject {
|
||||||
weak var delegate: TerminalSurfaceDelegate?
|
weak var delegate: TerminalSurfaceDelegate?
|
||||||
|
|
||||||
// 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
|
@ -16,9 +16,68 @@ struct TerminalView: View {
|
|||||||
// is up to date. See TerminalSurfaceView for why we don't use the NSView
|
// is up to date. See TerminalSurfaceView for why we don't use the NSView
|
||||||
// resize callback.
|
// resize callback.
|
||||||
GeometryReader { geo in
|
GeometryReader { geo in
|
||||||
TerminalSurfaceView(app, hasFocus: hasFocus, size: geo.size, title: $title)
|
TerminalSurface(app, hasFocus: hasFocus, size: geo.size, title: $title)
|
||||||
.focused($surfaceFocus)
|
.focused($surfaceFocus)
|
||||||
.navigationTitle(title)
|
.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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user