Skip to content

fix(tui): drop ESC-stripped SGR mouse reports instead of inserting them#872

Merged
esengine merged 1 commit into
mainfrom
fix/sgr-mouse-report-leak
May 15, 2026
Merged

fix(tui): drop ESC-stripped SGR mouse reports instead of inserting them#872
esengine merged 1 commit into
mainfrom
fix/sgr-mouse-report-leak

Conversation

@esengine

Copy link
Copy Markdown
Owner

Summary

  • ConPTY occasionally strips the leading ESC off CSI sequences. Mouse reports — \x1b[<btn;col;rowM/m — then arrive in the byte stream as [<btn;col;rowM/m, slip past the escapeless-CSI lookahead (which only knows arrow / page tails), and fall into the printable accumulator. The composer ends up with the literal SGR text on every wheel nudge.
  • Add tryEscapelessSgrMouse alongside the existing escapeless-paste / escapeless-arrow guards. Recognised reports dispatch the same mouseScroll* / mouseClick / mouseDrag / mouseRelease events the with-ESC path already emits; unmapped buttons are consumed and dropped silently.
  • Refactor: extract decodeSgrMouseBody so dispatchCsi and the new escapeless path share the button-decoding table.

This is the cheap step described in the issue — no DECSET state changes, no terminal-mode requests, just stop the garbage at the parser. Mouse-tracking enablement (DECSET 1000 + 1006) stays a separate, larger change.

Test plan

  • 9 new cases in tests/stdin-reader.test.ts: with-ESC wheel up/down, click press+release, unmapped-button drop, ESC-stripped wheel, burst of ESC-stripped reports, printable text adjacent to a report, ESC-stripped unmapped button, and a literal [<not-a-mouse-report that must arrive intact as text.
  • Existing 39 stdin-reader cases still pass (no regression in paste / arrow / Shift+Tab / heuristic-paste-rescue paths).
  • tests/comment-policy.test.ts clean.
  • tsc --noEmit clean.

Closes #867

ConPTY occasionally strips the leading ESC off CSI sequences. Mouse
reports — `\x1b[<btn;col;rowM/m` — then arrive in the byte stream as
`[<btn;col;rowM/m`, slip past the escapeless-CSI lookahead (which only
knows arrow / page tails), and fall into the printable accumulator. The
composer receives the literal SGR text and the user has to backspace
through every wheel nudge.

Add `tryEscapelessSgrMouse` alongside the existing escapeless-paste and
escapeless-arrow guards. Recognised reports dispatch the same
mouseScroll/Click/Drag/Release events the with-ESC path already emits;
unmapped buttons are consumed and dropped. Share `decodeSgrMouseBody`
with `dispatchCsi` so both paths surface the same shape.

Closes #867
@esengine esengine merged commit b84d944 into main May 15, 2026
3 checks passed
@esengine esengine deleted the fix/sgr-mouse-report-leak branch May 15, 2026 01:56
ChasLui pushed a commit to ChasLui/DeepSeek-Reasonix that referenced this pull request May 23, 2026
…em (esengine#872)

ConPTY occasionally strips the leading ESC off CSI sequences. Mouse
reports — `\x1b[<btn;col;rowM/m` — then arrive in the byte stream as
`[<btn;col;rowM/m`, slip past the escapeless-CSI lookahead (which only
knows arrow / page tails), and fall into the printable accumulator. The
composer receives the literal SGR text and the user has to backspace
through every wheel nudge.

Add `tryEscapelessSgrMouse` alongside the existing escapeless-paste and
escapeless-arrow guards. Recognised reports dispatch the same
mouseScroll/Click/Drag/Release events the with-ESC path already emits;
unmapped buttons are consumed and dropped. Share `decodeSgrMouseBody`
with `dispatchCsi` so both paths surface the same shape.

Closes esengine#867
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TUI: mouse-wheel scroll inserts raw SGR escape sequences into the composer

1 participant