mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
macos: use a MTKView subclass for the inspector
This commit is contained in:
@ -13,58 +13,83 @@ extension Ghostty {
|
||||
SplitView(.vertical, left: {
|
||||
SurfaceWrapper(surfaceView: surfaceView, isSplit: isSplit)
|
||||
}, right: {
|
||||
InspectorView()
|
||||
SurfaceInspector()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct InspectorView: View {
|
||||
struct SurfaceInspector: View {
|
||||
var body: some View {
|
||||
MetalView<Renderer>()
|
||||
MetalView<InspectorView>()
|
||||
}
|
||||
}
|
||||
|
||||
class Renderer: NSObject, MetalViewRenderer {
|
||||
let device: MTLDevice
|
||||
class InspectorView: MTKView {
|
||||
let commandQueue: MTLCommandQueue
|
||||
|
||||
required init(metalView: MTKView) {
|
||||
override init(frame: CGRect, device: MTLDevice?) {
|
||||
// Initialize our Metal primitives
|
||||
guard
|
||||
let device = MTLCreateSystemDefaultDevice(),
|
||||
let device = device ?? MTLCreateSystemDefaultDevice(),
|
||||
let commandQueue = device.makeCommandQueue() else {
|
||||
fatalError("GPU not available")
|
||||
}
|
||||
|
||||
self.device = device
|
||||
// Setup our properties before initializing the parent
|
||||
self.commandQueue = commandQueue
|
||||
super.init()
|
||||
super.init(frame: frame, device: device)
|
||||
|
||||
// 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)
|
||||
// After initializing the parent we can set our own properties
|
||||
self.device = MTLCreateSystemDefaultDevice()
|
||||
self.clearColor = MTLClearColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0)
|
||||
|
||||
// Setup our tracking areas for mouse events
|
||||
updateTrackingAreas()
|
||||
}
|
||||
|
||||
required init(coder: NSCoder) {
|
||||
fatalError("init(coder:) is not supported for this view")
|
||||
}
|
||||
|
||||
deinit {
|
||||
trackingAreas.forEach { removeTrackingArea($0) }
|
||||
}
|
||||
|
||||
override func updateTrackingAreas() {
|
||||
// To update our tracking area we just recreate it all.
|
||||
trackingAreas.forEach { removeTrackingArea($0) }
|
||||
|
||||
// This tracking area is across the entire frame to notify us of mouse movements.
|
||||
addTrackingArea(NSTrackingArea(
|
||||
rect: frame,
|
||||
options: [
|
||||
.mouseMoved,
|
||||
|
||||
// Only send mouse events that happen in our visible (not obscured) rect
|
||||
.inVisibleRect,
|
||||
|
||||
// We want active always because we want to still send mouse reports
|
||||
// even if we're not focused or key.
|
||||
.activeAlways,
|
||||
],
|
||||
owner: self,
|
||||
userInfo: nil))
|
||||
}
|
||||
|
||||
override func draw(_ dirtyRect: NSRect) {
|
||||
guard
|
||||
let commandBuffer = self.commandQueue.makeCommandBuffer(),
|
||||
let descriptor = self.currentRenderPassDescriptor,
|
||||
let renderEncoder =
|
||||
commandBuffer.makeRenderCommandEncoder(
|
||||
descriptor: descriptor) else {
|
||||
return
|
||||
}
|
||||
|
||||
renderEncoder.endEncoding()
|
||||
guard let drawable = self.currentDrawable else { return }
|
||||
commandBuffer.present(drawable)
|
||||
commandBuffer.commit()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
@ -1,24 +1,17 @@
|
||||
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?
|
||||
struct MetalView<V: MTKView>: View {
|
||||
@State private var metalView = V()
|
||||
|
||||
var body: some View {
|
||||
MetalViewRepresentable(metalView: $metalView)
|
||||
.onAppear { renderer = R(metalView: metalView) }
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate struct MetalViewRepresentable: NSViewRepresentable {
|
||||
@Binding var metalView: MTKView
|
||||
fileprivate struct MetalViewRepresentable<V: MTKView>: NSViewRepresentable {
|
||||
@Binding var metalView: V
|
||||
|
||||
func makeNSView(context: Context) -> some NSView {
|
||||
metalView
|
||||
|
Reference in New Issue
Block a user