Skip to content

Android keyCode-229 keyboards: a stray DEL rides the batched commit-plus-Enter path and eats a character #448

Closed

Description

@Ark0N

Found while reviewing #441, which fixed the neighbouring half of this path. Pre-existing on master, not introduced there.

What happens

On a device whose keydowns report keyCode: 229 (Chrome on Android, and any soft keyboard that routes through composition), committing the last character of a prompt and pressing Enter in one InputConnection transaction makes xterm emit a stray DEL before the \r.

The mechanism is xterm's own keyCode-229 rescue. CompositionHelper.keydown() schedules _handleAnyTextareaChanges(), a zero-delay diff of textarea.value. Enter clears the textarea, so when that diff runs it sees the value shrink and emits the difference as a deletion. With local echo on (the default on every touch device, per MobileDetection.isTouchDevice()), that DEL reaches the composer before the \r does and eats a character.

Why it is worth a separate issue

#441 strictly improved this path rather than causing it: before that change the batched shape lost two characters here, after it one. So a report that still shows a missing character on an Android device after 1.30.0 is this, not a regression from #441, and I would rather that be written down somewhere than rediscovered.

Where to look

  • src/web/public/terminal-keycode229-recovery.js is the module that already owns the neighbouring case (an insertText xterm's _inputEvent guard refuses). It deliberately does not touch anything xterm emitted itself, which is why this is out of its scope as written.
  • test/terminal-keycode229-recovery.browser.test.ts has the harness: it drives the real textarea and reports which bytes reach the send path and who produced them. The batched case added in ea5323d9 is the closest shape; a variant with keyCode: 229 and local echo enabled should show the stray DEL.

Not obvious, and worth deciding before writing code

Suppressing a DEL unconditionally would break real backspaces. The distinguishing evidence is that this one arrives from xterm's composition diff rather than from a key, in the same task as an Enter that has already cleared the textarea, so any fix needs to key off that rather than off the byte.

Not urgent: it costs one character in one input shape on one platform, and it has been there a while.

Activity

  1. Ark0N commented on Oct 14, 2026

    @Ark0N
    OwnerAuthor

    Fixed by #541 (thanks @opticon454), which shipped in 1.40.0. Its review commit f21ab39a handles exactly this shape: the keyCode-229 controller now diffs the textarea against what was already sent, and a pending edit is settled synchronously at the next keydown, before xterm clears the textarea for Enter. So the diff never sees the value shrink and sends no DEL. That keys off the composition path rather than the byte, so real backspaces are untouched, which was the open question above.

    test/terminal-keycode229-recovery.browser.test.ts pins it: "a 229 last character in the same task as Enter submits the whole line", with local echo both on and off, asserts no \x7f reaches the wire and the line arrives as hello\r. I re-ran that file on master today and all 17 tests pass.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions