diff --git a/src/App.zig b/src/App.zig index 3bbeff2c8..02089ae5b 100644 --- a/src/App.zig +++ b/src/App.zig @@ -76,34 +76,38 @@ first: bool = true, pub const CreateError = Allocator.Error || font.SharedGridSet.InitError; +/// Create a new app instance. This returns a stable pointer to the app +/// instance which is required for callbacks. +pub fn create(alloc: Allocator) CreateError!*App { + var app = try alloc.create(App); + errdefer alloc.destroy(app); + try app.init(alloc); + return app; +} + /// Initialize the main app instance. This creates the main window, sets /// up the renderer state, compiles the shaders, etc. This is the primary /// "startup" logic. /// /// After calling this function, well behaved apprts should then call /// `focusEvent` to set the initial focus state of the app. -pub fn create( +pub fn init( + self: *App, alloc: Allocator, -) CreateError!*App { - var app = try alloc.create(App); - errdefer alloc.destroy(app); - +) CreateError!void { var font_grid_set = try font.SharedGridSet.init(alloc); errdefer font_grid_set.deinit(); - app.* = .{ + self.* = .{ .alloc = alloc, .surfaces = .{}, .mailbox = .{}, .font_grid_set = font_grid_set, .config_conditional_state = .{}, }; - errdefer app.surfaces.deinit(alloc); - - return app; } -pub fn destroy(self: *App) void { +pub fn deinit(self: *App) void { // Clean up all our surfaces for (self.surfaces.items) |surface| surface.deinit(); self.surfaces.deinit(self.alloc); @@ -114,7 +118,13 @@ pub fn destroy(self: *App) void { // should gracefully close all surfaces. assert(self.font_grid_set.count() == 0); self.font_grid_set.deinit(); +} +pub fn destroy(self: *App) void { + // Deinitialize the app + self.deinit(); + + // Free the app memory self.alloc.destroy(self); } diff --git a/src/apprt/embedded.zig b/src/apprt/embedded.zig index 31dd2f46b..dec1e4135 100644 --- a/src/apprt/embedded.zig +++ b/src/apprt/embedded.zig @@ -117,10 +117,11 @@ pub const App = struct { config: Config, pub fn init( + self: *App, core_app: *CoreApp, config: *const Config, opts: Options, - ) !App { + ) !void { // We have to clone the config. const alloc = core_app.alloc; var config_clone = try config.clone(alloc); @@ -129,7 +130,7 @@ pub const App = struct { var keymap = try input.Keymap.init(); errdefer keymap.deinit(); - return .{ + self.* = .{ .core_app = core_app, .config = config_clone, .opts = opts, @@ -1316,13 +1317,13 @@ pub const CAPI = struct { opts: *const apprt.runtime.App.Options, config: *const Config, ) !*App { - var core_app = try CoreApp.create(global.alloc); + const core_app = try CoreApp.create(global.alloc); errdefer core_app.destroy(); // Create our runtime app var app = try global.alloc.create(App); errdefer global.alloc.destroy(app); - app.* = try .init(core_app, config, opts.*); + try app.init(core_app, config, opts.*); errdefer app.terminate(); return app; diff --git a/src/apprt/glfw.zig b/src/apprt/glfw.zig index 6e131435d..b82771d75 100644 --- a/src/apprt/glfw.zig +++ b/src/apprt/glfw.zig @@ -50,7 +50,7 @@ pub const App = struct { pub const Options = struct {}; - pub fn init(core_app: *CoreApp, _: Options) !App { + pub fn init(self: *App, core_app: *CoreApp, _: Options) !void { if (comptime builtin.target.os.tag.isDarwin()) { log.warn("WARNING WARNING WARNING: GLFW ON MAC HAS BUGS.", .{}); log.warn("You should use the AppKit-based app instead. The official download", .{}); @@ -107,7 +107,7 @@ pub const App = struct { // We want the event loop to wake up instantly so we can process our tick. glfw.postEmptyEvent(); - return .{ + self.* = .{ .app = core_app, .config = config, .darwin = darwin, diff --git a/src/apprt/gtk/App.zig b/src/apprt/gtk/App.zig index 93e069376..7786f976a 100644 --- a/src/apprt/gtk/App.zig +++ b/src/apprt/gtk/App.zig @@ -110,7 +110,7 @@ quit_timer: union(enum) { expired: void, } = .{ .off = {} }, -pub fn init(core_app: *CoreApp, opts: Options) !App { +pub fn init(self: *App, core_app: *CoreApp, opts: Options) !void { _ = opts; // Log our GTK version @@ -424,7 +424,7 @@ pub fn init(core_app: *CoreApp, opts: Options) !App { gtk.STYLE_PROVIDER_PRIORITY_APPLICATION + 3, ); - return .{ + self.* = .{ .core_app = core_app, .app = adw_app, .config = config, diff --git a/src/main_ghostty.zig b/src/main_ghostty.zig index 985c6c9bd..b75d8397c 100644 --- a/src/main_ghostty.zig +++ b/src/main_ghostty.zig @@ -98,11 +98,12 @@ pub fn main() !MainReturn { } // Create our app state - var app = try App.create(alloc); + const app: *App = try App.create(alloc); defer app.destroy(); // Create our runtime app - var app_runtime = try apprt.App.init(app, .{}); + var app_runtime: apprt.App = undefined; + try app_runtime.init(&app, .{}); defer app_runtime.terminate(); // Since - by definition - there are no surfaces when first started, the