Skip to content

fix(view): drop non-Press key events to fix Windows TUI double-dispatch#222

Merged
inureyes merged 1 commit into
mainfrom
fix/issue-212-windows-key-press-release
May 24, 2026
Merged

fix(view): drop non-Press key events to fix Windows TUI double-dispatch#222
inureyes merged 1 commit into
mainfrom
fix/issue-212-windows-key-press-release

Conversation

@inureyes

Copy link
Copy Markdown
Member

Summary

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 — the "flash" symptom that made the TUI effectively unusable on Windows.

Root cause

crossterm reports keyboard events differently per platform:

  • Unix (without keyboard-enhancement flags, which all-smi does not enable): only KeyEventKind::Press is delivered. Holding a key produces repeated Press via the terminal's own auto-repeat.
  • Windows: the console backend additionally delivers Release and Repeat.

A single h press on Windows therefore produced Pressshow_help = true, then Releaseshow_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_loop so both consumers — the live next_event() path and the drain_pending_events() batch path — are protected by one guard. The predicate is extracted into a small is_actionable_key_event(KeyEventKind) -> bool helper so it is unit-testable without a live terminal.

if let Event::Key(k) = &evt
    && !is_actionable_key_event(k.kind)
{
    continue;
}

No change in src/view/event_handler.rs — its dispatch logic is already correct once Release is filtered upstream. The change is a no-op on Unix.

Test plan

  • cargo fmt --check
  • cargo check --lib --tests
  • cargo clippy --lib --tests -- -D warnings
  • cargo test --bin all-smi view::ui_events::tests (20 passed, 0 failed; 6 new regression tests)
  • Manual Windows verification: h/1 opens and holds Help, A/M toggle cleanly, navigation moves once per press
  • Manual macOS/Linux verification: no behavioral regression

New regression tests (all in src/view/ui_events.rs)

  • test_is_actionable_key_event_accepts_press
  • test_is_actionable_key_event_rejects_release
  • test_is_actionable_key_event_rejects_repeat
  • test_reader_filter_drops_release_events
  • test_reader_filter_passes_press_events
  • test_reader_filter_passes_non_key_events

Closes #212

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 inureyes added type:bug Something isn't working priority:high High priority issue status:done Completed labels May 24, 2026
@inureyes inureyes merged commit f254b80 into main May 24, 2026
4 checks passed
@inureyes inureyes deleted the fix/issue-212-windows-key-press-release branch May 24, 2026 06:38
@inureyes inureyes self-assigned this May 24, 2026
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

priority:high High priority issue status:done Completed type:bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug] Windows: keys fire on both press and release, making the TUI unusable

1 participant