summaryrefslogtreecommitdiff
path: root/src/mouse.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/mouse.zig')
-rw-r--r--src/mouse.zig62
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;