Skip to content

feat(terminal): on-screen Esc/Tab/Ctrl/arrow keys for phone keyboards (#117) - #120

Merged
Lexus2016 merged 1 commit into
mainfrom
feat/117-mobile-terminal-keys
Sep 23, 2026
Merged

Lexus2016 merged 1 commit into
mainfrom
feat/117-mobile-terminal-keys

Conversation

@Lexus2016

Copy link
Copy Markdown
Owner

Closes #117.

What

A row Esc · Tab · Ctrl · ← · ↓ · ↑ · → under the terminal pane, shown only on touch devices (@media (pointer: coarse)). Desktop layouts are unchanged.

  • Each key sends the same {type:'input'} frame as a keystroke, through _reviveTerminal(), so a tap on a half-dead pane reconnects instead of being lost. Works on agent terminals and the engine pane.
  • Arrows honour DECCKM: ESC [ A normally, ESC O A when the TUI switched on application cursor mode. Ctrl+arrow → ESC [1;5 X.
  • Ctrl is one-shot: it applies to the next key, typed on Gboard (hooked into term.onData) or tapped in the row, then releases. aria-pressed shows the armed state.
  • A tap never takes focus: the action runs on pointerdown with the default prevented, and touchstart is cancelled (non-passive). A focused button would close Gboard on every key.

Verification

  • npm test → exit 0 (84 files). New test/terminal-keys.test.js (9 checks) runs the real block from index.html in a vm.
  • Headless Chromium, Pixel 7 emulation (isMobile, hasTouch), real server, /ws/terminal mocked with page.routeWebSocket to record frames:
    • frames: \x1b, \t, \x1b[A, \x1b[D, Ctrl then typed c → \x03, Ctrl + ↓ → \x1b[1;5B, then typed x → x (Ctrl released)
    • focus before and after the taps: xterm-helper-textarea
    • row height 43 px, 0 page errors
  • Desktop viewport (1280×800): row not visible.

Not done / risk

  • Not tested on a physical Android phone with Gboard. Emulation covers touch events and the pointer media query, not Gboard's IME composition. If Gboard delivers a composed chunk instead of one character, the armed Ctrl applies to its first character only.
  • No settings toggle: the row appears only on touch pointers, which covers the "only on mobile" ask without a new config key. A toggle can be added if someone needs it on a touch laptop.

🤖 Generated with Claude Code

…#117)

Gboard has no Esc, Tab, Ctrl or arrow keys, so a terminal tab on a phone
could not autocomplete, walk history or send Ctrl+C. A row of seven keys
now sits under the pane on touch devices (pointer: coarse); desktops do
not see it.

- Each key sends the same {type:'input'} frame a keystroke produces,
  through _reviveTerminal, so a tap on a half-dead pane reconnects.
- Arrows honour DECCKM (SS3 under application cursor mode); Ctrl+arrow
  sends CSI 1;5 X.
- Ctrl is one-shot: it applies to the NEXT key, typed on the phone
  keyboard (via term.onData) or tapped in the row, then releases.
- A tap never takes focus: the action runs on pointerdown with its default
  prevented and touchstart is cancelled, or Gboard would close per key.

test/terminal-keys.test.js runs the real block in a vm. 'Tab' joins the
keycap allowlist of the i18n markup scan next to Ctrl and Esc.

Fixes #117

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Lexus2016
Lexus2016 merged commit 4bdf165 into main Sep 23, 2026
2 checks passed
@Lexus2016
Lexus2016 deleted the feat/117-mobile-terminal-keys branch September 23, 2026 12:10
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.

Feature request: Add mobile terminal extra keys for Gboard users

1 participant