Skip to content

fix: cursor shape (DECSCUSR), Ctrl+V forwarding, and mouse scroll in alt screen#147

Open
jesse23 wants to merge 1 commit intocoder:mainfrom
jesse23:fix/pty-input-handling-gaps
Open

fix: cursor shape (DECSCUSR), Ctrl+V forwarding, and mouse scroll in alt screen#147
jesse23 wants to merge 1 commit intocoder:mainfrom
jesse23:fix/pty-input-handling-gaps

Conversation

@jesse23
Copy link
Copy Markdown

@jesse23 jesse23 commented Mar 28, 2026

Fixes all three issues reported in #145. Each fix is small and self-contained.

Bug 1 — DECSCUSR cursor shape silently dropped

GhosttyTerminal.getCursor() hardcoded style: 'block' and blinking: false with TODO comments. Added two new WASM exports to the patch:

  • ghostty_render_state_get_cursor_style(term)0=block, 1=bar, 2=underline (reads terminal.screens.active.cursor.cursor_style)
  • ghostty_render_state_get_cursor_blinking(term) → bool (reads terminal.modes.get(.cursor_blinking))

getCursor() now returns the live values so the renderer reflects cursor shape changes from PTY output.

Bug 2 — Ctrl+V not forwarded to PTY

handleKeyDown returned early on Ctrl+V/Cmd+V without emitting \x16, so apps that read it natively (image paste flows, readline yank) never received it. Now encodes and emits the keydown via onDataCallback before returning. The browser paste event still fires afterwards — handlePaste covers text paste unchanged.

Bug 3 — Mouse wheel sends arrow keys when mouse tracking is active

handleWheel sent \x1B[A/\x1B[B unconditionally on the alternate screen, ignoring whether the app had requested mouse events. Added a hasMouseTracking() guard: when active, emits an SGR scroll sequence (\x1b[<64/65;col;rowM) via dataEmitter instead. The arrow-key fallback is preserved for apps without mouse tracking (less, man, etc.).


Note: Bug 1 requires a WASM rebuild to take effect at runtime. The patch changes are ready; the resulting .wasm and .js bundle would need to be regenerated.

Ref: #145


Downstream pR to prove the fix works:
jesse23/webtty#21

Bug 1 — DECSCUSR cursor shape silently dropped:
Add ghostty_render_state_get_cursor_style and
ghostty_render_state_get_cursor_blinking WASM exports to the patch.
GhosttyTerminal.getCursor() now reads both from the terminal state
instead of hardcoding style:'block' and blinking:false.

Bug 2 — Ctrl+V not forwarded to PTY:
InputHandler.handleKeyDown emits the encoded \x16 byte to onDataCallback
before returning, so apps that read Ctrl+V natively (e.g. image paste
flows) receive it. The browser paste event still fires afterwards so
handlePaste continues to cover text paste unchanged.

Bug 3 — Mouse wheel sends arrow keys when mouse tracking is active:
Terminal.handleWheel checks hasMouseTracking() in the isAlternateScreen
branch. When active, it emits an SGR scroll sequence
(\x1b[<64/65;col;rowM) via dataEmitter instead of arrow keys, matching
xterm.js behaviour. The arrow-key fallback is preserved for apps without
mouse tracking (less, man, etc.).

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
@jesse23 jesse23 changed the title fix: three PTY input handling gaps (DECSCUSR cursor shape, Ctrl+V, mouse scroll) fix: cursor shape (DECSCUSR), Ctrl+V forwarding, and mouse scroll in alt screen Mar 28, 2026
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.

1 participant