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
/// 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;
}

View File

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

View File

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

View File

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

View File

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

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
/// point for modifying a configuration since a config can NOT be
/// modified once it is in use by an app or surface.