c: create/destroy surface API

This commit is contained in:
Mitchell Hashimoto
2023-02-17 12:31:35 -08:00
parent 6ceb5b847b
commit 55b05b22bb
4 changed files with 64 additions and 25 deletions

View File

@ -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

View File

@ -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);
}
};

View File

@ -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 {

View File

@ -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();
}