9d6c13c8
Add cursor cache rebuild logic
a73x 2026-04-08 19:20
Commit message
src/main.zig
| Old | New | ||
|---|---|---|---|
| @@ -711,6 +711,40 @@ test "repackRowCaches keeps cursor span explicit for empty and non-empty cursor | |||
| 711 | try std.testing.expectEqualDeep([2]f32{ 9.0, 10.0 }, packed_instances.items[2].cell_pos); | 711 | try std.testing.expectEqualDeep([2]f32{ 9.0, 10.0 }, packed_instances.items[2].cell_pos); |
| 712 | } | 712 | } |
| 713 | 713 | ||
| 714 | test "rebuildCursorInstances emits visible cursor instance without changing layout state when count is unchanged" { | ||
| 715 | var cache = RenderCache.empty; | ||
| 716 | defer cache.deinit(std.testing.allocator); | ||
| 717 | |||
| 718 | cache.cursor_instances = try makeTestInstances(std.testing.allocator, 1); | ||
| 719 | cache.cursor_instances.items[0].cell_pos = .{ 99.0, 99.0 }; | ||
| 720 | cache.layout_dirty = false; | ||
| 721 | |||
| 722 | var cursor_instances = try makeTestInstances(std.testing.allocator, 1); | ||
| 723 | defer cursor_instances.deinit(std.testing.allocator); | ||
| 724 | cursor_instances.items[0].cell_pos = .{ 4.0, 7.0 }; | ||
| 725 | |||
| 726 | const rebuilt = try cache.rebuildCursorInstances(std.testing.allocator, cursor_instances.items); | ||
| 727 | |||
| 728 | try std.testing.expect(!rebuilt.len_changed); | ||
| 729 | try std.testing.expectEqual(@as(usize, 1), cache.cursor_instances.items.len); | ||
| 730 | try std.testing.expectEqualDeep([2]f32{ 4.0, 7.0 }, cache.cursor_instances.items[0].cell_pos); | ||
| 731 | try std.testing.expect(!cache.layout_dirty); | ||
| 732 | } | ||
| 733 | |||
| 734 | test "rebuildCursorInstances marks layout dirty when cursor instance count changes" { | ||
| 735 | var cache = RenderCache.empty; | ||
| 736 | defer cache.deinit(std.testing.allocator); | ||
| 737 | |||
| 738 | cache.cursor_instances = try makeTestInstances(std.testing.allocator, 1); | ||
| 739 | cache.layout_dirty = false; | ||
| 740 | |||
| 741 | const rebuilt = try cache.rebuildCursorInstances(std.testing.allocator, &.{}); | ||
| 742 | |||
| 743 | try std.testing.expect(rebuilt.len_changed); | ||
| 744 | try std.testing.expectEqual(@as(usize, 0), cache.cursor_instances.items.len); | ||
| 745 | try std.testing.expect(cache.layout_dirty); | ||
| 746 | } | ||
| 747 | |||
| 714 | test "rebuildRowInstances emits expected instances for a colored glyph row" { | 748 | test "rebuildRowInstances emits expected instances for a colored glyph row" { |
| 715 | var term = try vt.Terminal.init(std.testing.allocator, .{ | 749 | var term = try vt.Terminal.init(std.testing.allocator, .{ |
| 716 | .cols = 80, | 750 | .cols = 80, |
| @@ -1012,6 +1046,23 @@ const RenderCache = struct { | |||
| 1012 | self.total_instance_count = 0; | 1046 | self.total_instance_count = 0; |
| 1013 | self.layout_dirty = true; | 1047 | self.layout_dirty = true; |
| 1014 | } | 1048 | } |
| 1049 | |||
| 1050 | fn rebuildCursorInstances( | ||
| 1051 | self: *RenderCache, | ||
| 1052 | alloc: std.mem.Allocator, | ||
| 1053 | cursor_instances: []const renderer.Instance, | ||
| 1054 | ) !RowRebuildResult { | ||
| 1055 | const old_len = self.cursor_instances.items.len; | ||
| 1056 | self.cursor_instances.clearRetainingCapacity(); | ||
| 1057 | try self.cursor_instances.appendSlice(alloc, cursor_instances); | ||
| 1058 | |||
| 1059 | const len_changed = markLayoutDirtyOnLenChange(old_len, self.cursor_instances.items.len); | ||
| 1060 | if (len_changed) self.layout_dirty = true; | ||
| 1061 | |||
| 1062 | return .{ | ||
| 1063 | .len_changed = len_changed, | ||
| 1064 | }; | ||
| 1065 | } | ||
| 1015 | }; | 1066 | }; |
| 1016 | 1067 | ||
| 1017 | const RowPackResult = struct { | 1068 | const RowPackResult = struct { |