mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
core: add input binding to control terminal inspector
This commit is contained in:
@ -49,6 +49,12 @@ typedef enum {
|
||||
GHOSTTY_SPLIT_FOCUS_RIGHT,
|
||||
} ghostty_split_focus_direction_e;
|
||||
|
||||
typedef enum {
|
||||
GHOSTTY_INSPECTOR_TOGGLE,
|
||||
GHOSTTY_INSPECTOR_SHOW,
|
||||
GHOSTTY_INSPECTOR_HIDE,
|
||||
} ghostty_inspector_mode_e;
|
||||
|
||||
typedef enum {
|
||||
GHOSTTY_MOUSE_RELEASE,
|
||||
GHOSTTY_MOUSE_PRESS,
|
||||
@ -323,6 +329,7 @@ typedef void (*ghostty_runtime_write_clipboard_cb)(void *, const char *, ghostty
|
||||
typedef void (*ghostty_runtime_new_split_cb)(void *, ghostty_split_direction_e, ghostty_surface_config_s);
|
||||
typedef void (*ghostty_runtime_new_tab_cb)(void *, ghostty_surface_config_s);
|
||||
typedef void (*ghostty_runtime_new_window_cb)(void *, ghostty_surface_config_s);
|
||||
typedef void (*ghostty_runtime_control_inspector_cb)(void *, ghostty_inspector_mode_e);
|
||||
typedef void (*ghostty_runtime_close_surface_cb)(void *, bool);
|
||||
typedef void (*ghostty_runtime_focus_split_cb)(void *, ghostty_split_focus_direction_e);
|
||||
typedef void (*ghostty_runtime_toggle_split_zoom_cb)(void *);
|
||||
@ -344,6 +351,7 @@ typedef struct {
|
||||
ghostty_runtime_new_split_cb new_split_cb;
|
||||
ghostty_runtime_new_tab_cb new_tab_cb;
|
||||
ghostty_runtime_new_window_cb new_window_cb;
|
||||
ghostty_runtime_control_inspector_cb control_inspector_cb;
|
||||
ghostty_runtime_close_surface_cb close_surface_cb;
|
||||
ghostty_runtime_focus_split_cb focus_split_cb;
|
||||
ghostty_runtime_toggle_split_zoom_cb toggle_split_zoom_cb;
|
||||
|
@ -36,6 +36,7 @@ class AppDelegate: NSObject, ObservableObject, NSApplicationDelegate, GhosttyApp
|
||||
@IBOutlet private var menuIncreaseFontSize: NSMenuItem?
|
||||
@IBOutlet private var menuDecreaseFontSize: NSMenuItem?
|
||||
@IBOutlet private var menuResetFontSize: NSMenuItem?
|
||||
@IBOutlet private var menuTerminalInspector: NSMenuItem?
|
||||
|
||||
/// The dock menu
|
||||
private var dockMenu: NSMenu = NSMenu()
|
||||
@ -216,6 +217,7 @@ class AppDelegate: NSObject, ObservableObject, NSApplicationDelegate, GhosttyApp
|
||||
syncMenuShortcut(action: "increase_font_size:1", menuItem: self.menuIncreaseFontSize)
|
||||
syncMenuShortcut(action: "decrease_font_size:1", menuItem: self.menuDecreaseFontSize)
|
||||
syncMenuShortcut(action: "reset_font_size", menuItem: self.menuResetFontSize)
|
||||
syncMenuShortcut(action: "inspector:toggle", menuItem: self.menuTerminalInspector)
|
||||
|
||||
// Dock menu
|
||||
reloadDockMenu()
|
||||
@ -394,4 +396,9 @@ class AppDelegate: NSObject, ObservableObject, NSApplicationDelegate, GhosttyApp
|
||||
guard let surface = focusedSurface() else { return }
|
||||
ghostty.changeFontSize(surface: surface, .reset)
|
||||
}
|
||||
|
||||
@IBAction func toggleTerminalInspector(_ sender: Any) {
|
||||
guard let surface = focusedSurface() else { return }
|
||||
ghostty.toggleTerminalInspector(surface: surface)
|
||||
}
|
||||
}
|
||||
|
@ -136,6 +136,7 @@ extension Ghostty {
|
||||
new_split_cb: { userdata, direction, surfaceConfig in AppState.newSplit(userdata, direction: direction, config: surfaceConfig) },
|
||||
new_tab_cb: { userdata, surfaceConfig in AppState.newTab(userdata, config: surfaceConfig) },
|
||||
new_window_cb: { userdata, surfaceConfig in AppState.newWindow(userdata, config: surfaceConfig) },
|
||||
control_inspector_cb: { userdata, mode in AppState.controlInspector(userdata, mode: mode) },
|
||||
close_surface_cb: { userdata, processAlive in AppState.closeSurface(userdata, processAlive: processAlive) },
|
||||
focus_split_cb: { userdata, direction in AppState.focusSplit(userdata, direction: direction) },
|
||||
toggle_split_zoom_cb: { userdata in AppState.toggleSplitZoom(userdata) },
|
||||
@ -299,6 +300,13 @@ extension Ghostty {
|
||||
AppDelegate.logger.warning("action failed action=\(action)")
|
||||
}
|
||||
}
|
||||
|
||||
func toggleTerminalInspector(surface: ghostty_surface_t) {
|
||||
let action = "inspector:toggle"
|
||||
if (!ghostty_surface_binding_action(surface, action, UInt(action.count))) {
|
||||
AppDelegate.logger.warning("action failed action=\(action)")
|
||||
}
|
||||
}
|
||||
|
||||
// Called when the selected keyboard changes. We have to notify Ghostty so that
|
||||
// it can reload the keyboard mapping for input.
|
||||
@ -494,6 +502,13 @@ extension Ghostty {
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
static func controlInspector(_ userdata: UnsafeMutableRawPointer?, mode: ghostty_inspector_mode_e) {
|
||||
guard let surface = self.surfaceUserdata(from: userdata) else { return }
|
||||
NotificationCenter.default.post(name: Notification.didControlInspector, object: surface, userInfo: [
|
||||
"mode": mode,
|
||||
])
|
||||
}
|
||||
|
||||
/// Returns the GhosttyState from the given userdata value.
|
||||
static private func appState(fromView view: SurfaceView) -> AppState? {
|
||||
|
@ -105,6 +105,9 @@ extension Ghostty.Notification {
|
||||
|
||||
/// Notification to render the inspector for a surface
|
||||
static let inspectorNeedsDisplay = Notification.Name("com.mitchellh.ghostty.inspectorNeedsDisplay")
|
||||
|
||||
/// Notification to show/hide the inspector
|
||||
static let didControlInspector = Notification.Name("com.mitchellh.ghostty.didControlInspector")
|
||||
}
|
||||
|
||||
// Make the input enum hashable.
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22154" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22155" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22154"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22155"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
|
||||
@ -33,6 +33,7 @@
|
||||
<outlet property="menuSelectSplitRight" destination="upj-mc-L7X" id="nLY-o1-lky"/>
|
||||
<outlet property="menuSplitHorizontal" destination="VUR-Ld-nLx" id="RxO-Zw-ovb"/>
|
||||
<outlet property="menuSplitVertical" destination="UDZ-4y-6xL" id="fgZ-Wb-8OR"/>
|
||||
<outlet property="menuTerminalInspector" destination="QwP-M5-fvh" id="wJi-Dh-S9f"/>
|
||||
<outlet property="menuToggleFullScreen" destination="8kY-Pi-KaY" id="yQg-6V-OO6"/>
|
||||
<outlet property="menuZoomSplit" destination="oPd-mn-IEH" id="wTu-jK-egI"/>
|
||||
</connections>
|
||||
@ -153,6 +154,13 @@
|
||||
<action selector="decreaseFontSize:" target="bbz-4X-AYv" id="rlw-0o-kA2"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="L3L-I8-sqk"/>
|
||||
<menuItem title="Terminal Inspector" id="QwP-M5-fvh">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleTerminalInspector:" target="bbz-4X-AYv" id="DON-fR-wyr"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
|
@ -2278,6 +2278,12 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
|
||||
} else log.warn("runtime doesn't implement toggleFullscreen", .{});
|
||||
},
|
||||
|
||||
.inspector => |mode| {
|
||||
if (@hasDecl(apprt.Surface, "controlInspector")) {
|
||||
self.rt_surface.controlInspector(mode);
|
||||
} else log.warn("runtime doesn't implement controlInspector", .{});
|
||||
},
|
||||
|
||||
.close_surface => self.close(),
|
||||
|
||||
.close_window => try self.app.closeSurface(self),
|
||||
|
@ -73,6 +73,9 @@ pub const App = struct {
|
||||
/// New window with options.
|
||||
new_window: ?*const fn (SurfaceUD, apprt.Surface.Options) callconv(.C) void = null,
|
||||
|
||||
/// Control the inspector visibility
|
||||
control_inspector: ?*const fn (SurfaceUD, input.InspectorMode) callconv(.C) void = null,
|
||||
|
||||
/// Close the current surface given by this function.
|
||||
close_surface: ?*const fn (SurfaceUD, bool) callconv(.C) void = null,
|
||||
|
||||
@ -326,6 +329,15 @@ pub const Surface = struct {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn controlInspector(self: *const Surface, mode: input.InspectorMode) void {
|
||||
const func = self.app.opts.control_inspector orelse {
|
||||
log.info("runtime embedder does not support the terminal inspector", .{});
|
||||
return;
|
||||
};
|
||||
|
||||
func(self.opts.userdata, mode);
|
||||
}
|
||||
|
||||
pub fn newSplit(self: *const Surface, direction: input.SplitDirection) !void {
|
||||
const func = self.app.opts.new_split orelse {
|
||||
log.info("runtime embedder does not support splits", .{});
|
||||
|
@ -8,6 +8,7 @@ pub const keycodes = @import("input/keycodes.zig");
|
||||
pub const kitty = @import("input/kitty.zig");
|
||||
pub const Binding = @import("input/Binding.zig");
|
||||
pub const KeyEncoder = @import("input/KeyEncoder.zig");
|
||||
pub const InspectorMode = Binding.Action.InspectorMode;
|
||||
pub const SplitDirection = Binding.Action.SplitDirection;
|
||||
pub const SplitFocusDirection = Binding.Action.SplitFocusDirection;
|
||||
|
||||
|
@ -176,6 +176,10 @@ pub const Action = union(enum) {
|
||||
/// zoom/unzoom the current split.
|
||||
toggle_split_zoom: void,
|
||||
|
||||
/// Show, hide, or toggle the terminal inspector for the currently
|
||||
/// focused terminal.
|
||||
inspector: InspectorMode,
|
||||
|
||||
/// Reload the configuration. The exact meaning depends on the app runtime
|
||||
/// in use but this usually involves re-reading the configuration file
|
||||
/// and applying any changes. Note that not all changes can be applied at
|
||||
@ -220,6 +224,13 @@ pub const Action = union(enum) {
|
||||
right,
|
||||
};
|
||||
|
||||
// Extern because it is used in the embedded runtime ABI.
|
||||
pub const InspectorMode = enum(c_int) {
|
||||
toggle,
|
||||
show,
|
||||
hide,
|
||||
};
|
||||
|
||||
/// Parse an action in the format of "key=value" where key is the
|
||||
/// action name and value is the action parameter. The parameter
|
||||
/// is optional depending on the action.
|
||||
|
Reference in New Issue
Block a user