mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-04-14 11:35:48 +00:00
85 lines
2.9 KiB
Swift
85 lines
2.9 KiB
Swift
import SwiftUI
|
|
import GhosttyKit
|
|
|
|
extension Ghostty {
|
|
/// The UIView implementation for a terminal surface.
|
|
class SurfaceView: OSSurfaceView {
|
|
// The current title of the surface as defined by the pty. This can be
|
|
// changed with escape codes.
|
|
@Published private(set) var title: String = "👻"
|
|
|
|
/// True when the bell is active. This is set inactive on focus or event.
|
|
@Published var bell: Bool = false
|
|
|
|
private(set) var _surface: ghostty_surface_t?
|
|
|
|
override var surface: ghostty_surface_t? {
|
|
_surface
|
|
}
|
|
|
|
init(_ app: ghostty_app_t, baseConfig: SurfaceConfiguration? = nil, uuid: UUID? = nil) {
|
|
|
|
// Initialize with some default frame size. The important thing is that this
|
|
// is non-zero so that our layer bounds are non-zero so that our renderer
|
|
// can do SOMETHING.
|
|
super.init(id: uuid, frame: CGRect(x: 0, y: 0, width: 800, height: 600))
|
|
|
|
// Setup our surface. This will also initialize all the terminal IO.
|
|
let surface_cfg = baseConfig ?? SurfaceConfiguration()
|
|
let surface = surface_cfg.withCValue(view: self) { surface_cfg_c in
|
|
ghostty_surface_new(app, &surface_cfg_c)
|
|
}
|
|
guard let surface = surface else {
|
|
// TODO
|
|
return
|
|
}
|
|
self._surface = surface
|
|
}
|
|
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) is not supported for this view")
|
|
}
|
|
|
|
deinit {
|
|
guard let surface = self.surface else { return }
|
|
ghostty_surface_free(surface)
|
|
}
|
|
|
|
override func focusDidChange(_ focused: Bool) {
|
|
guard let surface = self.surface else { return }
|
|
ghostty_surface_set_focus(surface, focused)
|
|
|
|
// On macOS 13+ we can store our continuous clock...
|
|
if focused {
|
|
focusInstant = ContinuousClock.now
|
|
}
|
|
}
|
|
|
|
override func sizeDidChange(_ size: CGSize) {
|
|
guard let surface = self.surface else { return }
|
|
|
|
// Ghostty wants to know the actual framebuffer size... It is very important
|
|
// here that we use "size" and NOT the view frame. If we're in the middle of
|
|
// an animation (i.e. a fullscreen animation), the frame will not yet be updated.
|
|
// The size represents our final size we're going for.
|
|
let scale = self.contentScaleFactor
|
|
ghostty_surface_set_content_scale(surface, scale, scale)
|
|
ghostty_surface_set_size(
|
|
surface,
|
|
UInt32(size.width * scale),
|
|
UInt32(size.height * scale)
|
|
)
|
|
}
|
|
|
|
// MARK: UIView
|
|
|
|
override class var layerClass: AnyClass {
|
|
return CAMetalLayer.self
|
|
}
|
|
|
|
override func didMoveToWindow() {
|
|
sizeDidChange(frame.size)
|
|
}
|
|
}
|
|
}
|