mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 00:06:09 +03:00
gtk: implement equalize_splits
This adds support for the equalize_splits feature that's already implemented for macOS. It's essentially a port of the Swift implementation, using the same weights-mechanism to equalize split sizes.
This commit is contained in:
@ -172,6 +172,46 @@ pub fn moveDivider(self: *Split, direction: input.SplitResizeDirection, amount:
|
||||
c.gtk_paned_set_position(self.paned, new);
|
||||
}
|
||||
|
||||
/// Equalize the splits in this split panel. Each split is equalized based on
|
||||
/// its weight, i.e. the number of Surfaces it contains.
|
||||
///
|
||||
/// It works recursively by equalizing the children of each split.
|
||||
///
|
||||
/// It returns this split's weight.
|
||||
pub fn equalize(self: *Split) i16 {
|
||||
// Calculate weights of top_left/bottom_right
|
||||
const top_left_weight = self.top_left.equalize();
|
||||
const bottom_right_weight = self.bottom_right.equalize();
|
||||
const weight = top_left_weight + bottom_right_weight;
|
||||
|
||||
// Ratio of top_left weight to overall weight, which gives the split ratio
|
||||
const ratio = @as(f16, @floatFromInt(top_left_weight)) / @as(f16, @floatFromInt(weight));
|
||||
|
||||
// Convert split ratio into new position for divider
|
||||
const max: f16 = @floatFromInt(self.maxPosition());
|
||||
const new: c_int = @intFromFloat(max * ratio);
|
||||
|
||||
c.gtk_paned_set_position(self.paned, new);
|
||||
|
||||
return weight;
|
||||
}
|
||||
|
||||
// maxPosition returns the maximum position of the GtkPaned, which is the
|
||||
// "max-position" attribute.
|
||||
fn maxPosition(self: *Split) c_int {
|
||||
var value: c.GValue = std.mem.zeroes(c.GValue);
|
||||
defer c.g_value_unset(&value);
|
||||
|
||||
_ = c.g_value_init(&value, c.G_TYPE_INT);
|
||||
c.g_object_get_property(
|
||||
@ptrCast(@alignCast(self.paned)),
|
||||
"max-position",
|
||||
&value,
|
||||
);
|
||||
|
||||
return c.g_value_get_int(&value);
|
||||
}
|
||||
|
||||
// This replaces the element at the given pointer with a new element.
|
||||
// The ptr must be either top_left or bottom_right (asserted in debug).
|
||||
// The memory of the old element must be freed or otherwise handled by
|
||||
|
@ -96,6 +96,13 @@ pub const Container = union(enum) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn equalize(self: Elem) i16 {
|
||||
return switch (self) {
|
||||
.surface => 1,
|
||||
.split => |s| s.equalize(),
|
||||
};
|
||||
}
|
||||
|
||||
/// The last surface in this container in the direction specified.
|
||||
/// Direction must be "top_left" or "bottom_right".
|
||||
pub fn deepestSurface(self: Elem, side: SplitSide) ?*Surface {
|
||||
@ -582,6 +589,15 @@ pub fn resizeSplit(self: *const Surface, direction: input.SplitResizeDirection,
|
||||
s.moveDivider(direction, amount);
|
||||
}
|
||||
|
||||
pub fn equalizeSplits(self: *const Surface) void {
|
||||
const tab = self.container.tab() orelse return;
|
||||
const top_split = switch (tab.elem) {
|
||||
.split => |s| s,
|
||||
else => return,
|
||||
};
|
||||
_ = top_split.equalize();
|
||||
}
|
||||
|
||||
pub fn newTab(self: *Surface) !void {
|
||||
const window = self.container.window() orelse {
|
||||
log.info("surface cannot create new tab when not attached to a window", .{});
|
||||
|
@ -1008,6 +1008,11 @@ pub fn default(alloc_gpa: Allocator) Allocator.Error!Config {
|
||||
.{ .key = .right, .mods = .{ .super = true, .ctrl = true, .shift = true } },
|
||||
.{ .resize_split = .{ .right, 10 } },
|
||||
);
|
||||
try result.keybind.set.put(
|
||||
alloc,
|
||||
.{ .key = .equal, .mods = .{ .super = true, .ctrl = true, .shift = true } },
|
||||
.{ .equalize_splits = {} },
|
||||
);
|
||||
|
||||
// Viewport scrolling
|
||||
try result.keybind.set.put(
|
||||
|
Reference in New Issue
Block a user