fix(view): drop non-Press key events to fix Windows TUI double-dispatch#222
Merged
Merged
Conversation
On Windows the crossterm console backend delivers both Press and Release (and Repeat) KeyEventKind variants for every keystroke. The TUI's terminal reader was forwarding every Event::Key it read, and the two dispatch sites in ui_loop.rs called handle_key_event without inspecting KeyEventKind. Toggle bindings (h/1 Help, A alerts, M topology mode, sort keys, T/V tab jumps) therefore fired on Press and then immediately undid themselves on Release, producing the "flash" symptom and making the TUI effectively unusable on Windows. Fix at the single chokepoint where terminal events are read so both the live next_event() path and the drain_pending_events() batch path are protected by one guard. Extract the predicate into a small testable helper (is_actionable_key_event) and add regression tests verifying that Release/Repeat events are filtered, Press events still flow, and non-key events (Resize) are not gated. Unix terminals already deliver only Press kinds without the keyboard-enhancement flags (which all-smi does not enable), so this is a no-op there. Closes #212
inureyes
added a commit
that referenced
this pull request
May 24, 2026
Refs #221, #222, #224, #225, #226, #227. Align config path active discovery with the implicit loader's first-existing-candidate semantics, correct record output help and resolver docs against the binary default, and make the swap-color regression test derive crossterm's current Red SGR sequence instead of hard-coding older encodings.
inureyes
added a commit
that referenced
this pull request
May 24, 2026
Refs #221, #222, #224, #225, #226, #227. Align config path active discovery with the implicit loader's first-existing-candidate semantics, correct record output help and resolver docs against the binary default, and make the swap-color regression test derive crossterm's current Red SGR sequence instead of hard-coding older encodings.
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.
Summary
On Windows the crossterm console backend delivers both
PressandRelease(andRepeat)KeyEventKindvariants for every keystroke. The TUI's terminal reader was forwarding everyEvent::Keyit read, and the two dispatch sites inui_loop.rscalledhandle_key_eventwithout inspectingKeyEventKind. Toggle bindings (h/1Help,Aalerts,Mtopology mode, sort keys,T/Vtab jumps) therefore fired onPressand then immediately undid themselves onRelease— the "flash" symptom that made the TUI effectively unusable on Windows.Root cause
crosstermreports keyboard events differently per platform:KeyEventKind::Pressis delivered. Holding a key produces repeatedPressvia the terminal's own auto-repeat.ReleaseandRepeat.A single
hpress on Windows therefore producedPress→show_help = true, thenRelease→show_help = false. Net effect: the help page appeared and instantly disappeared.Fix
Filter at the single chokepoint in
src/view/ui_events.rs::terminal_reader_loopso both consumers — the livenext_event()path and thedrain_pending_events()batch path — are protected by one guard. The predicate is extracted into a smallis_actionable_key_event(KeyEventKind) -> boolhelper so it is unit-testable without a live terminal.No change in
src/view/event_handler.rs— its dispatch logic is already correct onceReleaseis filtered upstream. The change is a no-op on Unix.Test plan
cargo fmt --checkcargo check --lib --testscargo clippy --lib --tests -- -D warningscargo test --bin all-smi view::ui_events::tests(20 passed, 0 failed; 6 new regression tests)h/1opens and holds Help,A/Mtoggle cleanly, navigation moves once per pressNew regression tests (all in
src/view/ui_events.rs)test_is_actionable_key_event_accepts_presstest_is_actionable_key_event_rejects_releasetest_is_actionable_key_event_rejects_repeattest_reader_filter_drops_release_eventstest_reader_filter_passes_press_eventstest_reader_filter_passes_non_key_eventsCloses #212