introduce split-preserve-zoom config to maintain zoomed splits during navigation

This commit is contained in:
lorenries
2025-10-08 12:04:42 -04:00
committed by Mitchell Hashimoto
parent 67eb480577
commit d364e421a8
5 changed files with 81 additions and 2 deletions

View File

@@ -340,6 +340,35 @@ pub const SplitTree = extern struct {
const surface = tree.nodes[target.idx()].leaf;
surface.grabFocus();
// We also need to setup our last_focused to this because if we
// trigger a tree change like below, the grab focus above never
// actually triggers in time to set this and this ensures we
// grab focus to the right thing.
const old_last_focused = self.private().last_focused.get();
defer if (old_last_focused) |v| v.unref(); // unref strong ref from get
self.private().last_focused.set(surface);
errdefer self.private().last_focused.set(old_last_focused);
if (tree.zoomed != null) {
const app = Application.default();
const config_obj = app.getConfig();
defer config_obj.unref();
const config = config_obj.get();
if (!config.@"split-preserve-zoom".navigation) {
tree.zoomed = null;
} else {
tree.zoom(target);
}
// When the zoom state changes our tree state changes and
// we need to send the proper notifications to trigger
// relayout.
const object = self.as(gobject.Object);
object.notifyByPspec(properties.tree.impl.param_spec);
object.notifyByPspec(properties.@"is-zoomed".impl.param_spec);
}
return true;
}

View File

@@ -985,6 +985,14 @@ palette: Palette = .{},
/// Available since: 1.1.0
@"split-divider-color": ?Color = null,
/// Control when Ghostty preserves the zoomed state of a split. This is a packed
/// struct so more options can be added in the future. The `navigation` option
/// keeps the current split zoomed when split navigation (`goto_split`) changes
/// the focused split.
///
/// Example: `split-preserve-zoom = navigation`
@"split-preserve-zoom": SplitPreserveZoom = .{},
/// The foreground and background color for search matches. This only applies
/// to non-focused search matches, also known as candidate matches.
///
@@ -7423,6 +7431,10 @@ pub const ShellIntegrationFeatures = packed struct {
path: bool = true,
};
pub const SplitPreserveZoom = packed struct {
navigation: bool = false,
};
pub const RepeatableCommand = struct {
value: std.ArrayListUnmanaged(inputpkg.Command) = .empty,

View File

@@ -222,3 +222,19 @@ test "c_get: background-blur" {
try testing.expectEqual(-2, cval);
}
}
test "c_get: split-preserve-zoom" {
const testing = std.testing;
const alloc = testing.allocator;
var c = try Config.default(alloc);
defer c.deinit();
var bits: c_uint = undefined;
try testing.expect(get(&c, .@"split-preserve-zoom", @ptrCast(&bits)));
try testing.expectEqual(@as(c_uint, 0), bits);
c.@"split-preserve-zoom".navigation = true;
try testing.expect(get(&c, .@"split-preserve-zoom", @ptrCast(&bits)));
try testing.expectEqual(@as(c_uint, 1), bits);
}