From f31d6fb8fe64ba52d5adde20a17c6709abe7d0c8 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 31 May 2023 21:08:50 -0700 Subject: [PATCH] apprt: clean up how apprt initializes surfaces --- src/App.zig | 4 ++-- src/apprt/embedded.zig | 18 +++--------------- src/apprt/glfw.zig | 19 ++++--------------- src/apprt/gtk.zig | 6 +++++- src/apprt/surface.zig | 21 +++++++++++++++++++++ src/config.zig | 15 +++++++++++++++ 6 files changed, 50 insertions(+), 33 deletions(-) diff --git a/src/App.zig b/src/App.zig index 5b638fdf2..b2893fdd3 100644 --- a/src/App.zig +++ b/src/App.zig @@ -129,7 +129,7 @@ pub fn deleteSurface(self: *App, rt_surface: *apprt.Surface) void { /// The last focused surface. This is only valid while on the main thread /// before tick is called. -pub fn focusedSurface(self: *App) ?*Surface { +pub fn focusedSurface(self: *const App) ?*Surface { const surface = self.focused_surface orelse return null; if (!self.hasSurface(surface)) return null; return surface; @@ -214,7 +214,7 @@ fn surfaceMessage(self: *App, surface: *Surface, msg: apprt.surface.Message) !vo // Not a problem. } -fn hasSurface(self: *App, surface: *Surface) bool { +fn hasSurface(self: *const App, surface: *const Surface) bool { for (self.surfaces.items) |v| { if (&v.core_surface == surface) return true; } diff --git a/src/apprt/embedded.zig b/src/apprt/embedded.zig index 29a8c96e7..36e7d3e77 100644 --- a/src/apprt/embedded.zig +++ b/src/apprt/embedded.zig @@ -144,8 +144,6 @@ pub const Surface = struct { }; pub fn init(self: *Surface, app: *App, opts: Options) !void { - const alloc = app.core_app.alloc; - self.* = .{ .app = app, .core_surface = undefined, @@ -163,24 +161,14 @@ pub const Surface = struct { try app.core_app.addSurface(self); errdefer app.core_app.deleteSurface(self); - // Our parent pwd will be tracked here - var parent_pwd: ?[]const u8 = null; - defer if (parent_pwd) |v| alloc.free(v); - // Shallow copy the config so that we can modify it. - var config = app.config.*; - - // Get our previously focused surface - const parent = app.core_app.focusedSurface(); - if (parent) |p| { - parent_pwd = try p.pwd(alloc); - if (parent_pwd) |v| config.@"working-directory" = v; - } + var config = try apprt.surface.newConfig(app.core_app, app.config); + defer config.deinit(); // Initialize our surface right away. We're given a view that is // ready to use. try self.core_surface.init( - alloc, + app.core_app.alloc, &config, .{ .rt_app = app, .mailbox = &app.core_app.mailbox }, self, diff --git a/src/apprt/glfw.zig b/src/apprt/glfw.zig index b65573a03..822437b50 100644 --- a/src/apprt/glfw.zig +++ b/src/apprt/glfw.zig @@ -346,24 +346,13 @@ pub const Surface = struct { try app.app.addSurface(self); errdefer app.app.deleteSurface(self); - // Our parent pwd will be tracked here - const alloc = app.app.alloc; - var parent_pwd: ?[]const u8 = null; - defer if (parent_pwd) |v| alloc.free(v); - - // Shallow copy the config so that we can modify it. - var config = app.config; - - // Get our previously focused surface - const parent = app.app.focusedSurface(); - if (parent) |p| { - parent_pwd = try p.pwd(alloc); - if (parent_pwd) |v| config.@"working-directory" = v; - } + // Get our new surface config + var config = try apprt.surface.newConfig(app.app, &app.config); + defer config.deinit(); // Initialize our surface now that we have the stable pointer. try self.core_surface.init( - alloc, + app.app.alloc, &config, .{ .rt_app = app, .mailbox = &app.app.mailbox }, self, diff --git a/src/apprt/gtk.zig b/src/apprt/gtk.zig index 51ca0d910..05e43cee3 100644 --- a/src/apprt/gtk.zig +++ b/src/apprt/gtk.zig @@ -722,10 +722,14 @@ pub const Surface = struct { try self.app.core_app.addSurface(self); errdefer self.app.core_app.deleteSurface(self); + // Get our new surface config + var config = try apprt.surface.newConfig(self.app.core_app, &self.app.config); + defer config.deinit(); + // Initialize our surface now that we have the stable pointer. try self.core_surface.init( self.app.core_app.alloc, - &self.app.config, + &config, .{ .rt_app = self.app, .mailbox = &self.app.core_app.mailbox }, self, ); diff --git a/src/apprt/surface.zig b/src/apprt/surface.zig index 859d694d5..67b4247e8 100644 --- a/src/apprt/surface.zig +++ b/src/apprt/surface.zig @@ -61,3 +61,24 @@ pub const Mailbox = struct { }, timeout); } }; + +/// Returns a new config for a surface for the given app that should be +/// used for any new surfaces. The resulting config should be deinitialized +/// after the surface is initialized. +pub fn newConfig(app: *const App, config: *const Config) !Config { + // Create a shallow clone + var copy = config.shallowClone(app.alloc); + + // Our allocator is our config's arena + const alloc = copy._arena.?.allocator(); + + // Get our previously focused surface for some inherited values. + const prev = app.focusedSurface(); + if (prev) |p| { + if (try p.pwd(alloc)) |pwd| { + copy.@"working-directory" = pwd; + } + } + + return copy; +} diff --git a/src/config.zig b/src/config.zig index 6d75e4e11..9a82c59d2 100644 --- a/src/config.zig +++ b/src/config.zig @@ -691,6 +691,21 @@ pub const Config = struct { } } + /// Create a shallow copy of this config. This will share all the memory + /// allocated with the previous config but will have a new arena for + /// any changes or new allocations. The config should have `deinit` + /// called when it is complete. + /// + /// Beware: these shallow clones are not meant for a long lifetime, + /// they are just meant to exist temporarily for the duration of some + /// modifications. It is very important that the original config not + /// be deallocated while shallow clones exist. + pub fn shallowClone(self: *const Config, alloc_gpa: Allocator) Config { + var result = self.*; + result._arena = ArenaAllocator.init(alloc_gpa); + return result; + } + /// Create a copy of this configuration. This is useful as a starting /// point for modifying a configuration since a config can NOT be /// modified once it is in use by an app or surface.