Skip to content

Ctrl+C over a selection copies instead of interrupting - #76

Merged
karngyan merged 3 commits into
mainfrom
ctrl-c-copies-selection
Aug 17, 2026
Merged

Ctrl+C over a selection copies instead of interrupting#76
karngyan merged 3 commits into
mainfrom
ctrl-c-copies-selection

Conversation

@karngyan

Copy link
Copy Markdown
Contributor

Closes#62.

What happens now

Select output with the mouse and press Ctrl+C: the selection is copied and the program keeps running. With nothing selected, Ctrl+C is still the interrupt it has always been. Ctrl+Shift+C is claimed for copy, so the chord no longer opens the DevTools inspector over the terminal. Ctrl+Shift+V is deliberately left to the browser, which already binds it to a plain-text paste on Windows and Linux.

How

All in the custom key event handler in web/src/emulator/xterm.ts, the seam the issue pointed at.

  • Ctrl+C with a selection returns false without preventDefault. xterm never encodes ETX, the browser's own copy runs, and xterm's copy listener fills the clipboard from the selection. The selection is then cleared on a deferred tick, so the next Ctrl+C interrupts: a held selection must not make SIGINT unreachable from the keyboard.
  • Ctrl+Shift+C is claimed on every platform: preventDefault, write the selection through navigator.clipboard, clear it on success only. A failed write keeps the selection, so there is something to try again with. An empty selection is swallowed rather than passed on, which is what keeps DevTools shut.
  • Ctrl+Shift+V stands aside. Chromium and Firefox on Windows and Linux fire a trusted paste event at xterm's helper textarea for this chord, which xterm's own paste handler consumes, bracketed paste included. Claiming it and reading the async clipboard would cost a permission prompt on exactly the platforms that press it, and would go dead on insecure origins.
  • Mac keyboards (new XtermOptions.macKeyboard, wired from isApplePlatform()) keep Ctrl+C as the interrupt even over a selection. Cmd+C owns copy there and already works, and macOS browsers do not copy on Ctrl+C, so claiming it would swallow the key entirely.

Tests

Ten new tests in web/src/emulator/emulator.test.ts cover the stand-aside, the clear-then-interrupt sequence, the empty-selection interrupt, the Mac gate, Cmd+C passthrough, both Ctrl+Shift+C paths including a refused clipboard write, and the Ctrl+Shift+V stand-aside. Full web suite: 1381 tests green, pnpm run lint clean.

🤖 Generated with Claude Code

xterm encodes Ctrl+C as ETX with no notion of a selection, so copying
output sent SIGINT to the program under it. The custom key handler now
stands aside for Ctrl+C over a selection so the browser's own copy
runs, then clears the selection so the next press still interrupts.
Ctrl+Shift+C is claimed for copy (unclaimed it opens DevTools) and
Ctrl+Shift+V for paste. Mac keyboards keep Ctrl+C as the interrupt:
Cmd+C already copies there.
Closes#62
Chromium and Firefox on Windows and Linux bind the chord to a
plain-text paste that fires a trusted paste event xterm already
consumes, bracketed paste included. Claiming it and reading the async
clipboard cost a permission prompt on those platforms and went dead on
insecure origins, where navigator.clipboard does not exist.
Also guard a clipboard object without writeText, and restore the
clipboard stubs after each test.
@karngyan
karngyan merged commit cfa4466 into mainAug 17, 2026
1 check passed
Sign up for freeto 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.

Ctrl+C in the browser terminal sends SIGINT even when there is a selection

1 participant

@karngyan