Give the right-click menu the copy and paste it never had

Fixkamo-internal
Shipped
September 6, 2026 at 1:03 AM UTC
Author
Kamo
Commit
20358db

Suppressing the browser's context menu (734f68cb) took the only copy/paste the terminal window actually had. That is not what it looked like — there are Copy and Paste buttons on the strip — so this is what was underneath. Reading the clipboard is permission-gated in every browser, and `paste()` threw its refusal away in a bare `catch`; `copySelection` was worse, awaiting **************** which cannot catch anything when `navigator.clipboard` is undefined because the property access throws before there is a promise. Both failed invisibly. The browser's own menu was the only route that needed no permission at all: xterm registers a native `paste` listener on its hidden textarea and on its root precisely so that a native Paste lands in the shell. So the right button becomes this window's, and the window draws the menu: - The press is stopped in the capture phase, above xterm's listeners, so it is never reported to tmux (`mouse on`, set by the desktop agent) and tmux draws no pane menu behind ours. One menu, which was the point of 734f68cb. Every other button is untouched. Verified in Chrome, not only in jsdom: the press does not reach the emulator, `contextmenu` still fires with its coordinates, and the native menu stays prevented. - Copy falls back to a scratch textarea and execCommand when the Clipboard API refuses, so a copy is always available. Paste uses readText, which is the half that can be refused. - Which is why each item names its shortcut. Ctrl+Shift+V is the browser's OWN paste and can never be refused: returning false from xterm's custom key handler returns from `_keyDown` before preventDefault, so the browser pastes into the textarea xterm is listening on. That last one also fixes a double paste. Ctrl+Shift+V returned false AND called readText, so the browser's paste and ours both landed — every paste doubled its own text for anyone who had granted the permission. Ctrl+Shift+C now cancels explicitly, or Chrome opens the element inspector over the terminal on copy.

All changes

Like what you see shipping?

Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.

Start Free ForeverView Pricing