diff options
Diffstat (limited to 'src/mouse.zig')
| -rw-r--r-- | src/mouse.zig | 62 |
1 files changed, 19 insertions, 43 deletions
diff --git a/src/mouse.zig b/src/mouse.zig index 4b624dca..df657ead 100644 --- a/src/mouse.zig +++ b/src/mouse.zig @@ -2,6 +2,7 @@ //! releases (acme's chords, border and seam drags, gestures), and the //! chrome targets a shell asks about. const pardes = @import("pardes.zig"); +const tagline = @import("tagline.zig"); const exec = @import("exec.zig"); const look = @import("look.zig"); const std = @import("std"); @@ -19,8 +20,7 @@ const pdf = panes.Pdf.pdf; const platform = pardes.platform; const Pane = panes.Pane; const MAX_PANES = pardes.MAX_PANES; -const TagHit = @import("tag_layer.zig").Hit; -const TagKind = @import("tag_layer.zig").Kind; +const tag_layer = @import("tag_layer.zig"); const TOPBAR_H = pardes.TOPBAR_H; const BOX_H = pardes.BOX_H; const TAG_GAP = pardes.TAG_GAP; @@ -176,30 +176,6 @@ pub fn bodyHitForPane(p: *const Pardes, id: usize, supplied: Mouse.BodyHit, clam return p.reprojectBodyHit(mapped_hit); } -pub fn sameTagCell(a: ?TagHit, b: ?TagHit) bool { - const first = a orelse return b == null; - const second = b orelse return false; - return first.kind == second.kind and first.id == second.id and first.serial == second.serial and first.col == second.col; -} - -/// The tag column a host's pointer is at. Clamped, a point off the tag is -/// brought back onto line `line` of it, for a drag that leaves it. -pub fn tagColumn(p: *const Pardes, kind: TagKind, id: usize, supplied: ?TagHit, clamp: bool, line: u16) ?u16 { - var point = supplied orelse return null; - if (point.kind != kind or point.id != id) return null; - if (clamp) for (p.surface.tagLayers()) |*layer| { - if (layer.cols == 0 or layer.kind != kind or layer.id != id or layer.serial != point.serial or layer.line != line) continue; - const bw: f32 = @floatFromInt(point.metrics.body_w); - const bh: f32 = @floatFromInt(point.metrics.body_h); - const left = @as(f32, @floatFromInt(layer.viewport.x)) * bw; - const right = @as(f32, @floatFromInt(layer.viewport.x + layer.viewport.w)) * bw; - point.pixel_x = std.math.clamp(point.pixel_x, left, @max(left, right - 0.001)); - point.pixel_y = (@as(f32, @floatFromInt(layer.viewport.y)) + 0.5) * bh; - break; - }; - return if (p.reprojectTagHit(point)) |mapped| mapped.col else null; -} - pub fn sameBodyCell(a: ?Mouse.BodyHit, b: ?Mouse.BodyHit) bool { const first = a orelse return b == null; const second = b orelse return false; @@ -294,7 +270,7 @@ pub fn handleMouse(p: *Pardes, m: Mouse) void { } } if (p.header_drag and m.button == config.select_button and (m.kind == .drag or m.kind == .release)) { - const t = p.focusedHeader() orelse { + const t = tagline.focusedHeader(p) orelse { p.header_drag = false; return; }; @@ -303,7 +279,7 @@ pub fn handleMouse(p: *Pardes, m: Mouse) void { 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)); const bar = modal.lineSlice(text, line); - const at = @min(bar.len, panes.File.rawAtDisplay(bar, (tagColumn(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, line) orelse (mcol -| x)) + p.header_scroll)); // the anchor stays where the press put it t.cur_row = line; t.cur_col = @intCast(at); @@ -338,23 +314,23 @@ pub fn handleMouse(p: *Pardes, m: Mouse) void { 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, (tagColumn(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, line) orelse (mcol -| x)) + scroll)); if (m.button == config.select_button) { // A clicked header is typed straight into, as a clicked tag is. - if (!focused) p.enterHeader(column); + if (!focused) tagline.enterHeader(p, column); t.mode = .insert; t.cur_row = line; t.cur_col = @intCast(at); t.vsel = .{ .active = false, .row = line, .col = @intCast(at) }; p.header_drag = true; } else { - const span = if (focused) Pardes.headerSelection(t, text, line) else null; + const span = if (focused) tagline.headerSelection(t, text, line) else null; const selected = if (span) |sp| (if (at >= sp.lo and at < sp.hi) bar[sp.lo..sp.hi] else wordAtCol(bar, at)) else wordAtCol(bar, at); const word = p.scratch.allocator().dupe(u8, selected) catch return; - p.exitHeader(); + tagline.exitHeader(p); if (word.len > 0) { if (m.button == config.exec_button) { const named = std.meta.stringToEnum(Builtin, word); @@ -366,7 +342,7 @@ pub fn handleMouse(p: *Pardes, m: Mouse) void { return; } if (m.kind == .press) { - p.exitHeader(); + tagline.exitHeader(p); } switch (m.button) { @@ -484,7 +460,7 @@ pub fn handleMouse(p: *Pardes, m: Mouse) void { pane.tag.msel.active = false; pane.tag.nsel = 0; pane.tag.cur_pinned = true; - const at = p.tagOffsetAt(pane, @intCast(@max(0, pointed.sel.r0)), @intCast(@max(0, pointed.sel.c0))) orelse modal.Cursor{ .row = 0, .col = 0 }; + const at = tagline.tagOffsetAt(p, pane, @intCast(@max(0, pointed.sel.r0)), @intCast(@max(0, pointed.sel.c0))) orelse modal.Cursor{ .row = 0, .col = 0 }; pane.tag.cur_row = @intCast(at.row); pane.tag.cur_col = @intCast(at.col); } @@ -626,7 +602,7 @@ pub fn dragUpdate(p: *Pardes, mcol: u16, mrow: u16, body_hit: ?Mouse.BodyHit) vo // nearest the pointer. const tag_y = p.tagTop(pane, r); const tag_line: u16 = @intCast(std.math.clamp(@as(i32, mrow) - @as(i32, tag_y), 0, tag_rows - 1)); - if (pane.sel[b].r0 < tag_rows) if (tagColumn(p, .pane, s.id, p.pointer_tag_hit, true, tag_line)) |value| { + if (pane.sel[b].r0 < tag_rows) if (tag_layer.columnAt(p, .pane, s.id, p.pointer_tag_hit, true, tag_line)) |value| { pane.sel[b].c1 = @as(i32, value) + pane.tag_scroll; pane.sel[b].r1 = tag_line; return; @@ -683,7 +659,7 @@ fn reportGesture( fn gestureRange(p: *Pardes, id: usize, text: []const u8, on_tag: bool, operand: exec.PointerOperand) ctlfs.pane.State.Range { const pane = p.panes[id] orelse return .{}; if (on_tag) { - const tag = p.tagText(p.scratch.allocator(), pane) catch return .{}; + 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)); @@ -847,11 +823,11 @@ fn dragRelease(p: *Pardes, button: Mouse.Button) void { if (sl.r0 < pane.tag_rows) { // On the tag the caret goes where the button came up. A // click on the path, if it can be renamed, drafts a name. - const at = p.tagOffsetAt(pane, @intCast(@max(0, sl.r1)), @intCast(@max(0, sl.c1))); + const at = tagline.tagOffsetAt(p, pane, @intCast(@max(0, sl.r1)), @intCast(@max(0, sl.c1))); if (at) |cursor| { pane.tag.cur_row = @intCast(cursor.row); pane.tag.cur_col = @intCast(cursor.col); - } else if (!dragged) p.draftName(pane, @intCast(@max(0, sl.c1))); + } else if (!dragged) tagline.draftName(p, pane, @intCast(@max(0, sl.c1))); return; } if (dragged) edit.capturePointerSelection(p, pane, sel_slot) catch {}; @@ -908,13 +884,13 @@ fn dragRelease(p: *Pardes, button: Mouse.Button) void { const txt = operand.text; const cmd = if (s.button == config.look_button) config.look_cmd else config.exec_cmd; if (clk.r0 == 0 and s.button == config.exec_button and pane.prompt == .name) { - const prefix_width = panes.File.displayWidth(p.tagPrefix(pane) catch return); + const prefix_width = panes.File.displayWidth(tagline.tagPrefix(p, pane) catch return); const on_name = @as(usize, @intCast(@max(0, clk.c0))) < prefix_width; - if (!p.commitTagName(pane)) return; + if (!tagline.commitTagName(p, pane)) return; // Executing a staged filename commits it; executing its // command tail uses the new identity (especially Save). if (on_name) return; - const new_width = panes.File.displayWidth(p.tagPrefix(pane) catch return); + const new_width = panes.File.displayWidth(tagline.tagPrefix(p, pane) catch return); const shift = @as(i32, @intCast(new_width)) - @as(i32, @intCast(prefix_width)); if (operand.expanded) |*sel| { sel.c0 += shift; @@ -962,8 +938,8 @@ fn chordCutPaste(p: *Pardes, cut: bool) void { const start = if (forward) .{ sl.r0, sl.c0 } else .{ sl.r1, sl.c1 }; const end = if (forward) .{ sl.r1, sl.c1 } else .{ sl.r0, sl.c0 }; const origin: modal.Cursor = .{ .row = 0, .col = 0 }; - const from = p.tagOffsetAt(pane, @intCast(@max(0, start[0])), @intCast(@max(0, start[1]))) orelse origin; - const to = p.tagOffsetAt(pane, @intCast(@max(0, end[0])), @intCast(@max(0, end[1]))) orelse origin; + const from = tagline.tagOffsetAt(p, pane, @intCast(@max(0, start[0])), @intCast(@max(0, start[1]))) orelse origin; + const to = tagline.tagOffsetAt(p, pane, @intCast(@max(0, end[0])), @intCast(@max(0, end[1]))) orelse origin; t.cur_row = @intCast(to.row); t.cur_col = @intCast(to.col); t.cur_pinned = true; |
