Repository navigation
Scroll full-screen TUI with mouse wheel on paired phones - #310
Conversation
Claude Code's fullscreen renderer runs in the alternate screen, which has no terminal history. The desktop pane scrolls it by sending mouse-wheel reports to the agent; the phone only scrolled its local xterm buffer, so it showed a single page. A swipe over an alternate-screen terminal now sends a `scroll` message. The server's mirror tracks the mouse encoding the agent asked for and writes matching wheel reports, only while the agent reads the wheel. Scrolling bypasses draft tracking so it never holds back peer prompts. Like view-size, it needs a paired phone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017VZQeYWdHG5Mpbg1FEyvZk
The Android terminal had the same single-page limit as the phone web UI in Claude Code's fullscreen mode, and it showed the shell's main-screen history above the alternate screen, which the desktop never shows. The alternate screen now shows alone, as in xterm. While it is up on a paired phone, a vertical drag the terminal view cannot follow turns into the server's `scroll` message, so the agent scrolls its own transcript. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017VZQeYWdHG5Mpbg1FEyvZk
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 690f89140f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (mouseEncoding === 'default') { | ||
| // Each value is one byte offset by 32, so cells past 223 cannot be reported. | ||
| if (x > 223 || y > 223) return null; | ||
| report = `\x1b[M${String.fromCharCode(button + 32, x + 32, y + 32)}`; |
There was a problem hiding this comment.
Preserve binary bytes in default mouse reports
When a TUI uses the legacy/default mouse encoding and the target column or row is 96–223, x + 32 or y + 32 is at least 128. This constructs those protocol bytes as Unicode characters, after which scrollAgent passes the string to a PTY configured with node-pty's default UTF-8 encoding, expanding each required single byte into a multibyte sequence and making wheel events over that part of a wide/tall terminal unparsable. Xterm deliberately emits default mouse reports through its binary channel, while node-pty accepts a Buffer; return binary data here or reject coordinates above 95. Xterm default encoder, node-pty encoding contract.
Useful? React with 👍 / 👎.
Default-encoded mouse reports carry cell positions as raw bytes. Written to the PTY as a string, a column or row of 96 or more became two UTF-8 bytes, and the program read a broken report followed by a stray key. The desktop pane never sends those reports at all: xterm emits them as binary events, which the renderer does not forward. Match it and send wheel turns only to programs that asked for SGR reports. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017VZQeYWdHG5Mpbg1FEyvZk
Adds support for scrolling full-screen terminal UIs (like vim or Claude Code's fullscreen mode) on paired phones by converting touch drags into mouse wheel reports that the TUI can read, keeping its transcript out of the terminal history.
Changes
Android app:
AgentWheelclass implementingNestedScrollConnectionto convert vertical drag gestures into mouse wheel turns for full-screen agentsTerminalTextto apply nested scroll handling and track line height for wheel calculationsTerminalScreen.alternateScreenproperty to detect when a full-screen program is activeAgentScreento pass wheel scroll callback when in full-screen modeAgentWheelbehaviorWeb/Electron:
ScrollCommandprotocol message type for wheel turns over a specific cellscrollAgent()function inws.tsto send scroll commands from the phonescrollAgent()handler inpty.tsthat converts wheel turns to mouse reports via the terminal's query responderwheelReport()inTerminalQueryResponderto generate SGR or default mouse encoding reports based on the program's active mouse tracking modeAgentDetailto detect full-screen mode and route scrolls toscrollAgent()instead of terminal history scrollingKey implementation details:
https://claude.ai/code/session_017VZQeYWdHG5Mpbg1FEyvZk