Achievement browser: clamp Stats scroll to content, drain queued key repeats#755
Merged
Merged
Conversation
…repeats Two reported bugs on the redesigned achievement screen: 1. On the Stats tab, a held Down ran the scroll offset far past the content (the input layer allows 100 and only the renderer knew the viewport) — the view stopped moving but every Up had to unwind the invisible excess first. render_stats_view now returns the offset it actually rendered (clamped to last-line-at-bottom) and the browser persists it, so the first Up always moves. Content that fits entirely on screen clamps to zero. Same fix reaches the character-select splash browser, whose Stats tab previously could not scroll at all (its Down handler passed the empty category's count of 0). 2. The game loop processed one key event per ~100ms frame in normal mode while terminal auto-repeat delivers ~25-30/s, so a held arrow queued events that kept replaying after release. The event loop now drains everything already queued before each frame, bounded at 32 events per frame so pasted input cannot starve the tick. Verified live (drive-game): a 30-Down burst settles the instant it stops, one Up scrolls immediately from the clamp, and the splash Stats tab scrolls. Regression test pins the renderer clamp; all snapshots byte-identical. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011F9nMko3AYUQBsrCtPjBKp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes the two bugs reported against the redesigned achievement screen.
Bug 1 — Stats tab scrolls into the void
On the summary (Stats) tab, holding Down ran the scroll offset far past the content: the view stopped moving, but every subsequent Up had to unwind the invisible excess before anything scrolled back. Root cause: the input layer allows up to 100 scroll steps (it can't know the viewport), while the renderer clamped only what it drew and threw the clamp away.
Fix:
render_stats_viewnow returns the offset it actually rendered — clamped so the last content line stops at the bottom of the viewport — and the browser persists it (render_achievement_browsertakes&mutstate). The first Up always moves immediately, and on a terminal tall enough to show everything the offset clamps to zero. The same fix reaches the character-select splash browser, whose Stats tab previously could not scroll at all (its Down handler passed the empty Stats category's count of 0).Bug 2 — held arrow keeps scrolling after release
Keyboard auto-repeat (~25–30 events/s) outran the game loop, which deliberately processed one key event per ~100ms frame in normal mode — so a held arrow built a backlog that kept replaying after the key was released.
Fix: the event loop now drains everything already queued before drawing each frame (matching what realtime-minigame mode always did), bounded at 32 events per frame so pasted input can't starve the tick loop. Non-press events no longer end the drain early.
Verification
stats_overscroll_is_clamped_back_by_the_rendererpins the clamp: overshoot clamps back, one Up moves from the clamp, re-render is a fixed point, tall-terminal clamps to zero.make checkgreen (fmt, clippy, 2908 lib + all integration tests incl.QUEST_ACT2=1 flag_on, progression check, voyage gate, audit).🤖 Generated with Claude Code
https://claude.ai/code/session_011F9nMko3AYUQBsrCtPjBKp
Generated by Claude Code