aboutsummaryrefslogtreecommitdiff
path: root/vendor/libghostty-vt/src/apprt/action.zig
diff options
context:
space:
mode:
authorCan Celik <ogulcancelik@gmail.com>2026-04-04 19:22:04 +0300
committerCan Celik <ogulcancelik@gmail.com>2026-04-05 01:23:06 +0300
commit41dd733ca7123c9ac4bfc6c781697a660e95b052 (patch)
tree3fc91815ca139ef2e0b281bba0abda4ef15175f4 /vendor/libghostty-vt/src/apprt/action.zig
parent55c138263e190a1e79d4b997bfb9397306c0ec1f (diff)
feat: finish ghostty pane backend integration
Diffstat (limited to 'vendor/libghostty-vt/src/apprt/action.zig')
-rw-r--r--vendor/libghostty-vt/src/apprt/action.zig1007
1 files changed, 1007 insertions, 0 deletions
diff --git a/vendor/libghostty-vt/src/apprt/action.zig b/vendor/libghostty-vt/src/apprt/action.zig
new file mode 100644
index 00000000..f6865af8
--- /dev/null
+++ b/vendor/libghostty-vt/src/apprt/action.zig
@@ -0,0 +1,1007 @@
+const std = @import("std");
+const build_config = @import("../build_config.zig");
+const assert = @import("../quirks.zig").inlineAssert;
+const apprt = @import("../apprt.zig");
+const configpkg = @import("../config.zig");
+const input = @import("../input.zig");
+const renderer = @import("../renderer.zig");
+const terminal = @import("../terminal/main.zig");
+const CoreSurface = @import("../Surface.zig");
+const lib = @import("../lib/main.zig");
+
+/// The target for an action. This is generally the thing that had focus
+/// while the action was made but the concept of "focus" is not guaranteed
+/// since actions can also be triggered by timers, scripts, etc.
+pub const Target = union(Key) {
+ app,
+ surface: *CoreSurface,
+
+ // Sync with: ghostty_target_tag_e
+ pub const Key = enum(c_int) {
+ app,
+ surface,
+
+ test "ghostty.h Target.Key" {
+ try lib.checkGhosttyHEnum(Key, "GHOSTTY_TARGET_");
+ }
+ };
+
+ // Sync with: ghostty_target_u
+ pub const CValue = extern union {
+ app: void,
+ surface: *apprt.Surface,
+ };
+
+ // Sync with: ghostty_target_s
+ pub const C = extern struct {
+ key: Key,
+ value: CValue,
+ };
+
+ /// Convert to ghostty_target_s.
+ pub fn cval(self: Target) C {
+ return .{
+ .key = @as(Key, self),
+ .value = switch (self) {
+ .app => .{ .app = {} },
+ .surface => |v| .{ .surface = v.rt_surface },
+ },
+ };
+ }
+};
+
+/// The possible actions an apprt has to react to. Actions are one-way
+/// messages that are sent to the app runtime to trigger some behavior.
+///
+/// Actions are very often key binding actions but can also be triggered
+/// by lifecycle events. For example, the `quit_timer` action is not bindable.
+///
+/// Importantly, actions are generally OPTIONAL to implement by an apprt.
+/// Required functionality is called directly on the runtime structure so
+/// there is a compiler error if an action is not implemented.
+pub const Action = union(Key) {
+ // A GUIDE TO ADDING NEW ACTIONS:
+ //
+ // 1. Add the action to the `Key` enum. The order of the enum matters
+ // because it maps directly to the libghostty C enum. For ABI
+ // compatibility, new actions should be added to the end of the enum.
+ //
+ // 2. Add the action and optional value to the Action union.
+ //
+ // 3. If the value type is not void, ensure the value is C ABI
+ // compatible (extern). If it is not, add a `C` decl to the value
+ // and a `cval` function to convert to the C ABI compatible value.
+ //
+ // 4. Update `include/ghostty.h`: add the new key, value, and union
+ // entry. If the value type is void then only the key needs to be
+ // added. Ensure the order matches exactly with the Zig code.
+
+ /// Quit the application.
+ quit,
+
+ /// Open a new window. The target determines whether properties such
+ /// as font size should be inherited.
+ new_window,
+
+ /// Open a new tab. If the target is a surface it should be opened in
+ /// the same window as the surface. If the target is the app then
+ /// the tab should be opened in a new window.
+ new_tab,
+
+ /// Closes the tab belonging to the currently focused split, or all other
+ /// tabs, depending on the mode.
+ close_tab: CloseTabMode,
+
+ /// Create a new split. The value determines the location of the split
+ /// relative to the target.
+ new_split: SplitDirection,
+
+ /// Close all open windows.
+ close_all_windows,
+
+ /// Toggle maximized window state.
+ toggle_maximize,
+
+ /// Toggle fullscreen mode.
+ toggle_fullscreen: Fullscreen,
+
+ /// Toggle tab overview.
+ toggle_tab_overview,
+
+ /// Toggle whether window directions are shown.
+ toggle_window_decorations,
+
+ /// Toggle the quick terminal in or out.
+ toggle_quick_terminal,
+
+ /// Toggle the command palette.
+ toggle_command_palette,
+
+ /// Toggle the visibility of all Ghostty terminal windows.
+ toggle_visibility,
+
+ /// Toggle the window background opacity. This only has an effect
+ /// if the window started as transparent (non-opaque), and toggles
+ /// it between fully opaque and the configured background opacity.
+ toggle_background_opacity,
+
+ /// Moves a tab by a relative offset.
+ ///
+ /// Adjusts the tab position based on `offset` (e.g., -1 for left, +1
+ /// for right). If the new position is out of bounds, it wraps around
+ /// cyclically within the tab range.
+ move_tab: MoveTab,
+
+ /// Jump to a specific tab. Must handle the scenario that the tab
+ /// value is invalid.
+ goto_tab: GotoTab,
+
+ /// Jump to a specific split.
+ goto_split: GotoSplit,
+
+ /// Jump to next/previous window.
+ goto_window: GotoWindow,
+
+ /// Resize the split in the given direction.
+ resize_split: ResizeSplit,
+
+ /// Equalize all the splits in the target window.
+ equalize_splits,
+
+ /// Toggle whether a split is zoomed or not. A zoomed split is resized
+ /// to take up the entire window.
+ toggle_split_zoom,
+
+ /// Present the target terminal whether its a tab, split, or window.
+ present_terminal,
+
+ /// Sets a size limit (in pixels) for the target terminal.
+ size_limit: SizeLimit,
+
+ /// Resets the window size to the default size. See the
+ /// `reset_window_size` keybinding for more information.
+ reset_window_size,
+
+ /// Specifies the initial size of the target terminal.
+ ///
+ /// This may be sent once during the initialization of a surface
+ /// (as part of the init call) to indicate the initial size requested
+ /// for the window if it is not maximized or fullscreen.
+ ///
+ /// This may also be sent at any time after the surface is initialized
+ /// to note the new "default size" of the window. This should in general
+ /// be ignored, but may be useful if the apprt wants to support
+ /// a "return to default size" action.
+ initial_size: InitialSize,
+
+ /// The cell size has changed to the given dimensions in pixels.
+ cell_size: CellSize,
+
+ /// The scrollbar is updating.
+ scrollbar: terminal.Scrollbar,
+
+ /// The target should be re-rendered. This usually has a specific
+ /// surface target but if the app is targeted then all active
+ /// surfaces should be redrawn.
+ render,
+
+ /// Control whether the inspector is shown or hidden.
+ inspector: Inspector,
+
+ /// Show the GTK inspector.
+ show_gtk_inspector,
+
+ /// The inspector for the given target has changes and should be
+ /// rendered at the next opportunity.
+ render_inspector,
+
+ /// Show a desktop notification.
+ desktop_notification: DesktopNotification,
+
+ /// Set the title of the target to the requested value.
+ set_title: SetTitle,
+
+ /// Set the tab title override for the target's tab.
+ set_tab_title: SetTitle,
+
+ /// Set the title of the target to a prompted value. It is up to
+ /// the apprt to prompt. The value specifies whether to prompt for the
+ /// surface title or the tab title.
+ prompt_title: PromptTitle,
+
+ /// The current working directory has changed for the target terminal.
+ pwd: Pwd,
+
+ /// Set the mouse cursor shape.
+ mouse_shape: terminal.MouseShape,
+
+ /// Set whether the mouse cursor is visible or not.
+ mouse_visibility: MouseVisibility,
+
+ /// Called when the mouse is over or recently left a link.
+ mouse_over_link: MouseOverLink,
+
+ /// The health of the renderer has changed.
+ renderer_health: renderer.Health,
+
+ /// Open the Ghostty configuration. This is platform-specific about
+ /// what it means; it can mean opening a dedicated UI or just opening
+ /// a file in a text editor.
+ open_config,
+
+ /// Called when there are no more surfaces and the app should quit
+ /// after the configured delay.
+ ///
+ /// Despite the name, this is the notification that libghostty sends
+ /// when there are no more surfaces regardless of if the configuration
+ /// wants to quit after close, has any delay set, etc. It's up to the
+ /// apprt to implement the proper logic based on the config.
+ ///
+ /// This can be cancelled by sending another quit_timer action with "stop".
+ /// Multiple "starts" shouldn't happen and can be ignored or cause a
+ /// restart it isn't that important.
+ quit_timer: QuitTimer,
+
+ /// Set the window floating state. A floating window is one that is
+ /// always on top of other windows even when not focused.
+ float_window: FloatWindow,
+
+ /// Set the secure input functionality on or off. "Secure input" means
+ /// that the user is currently at some sort of prompt where they may be
+ /// entering a password or other sensitive information. This can be used
+ /// by the app runtime to change the appearance of the cursor, setup
+ /// system APIs to not log the input, etc.
+ secure_input: SecureInput,
+
+ /// A sequenced key binding has started, continued, or stopped.
+ /// The UI should show some indication that the user is in a sequenced
+ /// key mode because other input may be ignored.
+ key_sequence: KeySequence,
+
+ /// A key table has been activated or deactivated.
+ key_table: KeyTable,
+
+ /// A terminal color was changed programmatically through things
+ /// such as OSC 10/11.
+ color_change: ColorChange,
+
+ /// A request to reload the configuration. The reload request can be
+ /// from a user or for some internal reason. The reload request may
+ /// request it is a soft reload or a full reload. See the struct for
+ /// more documentation.
+ ///
+ /// The configuration should be passed to updateConfig either at the
+ /// app or surface level depending on the target.
+ reload_config: ReloadConfig,
+
+ /// The configuration has changed. The value is a pointer to the new
+ /// configuration. The pointer is only valid for the duration of the
+ /// action and should not be stored.
+ ///
+ /// This should be used by apprts to update any internal state that
+ /// depends on configuration for the given target (i.e. headerbar colors).
+ /// The apprt should copy any data it needs since the memory lifetime
+ /// is only valid for the duration of the action.
+ ///
+ /// This allows an apprt to have config-dependent state reactively
+ /// change without having to store the entire configuration or poll
+ /// for changes.
+ config_change: ConfigChange,
+
+ /// Closes the currently focused window.
+ close_window,
+
+ /// Called when the bell character is seen. The apprt should do whatever
+ /// it needs to ring the bell. This is usually a sound or visual effect.
+ ring_bell,
+
+ /// Undo the last action. See the "undo" keybinding for more
+ /// details on what can and cannot be undone.
+ undo,
+
+ /// Redo the last undone action.
+ redo,
+
+ check_for_updates,
+
+ /// Open a URL using the native OS mechanisms. On macOS this might be `open`
+ /// or on Linux this might be `xdg-open`. The exact mechanism is up to the
+ /// apprt.
+ open_url: OpenUrl,
+
+ /// Show a native GUI notification that the child process has exited.
+ show_child_exited: apprt.surface.Message.ChildExited,
+
+ /// Show a native GUI notification about the progress of some TUI operation.
+ progress_report: terminal.osc.Command.ProgressReport,
+
+ /// Show the on-screen keyboard.
+ show_on_screen_keyboard,
+
+ /// A command has finished,
+ command_finished: CommandFinished,
+
+ /// Start the search overlay with an optional initial needle. If the
+ /// search is already active and the needle is non-empty, update the
+ /// current search needle and focus the search input.
+ start_search: StartSearch,
+
+ /// End the search overlay, clearing the search state and hiding it.
+ end_search,
+
+ /// The total number of matches found by the search.
+ search_total: SearchTotal,
+
+ /// The currently selected search match index (1-based).
+ search_selected: SearchSelected,
+
+ /// The readonly state of the surface has changed.
+ readonly: Readonly,
+
+ /// Copy the effective title of the surface to the clipboard.
+ /// The effective title is the user-overridden title if set,
+ /// otherwise the terminal-set title.
+ copy_title_to_clipboard,
+
+ /// Sync with: ghostty_action_tag_e
+ pub const Key = enum(c_int) {
+ quit,
+ new_window,
+ new_tab,
+ close_tab,
+ new_split,
+ close_all_windows,
+ toggle_maximize,
+ toggle_fullscreen,
+ toggle_tab_overview,
+ toggle_window_decorations,
+ toggle_quick_terminal,
+ toggle_command_palette,
+ toggle_visibility,
+ toggle_background_opacity,
+ move_tab,
+ goto_tab,
+ goto_split,
+ goto_window,
+ resize_split,
+ equalize_splits,
+ toggle_split_zoom,
+ present_terminal,
+ size_limit,
+ reset_window_size,
+ initial_size,
+ cell_size,
+ scrollbar,
+ render,
+ inspector,
+ show_gtk_inspector,
+ render_inspector,
+ desktop_notification,
+ set_title,
+ set_tab_title,
+ prompt_title,
+ pwd,
+ mouse_shape,
+ mouse_visibility,
+ mouse_over_link,
+ renderer_health,
+ open_config,
+ quit_timer,
+ float_window,
+ secure_input,
+ key_sequence,
+ key_table,
+ color_change,
+ reload_config,
+ config_change,
+ close_window,
+ ring_bell,
+ undo,
+ redo,
+ check_for_updates,
+ open_url,
+ show_child_exited,
+ progress_report,
+ show_on_screen_keyboard,
+ command_finished,
+ start_search,
+ end_search,
+ search_total,
+ search_selected,
+ readonly,
+ copy_title_to_clipboard,
+
+ test "ghostty.h Action.Key" {
+ try lib.checkGhosttyHEnum(Key, "GHOSTTY_ACTION_");
+ }
+ };
+
+ /// Sync with: ghostty_action_u
+ pub const CValue = cvalue: {
+ const key_fields = @typeInfo(Key).@"enum".fields;
+ var union_fields: [key_fields.len]std.builtin.Type.UnionField = undefined;
+ for (key_fields, 0..) |field, i| {
+ const action = @unionInit(Action, field.name, undefined);
+ const Type = t: {
+ const Type = @TypeOf(@field(action, field.name));
+ // Types can provide custom types for their CValue.
+ if (Type != void and @hasDecl(Type, "C")) break :t Type.C;
+ break :t Type;
+ };
+
+ union_fields[i] = .{
+ .name = field.name,
+ .type = Type,
+ .alignment = @alignOf(Type),
+ };
+ }
+
+ break :cvalue @Type(.{ .@"union" = .{
+ .layout = .@"extern",
+ .tag_type = null,
+ .fields = &union_fields,
+ .decls = &.{},
+ } });
+ };
+
+ /// Sync with: ghostty_action_s
+ pub const C = extern struct {
+ key: Key,
+ value: CValue,
+ };
+
+ comptime {
+ // For ABI compatibility, we expect that this is our union size.
+ // At the time of writing, we don't promise ABI compatibility
+ // so we can change this but I want to be aware of it.
+ assert(@sizeOf(CValue) == switch (@sizeOf(usize)) {
+ 4 => 16,
+ 8 => 24,
+ else => unreachable,
+ });
+ }
+
+ /// Returns the value type for the given key.
+ pub fn Value(comptime key: Key) type {
+ inline for (@typeInfo(Action).@"union".fields) |field| {
+ const field_key = @field(Key, field.name);
+ if (field_key == key) return field.type;
+ }
+
+ unreachable;
+ }
+
+ /// Convert to ghostty_action_s.
+ pub fn cval(self: Action) C {
+ const value: CValue = switch (self) {
+ inline else => |v, tag| @unionInit(
+ CValue,
+ @tagName(tag),
+ if (@TypeOf(v) != void and @hasDecl(@TypeOf(v), "cval")) v.cval() else v,
+ ),
+ };
+
+ return .{
+ .key = @as(Key, self),
+ .value = value,
+ };
+ }
+};
+
+// This is made extern (c_int) to make interop easier with our embedded
+// runtime. The small size cost doesn't make a difference in our union.
+pub const SplitDirection = enum(c_int) {
+ right,
+ down,
+ left,
+ up,
+
+ test "ghostty.h SplitDirection" {
+ try lib.checkGhosttyHEnum(SplitDirection, "GHOSTTY_SPLIT_DIRECTION_");
+ }
+};
+
+// This is made extern (c_int) to make interop easier with our embedded
+// runtime. The small size cost doesn't make a difference in our union.
+pub const GotoSplit = enum(c_int) {
+ previous,
+ next,
+
+ up,
+ left,
+ down,
+ right,
+
+ test "ghostty.h GotoSplit" {
+ try lib.checkGhosttyHEnum(GotoSplit, "GHOSTTY_GOTO_SPLIT_");
+ }
+};
+
+// This is made extern (c_int) to make interop easier with our embedded
+// runtime. The small size cost doesn't make a difference in our union.
+pub const GotoWindow = enum(c_int) {
+ previous,
+ next,
+
+ test "ghostty.h GotoWindow" {
+ try lib.checkGhosttyHEnum(GotoWindow, "GHOSTTY_GOTO_WINDOW_");
+ }
+};
+
+/// The amount to resize the split by and the direction to resize it in.
+pub const ResizeSplit = extern struct {
+ amount: u16,
+ direction: Direction,
+
+ pub const Direction = enum(c_int) {
+ up,
+ down,
+ left,
+ right,
+
+ test "ghostty.h ResizeSplit.Direction" {
+ try lib.checkGhosttyHEnum(Direction, "GHOSTTY_RESIZE_SPLIT_");
+ }
+ };
+};
+
+pub const MoveTab = extern struct {
+ amount: isize,
+};
+
+/// The tab to jump to. This is non-exhaustive so that integer values represent
+/// the index (zero-based) of the tab to jump to. Negative values are special
+/// values.
+pub const GotoTab = enum(c_int) {
+ previous = -1,
+ next = -2,
+ last = -3,
+ _,
+
+ // TODO: check non-exhaustive enums
+ // test "ghostty.h GotoTab" {
+ // try lib.checkGhosttyHEnum(GotoTab, "GHOSTTY_GOTO_TAB_");
+ // }
+};
+
+/// The fullscreen mode to toggle to if we're moving to fullscreen.
+pub const Fullscreen = enum(c_int) {
+ native,
+
+ /// macOS has a non-native fullscreen mode that is more like a maximized
+ /// window. This is much faster to enter and exit than the native mode.
+ macos_non_native,
+ macos_non_native_visible_menu,
+ macos_non_native_padded_notch,
+
+ test "ghostty.h Fullscreen" {
+ try lib.checkGhosttyHEnum(Fullscreen, "GHOSTTY_FULLSCREEN_");
+ }
+};
+
+pub const FloatWindow = enum(c_int) {
+ on,
+ off,
+ toggle,
+
+ test "ghostty.h FloatWindow" {
+ try lib.checkGhosttyHEnum(FloatWindow, "GHOSTTY_FLOAT_WINDOW_");
+ }
+};
+
+pub const SecureInput = enum(c_int) {
+ on,
+ off,
+ toggle,
+
+ test "ghostty.h SecureInput" {
+ try lib.checkGhosttyHEnum(SecureInput, "GHOSTTY_SECURE_INPUT_");
+ }
+};
+
+/// The inspector mode to toggle to if we're toggling the inspector.
+pub const Inspector = enum(c_int) {
+ toggle,
+ show,
+ hide,
+
+ test "ghostty.h Inspector" {
+ try lib.checkGhosttyHEnum(Inspector, "GHOSTTY_INSPECTOR_");
+ }
+};
+
+pub const QuitTimer = enum(c_int) {
+ start,
+ stop,
+
+ test "ghostty.h QuitTimer" {
+ try lib.checkGhosttyHEnum(QuitTimer, "GHOSTTY_QUIT_TIMER_");
+ }
+};
+
+pub const Readonly = enum(c_int) {
+ off,
+ on,
+
+ test "ghostty.h Readonly" {
+ try lib.checkGhosttyHEnum(Readonly, "GHOSTTY_READONLY_");
+ }
+};
+
+pub const MouseVisibility = enum(c_int) {
+ visible,
+ hidden,
+
+ test "ghostty.h MouseVisibility" {
+ try lib.checkGhosttyHEnum(MouseVisibility, "GHOSTTY_MOUSE_");
+ }
+};
+
+/// Whether to prompt for the surface title or tab title.
+pub const PromptTitle = enum(c_int) {
+ surface,
+ tab,
+
+ test "ghostty.h PromptTitle" {
+ try lib.checkGhosttyHEnum(PromptTitle, "GHOSTTY_PROMPT_TITLE_");
+ }
+};
+
+pub const MouseOverLink = struct {
+ url: [:0]const u8,
+
+ // Sync with: ghostty_action_mouse_over_link_s
+ pub const C = extern struct {
+ url: [*]const u8,
+ len: usize,
+ };
+
+ pub fn cval(self: MouseOverLink) C {
+ return .{
+ .url = self.url.ptr,
+ .len = self.url.len,
+ };
+ }
+};
+
+pub const SizeLimit = extern struct {
+ min_width: u32,
+ min_height: u32,
+ max_width: u32,
+ max_height: u32,
+};
+
+pub const InitialSize = extern struct {
+ width: u32,
+ height: u32,
+
+ /// Make this a valid gobject if we're in a GTK environment.
+ pub const getGObjectType = switch (build_config.app_runtime) {
+ .gtk => @import("gobject").ext.defineBoxed(
+ InitialSize,
+ .{ .name = "GhosttyApprtInitialSize" },
+ ),
+
+ .none => void,
+ };
+};
+
+pub const CellSize = extern struct {
+ width: u32,
+ height: u32,
+};
+
+pub const SetTitle = struct {
+ title: [:0]const u8,
+
+ // Sync with: ghostty_action_set_title_s
+ pub const C = extern struct {
+ title: [*:0]const u8,
+ };
+
+ pub fn cval(self: SetTitle) C {
+ return .{
+ .title = self.title.ptr,
+ };
+ }
+
+ pub fn format(
+ value: @This(),
+ comptime _: []const u8,
+ _: std.fmt.FormatOptions,
+ writer: *std.Io.Writer,
+ ) !void {
+ try writer.print("{s}{{ {s} }}", .{ @typeName(@This()), value.title });
+ }
+};
+
+pub const Pwd = struct {
+ pwd: [:0]const u8,
+
+ // Sync with: ghostty_action_set_pwd_s
+ pub const C = extern struct {
+ pwd: [*:0]const u8,
+ };
+
+ pub fn cval(self: Pwd) C {
+ return .{
+ .pwd = self.pwd.ptr,
+ };
+ }
+
+ pub fn format(
+ value: @This(),
+ comptime _: []const u8,
+ _: std.fmt.FormatOptions,
+ writer: *std.Io.Writer,
+ ) !void {
+ try writer.print("{s}{{ {s} }}", .{ @typeName(@This()), value.pwd });
+ }
+};
+
+/// The desktop notification to show.
+pub const DesktopNotification = struct {
+ title: [:0]const u8,
+ body: [:0]const u8,
+
+ // Sync with: ghostty_action_desktop_notification_s
+ pub const C = extern struct {
+ title: [*:0]const u8,
+ body: [*:0]const u8,
+ };
+
+ pub fn cval(self: DesktopNotification) C {
+ return .{
+ .title = self.title.ptr,
+ .body = self.body.ptr,
+ };
+ }
+
+ pub fn format(
+ value: @This(),
+ comptime _: []const u8,
+ _: std.fmt.FormatOptions,
+ writer: *std.Io.Writer,
+ ) !void {
+ try writer.print("{s}{{ title: {s}, body: {s} }}", .{
+ @typeName(@This()),
+ value.title,
+ value.body,
+ });
+ }
+};
+
+pub const KeySequence = union(enum) {
+ trigger: input.Trigger,
+ end,
+
+ // Sync with: ghostty_action_key_sequence_s
+ pub const C = extern struct {
+ active: bool,
+ trigger: input.Trigger.C,
+ };
+
+ pub fn cval(self: KeySequence) C {
+ return switch (self) {
+ .trigger => |t| .{ .active = true, .trigger = t.cval() },
+ .end => .{ .active = false, .trigger = .{} },
+ };
+ }
+};
+
+pub const KeyTable = union(enum) {
+ activate: []const u8,
+ deactivate,
+ deactivate_all,
+
+ // Sync with: ghostty_action_key_table_tag_e
+ pub const Tag = enum(c_int) {
+ activate,
+ deactivate,
+ deactivate_all,
+ };
+
+ // Sync with: ghostty_action_key_table_u
+ pub const CValue = extern union {
+ activate: extern struct {
+ name: [*]const u8,
+ len: usize,
+ },
+ };
+
+ // Sync with: ghostty_action_key_table_s
+ pub const C = extern struct {
+ tag: Tag,
+ value: CValue,
+ };
+
+ pub fn cval(self: KeyTable) C {
+ return switch (self) {
+ .activate => |name| .{
+ .tag = .activate,
+ .value = .{ .activate = .{ .name = name.ptr, .len = name.len } },
+ },
+ .deactivate => .{
+ .tag = .deactivate,
+ .value = undefined,
+ },
+ .deactivate_all => .{
+ .tag = .deactivate_all,
+ .value = undefined,
+ },
+ };
+ }
+};
+
+pub const ColorChange = extern struct {
+ kind: ColorKind,
+ r: u8,
+ g: u8,
+ b: u8,
+};
+
+pub const ColorKind = enum(c_int) {
+ // Negative numbers indicate some named kind
+ foreground = -1,
+ background = -2,
+ cursor = -3,
+
+ // 0+ values indicate a palette index
+ _,
+
+ // TODO: check non-non-exhaustive enums
+ // test "ghostty.h ColorKind" {
+ // try lib.checkGhosttyHEnum(ColorKind, "GHOSTTY_COLOR_KIND_");
+ // }
+};
+
+pub const ReloadConfig = extern struct {
+ /// A soft reload means that the configuration doesn't need to be
+ /// read off disk, but libghostty needs the full config again so call
+ /// updateConfig with it.
+ soft: bool = false,
+};
+
+pub const ConfigChange = struct {
+ config: *const configpkg.Config,
+
+ // Sync with: ghostty_action_config_change_s
+ pub const C = extern struct {
+ config: *const configpkg.Config,
+ };
+
+ pub fn cval(self: ConfigChange) C {
+ return .{
+ .config = self.config,
+ };
+ }
+};
+
+/// Open a URL
+pub const OpenUrl = struct {
+ /// The type of data that the URL refers to.
+ kind: Kind,
+
+ /// The URL.
+ url: []const u8,
+
+ /// The type of the data at the URL to open. This is used as a hint to
+ /// potentially open the URL in a different way.
+ ///
+ /// Sync with: ghostty_action_open_url_kind_e
+ pub const Kind = enum(c_int) {
+ /// The type is unknown. This is the default and apprts should
+ /// open the URL in the most generic way possible. For example,
+ /// on macOS this would be the equivalent of `open` or on Linux
+ /// this would be `xdg-open`.
+ unknown,
+
+ /// The URL is known to be a text file. In this case, the apprt
+ /// should try to open the URL in a text editor or viewer or
+ /// some equivalent, if possible.
+ text,
+
+ /// The URL is known to contain HTML content.
+ html,
+
+ test "ghostty.h OpenUrl.Kind" {
+ try lib.checkGhosttyHEnum(Kind, "GHOSTTY_ACTION_OPEN_URL_KIND_");
+ }
+ };
+
+ // Sync with: ghostty_action_open_url_s
+ pub const C = extern struct {
+ kind: Kind,
+ url: [*]const u8,
+ len: usize,
+ };
+
+ pub fn cval(self: OpenUrl) C {
+ return .{
+ .kind = self.kind,
+ .url = self.url.ptr,
+ .len = self.url.len,
+ };
+ }
+};
+
+/// sync with ghostty_action_close_tab_mode_e in ghostty.h
+pub const CloseTabMode = enum(c_int) {
+ /// Close the current tab.
+ this,
+ /// Close all other tabs.
+ other,
+ /// Close all tabs to the right of the current tab.
+ right,
+
+ test "ghostty.h CloseTabMode" {
+ try lib.checkGhosttyHEnum(CloseTabMode, "GHOSTTY_ACTION_CLOSE_TAB_MODE_");
+ }
+};
+
+pub const CommandFinished = struct {
+ exit_code: ?u8,
+ duration: configpkg.Config.Duration,
+
+ /// sync with ghostty_action_command_finished_s in ghostty.h
+ pub const C = extern struct {
+ exit_code: i16,
+ duration: u64,
+ };
+
+ pub fn cval(self: CommandFinished) C {
+ return .{
+ .exit_code = self.exit_code orelse -1,
+ .duration = self.duration.duration,
+ };
+ }
+};
+
+pub const StartSearch = struct {
+ needle: [:0]const u8,
+
+ // Sync with: ghostty_action_start_search_s
+ pub const C = extern struct {
+ needle: [*:0]const u8,
+ };
+
+ pub fn cval(self: StartSearch) C {
+ return .{
+ .needle = self.needle.ptr,
+ };
+ }
+};
+
+pub const SearchTotal = struct {
+ total: ?usize,
+
+ // Sync with: ghostty_action_search_total_s
+ pub const C = extern struct {
+ total: isize,
+ };
+
+ pub fn cval(self: SearchTotal) C {
+ return .{
+ .total = if (self.total) |t| @intCast(t) else -1,
+ };
+ }
+};
+
+pub const SearchSelected = struct {
+ selected: ?usize,
+
+ // Sync with: ghostty_action_search_selected_s
+ pub const C = extern struct {
+ selected: isize,
+ };
+
+ pub fn cval(self: SearchSelected) C {
+ return .{
+ .selected = if (self.selected) |s| @intCast(s) else -1,
+ };
+ }
+};
+
+test {
+ _ = std.testing.refAllDeclsRecursive(@This());
+}