From dd042e2fdd8133e251ae253e6595725229ae66e2 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Fri, 3 Jan 2025 13:52:47 +0100 Subject: [PATCH] feat: position cursor at closest glyph boundary on click when beam cursor is enabled closes #99 --- src/renderer/vaxis/Plane.zig | 11 +++++++++++ src/tui/editor.zig | 23 +++++++++++++++-------- src/tui/tui.zig | 7 +++++++ 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/renderer/vaxis/Plane.zig b/src/renderer/vaxis/Plane.zig index cac38b3..702103f 100644 --- a/src/renderer/vaxis/Plane.zig +++ b/src/renderer/vaxis/Plane.zig @@ -89,6 +89,17 @@ pub inline fn dim_x(self: Plane) c_uint { return @intCast(self.window.width); } +pub fn abs_yx_to_rel_nearest_x(self: Plane, y: c_int, x: c_int, xoffset: c_int) struct { c_int, c_int } { + if (self.window.screen.width == 0 or self.window.screen.height == 0) return self.abs_yx_to_rel(y, x); + const xextra = self.window.screen.width_pix % self.window.screen.width; + const xcell = (self.window.screen.width_pix - xextra) / self.window.screen.width; + if (xcell == 0) + return self.abs_yx_to_rel(y, x); + if (xoffset > xcell / 2) + return self.abs_yx_to_rel(y, x + 1); + return self.abs_yx_to_rel(y, x); +} + pub fn abs_yx_to_rel(self: Plane, y: c_int, x: c_int) struct { c_int, c_int } { return .{ y - self.abs_y(), x - self.abs_x() }; } diff --git a/src/tui/editor.zig b/src/tui/editor.zig index 0a93699..fe47e7b 100644 --- a/src/tui/editor.zig +++ b/src/tui/editor.zig @@ -4687,8 +4687,15 @@ pub const EditorWidget = struct { })(self, y, x, ypx, xpx); } - fn mouse_click_button1(self: *Self, y: c_int, x: c_int, _: c_int, _: c_int) Result { - const y_, const x_ = self.editor.plane.abs_yx_to_rel(y, x); + fn mouse_pos_abs(self: *Self, y: c_int, x: c_int, xoffset: c_int) struct { c_int, c_int } { + return if (tui.current().is_cursor_beam()) + self.editor.plane.abs_yx_to_rel_nearest_x(y, x, xoffset) + else + self.editor.plane.abs_yx_to_rel(y, x); + } + + fn mouse_click_button1(self: *Self, y: c_int, x: c_int, _: c_int, xoffset: c_int) Result { + const y_, const x_ = self.mouse_pos_abs(y, x, xoffset); if (self.last_btn == input.mouse.BUTTON1) { const click_time_ms = time.milliTimestamp() - self.last_btn_time_ms; if (click_time_ms <= double_click_time_ms) { @@ -4707,8 +4714,8 @@ pub const EditorWidget = struct { return; } - fn mouse_drag_button1(self: *Self, y: c_int, x: c_int, _: c_int, _: c_int) Result { - const y_, const x_ = self.editor.plane.abs_yx_to_rel(y, x); + fn mouse_drag_button1(self: *Self, y: c_int, x: c_int, _: c_int, xoffset: c_int) Result { + const y_, const x_ = self.mouse_pos_abs(y, x, xoffset); self.editor.primary_drag(y_, x_); } @@ -4716,13 +4723,13 @@ pub const EditorWidget = struct { fn mouse_drag_button2(_: *Self, _: c_int, _: c_int, _: c_int, _: c_int) Result {} - fn mouse_click_button3(self: *Self, y: c_int, x: c_int, _: c_int, _: c_int) Result { - const y_, const x_ = self.editor.plane.abs_yx_to_rel(y, x); + fn mouse_click_button3(self: *Self, y: c_int, x: c_int, _: c_int, xoffset: c_int) Result { + const y_, const x_ = self.mouse_pos_abs(y, x, xoffset); try self.editor.secondary_click(y_, x_); } - fn mouse_drag_button3(self: *Self, y: c_int, x: c_int, _: c_int, _: c_int) Result { - const y_, const x_ = self.editor.plane.abs_yx_to_rel(y, x); + fn mouse_drag_button3(self: *Self, y: c_int, x: c_int, _: c_int, xoffset: c_int) Result { + const y_, const x_ = self.mouse_pos_abs(y, x, xoffset); try self.editor.secondary_drag(y_, x_); } diff --git a/src/tui/tui.zig b/src/tui/tui.zig index d14594e..be9945e 100644 --- a/src/tui/tui.zig +++ b/src/tui/tui.zig @@ -1119,3 +1119,10 @@ pub fn get_cursor_shape(self: *Self) renderer.CursorShape { .beam => .beam, }; } + +pub fn is_cursor_beam(self: *Self) bool { + return switch (self.get_cursor_shape()) { + .beam, .beam_blink => true, + else => false, + }; +}