a73x

545e5683

Fix same-row cursor refresh planning

a73x   2026-04-08 18:30

Commit message
Fix same-row cursor refresh planning

src/main.zig
Old New
@@ -375,6 +375,8 @@ const RowRefreshState = enum {
375 const CursorRefreshContext = struct { 375 const CursorRefreshContext = struct {
376 old_row: ?usize, 376 old_row: ?usize,
377 new_row: ?usize, 377 new_row: ?usize,
378 old_col: ?usize,
379 new_col: ?usize,
378 old_visible: bool, 380 old_visible: bool,
379 new_visible: bool, 381 new_visible: bool,
380 }; 382 };
@@ -414,7 +416,9 @@ fn planRowRefresh(
414 } 416 }
415 417
416 fn cursorNeedsRebuild(cursor: CursorRefreshContext) bool { 418 fn cursorNeedsRebuild(cursor: CursorRefreshContext) bool {
417 return cursor.old_row != cursor.new_row or cursor.old_visible != cursor.new_visible; 419 return cursor.old_row != cursor.new_row or
420 cursor.old_col != cursor.new_col or
421 cursor.old_visible != cursor.new_visible;
418 } 422 }
419 423
420 fn appendCellInstances( 424 fn appendCellInstances(
@@ -531,6 +535,8 @@ test "planRowRefresh requests full rebuild for full dirty state" {
531 .cursor = .{ 535 .cursor = .{
532 .old_row = null, 536 .old_row = null,
533 .new_row = null, 537 .new_row = null,
538 .old_col = null,
539 .new_col = null,
534 .old_visible = false, 540 .old_visible = false,
535 .new_visible = false, 541 .new_visible = false,
536 }, 542 },
@@ -546,6 +552,8 @@ test "planRowRefresh selects only dirty rows for partial state" {
546 .cursor = .{ 552 .cursor = .{
547 .old_row = null, 553 .old_row = null,
548 .new_row = null, 554 .new_row = null,
555 .old_col = null,
556 .new_col = null,
549 .old_visible = false, 557 .old_visible = false,
550 .new_visible = false, 558 .new_visible = false,
551 }, 559 },
@@ -565,6 +573,8 @@ test "planRowRefresh handles cursor-only updates without unrelated rows" {
565 .cursor = .{ 573 .cursor = .{
566 .old_row = 1, 574 .old_row = 1,
567 .new_row = 2, 575 .new_row = 2,
576 .old_col = 4,
577 .new_col = 4,
568 .old_visible = true, 578 .old_visible = true,
569 .new_visible = true, 579 .new_visible = true,
570 }, 580 },
@@ -583,6 +593,8 @@ test "planRowRefresh forces full rebuild when dirty rows exceed fixed capacity"
583 .cursor = .{ 593 .cursor = .{
584 .old_row = null, 594 .old_row = null,
585 .new_row = null, 595 .new_row = null,
596 .old_col = null,
597 .new_col = null,
586 .old_visible = true, 598 .old_visible = true,
587 .new_visible = true, 599 .new_visible = true,
588 }, 600 },
@@ -593,6 +605,23 @@ test "planRowRefresh forces full rebuild when dirty rows exceed fixed capacity"
593 try std.testing.expectEqual(@as(usize, 0), plan.rows_to_rebuild.count()); 605 try std.testing.expectEqual(@as(usize, 0), plan.rows_to_rebuild.count());
594 } 606 }
595 607
608 test "planRowRefresh rebuilds cursor when only column changes on same row" {
609 const plan = planRowRefresh(.partial, &.{ false, false, false }, .{
610 .cursor = .{
611 .old_row = 2,
612 .new_row = 2,
613 .old_col = 1,
614 .new_col = 5,
615 .old_visible = true,
616 .new_visible = true,
617 },
618 });
619
620 try std.testing.expect(!plan.full_rebuild);
621 try std.testing.expect(plan.cursor_rebuild);
622 try std.testing.expectEqual(@as(usize, 0), plan.rows_to_rebuild.count());
623 }
624
596 fn runDrawSmokeTest(alloc: std.mem.Allocator) !void { 625 fn runDrawSmokeTest(alloc: std.mem.Allocator) !void {
597 var conn = try wayland_client.Connection.init(); 626 var conn = try wayland_client.Connection.init();
598 defer conn.deinit(); 627 defer conn.deinit();