apprt/gtk: set inherited working directory manually

Fixes #2745

GTK uses a delayed surface initialization since we initialize on
GTKGLArea realize not on the actual callback. Because of that, our
inherited directory doesn't always work since that depends on a
previously focused widget.

This copies our desired inherited directory to an allocation so that we
can set it during realize.
This commit is contained in:
Mitchell Hashimoto
2024-11-20 14:44:44 -08:00
parent 1798fc67bf
commit 7aeee06471

View File

@ -308,8 +308,8 @@ pub const URLWidget = struct {
/// surface has been initialized. /// surface has been initialized.
realized: bool = false, realized: bool = false,
/// True if this surface had a parent to start with. /// The config to use to initialize a surface.
parent_surface: bool = false, init_config: InitConfig,
/// The GUI container that this surface has been attached to. This /// The GUI container that this surface has been attached to. This
/// dictates some behaviors such as new splits, etc. /// dictates some behaviors such as new splits, etc.
@ -370,6 +370,36 @@ im_len: u7 = 0,
/// details on what this is. /// details on what this is.
cgroup_path: ?[]const u8 = null, cgroup_path: ?[]const u8 = null,
/// Configuration used for initializing the surface. We have to copy some
/// data since initialization is delayed with GTK (on realize).
pub const InitConfig = struct {
parent: bool = false,
pwd: ?[]const u8 = null,
pub fn init(
alloc: Allocator,
app: *App,
opts: Options,
) Allocator.Error!InitConfig {
const parent = opts.parent orelse return .{};
const pwd: ?[]const u8 = if (app.config.@"window-inherit-working-directory")
try parent.pwd(alloc)
else
null;
errdefer if (pwd) |p| alloc.free(p);
return .{
.parent = true,
.pwd = pwd,
};
}
pub fn deinit(self: *InitConfig, alloc: Allocator) void {
if (self.pwd) |pwd| alloc.free(pwd);
}
};
pub fn create(alloc: Allocator, app: *App, opts: Options) !*Surface { pub fn create(alloc: Allocator, app: *App, opts: Options) !*Surface {
var surface = try alloc.create(Surface); var surface = try alloc.create(Surface);
errdefer alloc.destroy(surface); errdefer alloc.destroy(surface);
@ -494,6 +524,10 @@ pub fn init(self: *Surface, app: *App, opts: Options) !void {
}; };
errdefer if (cgroup_path) |path| app.core_app.alloc.free(path); errdefer if (cgroup_path) |path| app.core_app.alloc.free(path);
// Build our initialization config
const init_config = try InitConfig.init(app.core_app.alloc, app, opts);
errdefer init_config.deinit(app.core_app.alloc);
// Build our result // Build our result
self.* = .{ self.* = .{
.app = app, .app = app,
@ -504,7 +538,7 @@ pub fn init(self: *Surface, app: *App, opts: Options) !void {
.title_text = null, .title_text = null,
.core_surface = undefined, .core_surface = undefined,
.font_size = font_size, .font_size = font_size,
.parent_surface = opts.parent != null, .init_config = init_config,
.size = .{ .width = 800, .height = 600 }, .size = .{ .width = 800, .height = 600 },
.cursor_pos = .{ .x = 0, .y = 0 }, .cursor_pos = .{ .x = 0, .y = 0 },
.im_context = im_context, .im_context = im_context,
@ -555,7 +589,11 @@ fn realize(self: *Surface) !void {
// Get our new surface config // Get our new surface config
var config = try apprt.surface.newConfig(self.app.core_app, &self.app.config); var config = try apprt.surface.newConfig(self.app.core_app, &self.app.config);
defer config.deinit(); defer config.deinit();
if (!self.parent_surface) {
if (self.init_config.pwd) |pwd| {
// If we have a working directory we want, then we force that.
config.@"working-directory" = pwd;
} else if (!self.init_config.parent) {
// A hack, see the "parent_surface" field for more information. // A hack, see the "parent_surface" field for more information.
config.@"working-directory" = self.app.config.@"working-directory"; config.@"working-directory" = self.app.config.@"working-directory";
} }
@ -583,6 +621,7 @@ fn realize(self: *Surface) !void {
} }
pub fn deinit(self: *Surface) void { pub fn deinit(self: *Surface) void {
self.init_config.deinit(self.app.core_app.alloc);
if (self.title_text) |title| self.app.core_app.alloc.free(title); if (self.title_text) |title| self.app.core_app.alloc.free(title);
// We don't allocate anything if we aren't realized. // We don't allocate anything if we aren't realized.