apprt: clean up how apprt initializes surfaces

This commit is contained in:
Mitchell Hashimoto
2023-05-31 21:08:50 -07:00
parent 0fca74c089
commit f31d6fb8fe
6 changed files with 50 additions and 33 deletions

View File

@@ -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 /// The last focused surface. This is only valid while on the main thread
/// before tick is called. /// 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; const surface = self.focused_surface orelse return null;
if (!self.hasSurface(surface)) return null; if (!self.hasSurface(surface)) return null;
return surface; return surface;
@@ -214,7 +214,7 @@ fn surfaceMessage(self: *App, surface: *Surface, msg: apprt.surface.Message) !vo
// Not a problem. // Not a problem.
} }
fn hasSurface(self: *App, surface: *Surface) bool { fn hasSurface(self: *const App, surface: *const Surface) bool {
for (self.surfaces.items) |v| { for (self.surfaces.items) |v| {
if (&v.core_surface == surface) return true; if (&v.core_surface == surface) return true;
} }

View File

@@ -144,8 +144,6 @@ pub const Surface = struct {
}; };
pub fn init(self: *Surface, app: *App, opts: Options) !void { pub fn init(self: *Surface, app: *App, opts: Options) !void {
const alloc = app.core_app.alloc;
self.* = .{ self.* = .{
.app = app, .app = app,
.core_surface = undefined, .core_surface = undefined,
@@ -163,24 +161,14 @@ pub const Surface = struct {
try app.core_app.addSurface(self); try app.core_app.addSurface(self);
errdefer app.core_app.deleteSurface(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. // Shallow copy the config so that we can modify it.
var config = app.config.*; var config = try apprt.surface.newConfig(app.core_app, app.config);
defer config.deinit();
// 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;
}
// Initialize our surface right away. We're given a view that is // Initialize our surface right away. We're given a view that is
// ready to use. // ready to use.
try self.core_surface.init( try self.core_surface.init(
alloc, app.core_app.alloc,
&config, &config,
.{ .rt_app = app, .mailbox = &app.core_app.mailbox }, .{ .rt_app = app, .mailbox = &app.core_app.mailbox },
self, self,

View File

@@ -346,24 +346,13 @@ pub const Surface = struct {
try app.app.addSurface(self); try app.app.addSurface(self);
errdefer app.app.deleteSurface(self); errdefer app.app.deleteSurface(self);
// Our parent pwd will be tracked here // Get our new surface config
const alloc = app.app.alloc; var config = try apprt.surface.newConfig(app.app, &app.config);
var parent_pwd: ?[]const u8 = null; defer config.deinit();
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;
}
// Initialize our surface now that we have the stable pointer. // Initialize our surface now that we have the stable pointer.
try self.core_surface.init( try self.core_surface.init(
alloc, app.app.alloc,
&config, &config,
.{ .rt_app = app, .mailbox = &app.app.mailbox }, .{ .rt_app = app, .mailbox = &app.app.mailbox },
self, self,

View File

@@ -722,10 +722,14 @@ pub const Surface = struct {
try self.app.core_app.addSurface(self); try self.app.core_app.addSurface(self);
errdefer self.app.core_app.deleteSurface(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. // Initialize our surface now that we have the stable pointer.
try self.core_surface.init( try self.core_surface.init(
self.app.core_app.alloc, self.app.core_app.alloc,
&self.app.config, &config,
.{ .rt_app = self.app, .mailbox = &self.app.core_app.mailbox }, .{ .rt_app = self.app, .mailbox = &self.app.core_app.mailbox },
self, self,
); );

View File

@@ -61,3 +61,24 @@ pub const Mailbox = struct {
}, timeout); }, 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;
}

View File

@@ -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 /// Create a copy of this configuration. This is useful as a starting
/// point for modifying a configuration since a config can NOT be /// point for modifying a configuration since a config can NOT be
/// modified once it is in use by an app or surface. /// modified once it is in use by an app or surface.