From 781f8c4661092b97b51f96fe664d7bd34af6ea3c Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 28 Nov 2025 14:58:58 -0800 Subject: [PATCH] apprt/embedded: expose C APIs for layouts --- include/ghostty.h | 30 +++++++++++++++++++++++++++--- src/apprt/embedded.zig | 14 ++++++++++++++ src/apprt/layout.zig | 2 +- src/datastruct/split_tree.zig | 2 +- 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/include/ghostty.h b/include/ghostty.h index 1d3db534f..77f7decff 100644 --- a/include/ghostty.h +++ b/include/ghostty.h @@ -30,8 +30,19 @@ typedef void* ghostty_app_t; typedef void* ghostty_config_t; typedef void* ghostty_surface_t; typedef void* ghostty_inspector_t; -typedef void* ghostty_layout_window_t; -typedef void* ghostty_layout_tab_t; + +// Layout API +typedef void* ghostty_window_layout_t; +typedef void* ghostty_tab_layout_t; +typedef void* ghostty_tab_layout_leaf_t; +typedef uint16_t ghostty_tab_layout_node_t; + +typedef struct { + bool horizontal; + float ratio; + ghostty_tab_layout_node_t left; + ghostty_tab_layout_node_t right; +} ghostty_tab_layout_split_s; // All the types below are fully defined and must be kept in sync with // their Zig counterparts. Any changes to these types MUST have an associated @@ -837,7 +848,7 @@ typedef enum { typedef union { ghostty_action_split_direction_e new_split; - ghostty_layout_window_t new_window_layout; + ghostty_window_layout_t new_window_layout; ghostty_action_fullscreen_e toggle_fullscreen; ghostty_action_move_tab_s move_tab; ghostty_action_goto_tab_e goto_tab; @@ -1070,6 +1081,19 @@ void ghostty_inspector_metal_render(ghostty_inspector_t, void*, void*); bool ghostty_inspector_metal_shutdown(ghostty_inspector_t); #endif +// Layout API +size_t ghostty_window_layout_get_tabs_len(ghostty_window_layout_t); +const ghostty_tab_layout_t* ghostty_window_layout_get_tabs(ghostty_window_layout_t); +bool ghostty_tab_layout_is_empty(ghostty_tab_layout_t); +size_t ghostty_tab_layout_get_nodes_len(ghostty_tab_layout_t); +bool ghostty_tab_layout_is_split_node(ghostty_tab_layout_t, ghostty_tab_layout_node_t); +ghostty_tab_layout_split_s ghostty_tab_layout_get_split_node(ghostty_tab_layout_t, + ghostty_tab_layout_node_t); +ghostty_tab_layout_leaf_t ghostty_tab_layout_get_leaf_node(ghostty_tab_layout_t, + ghostty_tab_layout_node_t); +uint64_t ghostty_tab_layout_leaf_get_id(ghostty_tab_layout_leaf_t); +ghostty_config_t ghostty_tab_layout_leaf_get_config(ghostty_tab_layout_leaf_t); + // APIs I'd like to get rid of eventually but are still needed for now. // Don't use these unless you know what you're doing. void ghostty_set_window_background_blur(ghostty_app_t, void*); diff --git a/src/apprt/embedded.zig b/src/apprt/embedded.zig index da7a585a5..948a2574d 100644 --- a/src/apprt/embedded.zig +++ b/src/apprt/embedded.zig @@ -20,6 +20,7 @@ const CoreInspector = @import("../inspector/main.zig").Inspector; const CoreSurface = @import("../Surface.zig"); const configpkg = @import("../config.zig"); const Config = configpkg.Config; +const layout = @import("layout.zig"); const log = std.log.scoped(.embedded_window); @@ -1340,6 +1341,19 @@ pub const CAPI = struct { } } + // Layout C API exports + comptime { + @export(&layout.Window.CApi.get_tabs_len, .{ .name = "ghostty_window_layout_get_tabs_len" }); + @export(&layout.Window.CApi.get_tabs, .{ .name = "ghostty_window_layout_get_tabs" }); + @export(&layout.SplitTree.CApi.is_empty, .{ .name = "ghostty_tab_layout_is_empty" }); + @export(&layout.SplitTree.CApi.len, .{ .name = "ghostty_tab_layout_get_nodes_len" }); + @export(&layout.SplitTree.CApi.is_split, .{ .name = "ghostty_tab_layout_is_split_node" }); + @export(&layout.SplitTree.CApi.get_split, .{ .name = "ghostty_tab_layout_get_split_node" }); + @export(&layout.SplitTree.CApi.get_leaf, .{ .name = "ghostty_tab_layout_get_leaf_node" }); + @export(&layout.SplitTree.View.CApi.get_id, .{ .name = "ghostty_tab_layout_leaf_get_id" }); + @export(&layout.SplitTree.View.CApi.get_config, .{ .name = "ghostty_tab_layout_leaf_get_config" }); + } + /// Create a new app. export fn ghostty_app_new( opts: *const apprt.runtime.App.Options, diff --git a/src/apprt/layout.zig b/src/apprt/layout.zig index 32c1aa145..09a4688d2 100644 --- a/src/apprt/layout.zig +++ b/src/apprt/layout.zig @@ -17,7 +17,7 @@ pub const Window = struct { } pub fn get_tabs(self: *const Window) callconv(.c) [*]const SplitTree { - return &self.tabs; + return self.tabs.ptr; } }; }; diff --git a/src/datastruct/split_tree.zig b/src/datastruct/split_tree.zig index 78a8b691c..a6f8a9511 100644 --- a/src/datastruct/split_tree.zig +++ b/src/datastruct/split_tree.zig @@ -1351,7 +1351,7 @@ pub fn SplitTree(comptime V: type) type { }; } - pub fn get_leaf(self: *const Self, handle: Node.Handle) *View { + pub fn get_leaf(self: *const Self, handle: Node.Handle) callconv(.c) *View { return self.nodes[handle.idx()].leaf; } };