libghostty als zweite Terminal-Engine integriert (Default ghostty, SwiftTerm Fallback)

- vendor/libghostty: vorgebaute macOS-libghostty.a (arm64) + Header + Build-Patches + README
- Sources/CGhostty: C-Modul der libghostty-C-API
- Sources/MiniTerm/Ghostty.swift: GhosttyApp + GhosttySurfaceView (Surface, Input, Größe, Fokus)
- main.swift: Engine-Wahl per Info.plist MTEngine
- Package.swift: CGhostty-Target + Link gegen libghostty + Frameworks
- STATUS.md: Stand, Build-Weg (macOS-15-VM), offene Punkte
This commit is contained in:
marcus.hinz
2026-06-21 21:40:00 +02:00
parent 51cb14a782
commit c8f5714b1e
22 changed files with 4970 additions and 11 deletions
+39 -10
View File
@@ -20,6 +20,7 @@ struct AppConfig {
let fontSize: CGFloat
let fontName: String
let windowTitle: String
let engine: String // "ghostty" (Default) oder "swiftterm"
static func load() -> AppConfig {
let info = Bundle.main.infoDictionary ?? [:]
@@ -27,6 +28,9 @@ struct AppConfig {
let cmd = ((info["MTCommand"] as? String) ?? "")
.trimmingCharacters(in: .whitespacesAndNewlines)
let engine = ((info["MTEngine"] as? String) ?? "ghostty")
.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()
var workdir: String? = nil
if let raw = info["MTWorkingDirectory"] as? String,
!raw.trimmingCharacters(in: .whitespaces).isEmpty {
@@ -46,7 +50,8 @@ struct AppConfig {
workingDirectory: workdir,
fontSize: CGFloat(size),
fontName: fontName.isEmpty ? "Menlo" : fontName,
windowTitle: title)
windowTitle: title,
engine: engine == "swiftterm" ? "swiftterm" : "ghostty")
}
}
@@ -55,30 +60,54 @@ final class AppDelegate: NSObject, NSApplicationDelegate, LocalProcessTerminalVi
private var window: NSWindow!
private var terminalView: LocalProcessTerminalView!
private var keyMonitor: Any?
private var ghosttyApp: GhosttyApp?
private var ghosttyView: GhosttySurfaceView?
private let config = AppConfig.load()
func applicationDidFinishLaunching(_ notification: Notification) {
let frame = NSRect(x: 0, y: 0, width: 900, height: 560)
terminalView = LocalProcessTerminalView(frame: frame)
terminalView.processDelegate = self
terminalView.font = resolvedFont()
installKeyMonitor()
window = NSWindow(
contentRect: frame,
styleMask: [.titled, .closable, .miniaturizable, .resizable],
backing: .buffered,
defer: false)
window.title = config.windowTitle
window.contentView = terminalView
window.setFrameAutosaveName("MiniTermMain")
window.center()
window.makeKeyAndOrderFront(nil)
window.makeFirstResponder(terminalView)
// Engine wählen. libghostty (GPU-Renderer) ist Default; SwiftTerm bleibt
// als Fallback (auch wenn die libghostty-Init scheitert).
if config.engine == "ghostty", let contentView = setupGhostty(frame: frame) {
window.contentView = contentView
window.makeKeyAndOrderFront(nil)
window.makeFirstResponder(contentView)
} else {
setupSwiftTerm(frame: frame)
}
setupMenu()
}
private func setupGhostty(frame: NSRect) -> NSView? {
guard let gapp = GhosttyApp() else {
NSLog("libghostty-Init fehlgeschlagen Fallback auf SwiftTerm")
return nil
}
ghosttyApp = gapp
let view = GhosttySurfaceView(ghostty: gapp, appConfig: config, frame: frame)
ghosttyView = view
return view
}
private func setupSwiftTerm(frame: NSRect) {
terminalView = LocalProcessTerminalView(frame: frame)
terminalView.processDelegate = self
terminalView.font = resolvedFont()
installKeyMonitor()
window.contentView = terminalView
window.makeKeyAndOrderFront(nil)
window.makeFirstResponder(terminalView)
launchProcess()
}