fix: prevent double paste on Ctrl+Shift+V
Our custom handler sent clipboard text via WebSocket, but the browser's native paste event also fired on xterm.js's hidden textarea, causing xterm's built-in paste handler to send the same text again. Fix: e.preventDefault() suppresses the browser paste event.
This commit is contained in:
@@ -364,6 +364,7 @@ function openTerminal(sessionName, remoteId) {
|
|||||||
|
|
||||||
// Ctrl+Shift+V → paste from clipboard into terminal
|
// Ctrl+Shift+V → paste from clipboard into terminal
|
||||||
if (e.ctrlKey && e.shiftKey && (e.key === 'V' || e.code === 'KeyV')) {
|
if (e.ctrlKey && e.shiftKey && (e.key === 'V' || e.code === 'KeyV')) {
|
||||||
|
e.preventDefault(); // suppress browser native paste event (prevents double-paste via xterm textarea)
|
||||||
if (navigator.clipboard && navigator.clipboard.readText) {
|
if (navigator.clipboard && navigator.clipboard.readText) {
|
||||||
navigator.clipboard.readText().then(function(text) {
|
navigator.clipboard.readText().then(function(text) {
|
||||||
if (text && _ws && _ws.readyState === WebSocket.OPEN) {
|
if (text && _ws && _ws.readyState === WebSocket.OPEN) {
|
||||||
|
|||||||
@@ -991,4 +991,25 @@ test('terminal.js loads xterm-addon-image for inline graphics', () => {
|
|||||||
assert.ok(source.includes('ImageAddon'), 'must reference ImageAddon');
|
assert.ok(source.includes('ImageAddon'), 'must reference ImageAddon');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// --- Clipboard double-paste bug fix ---
|
||||||
|
|
||||||
|
test('terminal.js Ctrl+Shift+V handler calls preventDefault to suppress double paste', () => {
|
||||||
|
// Regression: without e.preventDefault(), the browser fires a native paste event on
|
||||||
|
// xterm.js's hidden textarea after our handler sends via WebSocket, causing double paste.
|
||||||
|
const source = fs.readFileSync(new URL('../terminal.js', import.meta.url), 'utf8');
|
||||||
|
|
||||||
|
// Locate the Ctrl+Shift+V block by finding the key check, then extracting the block
|
||||||
|
const vIdx = source.indexOf("e.key === 'V'");
|
||||||
|
assert.ok(vIdx !== -1, "must have a Ctrl+Shift+V key check");
|
||||||
|
const blockStart = source.lastIndexOf('if (', vIdx);
|
||||||
|
const blockEnd = source.indexOf('return false', vIdx);
|
||||||
|
const vBlock = source.substring(blockStart, blockEnd);
|
||||||
|
|
||||||
|
assert.ok(
|
||||||
|
vBlock.includes('preventDefault'),
|
||||||
|
'Ctrl+Shift+V handler must call e.preventDefault() before the async clipboard read ' +
|
||||||
|
'to suppress the browser native paste event (which causes double-paste via xterm textarea)',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user