mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
c: create/destroy surface API
This commit is contained in:
@ -27,6 +27,7 @@ typedef struct {
|
||||
void *userdata;
|
||||
ghostty_runtime_wakeup_cb wakeup_cb;
|
||||
} ghostty_runtime_config_s;
|
||||
typedef struct {} ghostty_surface_config_s;
|
||||
|
||||
// Opaque types
|
||||
typedef void *ghostty_app_t;
|
||||
@ -47,6 +48,9 @@ ghostty_app_t ghostty_app_new(ghostty_runtime_config_s *, ghostty_config_t);
|
||||
void ghostty_app_free(ghostty_app_t);
|
||||
int ghostty_app_tick(ghostty_app_t);
|
||||
|
||||
ghostty_surface_t ghostty_surface_new(ghostty_app_t, ghostty_surface_config_s*);
|
||||
void ghostty_surface_free(ghostty_app_t, ghostty_surface_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
82
src/App.zig
82
src/App.zig
@ -115,13 +115,6 @@ pub fn create(
|
||||
}
|
||||
errdefer if (comptime builtin.target.isDarwin()) app.darwin.deinit();
|
||||
|
||||
// Create the first window if we're an executable. If we're a lib we
|
||||
// do NOT create the first window because we expect the embedded API
|
||||
// to do it via surfaces.
|
||||
if (build_config.artifact == .exe) {
|
||||
_ = try app.newWindow(.{});
|
||||
}
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
@ -174,6 +167,37 @@ pub fn tick(self: *App) !void {
|
||||
if (!self.quit) try self.drainMailbox();
|
||||
}
|
||||
|
||||
/// Create a new window. This can be called only on the main thread. This
|
||||
/// can be called prior to ever running the app loop.
|
||||
pub fn newWindow(self: *App, msg: Message.NewWindow) !*Window {
|
||||
var window = try Window.create(self.alloc, self, self.config, msg.runtime);
|
||||
errdefer window.destroy();
|
||||
|
||||
try self.windows.append(self.alloc, window);
|
||||
errdefer _ = self.windows.pop();
|
||||
|
||||
// Set initial font size if given
|
||||
if (msg.font_size) |size| window.setFontSize(size);
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
/// Close a window and free all resources associated with it. This can
|
||||
/// only be called from the main thread.
|
||||
pub fn closeWindow(self: *App, window: *Window) void {
|
||||
var i: usize = 0;
|
||||
while (i < self.windows.items.len) {
|
||||
const current = self.windows.items[i];
|
||||
if (window == current) {
|
||||
window.destroy();
|
||||
_ = self.windows.swapRemove(i);
|
||||
return;
|
||||
}
|
||||
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// Drain the mailbox.
|
||||
fn drainMailbox(self: *App) !void {
|
||||
while (self.mailbox.pop()) |message| {
|
||||
@ -187,23 +211,6 @@ fn drainMailbox(self: *App) !void {
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new window
|
||||
fn newWindow(self: *App, msg: Message.NewWindow) !*Window {
|
||||
if (comptime build_config.artifact != .exe) {
|
||||
@panic("newWindow is not supported for embedded ghostty");
|
||||
}
|
||||
|
||||
var window = try Window.create(self.alloc, self, self.config, .{});
|
||||
errdefer window.destroy();
|
||||
try self.windows.append(self.alloc, window);
|
||||
errdefer _ = self.windows.pop();
|
||||
|
||||
// Set initial font size if given
|
||||
if (msg.font_size) |size| window.setFontSize(size);
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
/// Create a new tab in the parent window
|
||||
fn newTab(self: *App, msg: Message.NewWindow) !void {
|
||||
if (comptime !builtin.target.isDarwin()) {
|
||||
@ -286,6 +293,9 @@ pub const Message = union(enum) {
|
||||
},
|
||||
|
||||
const NewWindow = struct {
|
||||
/// Runtime-specific window options.
|
||||
runtime: apprt.runtime.Window.Options = .{},
|
||||
|
||||
/// The parent window, only used for new tabs.
|
||||
parent: ?*Window = null,
|
||||
|
||||
@ -361,4 +371,28 @@ pub const CAPI = struct {
|
||||
v.alloc.destroy(v);
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new surface as part of an app.
|
||||
export fn ghostty_surface_new(
|
||||
app: *App,
|
||||
opts: *const apprt.runtime.Window.Options,
|
||||
) ?*Window {
|
||||
return surface_new_(app, opts) catch |err| {
|
||||
log.err("error initializing surface err={}", .{err});
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
fn surface_new_(
|
||||
app: *App,
|
||||
opts: *const apprt.runtime.Window.Options,
|
||||
) !*Window {
|
||||
_ = opts;
|
||||
const w = try app.newWindow(.{});
|
||||
return w;
|
||||
}
|
||||
|
||||
export fn ghostty_surface_free(ptr: ?*Window) void {
|
||||
if (ptr) |v| v.app.closeWindow(v);
|
||||
}
|
||||
};
|
||||
|
@ -46,7 +46,7 @@ pub const App = struct {
|
||||
|
||||
pub const Window = struct {
|
||||
pub const Options = extern struct {
|
||||
id: usize,
|
||||
id: usize = 0,
|
||||
};
|
||||
|
||||
pub fn init(app: *const CoreApp, core_win: *CoreWindow, opts: Options) !Window {
|
||||
|
@ -94,6 +94,7 @@ pub fn main() !void {
|
||||
// Run our app with a single initial window to start.
|
||||
var app = try App.create(alloc, .{}, &config);
|
||||
defer app.destroy();
|
||||
_ = try app.newWindow(.{});
|
||||
try app.run();
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user