diff options
| author | Gabriel Schneider <[email protected]> | 2026-09-29 00:17:45 -0300 |
|---|---|---|
| committer | Gabriel Schneider <[email protected]> | 2026-10-01 00:12:15 -0300 |
| commit | 15ddd805905f785f4dde463d4d6b91e1d2c41e26 (patch) | |
| tree | d812a922785101f0b14f672ca47be6fd67b49833 | |
| parent | 64b6a0dbdaab4b314ccbce667709d71a8561daf0 (diff) | |
| download | pardes-15ddd805905f785f4dde463d4d6b91e1d2c41e26.tar.gz pardes-15ddd805905f785f4dde463d4d6b91e1d2c41e26.zip | |
A pane's last row of text is no resize handle; the grip is, and the GUI's rule
A press on a pane's last row began a seam drag, so the row could not be
clicked or swept like the rest of the text (rsearch dragged the handle out
of the way first). Now no row of text is a handle: in the GUI a press on
the 2 px rule between two panes drags their seam, and anywhere the grip
does, as acme's button moves a window -- dragged up or down its own column
it moves the pane's top, either pane down to its tag alone (acme's
coldragwin), dragged down inside itself too. The hover hint over a last row
is gone; column edges resize as they did. Scripts that dragged a seam drag
a grip instead and match their goldens; six goldens lost the hint or moved a
cursor to the clicked text, re-recorded by name.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
| -rw-r--r-- | docs/tags.md | 9 | ||||
| -rw-r--r-- | src/draw.zig | 11 | ||||
| -rw-r--r-- | src/gui/gui.zig | 9 | ||||
| -rw-r--r-- | src/layout.zig | 17 | ||||
| -rw-r--r-- | src/mouse.zig | 59 | ||||
| -rw-r--r-- | src/pardes.zig | 5 | ||||
| -rw-r--r-- | src/tutor.txt | 9 | ||||
| -rw-r--r-- | test/snapshots/builtins.golden | 1 | ||||
| -rw-r--r-- | test/snapshots/lookrange.golden | 1 | ||||
| -rw-r--r-- | test/snapshots/lsprelpath.golden | 1 | ||||
| -rw-r--r-- | test/snapshots/rsearch.golden | 17 | ||||
| -rw-r--r-- | test/snapshots/rsearch.snap | 9 | ||||
| -rw-r--r-- | test/snapshots/shrinktag.snap | 37 | ||||
| -rw-r--r-- | test/snapshots/splitparent.snap | 9 | ||||
| -rw-r--r-- | test/snapshots/tagbottom.golden | 4 | ||||
| -rw-r--r-- | test/snapshots/tagbottom.snap | 18 | ||||
| -rw-r--r-- | test/snapshots/windowops.golden | 3 | ||||
| -rw-r--r-- | test/snapshots/windowops.snap | 13 |
18 files changed, 149 insertions, 83 deletions
diff --git a/docs/tags.md b/docs/tags.md index 885eb22f..c1034cb4 100644 --- a/docs/tags.md +++ b/docs/tags.md @@ -30,6 +30,15 @@ edge will land, beside the rule as a border drag's rail does. Only columns between the old and new positions shift. Each column keeps its width, panes and command text. +Two panes in a column are resized as acme's windows are, by the grip: drag +a pane's grip up or down its own column and its top follows, the pane above +taking or giving the rows, either one down to its tag alone (acme's +coldragwin keeps a window its tag line); drop it in another column and the +pane moves there. In the GUI the 2 px rule between two panes also drags +their seam. No row of text is a handle: a pane's last row takes a click like +any other, and a terminal, which draws no rule, resizes by the grip. A +column's right edge still drags its width. + When Look opens the first document and its source column is too narrow for a new column, it splits below the originating pane, just like `Tty`, instead of inserting at the top of the leftmost column. The originating terminal is diff --git a/src/draw.zig b/src/draw.zig index fb770b60..4ad1a1fe 100644 --- a/src/draw.zig +++ b/src/draw.zig @@ -504,15 +504,8 @@ pub fn render(p: *Pardes, arena: std.mem.Allocator) !*Surface { s.addRegion(.{ .kind = .guide, .rect = .{ .x = p.hover_col, .y = p.topBarHeight(), .w = 1, .h = s.rows -| p.topBarHeight() } }); } } - for (0..p.ncol) |cc| { - if (p.hover_col < p.col_x[cc] or p.hover_col >= p.col_x[cc] + p.col_w[cc]) continue; - // the same seam the h-handle hit test picks (see there) - if (mouse.seamIdxAt(p, cc, p.hover_row) != null) { - var col = p.col_x[cc]; - while (col < p.col_x[cc] + p.col_w[cc]) : (col += 1) s.overlayDash(col, p.hover_row, "╌"); - s.addRegion(.{ .kind = .guide, .rect = .{ .x = p.col_x[cc], .y = p.hover_row, .w = p.col_w[cc], .h = 1 } }); - } - } + // No hint over a pane's last row: a row of text is no handle; two + // panes resize by the rule between them or by the grip. for (0..p.ncol -| 1) |cn| { if (p.hover_col != p.col_x[cn] + p.col_w[cn] -| 1) continue; if (mouse.seamIdxAt(p, cn, p.hover_row) != null) continue; diff --git a/src/gui/gui.zig b/src/gui/gui.zig index 141a802a..ab281cb6 100644 --- a/src/gui/gui.zig +++ b/src/gui/gui.zig @@ -1972,7 +1972,11 @@ fn glyphForCodepoint(g: *const Gui, cp: u32) FaceGlyph { } const CellLayout = struct { w: f32, h: f32, x_off: f32, y_off: f32 }; -const MouseCell = struct { col: u16, row: u16, body_hit: ?pardes.Mouse.BodyHit = null, tag_hit: ?pardes.TagHit = null }; +const MouseCell = struct { col: u16, row: u16, body_hit: ?pardes.Mouse.BodyHit = null, tag_hit: ?pardes.TagHit = null, rule_above: bool = false }; + +/// How near a row's top edge a press is on the rule drawn there between two +/// panes: the rule's 2 px and a pixel either side. +const rule_grab_px: f32 = 3; const WindowGeometry = struct { window_w: f32, window_h: f32, @@ -3420,6 +3424,7 @@ fn dispatch(g: *Gui, in: *Input, sev: *const c.SDL_Event) void { .row = mc.row, .tag_hit = mc.tag_hit, .body_hit = mc.body_hit, + .rule_above = mc.rule_above, .ctrl = (c.SDL_GetModState() & c.SDL_KMOD_CTRL) != 0, }, }); @@ -3720,6 +3725,8 @@ fn gridCellAtDimensions( ) MouseCell { const row: u16 = @intFromFloat(@min(@floor(@max(y, 0) / @max(body_h, 1)), 10_000)); var point: MouseCell = .{ .col = @intFromFloat(@min(@floor(@max(x, 0) / @max(body_w, 1)), 10_000)), .row = row }; + // On the rule over this row, which is where two panes meet if they do. + point.rule_above = row > 0 and @max(y, 0) - @as(f32, @floatFromInt(row)) * @max(body_h, 1) < rule_grab_px; if (core) |p| if (p.presentation.pointerFractional(p.screen_w, p.screen_h, x / @max(body_w, 1), y / @max(body_h, 1))) |mapped| { for (p.surface.tagLayers()) |*layer| { if (layer.tagHit(mapped.x * body_w, mapped.y * body_h, body_w, body_h, tagline_w, @floatFromInt(p.row_metrics.tagline_h))) |hit| { diff --git a/src/layout.zig b/src/layout.zig index 6de7a912..25c95d30 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; }; diff --git a/src/mouse.zig b/src/mouse.zig index 36786612..1ca53017 100644 --- a/src/mouse.zig +++ b/src/mouse.zig @@ -97,13 +97,50 @@ fn cornerFixture(gpa: std.mem.Allocator) !*Pardes { return p; } +test "a pane's last row of text is no resize handle; the rule over the next pane is" { + if (platform == .web) return; + const p = try cornerFixture(std.testing.allocator); + defer p.deinit(); + const seam = seamRowOf(p, 1, 0); + const inside = p.col_x[1] + p.col_w[1] / 2; + p.update(.{ .mouse = .{ .button = .left, .kind = .press, .col = inside, .row = seam } }); + try std.testing.expect(p.drag != .border_h); + p.update(.{ .mouse = .{ .button = .left, .kind = .release, .col = inside, .row = seam } }); + try std.testing.expect(nudgeRightSeam(p, 2) == seam + 2); +} + +test "a pane's grip dragged up or down its own column moves its top, down to a tag alone above" { + if (platform == .web) return; + const p = try cornerFixture(std.testing.allocator); + defer p.deinit(); + const upper = p.col_panes[1][0]; + const lower = p.col_panes[1][1]; + const grip_x = p.rects[lower].x; + // Up, past the pane above's first row: it keeps one row, its tag. + const top = p.rects[upper].y; + p.update(.{ .mouse = .{ .button = .left, .kind = .press, .col = grip_x, .row = p.rects[lower].y } }); + p.update(.{ .mouse = .{ .button = .left, .kind = .drag, .col = grip_x, .row = top } }); + p.update(.{ .mouse = .{ .button = .left, .kind = .release, .col = grip_x, .row = top } }); + p.sync(); + try std.testing.expectEqual(@as(u16, 1), p.rects[upper].h); + try std.testing.expectEqual(lower, p.col_panes[1][1]); + // Down, inside itself: its top follows, the pane above taking the rows. + const to = p.rects[lower].y + 6; + p.update(.{ .mouse = .{ .button = .left, .kind = .press, .col = grip_x, .row = p.rects[lower].y } }); + p.update(.{ .mouse = .{ .button = .left, .kind = .drag, .col = grip_x, .row = to } }); + p.update(.{ .mouse = .{ .button = .left, .kind = .release, .col = grip_x, .row = to } }); + p.sync(); + try std.testing.expectEqual(to, p.rects[lower].y); +} + fn nudgeRightSeam(p: *Pardes, delta: i32) u16 { const from = seamRowOf(p, 1, 0); const inside = p.col_x[1] + p.col_w[1] / 2; const to: u16 = @intCast(@as(i32, from) + delta); - p.update(.{ .mouse = .{ .button = .left, .kind = .press, .col = inside, .row = from } }); - p.update(.{ .mouse = .{ .button = .left, .kind = .drag, .col = inside, .row = to } }); - p.update(.{ .mouse = .{ .button = .left, .kind = .release, .col = inside, .row = to } }); + // On the rule a pixel frontend draws over the lower pane's first row. + p.update(.{ .mouse = .{ .button = .left, .kind = .press, .col = inside, .row = from + 1, .rule_above = true } }); + p.update(.{ .mouse = .{ .button = .left, .kind = .drag, .col = inside, .row = to + 1 } }); + p.update(.{ .mouse = .{ .button = .left, .kind = .release, .col = inside, .row = to + 1 } }); p.sync(); return seamRowOf(p, 1, 0); } @@ -437,13 +474,17 @@ pub fn handleMouse(p: *Pardes, m: Mouse) void { return; } } - for (0..p.ncol) |cc| { + // Two panes are resized on the rule between them, never on a + // row of text; with no rule, by the grip, as acme moves a + // window by its button. + if (m.rule_above and mrow > 0) for (0..p.ncol) |cc| { if (mcol < p.col_x[cc] or mcol >= p.col_x[cc] + p.col_w[cc]) continue; - if (seamIdxAt(p, cc, mrow)) |k| { - p.drag = .{ .border_h = .{ .col = cc, .top_idx = k, .cur_y = mrow } }; + const seam = if (p.settings.tag_bottom) mrow else mrow - 1; + if (seamIdxAt(p, cc, seam)) |k| { + p.drag = .{ .border_h = .{ .col = cc, .top_idx = k, .cur_y = seam } }; return; } - } + }; const id = hovered orelse return; const r = p.rects[id]; const pane = p.panes[id] orelse return; @@ -597,7 +638,9 @@ pub fn dragUpdate(p: *Pardes, mcol: u16, mrow: u16, body_hit: ?Mouse.BodyHit) vo if (k + 1 < p.col_n[cc]) { const a = p.rects[p.col_panes[cc][k]]; const b = p.rects[p.col_panes[cc][k + 1]]; - d.cur_y = clampBorderRow(a.y, a.h, b.h, mrow, p.settings.tag_bottom); + // Held by the rule over the lower pane: the seam is the row above. + const seam = if (p.settings.tag_bottom) mrow else mrow -| 1; + d.cur_y = clampBorderRow(a.y, a.h, b.h, seam, p.settings.tag_bottom); } else d.cur_y = mrow; }, .column_move => |*d| d.cur_x = mcol, diff --git a/src/pardes.zig b/src/pardes.zig index ea03b3eb..8dbe6744 100644 --- a/src/pardes.zig +++ b/src/pardes.zig @@ -3483,6 +3483,11 @@ pub const Mouse = struct { ctrl: bool = false, body_hit: ?BodyHit = null, tag_hit: ?TagHit = null, + /// A pixel frontend's press on the rule it draws at the top of this row, + /// which is where two panes meet if they do: the one grab that resizes + /// them there. A row of text never is one; a terminal, with no rule, + /// resizes by the grip. + rule_above: bool = false, }; pub const Key = struct { diff --git a/src/tutor.txt b/src/tutor.txt index 0893415e..c59deeae 100644 --- a/src/tutor.txt +++ b/src/tutor.txt @@ -132,6 +132,15 @@ DelAbove close it, giving the space to the pane above (Del k) DelBelow close it, giving the space to the pane below (Del j) + RESIZE, AS ACME MOVES A WINDOW + the grip (the box left of a pane's tag) drag it: drop it in another + column to move the pane there, or up or down its own + column to move its top, the pane above taking or giving + the rows -- down to its tag alone + the rule in the GUI, the line between two panes drags their seam + a column's right edge drags the column's width + A pane's last row is text like any other, never a handle. + A new file opens in a new COLUMN only if both panes would still get 100 columns of width. Otherwise it stacks in the one you are in. diff --git a/test/snapshots/builtins.golden b/test/snapshots/builtins.golden index 00f53a1b..f40d563e 100644 --- a/test/snapshots/builtins.golden +++ b/test/snapshots/builtins.golden @@ -27,7 +27,6 @@ |16: == snap tutor-from-index grid=120x67 cursor=7,16 |10: 1 pardes builtins under SPC h Tutor -|14: ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ |15: /Tutor Save Tty Collapse Del |16: 1 |17: 2 PARDES TUTOR diff --git a/test/snapshots/lookrange.golden b/test/snapshots/lookrange.golden index 7d802b0b..f070a953 100644 --- a/test/snapshots/lookrange.golden +++ b/test/snapshots/lookrange.golden @@ -62,7 +62,6 @@ |12: 0-0 d,#608269, 1-1 d,#0d1410, 2-6 #616f64,#0d1410,b 7-9 #f5f7ee,#3c614a, 10-10 #e5eee5,#0d1410, 11-149 d,#0d1410, |14: 0-0 d,#608269, 1-1 d,#0d1410, 2-6 #59675c,#0d1410, 7-18 #e5eee5,#0d1410, 19-149 d,#0d1410, == snap stale grid=150x31 cursor=10,16 -|6: ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ == style stale grid=150x31 |10: 0-0 d,#608269, 1-1 d,#0d1410, 2-6 #59675c,#0d1410, 7-15 #e5eee5,#0d1410, 16-149 d,#0d1410, |11: 0-0 d,#608269, 1-1 d,#0d1410, 2-6 #59675c,#0d1410, 7-10 #e5eee5,#0d1410, 11-149 d,#0d1410, diff --git a/test/snapshots/lsprelpath.golden b/test/snapshots/lsprelpath.golden index c8121b5a..4cc687ab 100644 --- a/test/snapshots/lsprelpath.golden +++ b/test/snapshots/lsprelpath.golden @@ -117,4 +117,3 @@ |33: 0-0 d,#608269, 1-1 d,#0d1410, 2-6 #59675c,#0d1410, 7-99 d,#0d1410, |34: 0-0 d,#608269, 1-1 d,#0d1410, 2-6 #59675c,#0d1410, 7-99 d,#0d1410, == snap clicked grid=100x35 cursor=16,16 -|12: ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ diff --git a/test/snapshots/rsearch.golden b/test/snapshots/rsearch.golden index efbd81c9..89c4f7bd 100644 --- a/test/snapshots/rsearch.golden +++ b/test/snapshots/rsearch.golden @@ -18,13 +18,11 @@ |15: 4 count_x again |16: 5 == snap select grid=210x31 cursor=14,10 -|10: ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ |16: /tmp/pardes-snap/rsearch/cwd/+Search Save Tty Collapse Del LocationsConfig |17: 1 code.txt:4:1-8 |18: 2 pick two words |19: 3 == snap path-open grid=210x31 cursor=16,22 -|10: 4 pick two words |19: /tmp/pardes-snap/rsearch/cwd/sub/dep.txt Save Tty Collapse Del |20: 1 d1 |21: 2 d2 @@ -36,13 +34,8 @@ == snap step2 grid=210x31 cursor=13,9 == snap step3 grid=210x31 cursor=13,9 == snap selclick grid=210x31 cursor=14,10 -|11: -|12: -|13: -|14: -|15: /tmp/pardes-snap/rsearch/cwd/+Search Save Tty Collapse Del LocationsConfig -== snap outside grid=210x31 cursor=14,10 -|10: /tmp/pardes-snap/rsearch/cwd/+Search Save Tty Collapse Del LocationsConfig -|11: 1 code.txt:4:10-14 -|12: 2 pick two words -|13: 3 +== snap outside grid=210x31 cursor=20,10 +|25: /tmp/pardes-snap/rsearch/cwd/+Search Save Tty Collapse Del LocationsConfig +|26: 1 code.txt:4:10-14 +|27: 2 pick two words +|28: 3 diff --git a/test/snapshots/rsearch.snap b/test/snapshots/rsearch.snap index 0ce257bd..8c81db1d 100644 --- a/test/snapshots/rsearch.snap +++ b/test/snapshots/rsearch.snap @@ -74,13 +74,8 @@ press right 10 10 release right 10 10 stable 700 15000 snap step3 -# acme sized code.txt to its four lines, so line 4 is on its last row, and a -# pane's last row is its resize handle: a press there would drag the seam, not -# sweep text. Drag that handle down four rows first. -press left 40 11 -drag left 40 15 -release left 40 15 -stable 700 15000 +# acme sized code.txt to its four lines, so line 4 is on its last row: a +# pane's last row is text like any other, never a resize handle. # A LEFT sweep over `pick two` (line 4, cols 8..15) and then a right CLICK # INSIDE it: the click takes the whole selection — the search is for the # two-word span (`4:1-8`), which the file-ish word expansion could never diff --git a/test/snapshots/shrinktag.snap b/test/snapshots/shrinktag.snap index f17c402f..31edad14 100644 --- a/test/snapshots/shrinktag.snap +++ b/test/snapshots/shrinktag.snap @@ -1,6 +1,8 @@ -# a pane can shrink to just its tagline: border-drag the handle to the tag row -# (0 body rows), the gutter box still grabs a move, and dragging back down -# restores the body intact (the hidden pane's pty/vt is never resized) +# a pane can shrink to just its tagline: the pane below dragged by its grip up +# to the tag row (0 body rows) -- a terminal has no rule between panes, so +# the grip is the handle, as acme's button is -- the gutter box still grabs a +# move, and dragging back down restores the body intact (the hidden pane's +# pty/vt is never resized) file w.txt x start 31 100 -n 3 wait 8000 w.txt @@ -16,16 +18,15 @@ key esc settle 100 stable 400 5000 snap before -# drag pane 0's bottom handle (its last row) up to its tag row: tag-only pane -press left 20 17 -drag left 20 3 -release left 20 3 +# drag the lower pane's grip up under pane 0's tag row: tag-only pane +press left 1 18 +drag left 1 3 +release left 1 3 motion 40 25 stable 500 8000 snap shrunk -# the shrunk pane's single row is now the pair's resize handle, but the gutter -# box must still win: grab it, preview a move into the right column, abort by -# releasing over the pane itself +# the shrunk pane's gutter box grabs a move: preview one into the right +# column, abort by releasing over the pane itself press left 1 3 drag left 70 9 stable 400 5000 @@ -33,17 +34,17 @@ snap move-preview drag left 20 3 release left 20 3 stable 400 5000 -# re-enlarge: the tag row doubles as the drag handle, pull it back down -press left 20 3 -drag left 20 17 -release left 20 17 +# re-enlarge: the lower pane's grip, now under pane 0's tag, pulled back down +press left 1 4 +drag left 1 18 +release left 1 18 motion 40 25 stable 500 8000 snap restored -# the bottom pane can shrink to ITS tag too: drag past the bottom, clamp holds -press left 20 17 -drag left 20 31 -release left 20 31 +# the bottom pane can shrink to ITS tag too: its grip dragged past the bottom +press left 1 18 +drag left 1 31 +release left 1 31 motion 40 25 stable 500 8000 snap bottom-shrunk diff --git a/test/snapshots/splitparent.snap b/test/snapshots/splitparent.snap index 3ec42b14..b9038af2 100644 --- a/test/snapshots/splitparent.snap +++ b/test/snapshots/splitparent.snap @@ -5,10 +5,11 @@ config Placement pardes start 31 100 -n 3 stable 700 20000 -# shrink pane 0 (top-left) to just its tagline -press left 20 17 -drag left 20 3 -release left 20 3 +# shrink pane 0 (top-left) to just its tagline: the pane below's grip dragged +# up under it (a terminal has no rule between panes; the grip is the handle) +press left 1 18 +drag left 1 3 +release left 1 3 motion 40 25 stable 500 8000 snap shrunk diff --git a/test/snapshots/tagbottom.golden b/test/snapshots/tagbottom.golden index a86bb8fb..d5f1f720 100644 --- a/test/snapshots/tagbottom.golden +++ b/test/snapshots/tagbottom.golden @@ -131,8 +131,8 @@ |27: |30: /tmp/pardes-snap/tagbottom/cwd/bottom.txt Save Tty Collapse Del == snap body-cursor grid=100x31 cursor=9,6 -== snap seam-noop grid=100x31 cursor=9,6 -== snap seam-dragged grid=100x31 cursor=9,6 +== snap seam-noop grid=100x31 cursor=12,16 +== snap seam-dragged grid=100x31 cursor=12,12 |11: /tmp/pardes-snap/tagbottom/cwd/top.txt Save Tty Collapse Del bottom.txt |12: 1 ZZONE |13: 2 ZZTWO diff --git a/test/snapshots/tagbottom.snap b/test/snapshots/tagbottom.snap index a70ace1f..68b79fc7 100644 --- a/test/snapshots/tagbottom.snap +++ b/test/snapshots/tagbottom.snap @@ -67,19 +67,21 @@ press left 10 7 release left 10 7 stable 400 8000 snap body-cursor -# The h-resize seam. With top taglines it is the upper pane's LAST row; here -# that row is the upper pane's TAG, so the handle is the lower pane's FIRST row -# (grid 16, click row 17). A no-drag click on it must leave both sizes alone. +# No row of text is a resize handle: a click on the lower pane's FIRST row +# (grid 16, click row 17), where the seam used to be, is a click in its text, +# and both sizes stay. press left 40 17 release left 40 17 motion 40 25 stable 500 8000 snap seam-noop -# ...and the real drag, four rows up: the upper pane keeps 10 rows, the lower -# grows to 19. Both taglines follow their own pane's bottom. -press left 40 17 -drag left 40 13 -release left 40 13 +# A terminal has no rule between panes, so the grip resizes them, as acme's +# button moves a window: the lower pane's, on its tag at the bottom, dragged up +# to row 13. The upper pane keeps 10 rows, the lower grows to 19. Both +# taglines follow their own pane's bottom. +press left 1 31 +drag left 1 13 +release left 1 13 motion 40 25 stable 500 8000 snap seam-dragged diff --git a/test/snapshots/windowops.golden b/test/snapshots/windowops.golden index 965486d3..38450ac2 100644 --- a/test/snapshots/windowops.golden +++ b/test/snapshots/windowops.golden @@ -112,7 +112,7 @@ |9: |10: |11: -|12: ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ +|12: |13: /tmp/pardes-snap/windowops/cwd Tty+ba |14: sh Save Mode Filter Collapse Del |15: ls @@ -132,7 +132,6 @@ |29: |30: == snap move-preview grid=100x31 cursor=4,17 -|12: == snap moved grid=100x31 cursor=4,17 == snap altn grid=100x31 cursor=4,22 |18: /tmp/pardes-snap/windowops/cwd Tty+ba diff --git a/test/snapshots/windowops.snap b/test/snapshots/windowops.snap index 32d8c83b..8166f663 100644 --- a/test/snapshots/windowops.snap +++ b/test/snapshots/windowops.snap @@ -1,4 +1,4 @@ -# hover resize hints, border drags, move drag, Alt-n, Ctrl-w focus (routed through the Right builtin), Debug box +# hover resize hints, border drags, grip resize, move drag, Alt-n, Ctrl-w focus (routed through the Right builtin), Debug box file w.txt x start 31 100 -n 3 wait 8000 w.txt @@ -7,7 +7,7 @@ stable 700 20000 motion 50 10 stable 400 5000 snap hover-v -# hover over the top-left pane's last row: horizontal dash hint +# hover over the top-left pane's last row: no hint, a row of text is no handle motion 20 16 stable 400 5000 snap hover-h @@ -19,10 +19,11 @@ snap border-drag release left 40 11 stable 500 8000 snap border-done -# drag the horizontal border up 4 rows (pane 0's new last row) -press left 20 17 -drag left 20 13 -release left 20 13 +# resize the left pair by the lower pane's grip, 4 rows up (a terminal has no +# rule between panes; pane 0's last row is now 13) +press left 1 18 +drag left 1 14 +release left 1 14 stable 500 8000 snap hborder-done # move pane 1 (its gutter box) into the right column |
