refactor: remove ALL custom paste handlers — clean slate per COE review
After 9 clipboard commits that kept breaking each other, COE review determined: ttyd uses ClipboardAddon, not custom handlers. Ctrl+Shift+V on Linux and Cmd+V on macOS both trigger native browser paste events that xterm.js catches via its hidden textarea handler. Zero custom paste code needed. Deleted synthetic ClipboardEvent dispatch, readText calls, and all paste-related comments. Kept: Ctrl+Shift+C copy, auto-copy on selection, OSC 52, Ctrl+F search.
This commit is contained in:
@@ -364,13 +364,9 @@ function openTerminal(sessionName, remoteId) {
|
||||
_term.open(container);
|
||||
|
||||
// --- Clipboard integration ---
|
||||
// Ctrl+Shift+C: copy selection to system clipboard (Ctrl+C still sends SIGINT)
|
||||
// Ctrl+Shift+V: Ctrl+Shift+V does NOT trigger a native browser paste event (unlike Cmd+V
|
||||
// on macOS). We read the clipboard via navigator.clipboard.readText() and dispatch a
|
||||
// synthetic ClipboardEvent on xterm.js's hidden textarea. xterm.js catches this via its
|
||||
// built-in handlePasteEvent listener → prepareTextForTerminal → bracketTextForPaste
|
||||
// → triggerDataEvent → onData → WebSocket. This is the same path as Cmd+V and correctly
|
||||
// handles CR/LF normalization, bracketed paste mode, and UTF-8 encoding.
|
||||
// Copy: Ctrl+Shift+C intercepts and copies selection to system clipboard
|
||||
// Paste: handled natively by xterm.js (browser paste event → hidden textarea → onData → WebSocket)
|
||||
// Cmd+V (macOS) and Ctrl+Shift+V (Linux) both trigger native browser paste events
|
||||
_term.attachCustomKeyEventHandler(function(e) {
|
||||
if (e.type !== 'keydown') return true;
|
||||
|
||||
@@ -381,24 +377,6 @@ function openTerminal(sessionName, remoteId) {
|
||||
return false; // prevent xterm from processing
|
||||
}
|
||||
|
||||
// Ctrl+Shift+V → paste from system clipboard via synthetic ClipboardEvent on xterm textarea.
|
||||
// Dispatching on _term.textarea triggers xterm.js's built-in handlePasteEvent, which
|
||||
// handles CR/LF normalization, bracketed paste mode, and correct UTF-8 encoding —
|
||||
// the exact same code path as a native Cmd+V paste on macOS.
|
||||
if (e.ctrlKey && e.shiftKey && (e.key === 'V' || e.code === 'KeyV')) {
|
||||
if (navigator.clipboard && navigator.clipboard.readText && _term && _term.textarea) {
|
||||
navigator.clipboard.readText().then(function(text) {
|
||||
if (!text || !_term || !_term.textarea) return;
|
||||
var pasteEvent = new ClipboardEvent('paste', {
|
||||
clipboardData: new DataTransfer(),
|
||||
});
|
||||
pasteEvent.clipboardData.setData('text/plain', text);
|
||||
_term.textarea.dispatchEvent(pasteEvent);
|
||||
}).catch(function() {});
|
||||
}
|
||||
return false; // prevent xterm from processing the raw key
|
||||
}
|
||||
|
||||
// Ctrl+F → open search bar
|
||||
if (e.ctrlKey && !e.shiftKey && (e.key === 'f' || e.key === 'F' || e.code === 'KeyF')) {
|
||||
_openSearch();
|
||||
|
||||
@@ -993,25 +993,22 @@ test('terminal.js loads xterm-addon-image for inline graphics', () => {
|
||||
assert.ok(source.includes('ImageAddon'), 'must reference ImageAddon');
|
||||
});
|
||||
|
||||
// --- Ctrl+Shift+V: synthetic paste event on xterm textarea ---
|
||||
// --- Ctrl+Shift+V: xterm.js handles paste natively, no custom interception ---
|
||||
|
||||
test('terminal.js Ctrl+Shift+V dispatches synthetic paste event on textarea', () => {
|
||||
// Ctrl+Shift+V does NOT trigger a native browser paste event (unlike Cmd+V on macOS).
|
||||
// Fix: read clipboard via navigator.clipboard.readText(), then dispatch a synthetic
|
||||
// ClipboardEvent on xterm.js's hidden textarea. This goes through xterm.js's built-in
|
||||
// handlePasteEvent which handles CR/LF normalization, bracketed paste, and correct encoding.
|
||||
test('terminal.js does NOT intercept Ctrl+Shift+V in attachCustomKeyEventHandler', () => {
|
||||
// COE review: every custom paste handler we built caused either double-paste or encoding issues.
|
||||
// On Linux, Ctrl+Shift+V is a native browser paste shortcut — it fires a paste event on the
|
||||
// focused textarea, xterm.js catches it natively. On macOS, Cmd+V does the same.
|
||||
// Zero custom paste code needed.
|
||||
const source = fs.readFileSync(new URL('../terminal.js', import.meta.url), 'utf8');
|
||||
const handlerStart = source.indexOf('attachCustomKeyEventHandler');
|
||||
const handlerEnd = source.indexOf('// Auto-copy:', handlerStart);
|
||||
const handlerEnd = source.indexOf('onSelectionChange', handlerStart);
|
||||
const handlerBlock = source.substring(handlerStart, handlerEnd);
|
||||
assert.ok(
|
||||
handlerBlock.includes("e.key === 'V'") || handlerBlock.includes("e.code === 'KeyV'"),
|
||||
'attachCustomKeyEventHandler must intercept Ctrl+Shift+V to trigger paste',
|
||||
);
|
||||
assert.ok(
|
||||
handlerBlock.includes('ClipboardEvent') || handlerBlock.includes('dispatchEvent'),
|
||||
'must dispatch synthetic paste event so xterm.js handlePasteEvent handles encoding correctly',
|
||||
);
|
||||
// Must NOT have any V key interception
|
||||
assert.ok(!handlerBlock.includes("e.key === 'V'"),
|
||||
'must NOT intercept Ctrl+Shift+V — xterm.js handles paste natively via browser events');
|
||||
assert.ok(!handlerBlock.includes("e.code === 'KeyV'"),
|
||||
'must NOT intercept KeyV — xterm.js handles paste natively via browser events');
|
||||
});
|
||||
|
||||
// --- UTF-8 output decoding via TextDecoder ---
|
||||
|
||||
Reference in New Issue
Block a user