summaryrefslogtreecommitdiff
path: root/src/layout.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/layout.zig')
-rw-r--r--src/layout.zig29
1 files changed, 25 insertions, 4 deletions
diff --git a/src/layout.zig b/src/layout.zig
index c58f3bcf..b9b24e79 100644
--- a/src/layout.zig
+++ b/src/layout.zig
@@ -162,8 +162,15 @@ pub fn targetColumn(p: *Pardes, cur_x: u16) usize {
}
pub fn splitRowForExtent(y: u16, h: u16, cur_y: u16) ?u16 {
+ return splitRowFor(y, h, cur_y, null);
+}
+
+/// As `splitRowForExtent`, each pane keeping at least `least` rows when
+/// given: a pane dragged by its grip within its own column is how a
+/// terminal resizes, and acme lets either window keep only its tag.
+fn splitRowFor(y: u16, h: u16, cur_y: u16, least: ?u16) ?u16 {
if (h < 2) return null;
- const min_each: u16 = if (h >= config.MINH * 2) config.MINH else 1;
+ const min_each: u16 = least orelse if (h >= config.MINH * 2) config.MINH else 1;
const lo = y +| min_each;
const hi = y + h - min_each;
if (lo > hi) return y + h / 2;
@@ -176,7 +183,11 @@ pub fn movePlacement(p: *Pardes, id: usize, cur_x: u16, cur_y: u16) ?MovePlaceme
if (tc == src.col and p.col_n[src.col] == 1) return null;
if (tc == src.col) {
const sr = p.rects[id];
- if (cur_y >= sr.y and cur_y < sr.y + sr.h) return null;
+ // Dropped on itself it stays, unless dragged down from its top with
+ // a pane above: its top moves down there, the pane above taking the
+ // rows, as acme's window dragged by its button does. With no rule
+ // between panes, that is how a terminal resizes them.
+ if (cur_y >= sr.y and cur_y < sr.y + sr.h and (src.idx == 0 or cur_y <= sr.y)) return null;
}
var heights: [MAX_PANES]u16 = @splat(0);
for (0..p.ncol) |c| {
@@ -196,7 +207,7 @@ pub fn movePlacement(p: *Pardes, id: usize, cur_x: u16, cur_y: u16) ?MovePlaceme
const pid = p.col_panes[tc][k];
if (pid == id) continue;
const h = heights[pid];
- const row = splitRowForExtent(y, h, cur_y) orelse {
+ const row = splitRowFor(y, h, cur_y, if (tc == src.col) BOX_H else null) orelse {
y +|= h;
continue;
};
@@ -280,7 +291,7 @@ pub fn applyRowSplit(p: *Pardes, cc: usize, k: usize, cur_y: u16) void {
b.vweight = pair - a.vweight;
}
-pub fn findPane(p: *Pardes, id: usize) ?struct { col: usize, idx: usize } {
+pub fn findPane(p: *const Pardes, id: usize) ?struct { col: usize, idx: usize } {
for (0..p.ncol) |c| {
for (0..p.col_n[c]) |k| {
if (p.col_panes[c][k] == id) return .{ .col = c, .idx = k };
@@ -311,6 +322,7 @@ pub fn removePane(p: *Pardes, id: usize) void {
/// it (the first column's to its right), as acme's rowclose gives it.
pub fn dropColumn(p: *Pardes, c: usize) void {
std.debug.assert(p.col_n[c] == 0);
+ const serial = columnSerial(p, c);
tagline.exitHeader(p);
if (p.ncol > 1) p.col_weight[if (c > 0) c - 1 else c + 1] +|= p.col_weight[c];
p.col_tags[c].deinit(p.gpa);
@@ -325,6 +337,14 @@ pub fn dropColumn(p: *Pardes, c: usize) void {
p.ncol -= 1;
p.col_tags[p.ncol] = .{ .what = .column, .gpa = p.gpa };
p.col_serial[p.ncol] = 0;
+ noteColumn(p, "delcol", serial);
+}
+
+/// `newcol <serial>` or `delcol <serial>` in the log: the column's serial,
+/// as /layout and /col name it.
+fn noteColumn(p: *Pardes, what: []const u8, serial: u32) void {
+ var buf: [16]u8 = undefined;
+ pardes.ctlfs.events.notePath(p, what, std.fmt.bufPrint(&buf, "{d}", .{serial}) catch return);
}
/// Fold column `c` into the one on its right, its panes below theirs.
@@ -480,6 +500,7 @@ pub fn insertColumn(p: *Pardes, col: usize, before: bool) ?usize {
p.col_serial[c] = 0;
p.col_n[c] = 0;
p.ncol += 1;
+ noteColumn(p, "newcol", columnSerial(p, c));
return c;
}