terminal: C terminal wrapper allocates the kitty temp dir path only when it is set

This commit is contained in:
Mitchell Hashimoto
2026-09-03 14:01:39 -07:00
parent 35a6fb747f
commit 105d0a5453

View File

@@ -105,9 +105,10 @@ const TerminalWrapper = struct {
/// created by `new` or transferred from snapshot decoding until `free`.
/// Freestanding owners contain no native allocation and expose failing I/O.
io: Io,
/// We also need to store a temp dir path for some operations (e.g., kitty
/// graphics). This provides stable storage for the API calls.
tmp_dir_path: [max_path_bytes]u8,
/// Allocator-owned copy of the temporary directory path for some
/// operations (e.g. kitty graphics). This is only allocated once the
/// embedder sets the option.
tmp_dir_path: ?[]u8 = null,
/// The terminfo name reported for XTGETTCAP "TN". The stream handler holds
/// a slice into this.
terminfo_name_buf: [Handler.max_terminfo_name_bytes]u8,
@@ -728,7 +729,6 @@ fn wrap(
wrapper.* = .{
.terminal = t,
.io = io,
.tmp_dir_path = undefined,
.terminfo_name_buf = undefined,
.stream = Stream.init(.{
.allocator = alloc,
@@ -1393,22 +1393,31 @@ fn setTyped(
},
.kitty_image_medium_temp_file => {
if (comptime !build_options.kitty_graphics) return .success;
const alloc = wrapper.terminal.gpa();
if (value) |v| {
if (v.len > wrapper.tmp_dir_path.len) return .out_of_memory;
@memcpy(wrapper.tmp_dir_path[0..v.len], v.ptr[0..v.len]);
if (v.len > max_path_bytes) return .out_of_memory;
const path = alloc.dupe(u8, v.ptr[0..v.len]) catch
return .out_of_memory;
var it = wrapper.terminal.screens.all.iterator();
while (it.next()) |entry| {
const screen = entry.value.*;
screen.kitty_images.image_limits.temporary_file = .{
.enabled = .{ .directory = wrapper.tmp_dir_path[0..v.len] },
.enabled = .{ .directory = path },
};
}
// Every screen points at the new copy now so the previous
// one can be released.
if (wrapper.tmp_dir_path) |old| alloc.free(old);
wrapper.tmp_dir_path = path;
} else {
var it = wrapper.terminal.screens.all.iterator();
while (it.next()) |entry| {
const screen = entry.value.*;
screen.kitty_images.image_limits.temporary_file = .disabled;
}
if (wrapper.tmp_dir_path) |old| alloc.free(old);
wrapper.tmp_dir_path = null;
}
},
.apc_max_bytes => {
@@ -1861,6 +1870,7 @@ pub fn free(terminal_: Terminal) callconv(lib.calling_conv) void {
wrapper.searches.deinit(alloc);
wrapper.stream.deinit();
t.deinit(alloc);
if (wrapper.tmp_dir_path) |path| alloc.free(path);
wrapper.io.deinit(alloc);
alloc.destroy(t);
alloc.destroy(wrapper);