e0e1171e
main: widen computePollTimeoutMs to accept a second deadline
a73x 2026-04-19 07:00
Commit message
src/main.zig
| Old | New | ||
|---|---|---|---|
| @@ -341,7 +341,8 @@ fn runTerminal(alloc: std.mem.Allocator) !void { | |||
| 341 | 341 | ||
| 342 | while (!window.should_close and p.isChildAlive()) { | 342 | while (!window.should_close and p.isChildAlive()) { |
| 343 | const repeat_timeout_ms = remainingRepeatTimeoutMs(keyboard.nextRepeatDeadlineNs()); | 343 | const repeat_timeout_ms = remainingRepeatTimeoutMs(keyboard.nextRepeatDeadlineNs()); |
| 344 | const timeout = computePollTimeoutMs(repeat_timeout_ms, render_pending); | 344 | // Blink deadline wired up in Task 4; null for now. |
| 345 | const timeout = computePollTimeoutMs(repeat_timeout_ms, null, render_pending); | ||
| 345 | try frame_loop.waitForWork(&pollfds_extra, timeout); | 346 | try frame_loop.waitForWork(&pollfds_extra, timeout); |
| 346 | 347 | ||
| 347 | // PTY output | 348 | // PTY output |
| @@ -788,9 +789,17 @@ fn remainingRepeatTimeoutMs(deadline_ns: ?i128) ?i32 { | |||
| 788 | return @intCast(@divTrunc(remaining_ns + std.time.ns_per_ms - 1, std.time.ns_per_ms)); | 789 | return @intCast(@divTrunc(remaining_ns + std.time.ns_per_ms - 1, std.time.ns_per_ms)); |
| 789 | } | 790 | } |
| 790 | 791 | ||
| 791 | fn computePollTimeoutMs(next_repeat_in_ms: ?i32, render_pending: bool) i32 { | 792 | fn computePollTimeoutMs( |
| 793 | next_repeat_in_ms: ?i32, | ||
| 794 | next_blink_in_ms: ?i32, | ||
| 795 | render_pending: bool, | ||
| 796 | ) i32 { | ||
| 792 | if (render_pending) return 0; | 797 | if (render_pending) return 0; |
| 793 | return next_repeat_in_ms orelse -1; | 798 | if (next_repeat_in_ms) |r| { |
| 799 | if (next_blink_in_ms) |b| return if (r < b) r else b; | ||
| 800 | return r; | ||
| 801 | } | ||
| 802 | return next_blink_in_ms orelse -1; | ||
| 794 | } | 803 | } |
| 795 | 804 | ||
| 796 | fn extractSelectedText( | 805 | fn extractSelectedText( |
| @@ -1627,10 +1636,26 @@ fn mapKeysymToInputKey(keysym: u32) ?vt.InputKey { | |||
| 1627 | }; | 1636 | }; |
| 1628 | } | 1637 | } |
| 1629 | 1638 | ||
| 1630 | test "event loop waits indefinitely when idle and wakes for imminent repeat" { | 1639 | test "computePollTimeoutMs: idle with no deadlines returns -1" { |
| 1631 | try std.testing.expectEqual(@as(i32, -1), computePollTimeoutMs(null, false)); | 1640 | try std.testing.expectEqual(@as(i32, -1), computePollTimeoutMs(null, null, false)); |
| 1632 | try std.testing.expectEqual(@as(i32, 0), computePollTimeoutMs(5, true)); | 1641 | } |
| 1633 | try std.testing.expectEqual(@as(i32, 17), computePollTimeoutMs(17, false)); | 1642 | |
| 1643 | test "computePollTimeoutMs: render_pending forces zero regardless of deadlines" { | ||
| 1644 | try std.testing.expectEqual(@as(i32, 0), computePollTimeoutMs(5, null, true)); | ||
| 1645 | try std.testing.expectEqual(@as(i32, 0), computePollTimeoutMs(null, 5, true)); | ||
| 1646 | try std.testing.expectEqual(@as(i32, 0), computePollTimeoutMs(3, 7, true)); | ||
| 1647 | try std.testing.expectEqual(@as(i32, 0), computePollTimeoutMs(null, null, true)); | ||
| 1648 | } | ||
| 1649 | |||
| 1650 | test "computePollTimeoutMs: single deadline passes through" { | ||
| 1651 | try std.testing.expectEqual(@as(i32, 17), computePollTimeoutMs(17, null, false)); | ||
| 1652 | try std.testing.expectEqual(@as(i32, 500), computePollTimeoutMs(null, 500, false)); | ||
| 1653 | } | ||
| 1654 | |||
| 1655 | test "computePollTimeoutMs: returns min of two deadlines" { | ||
| 1656 | try std.testing.expectEqual(@as(i32, 17), computePollTimeoutMs(17, 500, false)); | ||
| 1657 | try std.testing.expectEqual(@as(i32, 17), computePollTimeoutMs(500, 17, false)); | ||
| 1658 | try std.testing.expectEqual(@as(i32, 7), computePollTimeoutMs(7, 7, false)); | ||
| 1634 | } | 1659 | } |
| 1635 | 1660 | ||
| 1636 | test "planRowRefresh requests full rebuild for full dirty state" { | 1661 | test "planRowRefresh requests full rebuild for full dirty state" { |