summaryrefslogtreecommitdiff
path: root/src/tty/tty.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/tty/tty.zig')
-rw-r--r--src/tty/tty.zig24
1 files changed, 22 insertions, 2 deletions
diff --git a/src/tty/tty.zig b/src/tty/tty.zig
index f0f41747..ca2cb939 100644
--- a/src/tty/tty.zig
+++ b/src/tty/tty.zig
@@ -2466,14 +2466,34 @@ fn mouseEvent(m: vaxis.Mouse) ?pardes.Event {
.motion => .motion,
.drag => .drag,
},
- .col = @intCast(m.col),
- .row = @intCast(m.row),
+ .col = cellOf(m.col),
+ .row = cellOf(m.row),
.ctrl = m.mods.ctrl,
.shift = m.mods.shift,
.alt = m.mods.alt,
} };
}
+/// A report's cell, 0-based: one before the first (SGR's 0, a drag past
+/// the window's top or left edge, in cells or in 1016's pixels) is the
+/// first, never a panic; past the far edge the core clamps it.
+pub fn cellOf(v: i16) u16 {
+ return @intCast(@max(0, v));
+}
+
+test "a mouse report at row or column 0, or before it, is the window's edge, never a panic" {
+ const p = try pardes.Pardes.init(std.testing.allocator, .{ .tty_only = true });
+ defer p.deinit();
+ for ([_][]const u8{ "\x1b[<1;42;0M", "\x1b[<0;0;5M", "\x1b[<32;0;0M", "\x1b[<0;0;0m" }) |sequence| {
+ var parser: vaxis.Parser = .{};
+ const result = try parser.parse(sequence, std.testing.allocator);
+ const m = result.event.?.mouse;
+ const event = mouseEvent(m) orelse continue;
+ try std.testing.expect(event.mouse.col <= 41 and event.mouse.row <= 4);
+ p.update(event);
+ }
+}
+
test "a mouse's side buttons, xterm's 8 and 9, are Back and Forward, as SDL's X1 and X2 are" {
for ([_]vaxis.Mouse.Button{ .button_8, .button_9 }, [_]pardes.Mouse.Button{ .back, .forward }) |from, to| {
const event = mouseEvent(.{ .col = 3, .row = 2, .button = from, .mods = .{}, .type = .press }).?;