mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-08-29 10:31:40 +00:00
macos: MetalView, render an MTKView
This commit is contained in:
@@ -30,7 +30,7 @@ extension Ghostty {
|
||||
// surface. We need to keep the split root around so that we don't
|
||||
// lose all of the surface state so this must be a ZStack.
|
||||
if let surfaceView = zoomedSurface {
|
||||
SurfaceWrapper(surfaceView: surfaceView)
|
||||
InspectableSurface(surfaceView: surfaceView)
|
||||
}
|
||||
}
|
||||
.focusedValue(\.ghosttySurfaceZoomed, zoomedSurface != nil)
|
||||
@@ -343,7 +343,7 @@ extension Ghostty {
|
||||
let pubClose = center.publisher(for: Notification.ghosttyCloseSurface, object: leaf.surface)
|
||||
let pubFocus = center.publisher(for: Notification.ghosttyFocusSplit, object: leaf.surface)
|
||||
|
||||
SurfaceWrapper(surfaceView: leaf.surface, isSplit: !neighbors.isEmpty())
|
||||
InspectableSurface(surfaceView: leaf.surface, isSplit: !neighbors.isEmpty())
|
||||
.onReceive(pub) { onNewSplit(notification: $0) }
|
||||
.onReceive(pubClose) { onClose(notification: $0) }
|
||||
.onReceive(pubFocus) { onMoveFocus(notification: $0) }
|
||||
|
||||
70
macos/Sources/Ghostty/InspectorView.swift
Normal file
70
macos/Sources/Ghostty/InspectorView.swift
Normal file
@@ -0,0 +1,70 @@
|
||||
import Foundation
|
||||
import MetalKit
|
||||
import SwiftUI
|
||||
|
||||
extension Ghostty {
|
||||
/// InspectableSurface is a type of Surface view that allows an inspector to be attached.
|
||||
struct InspectableSurface: View {
|
||||
/// Same as SurfaceWrapper, see the doc comments there.
|
||||
@ObservedObject var surfaceView: SurfaceView
|
||||
var isSplit: Bool = false
|
||||
|
||||
var body: some View {
|
||||
SplitView(.vertical, left: {
|
||||
SurfaceWrapper(surfaceView: surfaceView, isSplit: isSplit)
|
||||
}, right: {
|
||||
InspectorView()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct InspectorView: View {
|
||||
var body: some View {
|
||||
MetalView<Renderer>()
|
||||
}
|
||||
}
|
||||
|
||||
class Renderer: NSObject, MetalViewRenderer {
|
||||
let device: MTLDevice
|
||||
let commandQueue: MTLCommandQueue
|
||||
|
||||
required init(metalView: MTKView) {
|
||||
// Initialize our Metal primitives
|
||||
guard
|
||||
let device = MTLCreateSystemDefaultDevice(),
|
||||
let commandQueue = device.makeCommandQueue() else {
|
||||
fatalError("GPU not available")
|
||||
}
|
||||
|
||||
self.device = device
|
||||
self.commandQueue = commandQueue
|
||||
super.init()
|
||||
|
||||
// Setup the view to point to this renderer
|
||||
metalView.device = device
|
||||
metalView.delegate = self
|
||||
metalView.clearColor = MTLClearColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Ghostty.Renderer: MTKViewDelegate {
|
||||
func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {
|
||||
}
|
||||
|
||||
func draw(in view: MTKView) {
|
||||
guard
|
||||
let commandBuffer = self.commandQueue.makeCommandBuffer(),
|
||||
let descriptor = view.currentRenderPassDescriptor,
|
||||
let renderEncoder =
|
||||
commandBuffer.makeRenderCommandEncoder(
|
||||
descriptor: descriptor) else {
|
||||
return
|
||||
}
|
||||
|
||||
renderEncoder.endEncoding()
|
||||
guard let drawable = view.currentDrawable else { return }
|
||||
commandBuffer.present(drawable)
|
||||
commandBuffer.commit()
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ extension Ghostty {
|
||||
content(surfaceView)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct SurfaceWrapper: View {
|
||||
// The surface to create a view for. This must be created upstream. As long as this
|
||||
// remains the same, the surface that is being rendered remains the same.
|
||||
|
||||
33
macos/Sources/Helpers/MetalView.swift
Normal file
33
macos/Sources/Helpers/MetalView.swift
Normal file
@@ -0,0 +1,33 @@
|
||||
import SwiftUI
|
||||
import MetalKit
|
||||
|
||||
/// Implements the logic for a metal view used by MetalView.
|
||||
protocol MetalViewRenderer: MTKViewDelegate {
|
||||
init(metalView: MTKView)
|
||||
}
|
||||
|
||||
/// Renders an MTKView with the given renderer class.
|
||||
struct MetalView<R: MetalViewRenderer>: View {
|
||||
@State private var metalView = MTKView()
|
||||
@State private var renderer: R?
|
||||
|
||||
var body: some View {
|
||||
MetalViewRepresentable(metalView: $metalView)
|
||||
.onAppear { renderer = R(metalView: metalView) }
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate struct MetalViewRepresentable: NSViewRepresentable {
|
||||
@Binding var metalView: MTKView
|
||||
|
||||
func makeNSView(context: Context) -> some NSView {
|
||||
metalView
|
||||
}
|
||||
|
||||
func updateNSView(_ view: NSViewType, context: Context) {
|
||||
updateMetalView()
|
||||
}
|
||||
|
||||
func updateMetalView() {
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user