Skip to content

SGR mouse reports with non-numeric coordinates get reissued as keystrokes #6573

Description

@le-codeur-rapide

Hello everyone !
Thank you for this library! I am using it for the mistral vibe CLI and encountered a bug.

SGR mouse reports with non-numeric coordinates get reissued as keystrokes

When a terminal emits a malformed SGR mouse report with non-numeric coordinates (e.g. \x1b[<32;NaN;NaNM), Textual fails to recognize it as a mouse event and falls back to reissue_sequence_as_keys, which re-emits each character as a keystroke. The result is garbage text dumped into the focused widget.

How to reproduce

This was reported by several Mistral Vibe CLI users across various configurations. I could reproduce it reliably in the VS Code integrated terminal by switching tabs using the side button of the mouse while hovering over the terminal.

During a focus/tab transition xterm.js's geometry is briefly invalid and it computes mouse cell coordinates as NaN, emitting reports like \x1b[<32;NaN;NaNM. In a Textual app this fills the focused input with [<32;NaN;NaNM.

What does textual

The mouse regex in _xterm_parser.py only matches decimal coordinates:

_re_mouse_event = re.compile("^" + re.escape("\x1b[") + r"(<?[-\d;]+[mM]|M...)\Z")

So \x1b[<32;NaN;NaNM doesn't match — that part is fine. The problem is the fallback: a sequence that is clearly a (broken) SGR mouse report still gets treated as user typing. \x1b[<...M/m is an unambiguous mouse-report shape; if the parameters are invalid, the right move is to drop it, not to type it.

Right now the only solution I found is to patch the textual xterm driver to filter these out. It'd be much nicer if Textual recognized the \x1b[<...M/m envelope and discarded reports with non-numeric coordinates rather than reissuing them as keys.

Suggested fix

Detect the SGR mouse envelope before the keystroke fallback and discard malformed instances. Valid reports (including negative SGR-Pixels coordinates) and all real key sequences should be untouched.

Happy to open a PR if this direction sounds good.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions