summaryrefslogtreecommitdiff
path: root/src/mouse.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-28 01:01:35 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:14 -0300
commit9d2e07e997de155c7dbb894a79e5c11839eab39e (patch)
tree45d09fbe224693b2b9426213e59e56d5b1f35224 /src/mouse.zig
parent425d9beb9c977df364ed83743cb2efdef9429478 (diff)
downloadpardes-9d2e07e997de155c7dbb894a79e5c11839eab39e.tar.gz
pardes-9d2e07e997de155c7dbb894a79e5c11839eab39e.zip
Scroll a tag taller than its rows to keep its caret in view
A tag shows at most eight rows, so a longer one (a 9P write of many lines, or `o` in the tag) put its caret on a line that was never drawn. Pane, column and workspace tags now keep a first line on screen that follows the caret while they have the keyboard, and the pointer and the pane text count their rows from it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/mouse.zig')
-rw-r--r--src/mouse.zig16
1 files changed, 10 insertions, 6 deletions
diff --git a/src/mouse.zig b/src/mouse.zig
index df657ead..69feea29 100644
--- a/src/mouse.zig
+++ b/src/mouse.zig
@@ -276,10 +276,13 @@ pub fn handleMouse(p: *Pardes, m: Mouse) void {
};
const x = if (p.header_column) |c| p.col_x[c] + TAG_TEXT_INSET else 0;
const text = edit.flatSurface(p, t) catch return;
- const top = if (p.header_column != null) p.topBarHeight() else 0;
- const line: u16 = @intCast(@min(mrow -| top, modal.lineCount(text) -| 1, (if (p.header_column != null) p.columnBarHeight() else p.topBarHeight()) -| 1));
+ // `row` is the header's row on screen, `line` the line of its text
+ // shown there.
+ const base = if (p.header_column != null) p.topBarHeight() else 0;
+ const row: u16 = @intCast(@min(mrow -| base, (if (p.header_column != null) p.columnBarHeight() else p.topBarHeight()) -| 1));
+ const line: u16 = @intCast(@min(row + p.header_top, modal.lineCount(text) -| 1));
const bar = modal.lineSlice(text, line);
- const at = @min(bar.len, panes.File.rawAtDisplay(bar, (tag_layer.columnAt(p, if (p.header_column != null) .column else .workspace, p.header_column orelse 0, p.pointer_tag_hit, p.header_drag, line) orelse (mcol -| x)) + p.header_scroll));
+ const at = @min(bar.len, panes.File.rawAtDisplay(bar, (tag_layer.columnAt(p, if (p.header_column != null) .column else .workspace, p.header_column orelse 0, p.pointer_tag_hit, p.header_drag, row) orelse (mcol -| x)) + p.header_scroll));
// the anchor stays where the press put it
t.cur_row = line;
t.cur_col = @intCast(at);
@@ -310,11 +313,12 @@ pub fn handleMouse(p: *Pardes, m: Mouse) void {
const t = if (column) |c| &p.col_tags[c] else &p.global_tag;
const focused = p.header_focus and p.header_column == column;
const text = edit.flatSurface(p, t) catch return;
- const line: u16 = @intCast(mrow - if (column != null) p.topBarHeight() else 0);
+ const row: u16 = @intCast(mrow - if (column != null) p.topBarHeight() else 0);
+ const line: u16 = @intCast(row + if (focused) p.header_top else 0);
if (line > 0 and line >= modal.lineCount(text)) return;
const bar = modal.lineSlice(text, line);
const scroll = if (focused) p.header_scroll else 0;
- const at = @min(bar.len, panes.File.rawAtDisplay(bar, (tag_layer.columnAt(p, if (column != null) .column else .workspace, column orelse 0, p.pointer_tag_hit, p.header_drag, line) orelse (mcol -| x)) + scroll));
+ const at = @min(bar.len, panes.File.rawAtDisplay(bar, (tag_layer.columnAt(p, if (column != null) .column else .workspace, column orelse 0, p.pointer_tag_hit, p.header_drag, row) orelse (mcol -| x)) + scroll));
if (m.button == config.select_button) {
// A clicked header is typed straight into, as a clicked tag is.
if (!focused) tagline.enterHeader(p, column);
@@ -662,7 +666,7 @@ fn gestureRange(p: *Pardes, id: usize, text: []const u8, on_tag: bool, operand:
const tag = tagline.tagText(p, p.scratch.allocator(), pane) catch return .{};
const sel = operand.expanded orelse operand.preview orelse return .{};
const lead = if (sel.r0 < sel.r1 or (sel.r0 == sel.r1 and sel.c0 <= sel.c1)) sel else Pane.Sel{ .r0 = sel.r1, .c0 = sel.c1 };
- const row: usize = @intCast(@max(0, lead.r0));
+ const row: usize = @as(usize, @intCast(@max(0, lead.r0))) + pane.tag_top;
const start = modal.lineStartOffset(tag, row);
const at = start + panes.File.rawAtDisplay(modal.lineSlice(tag, row), @intCast(@max(0, lead.c0)));
const q0: u32 = @intCast(@min(at, tag.len));