diff --git a/src/tui/editor.zig b/src/tui/editor.zig index 6ca52e2..2c995d7 100644 --- a/src/tui/editor.zig +++ b/src/tui/editor.zig @@ -848,7 +848,6 @@ pub const Editor = struct { self.buffer = null; self.plane.erase(); self.plane.home(); - tui.rdr().cursor_disable(); _ = try self.handlers.msg(.{ "E", "close" }); if (self.syntax) |_| if (self.file_path) |file_path| project_manager.did_close(file_path) catch {}; @@ -1285,8 +1284,7 @@ pub const Editor = struct { const cursor = cursel.cursor; try self.render_cursor_secondary(&cursor, theme, cell_map, focused); }; - const cursor = self.get_primary().cursor; - try self.render_cursor_primary(&cursor, theme, cell_map, focused); + try self.render_cursor_primary(&self.get_primary().cursor, theme, cell_map, focused); } fn render_cursor_primary(self: *Self, cursor: *const Cursor, theme: *const Widget.Theme, cell_map: CellMap, focused: bool) !void { @@ -1300,36 +1298,46 @@ pub const Editor = struct { .underline_blink => .block_blink, else => configured_shape, } else configured_shape; - if (self.screen_cursor(cursor)) |pos| { - set_cell_map_cursor(cell_map, pos.row, pos.col); - if (!focused or !tui.is_mainview_focused() or !self.enable_terminal_cursor) { - self.plane.cursor_move_yx(@intCast(pos.row), @intCast(pos.col)); - const style = if (focused and tui.is_mainview_focused()) theme.editor_cursor else theme.editor_cursor_secondary; - self.render_cursor_cell(style); - } else { - const y, const x = self.plane.rel_yx_to_abs(@intCast(pos.row), @intCast(pos.col)); - tui.rdr().set_terminal_cursor_color(theme.editor_cursor.bg.?); - tui.rdr().cursor_enable(y, x, cursor_shape) catch {}; + const screen_pos = self.screen_cursor(cursor); + if (screen_pos) |pos| set_cell_map_cursor(cell_map, pos.row, pos.col); + + if (focused and self.enable_terminal_cursor) { + if (screen_pos) |pos| { + self.render_term_cursor(pos, cursor_shape); + } else if (tui.is_mainview_focused() and tui.rdr().vx.caps.multi_cursor and self.has_secondary_cursors()) { + self.hide_term_cursor(theme.statusbar.bg.?, cursor_shape); } - } else { - if (focused and self.enable_terminal_cursor) { - tui.rdr().set_terminal_cursor_color(theme.statusbar.bg.?); - tui.rdr().cursor_enable(-1, -1, cursor_shape) catch {}; - } - } + } else if (screen_pos) |pos| + self.render_soft_cursor(pos, if (focused) theme.editor_cursor else theme.editor_cursor_secondary); } fn render_cursor_secondary(self: *Self, cursor: *const Cursor, theme: *const Widget.Theme, cell_map: CellMap, focused: bool) !void { - if (self.screen_cursor(cursor)) |pos| { - set_cell_map_cursor(cell_map, pos.row, pos.col); - if (!focused or !tui.is_mainview_focused() or !self.enable_terminal_cursor or !tui.rdr().vx.caps.multi_cursor) { - self.plane.cursor_move_yx(@intCast(pos.row), @intCast(pos.col)); - self.render_cursor_cell(theme.editor_cursor_secondary); - } else { - const y, const x = self.plane.rel_yx_to_abs(@intCast(pos.row), @intCast(pos.col)); - tui.rdr().show_multi_cursor_yx(y, x) catch return; - } - } + const pos = self.screen_cursor(cursor) orelse return; + set_cell_map_cursor(cell_map, pos.row, pos.col); + if (focused and self.enable_terminal_cursor and tui.rdr().vx.caps.multi_cursor) + self.render_term_cursor_secondary(pos) + else + self.render_soft_cursor(pos, theme.editor_cursor_secondary); + } + + inline fn render_term_cursor(self: *Self, pos: Cursor, shape: anytype) void { + const y, const x = self.plane.rel_yx_to_abs(@intCast(pos.row), @intCast(pos.col)); + tui.rdr().cursor_enable(y, x, shape) catch {}; + } + + inline fn render_term_cursor_secondary(self: *Self, pos: Cursor) void { + const y, const x = self.plane.rel_yx_to_abs(@intCast(pos.row), @intCast(pos.col)); + tui.rdr().show_multi_cursor_yx(y, x) catch return; + } + + inline fn hide_term_cursor(_: *Self, color: Widget.Theme.Color, shape: anytype) void { + tui.rdr().set_terminal_cursor_color(color); + tui.rdr().cursor_enable(-1, -1, shape) catch {}; + } + + inline fn render_soft_cursor(self: *Self, pos: Cursor, style: Widget.Theme.Style) void { + self.plane.cursor_move_yx(@intCast(pos.row), @intCast(pos.col)); + self.render_cursor_cell(style); } inline fn render_cursor_cell(self: *Self, style: Widget.Theme.Style) void { @@ -7050,7 +7058,7 @@ pub const EditorWidget = struct { } pub fn render(self: *Self, theme: *const Widget.Theme) bool { - return self.editor.render(theme, self.focused); + return self.editor.render(theme, self.focused and tui.is_mainview_focused()); } pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool { diff --git a/src/tui/tui.zig b/src/tui/tui.zig index fa79a67..7c816e3 100644 --- a/src/tui/tui.zig +++ b/src/tui/tui.zig @@ -637,7 +637,13 @@ fn render(self: *Self) void { const frame = tracy.initZone(@src(), .{ .name = "tui render" }); defer frame.deinit(); self.rdr_.stdplane().erase(); - const continue_mainview = if (self.mainview_) |mv| mv.render(self.current_theme()) else false; + const theme_ = self.current_theme(); + if (self.config_.enable_terminal_cursor) { + self.rdr_.cursor_disable(); + if (self.rdr_.vx.caps.multi_cursor) self.rdr_.clear_all_multi_cursors() catch {}; + self.rdr_.set_terminal_cursor_color(theme_.editor_cursor.bg.?); + } + const continue_mainview = if (self.mainview_) |mv| mv.render(theme_) else false; switch (self.hint_mode) { .prefix => if (self.config_.enable_prefix_keyhints) @@ -1403,7 +1409,6 @@ const cmds = struct { pub const change_fontface_meta: Meta = .{ .description = "Change font" }; pub fn exit_overlay_mode(self: *Self, _: Ctx) Result { - self.rdr_.cursor_disable(); if (self.input_mode_outer_ == null) return enter_mode_default(self, .{}); if (self.input_mode_) |*mode| mode.deinit(); self.input_mode_ = self.input_mode_outer_; @@ -1514,7 +1519,6 @@ const cmds = struct { } pub fn exit_mini_mode(self: *Self, _: Ctx) Result { - self.rdr_.cursor_disable(); if (self.mini_mode_) |_| {} else return; if (self.input_mode_) |*mode| mode.deinit(); self.input_mode_ = self.input_mode_outer_;