macos: starting to work on new libghostty data models
parent
bbb69c8f27
commit
5259d0fa55
|
|
@ -53,7 +53,6 @@
|
||||||
A54B0CED2D0CFB7700CBEFF8 /* ColorizedGhosttyIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = A54B0CEC2D0CFB7300CBEFF8 /* ColorizedGhosttyIcon.swift */; };
|
A54B0CED2D0CFB7700CBEFF8 /* ColorizedGhosttyIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = A54B0CEC2D0CFB7300CBEFF8 /* ColorizedGhosttyIcon.swift */; };
|
||||||
A54B0CEF2D0D2E2800CBEFF8 /* ColorizedGhosttyIconImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = A54B0CEE2D0D2E2400CBEFF8 /* ColorizedGhosttyIconImage.swift */; };
|
A54B0CEF2D0D2E2800CBEFF8 /* ColorizedGhosttyIconImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = A54B0CEE2D0D2E2400CBEFF8 /* ColorizedGhosttyIconImage.swift */; };
|
||||||
A54D786C2CA7978E001B19B1 /* BaseTerminalController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A54D786B2CA79788001B19B1 /* BaseTerminalController.swift */; };
|
A54D786C2CA7978E001B19B1 /* BaseTerminalController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A54D786B2CA79788001B19B1 /* BaseTerminalController.swift */; };
|
||||||
A55685E029A03A9F004303CE /* AppError.swift in Sources */ = {isa = PBXBuildFile; fileRef = A55685DF29A03A9F004303CE /* AppError.swift */; };
|
|
||||||
A5593FDF2DF8D57C00B47B10 /* TerminalWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5593FDE2DF8D57100B47B10 /* TerminalWindow.swift */; };
|
A5593FDF2DF8D57C00B47B10 /* TerminalWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5593FDE2DF8D57100B47B10 /* TerminalWindow.swift */; };
|
||||||
A5593FE12DF8D74000B47B10 /* HiddenTitlebarTerminalWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5593FE02DF8D73400B47B10 /* HiddenTitlebarTerminalWindow.swift */; };
|
A5593FE12DF8D74000B47B10 /* HiddenTitlebarTerminalWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5593FE02DF8D73400B47B10 /* HiddenTitlebarTerminalWindow.swift */; };
|
||||||
A5593FE32DF8D78600B47B10 /* TerminalHiddenTitlebar.xib in Resources */ = {isa = PBXBuildFile; fileRef = A5593FE22DF8D78600B47B10 /* TerminalHiddenTitlebar.xib */; };
|
A5593FE32DF8D78600B47B10 /* TerminalHiddenTitlebar.xib in Resources */ = {isa = PBXBuildFile; fileRef = A5593FE22DF8D78600B47B10 /* TerminalHiddenTitlebar.xib */; };
|
||||||
|
|
@ -124,6 +123,9 @@
|
||||||
A5E408302E0271320035FEAC /* GhosttyIntentError.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E4082F2E0271320035FEAC /* GhosttyIntentError.swift */; };
|
A5E408302E0271320035FEAC /* GhosttyIntentError.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E4082F2E0271320035FEAC /* GhosttyIntentError.swift */; };
|
||||||
A5E408322E02FEDF0035FEAC /* TerminalEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E408312E02FEDC0035FEAC /* TerminalEntity.swift */; };
|
A5E408322E02FEDF0035FEAC /* TerminalEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E408312E02FEDC0035FEAC /* TerminalEntity.swift */; };
|
||||||
A5E408342E0320140035FEAC /* GetTerminalDetailsIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E408332E03200F0035FEAC /* GetTerminalDetailsIntent.swift */; };
|
A5E408342E0320140035FEAC /* GetTerminalDetailsIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E408332E03200F0035FEAC /* GetTerminalDetailsIntent.swift */; };
|
||||||
|
A5E408382E03C7DA0035FEAC /* Ghostty.Surface.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E408372E03C7D80035FEAC /* Ghostty.Surface.swift */; };
|
||||||
|
A5E4083A2E0449BD0035FEAC /* Ghostty.Command.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E408392E0449BB0035FEAC /* Ghostty.Command.swift */; };
|
||||||
|
A5E4083C2E044DB50035FEAC /* Ghostty.Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E4083B2E044DB40035FEAC /* Ghostty.Error.swift */; };
|
||||||
A5FEB3002ABB69450068369E /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5FEB2FF2ABB69450068369E /* main.swift */; };
|
A5FEB3002ABB69450068369E /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5FEB2FF2ABB69450068369E /* main.swift */; };
|
||||||
AEE8B3452B9AA39600260C5E /* NSPasteboard+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEE8B3442B9AA39600260C5E /* NSPasteboard+Extension.swift */; };
|
AEE8B3452B9AA39600260C5E /* NSPasteboard+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEE8B3442B9AA39600260C5E /* NSPasteboard+Extension.swift */; };
|
||||||
C159E81D2B66A06B00FDFE9C /* OSColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C159E81C2B66A06B00FDFE9C /* OSColor+Extension.swift */; };
|
C159E81D2B66A06B00FDFE9C /* OSColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C159E81C2B66A06B00FDFE9C /* OSColor+Extension.swift */; };
|
||||||
|
|
@ -175,7 +177,6 @@
|
||||||
A54B0CEC2D0CFB7300CBEFF8 /* ColorizedGhosttyIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorizedGhosttyIcon.swift; sourceTree = "<group>"; };
|
A54B0CEC2D0CFB7300CBEFF8 /* ColorizedGhosttyIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorizedGhosttyIcon.swift; sourceTree = "<group>"; };
|
||||||
A54B0CEE2D0D2E2400CBEFF8 /* ColorizedGhosttyIconImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorizedGhosttyIconImage.swift; sourceTree = "<group>"; };
|
A54B0CEE2D0D2E2400CBEFF8 /* ColorizedGhosttyIconImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorizedGhosttyIconImage.swift; sourceTree = "<group>"; };
|
||||||
A54D786B2CA79788001B19B1 /* BaseTerminalController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseTerminalController.swift; sourceTree = "<group>"; };
|
A54D786B2CA79788001B19B1 /* BaseTerminalController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseTerminalController.swift; sourceTree = "<group>"; };
|
||||||
A55685DF29A03A9F004303CE /* AppError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppError.swift; sourceTree = "<group>"; };
|
|
||||||
A5593FDE2DF8D57100B47B10 /* TerminalWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalWindow.swift; sourceTree = "<group>"; };
|
A5593FDE2DF8D57100B47B10 /* TerminalWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalWindow.swift; sourceTree = "<group>"; };
|
||||||
A5593FE02DF8D73400B47B10 /* HiddenTitlebarTerminalWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HiddenTitlebarTerminalWindow.swift; sourceTree = "<group>"; };
|
A5593FE02DF8D73400B47B10 /* HiddenTitlebarTerminalWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HiddenTitlebarTerminalWindow.swift; sourceTree = "<group>"; };
|
||||||
A5593FE22DF8D78600B47B10 /* TerminalHiddenTitlebar.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TerminalHiddenTitlebar.xib; sourceTree = "<group>"; };
|
A5593FE22DF8D78600B47B10 /* TerminalHiddenTitlebar.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TerminalHiddenTitlebar.xib; sourceTree = "<group>"; };
|
||||||
|
|
@ -248,6 +249,9 @@
|
||||||
A5E4082F2E0271320035FEAC /* GhosttyIntentError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GhosttyIntentError.swift; sourceTree = "<group>"; };
|
A5E4082F2E0271320035FEAC /* GhosttyIntentError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GhosttyIntentError.swift; sourceTree = "<group>"; };
|
||||||
A5E408312E02FEDC0035FEAC /* TerminalEntity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalEntity.swift; sourceTree = "<group>"; };
|
A5E408312E02FEDC0035FEAC /* TerminalEntity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalEntity.swift; sourceTree = "<group>"; };
|
||||||
A5E408332E03200F0035FEAC /* GetTerminalDetailsIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetTerminalDetailsIntent.swift; sourceTree = "<group>"; };
|
A5E408332E03200F0035FEAC /* GetTerminalDetailsIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetTerminalDetailsIntent.swift; sourceTree = "<group>"; };
|
||||||
|
A5E408372E03C7D80035FEAC /* Ghostty.Surface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Ghostty.Surface.swift; sourceTree = "<group>"; };
|
||||||
|
A5E408392E0449BB0035FEAC /* Ghostty.Command.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Ghostty.Command.swift; sourceTree = "<group>"; };
|
||||||
|
A5E4083B2E044DB40035FEAC /* Ghostty.Error.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Ghostty.Error.swift; sourceTree = "<group>"; };
|
||||||
A5FEB2FF2ABB69450068369E /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
|
A5FEB2FF2ABB69450068369E /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
|
||||||
AEE8B3442B9AA39600260C5E /* NSPasteboard+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSPasteboard+Extension.swift"; sourceTree = "<group>"; };
|
AEE8B3442B9AA39600260C5E /* NSPasteboard+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSPasteboard+Extension.swift"; sourceTree = "<group>"; };
|
||||||
C159E81C2B66A06B00FDFE9C /* OSColor+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OSColor+Extension.swift"; sourceTree = "<group>"; };
|
C159E81C2B66A06B00FDFE9C /* OSColor+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OSColor+Extension.swift"; sourceTree = "<group>"; };
|
||||||
|
|
@ -440,12 +444,14 @@
|
||||||
A5333E152B59DE8E008AEFF7 /* SurfaceView_UIKit.swift */,
|
A5333E152B59DE8E008AEFF7 /* SurfaceView_UIKit.swift */,
|
||||||
A59FB5CE2AE0DB50009128F3 /* InspectorView.swift */,
|
A59FB5CE2AE0DB50009128F3 /* InspectorView.swift */,
|
||||||
A53D0C992B543F3B00305CE6 /* Ghostty.App.swift */,
|
A53D0C992B543F3B00305CE6 /* Ghostty.App.swift */,
|
||||||
|
A5E408392E0449BB0035FEAC /* Ghostty.Command.swift */,
|
||||||
A514C8D52B54A16400493A16 /* Ghostty.Config.swift */,
|
A514C8D52B54A16400493A16 /* Ghostty.Config.swift */,
|
||||||
A53A6C022CCC1B7D00943E98 /* Ghostty.Action.swift */,
|
A53A6C022CCC1B7D00943E98 /* Ghostty.Action.swift */,
|
||||||
|
A5E4083B2E044DB40035FEAC /* Ghostty.Error.swift */,
|
||||||
A5CF66D62D29DDB100139794 /* Ghostty.Event.swift */,
|
A5CF66D62D29DDB100139794 /* Ghostty.Event.swift */,
|
||||||
A5278A9A2AA05B2600CD3039 /* Ghostty.Input.swift */,
|
A5278A9A2AA05B2600CD3039 /* Ghostty.Input.swift */,
|
||||||
A56D58852ACDDB4100508D2C /* Ghostty.Shell.swift */,
|
A56D58852ACDDB4100508D2C /* Ghostty.Shell.swift */,
|
||||||
A55685DF29A03A9F004303CE /* AppError.swift */,
|
A5E408372E03C7D80035FEAC /* Ghostty.Surface.swift */,
|
||||||
A52FFF5A2CAA54A8000C6A5B /* FullscreenMode+Extension.swift */,
|
A52FFF5A2CAA54A8000C6A5B /* FullscreenMode+Extension.swift */,
|
||||||
A5CF66D32D289CEA00139794 /* NSEvent+Extension.swift */,
|
A5CF66D32D289CEA00139794 /* NSEvent+Extension.swift */,
|
||||||
);
|
);
|
||||||
|
|
@ -766,6 +772,7 @@
|
||||||
A5CBD0602CA0C90A0017A1AE /* QuickTerminalWindow.swift in Sources */,
|
A5CBD0602CA0C90A0017A1AE /* QuickTerminalWindow.swift in Sources */,
|
||||||
A5CBD05E2CA0C5EC0017A1AE /* QuickTerminalController.swift in Sources */,
|
A5CBD05E2CA0C5EC0017A1AE /* QuickTerminalController.swift in Sources */,
|
||||||
A5CF66D72D29DDB500139794 /* Ghostty.Event.swift in Sources */,
|
A5CF66D72D29DDB500139794 /* Ghostty.Event.swift in Sources */,
|
||||||
|
A5E408382E03C7DA0035FEAC /* Ghostty.Surface.swift in Sources */,
|
||||||
A5593FE72DF927D200B47B10 /* TransparentTitlebarTerminalWindow.swift in Sources */,
|
A5593FE72DF927D200B47B10 /* TransparentTitlebarTerminalWindow.swift in Sources */,
|
||||||
A5A2A3CA2D4445E30033CF96 /* Dock.swift in Sources */,
|
A5A2A3CA2D4445E30033CF96 /* Dock.swift in Sources */,
|
||||||
A586365F2DEE6C2300E04A10 /* SplitTree.swift in Sources */,
|
A586365F2DEE6C2300E04A10 /* SplitTree.swift in Sources */,
|
||||||
|
|
@ -800,6 +807,7 @@
|
||||||
A5985CD72C320C4500C57AD3 /* String+Extension.swift in Sources */,
|
A5985CD72C320C4500C57AD3 /* String+Extension.swift in Sources */,
|
||||||
A5A2A3CC2D444ABB0033CF96 /* NSApplication+Extension.swift in Sources */,
|
A5A2A3CC2D444ABB0033CF96 /* NSApplication+Extension.swift in Sources */,
|
||||||
A5E408302E0271320035FEAC /* GhosttyIntentError.swift in Sources */,
|
A5E408302E0271320035FEAC /* GhosttyIntentError.swift in Sources */,
|
||||||
|
A5E4083A2E0449BD0035FEAC /* Ghostty.Command.swift in Sources */,
|
||||||
A5FEB3002ABB69450068369E /* main.swift in Sources */,
|
A5FEB3002ABB69450068369E /* main.swift in Sources */,
|
||||||
A53A297F2DB4480F00B6E02C /* EventModifiers+Extension.swift in Sources */,
|
A53A297F2DB4480F00B6E02C /* EventModifiers+Extension.swift in Sources */,
|
||||||
A5E4082E2E0237460035FEAC /* NewTerminalIntent.swift in Sources */,
|
A5E4082E2E0237460035FEAC /* NewTerminalIntent.swift in Sources */,
|
||||||
|
|
@ -809,13 +817,13 @@
|
||||||
A57D79272C9C879B001D522E /* SecureInput.swift in Sources */,
|
A57D79272C9C879B001D522E /* SecureInput.swift in Sources */,
|
||||||
A5CEAFDC29B8009000646FDA /* SplitView.swift in Sources */,
|
A5CEAFDC29B8009000646FDA /* SplitView.swift in Sources */,
|
||||||
A5593FE12DF8D74000B47B10 /* HiddenTitlebarTerminalWindow.swift in Sources */,
|
A5593FE12DF8D74000B47B10 /* HiddenTitlebarTerminalWindow.swift in Sources */,
|
||||||
|
A5E4083C2E044DB50035FEAC /* Ghostty.Error.swift in Sources */,
|
||||||
A5CDF1932AAF9E0800513312 /* ConfigurationErrorsController.swift in Sources */,
|
A5CDF1932AAF9E0800513312 /* ConfigurationErrorsController.swift in Sources */,
|
||||||
A53A6C032CCC1B7F00943E98 /* Ghostty.Action.swift in Sources */,
|
A53A6C032CCC1B7F00943E98 /* Ghostty.Action.swift in Sources */,
|
||||||
A54B0CED2D0CFB7700CBEFF8 /* ColorizedGhosttyIcon.swift in Sources */,
|
A54B0CED2D0CFB7700CBEFF8 /* ColorizedGhosttyIcon.swift in Sources */,
|
||||||
A5CA378C2D2A4DEB00931030 /* KeyboardLayout.swift in Sources */,
|
A5CA378C2D2A4DEB00931030 /* KeyboardLayout.swift in Sources */,
|
||||||
A54B0CEF2D0D2E2800CBEFF8 /* ColorizedGhosttyIconImage.swift in Sources */,
|
A54B0CEF2D0D2E2800CBEFF8 /* ColorizedGhosttyIconImage.swift in Sources */,
|
||||||
A59FB5D12AE0DEA7009128F3 /* MetalView.swift in Sources */,
|
A59FB5D12AE0DEA7009128F3 /* MetalView.swift in Sources */,
|
||||||
A55685E029A03A9F004303CE /* AppError.swift in Sources */,
|
|
||||||
A599CDB02CF103F60049FA26 /* NSAppearance+Extension.swift in Sources */,
|
A599CDB02CF103F60049FA26 /* NSAppearance+Extension.swift in Sources */,
|
||||||
A52FFF572CA90484000C6A5B /* QuickTerminalScreen.swift in Sources */,
|
A52FFF572CA90484000C6A5B /* QuickTerminalScreen.swift in Sources */,
|
||||||
A5CC36132C9CD72D004D6760 /* SecureInputOverlay.swift in Sources */,
|
A5CC36132C9CD72D004D6760 /* SecureInputOverlay.swift in Sources */,
|
||||||
|
|
|
||||||
|
|
@ -17,33 +17,19 @@ struct TerminalCommandPaletteView: View {
|
||||||
|
|
||||||
// The commands available to the command palette.
|
// The commands available to the command palette.
|
||||||
private var commandOptions: [CommandOption] {
|
private var commandOptions: [CommandOption] {
|
||||||
guard let surface = surfaceView.surface else { return [] }
|
guard let surface = surfaceView.surfaceModel else { return [] }
|
||||||
|
do {
|
||||||
var ptr: UnsafeMutablePointer<ghostty_command_s>? = nil
|
return try surface.commands().map { c in
|
||||||
var count: Int = 0
|
return CommandOption(
|
||||||
ghostty_surface_commands(surface, &ptr, &count)
|
title: c.title,
|
||||||
guard let ptr else { return [] }
|
description: c.description,
|
||||||
|
symbols: ghosttyConfig.keyboardShortcut(for: c.action)?.keyList
|
||||||
let buffer = UnsafeBufferPointer(start: ptr, count: count)
|
) {
|
||||||
return Array(buffer).filter { c in
|
onAction(c.action)
|
||||||
let key = String(cString: c.action_key)
|
}
|
||||||
switch (key) {
|
|
||||||
case "toggle_tab_overview",
|
|
||||||
"toggle_window_decorations",
|
|
||||||
"show_gtk_inspector":
|
|
||||||
return false
|
|
||||||
default:
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}.map { c in
|
|
||||||
let action = String(cString: c.action)
|
|
||||||
return CommandOption(
|
|
||||||
title: String(cString: c.title),
|
|
||||||
description: String(cString: c.description),
|
|
||||||
symbols: ghosttyConfig.keyboardShortcut(for: action)?.keyList
|
|
||||||
) {
|
|
||||||
onAction(action)
|
|
||||||
}
|
}
|
||||||
|
} catch {
|
||||||
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
enum AppError: Error {
|
|
||||||
case surfaceCreateError
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
import GhosttyKit
|
||||||
|
|
||||||
|
extension Ghostty {
|
||||||
|
/// `ghostty_command_s`
|
||||||
|
struct Command: Sendable {
|
||||||
|
private let cValue: ghostty_command_s
|
||||||
|
|
||||||
|
/// The title of the command.
|
||||||
|
var title: String {
|
||||||
|
String(cString: cValue.title)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Human-friendly description of what this command will do.
|
||||||
|
var description: String {
|
||||||
|
String(cString: cValue.description)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The full action that must be performed to invoke this command.
|
||||||
|
var action: String {
|
||||||
|
String(cString: cValue.action)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Only the key portion of the action so you can compare action types, e.g. `goto_split`
|
||||||
|
/// instead of `goto_split:left`.
|
||||||
|
var actionKey: String {
|
||||||
|
String(cString: cValue.action_key)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// True if this can be performed on this target.
|
||||||
|
var isSupported: Bool {
|
||||||
|
!Self.unsupportedActionKeys.contains(actionKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Unsupported action keys, because they either don't make sense in the context of our
|
||||||
|
/// target platform or they just aren't implemented yet.
|
||||||
|
static let unsupportedActionKeys: [String] = [
|
||||||
|
"toggle_tab_overview",
|
||||||
|
"toggle_window_decorations",
|
||||||
|
"show_gtk_inspector",
|
||||||
|
]
|
||||||
|
|
||||||
|
init(cValue: ghostty_command_s) {
|
||||||
|
self.cValue = cValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
extension Ghostty {
|
||||||
|
/// Possible errors from internal Ghostty calls.
|
||||||
|
enum Error: Swift.Error, CustomLocalizedStringResourceConvertible {
|
||||||
|
case apiFailed
|
||||||
|
|
||||||
|
var localizedStringResource: LocalizedStringResource {
|
||||||
|
switch self {
|
||||||
|
case .apiFailed: return "libghostty API call failed"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
import GhosttyKit
|
||||||
|
|
||||||
|
extension Ghostty {
|
||||||
|
/// Represents a single surface within Ghostty.
|
||||||
|
///
|
||||||
|
/// NOTE(mitchellh): This is a work-in-progress class as part of a general refactor
|
||||||
|
/// of our Ghostty data model. At the time of writing there's still a ton of surface
|
||||||
|
/// functionality that is not encapsulated in this class. It is planned to migrate that
|
||||||
|
/// all over.
|
||||||
|
///
|
||||||
|
/// Wraps a `ghostty_surface_t`
|
||||||
|
final class Surface: Sendable {
|
||||||
|
private let surface: ghostty_surface_t
|
||||||
|
|
||||||
|
/// Read the underlying C value for this surface. This is unsafe because the value will be
|
||||||
|
/// freed when the Surface class is deinitialized.
|
||||||
|
var unsafeCValue: ghostty_surface_t {
|
||||||
|
surface
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initialize from the C structure.
|
||||||
|
init(cSurface: ghostty_surface_t) {
|
||||||
|
self.surface = cSurface
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
// deinit is not guaranteed to happen on the main actor and our API
|
||||||
|
// calls into libghostty must happen there so we capture the surface
|
||||||
|
// value so we don't capture `self` and then we detach it in a task.
|
||||||
|
// We can't wait for the task to succeed so this will happen sometime
|
||||||
|
// but that's okay.
|
||||||
|
let surface = self.surface
|
||||||
|
Task.detached { @MainActor in
|
||||||
|
ghostty_surface_free(surface)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Perform a keybinding action.
|
||||||
|
///
|
||||||
|
/// The action can be any valid keybind parameter. e.g. `keybind = goto_tab:4`
|
||||||
|
/// you can perform `goto_tab:4` with this.
|
||||||
|
///
|
||||||
|
/// Returns true if the action was performed. Invalid actions return false.
|
||||||
|
@MainActor
|
||||||
|
func perform(action: String) -> Bool {
|
||||||
|
let len = action.utf8CString.count
|
||||||
|
if (len == 0) { return false }
|
||||||
|
return action.withCString { cString in
|
||||||
|
ghostty_surface_binding_action(surface, cString, UInt(len - 1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Command options for this surface.
|
||||||
|
@MainActor
|
||||||
|
func commands() throws -> [Command] {
|
||||||
|
var ptr: UnsafeMutablePointer<ghostty_command_s>? = nil
|
||||||
|
var count: Int = 0
|
||||||
|
ghostty_surface_commands(surface, &ptr, &count)
|
||||||
|
guard let ptr else { throw Error.apiFailed }
|
||||||
|
let buffer = UnsafeBufferPointer(start: ptr, count: count)
|
||||||
|
return Array(buffer).map { Command(cValue: $0) }.filter { $0.isSupported }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -19,6 +19,15 @@ struct Ghostty {
|
||||||
static let userNotificationActionShow = "com.mitchellh.ghostty.userNotification.Show"
|
static let userNotificationActionShow = "com.mitchellh.ghostty.userNotification.Show"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: C Extensions
|
||||||
|
|
||||||
|
/// A command is fully self-contained so it is Sendable.
|
||||||
|
extension ghostty_command_s: @unchecked @retroactive Sendable {}
|
||||||
|
|
||||||
|
/// A surface is sendable because it is just a reference type. Using the surface in parameters
|
||||||
|
/// may be unsafe but the value itself is safe to send across threads.
|
||||||
|
extension ghostty_surface_t: @unchecked @retroactive Sendable {}
|
||||||
|
|
||||||
// MARK: Build Info
|
// MARK: Build Info
|
||||||
|
|
||||||
extension Ghostty {
|
extension Ghostty {
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ extension Ghostty {
|
||||||
let pubResign = center.publisher(for: NSWindow.didResignKeyNotification)
|
let pubResign = center.publisher(for: NSWindow.didResignKeyNotification)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Surface(view: surfaceView, size: geo.size)
|
SurfaceRepresentable(view: surfaceView, size: geo.size)
|
||||||
.focused($surfaceFocus)
|
.focused($surfaceFocus)
|
||||||
.focusedValue(\.ghosttySurfacePwd, surfaceView.pwd)
|
.focusedValue(\.ghosttySurfacePwd, surfaceView.pwd)
|
||||||
.focusedValue(\.ghosttySurfaceView, surfaceView)
|
.focusedValue(\.ghosttySurfaceView, surfaceView)
|
||||||
|
|
@ -381,7 +381,7 @@ extension Ghostty {
|
||||||
/// 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 Surface: OSViewRepresentable {
|
struct SurfaceRepresentable: OSViewRepresentable {
|
||||||
/// The view to render for the terminal surface.
|
/// The view to render for the terminal surface.
|
||||||
let view: SurfaceView
|
let view: SurfaceView
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -115,10 +115,20 @@ extension Ghostty {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the data model for this surface.
|
||||||
|
///
|
||||||
|
/// Note: eventually, all surface access will be through this, but presently its in a transition
|
||||||
|
/// state so we're mixing this with direct surface access.
|
||||||
|
private(set) var surfaceModel: Ghostty.Surface?
|
||||||
|
|
||||||
|
/// Returns the underlying C value for the surface. See "note" on surfaceModel.
|
||||||
|
var surface: ghostty_surface_t? {
|
||||||
|
surfaceModel?.unsafeCValue
|
||||||
|
}
|
||||||
|
|
||||||
// Notification identifiers associated with this surface
|
// Notification identifiers associated with this surface
|
||||||
var notificationIdentifiers: Set<String> = []
|
var notificationIdentifiers: Set<String> = []
|
||||||
|
|
||||||
private(set) var surface: ghostty_surface_t?
|
|
||||||
private var markedText: NSMutableAttributedString
|
private var markedText: NSMutableAttributedString
|
||||||
private(set) var focused: Bool = true
|
private(set) var focused: Bool = true
|
||||||
private var prevPressureStage: Int = 0
|
private var prevPressureStage: Int = 0
|
||||||
|
|
@ -282,10 +292,10 @@ extension Ghostty {
|
||||||
let surface_cfg = baseConfig ?? SurfaceConfiguration()
|
let surface_cfg = baseConfig ?? SurfaceConfiguration()
|
||||||
var surface_cfg_c = surface_cfg.ghosttyConfig(view: self)
|
var surface_cfg_c = surface_cfg.ghosttyConfig(view: self)
|
||||||
guard let surface = ghostty_surface_new(app, &surface_cfg_c) else {
|
guard let surface = ghostty_surface_new(app, &surface_cfg_c) else {
|
||||||
self.error = AppError.surfaceCreateError
|
self.error = Ghostty.Error.apiFailed
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.surface = surface;
|
self.surfaceModel = Ghostty.Surface(cSurface: surface)
|
||||||
|
|
||||||
// Setup our tracking area so we get mouse moved events
|
// Setup our tracking area so we get mouse moved events
|
||||||
updateTrackingAreas()
|
updateTrackingAreas()
|
||||||
|
|
@ -340,11 +350,6 @@ extension Ghostty {
|
||||||
// Remove any notifications associated with this surface
|
// Remove any notifications associated with this surface
|
||||||
let identifiers = Array(self.notificationIdentifiers)
|
let identifiers = Array(self.notificationIdentifiers)
|
||||||
UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: identifiers)
|
UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: identifiers)
|
||||||
|
|
||||||
// Free our core surface resources
|
|
||||||
if let surface = self.surface {
|
|
||||||
ghostty_surface_free(surface)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func focusDidChange(_ focused: Bool) {
|
func focusDidChange(_ focused: Bool) {
|
||||||
|
|
|
||||||
|
|
@ -1837,12 +1837,10 @@ pub const CAPI = struct {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
_ = ptr.core_surface.performBindingAction(action) catch |err| {
|
return ptr.core_surface.performBindingAction(action) catch |err| {
|
||||||
log.err("error performing binding action action={} err={}", .{ action, err });
|
log.err("error performing binding action action={} err={}", .{ action, err });
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Complete a clipboard read request started via the read callback.
|
/// Complete a clipboard read request started via the read callback.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue