mirror of
https://github.com/anomalyco/opentui.git
synced 2026-04-25 04:55:58 +03:00
[GH-ISSUE #748] High-frequency scroll events cause input starvation and dropped keyboard data #972
Labels
No labels
bug
core
documentation
feature
good first issue
help wanted
pull-request
question
react
solid
tmux
windows
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/opentui#972
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @androolloyd on GitHub (Feb 27, 2026).
Original GitHub issue: https://github.com/anomalyco/opentui/issues/748
Bug
When using a mouse with a free-spinning scroll wheel (e.g. Logitech MX Master 3 with ratchet unlocked), scrolling in any opentui-based app can freeze keyboard input entirely. On Ghostty, raw SGR escape sequences like
\e[<65;93;34Malso appear as visible text.Root cause
Two issues in
packages/core/src/renderer.ts:1.
stdinListenerdrops non-mouse data from mixed chunksWhen
parseAllMouseEventsencounters non-mouse data (keyboard input, focus-in/out sequences, etc.) after mouse events in the same stdin chunk, it stops parsing. ButhandleMouseDatareturnstrueandstdinListenerreturns early — the non-mouse remainder is silently dropped.This means keyboard input, focus-in (
\e[I), and other control sequences that arrive in the same OS read as mouse data are permanently lost.2. No scroll event coalescing
Every scroll event is dispatched individually with no throttling or batching. Free-spinning wheels generate hundreds of events per second. Each event triggers hit testing → MouseEvent construction →
processMouseEvent→ Solid reactivity → layout. This saturates the Node.js event loop, starving keyboard event processing.Reproduction
Environment
Fix
PR forthcoming with:
parseAllMouseEventsreturns consumed byte count;stdinListenerforwards remainder toStdinBufferdelta