Since #83 the loop commits the device layer once per frame (input_drive), but a game that ALSO called Input.poll by hand committed a second time in the same frame; input_device_commit copies in_held into in_prev at the top of every commit, so the second commit left in_prev == in_held and the edges (held && !prev) could never see a transition. Fix: an in_have_frame_driver flag. The loop's input_drive sets it; a manual Input.poll under the loop then becomes a no-op returning the frame's key instead of re-committing. An entry-driven harness has no loop, so the flag stays false and each Input.poll commits a frame as before (the #7/#50 record/replay + device tests are unchanged). Frame loop now calls input_drive. Example input_edge (press edge on the down frame, release edge on the up frame). Full suite 110/0, goldens byte-identical, fixpoint holds. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
994 B
bump: patch
type: fix
Input.key_pressed / key_released edges now fire (#87). In a frame-loop game the edges never triggered: the loop (since #83) commits the device layer once per frame via input_drive, but a game that also called Input.poll by hand committed a second time in the same frame, and input_device_commit copies in_held into in_prev at the top of every commit — so the second commit left in_prev == in_held and key_pressed (held && !prev) / key_released could never see a transition. Fixed with an in_have_frame_driver flag: the loop's input_drive sets it, and a manual Input.poll under the loop becomes a no-op that returns the frame's key instead of re-committing. An entry-driven harness has no loop, so the flag stays false and each Input.poll still commits a frame of input as before (record/replay and the #50 device tests are unchanged). Example: examples/library/input_edge.ludic (press edge on the down frame, release edge on the up frame).