hterm: Don't clear selection on copy
Clearing the selection on a non-keyboard copy was tricky, because
we don't want to do it right away, but the delay sucks if you're
trying to work quickly.
Unfortunately we *have* to clear the selection as part of the copy
process, so this patch restores it right after the copy completes.
BUG=none
TEST=text_harness.html, 64/64 tests passed.
Change-Id: I489093dcbebb170c92d64a6f4e11ef4f86fd97b1
Reviewed-on: https://gerrit.chromium.org/gerrit/31061
Reviewed-by: Marius Schilder <mschilder@google.com>
Commit-Ready: Robert Ginda <rginda@chromium.org>
Reviewed-by: Robert Ginda <rginda@chromium.org>
Tested-by: Robert Ginda <rginda@chromium.org>
diff --git a/hterm/js/hterm_keyboard_keymap.js b/hterm/js/hterm_keyboard_keymap.js
index b2b66ae..e918bfa 100644
--- a/hterm/js/hterm_keyboard_keymap.js
+++ b/hterm/js/hterm_keyboard_keymap.js
@@ -401,14 +401,16 @@
* the key again.
*/
hterm.Keyboard.KeyMap.prototype.onCtrlC_ = function(e, keyDef) {
- var document = this.keyboard.terminal.getDocument();
- if (e.shiftKey || document.getSelection().isCollapsed) {
- // If the shift key is being held, or there is no document selection, send
- // a ^C.
+ var selection = this.keyboard.terminal.getDocument().getSelection();
+ if (e.shiftKey || selection.isCollapsed) {
+ // If the shift key is being held or there is no document selection, then
+ // send a ^C.
return '\x03';
}
- // Otherwise let the browser handle it as a copy command.
+ // Otherwise let the browser handle it as a copy command. Clear the selection
+ // soon after a Ctrl-C copy, so that it frees up Ctrl-C to send ^C.
+ setTimeout(selection.collapseToEnd.bind(selection), 750);
return hterm.Keyboard.KeyActions.PASS;
};
diff --git a/hterm/js/hterm_scrollport.js b/hterm/js/hterm_scrollport.js
index 17b4a8c..5dad219 100644
--- a/hterm/js/hterm_scrollport.js
+++ b/hterm/js/hterm_scrollport.js
@@ -161,8 +161,8 @@
}
if (!anchorRow) {
- console.log('Selection anchor is not rooted in a row node: ' +
- selection.anchorNode.nodeName);
+ console.error('Selection anchor is not rooted in a row node: ' +
+ selection.anchorNode.nodeName);
return;
}
@@ -172,8 +172,8 @@
}
if (!focusRow) {
- console.log('Selection focus is not rooted in a row node: ' +
- selection.focusNode.nodeName);
+ console.error('Selection focus is not rooted in a row node: ' +
+ selection.focusNode.nodeName);
return;
}
diff --git a/hterm/js/hterm_terminal.js b/hterm/js/hterm_terminal.js
index a3e6ed8..0d0411d 100644
--- a/hterm/js/hterm_terminal.js
+++ b/hterm/js/hterm_terminal.js
@@ -2281,7 +2281,7 @@
* Note: If there is a selected range in the terminal, it'll be cleared.
*/
hterm.Terminal.prototype.copyStringToClipboard = function(str) {
- this.showOverlay(hterm.msg('NOTIFY_COPY'), 500);
+ setTimeout(this.showOverlay.bind(this, hterm.msg('NOTIFY_COPY'), 500), 200);
var copySource = this.document_.createElement('pre');
copySource.textContent = str;
@@ -2291,11 +2291,20 @@
'top: -99px');
this.document_.body.appendChild(copySource);
+
var selection = this.document_.getSelection();
+ var anchorNode = selection.anchorNode;
+ var anchorOffset = selection.anchorOffset;
+ var focusNode = selection.focusNode;
+ var focusOffset = selection.focusOffset;
+
selection.selectAllChildren(copySource);
hterm.copySelectionToClipboard(this.document_);
+ selection.collapse(anchorNode, anchorOffset);
+ selection.extend(focusNode, focusOffset);
+
copySource.parentNode.removeChild(copySource);
};
@@ -2362,6 +2371,19 @@
* coordinates for the mouse event.
*/
hterm.Terminal.prototype.onMouse_ = function(e) {
+ if (e.processedByTerminalHandler_) {
+ // We register our event handlers on the document, as well as the cursor
+ // and the scroll blocker. Mouse events that occur on the cursor or
+ // scroll blocker will also appear on the document, but we don't want to
+ // process them twice.
+ //
+ // We can't just prevent bubbling because that has other side effects, so
+ // we decorate the event object with this property instead.
+ return;
+ }
+
+ e.processedByTerminalHandler_ = true;
+
if (e.type == 'mousedown' && e.which == this.mousePasteButton) {
this.paste();
return;
@@ -2369,7 +2391,7 @@
if (e.type == 'mouseup' && e.which == 1 && this.copyOnSelect &&
!this.document_.getSelection().isCollapsed) {
- this.copySelectionToClipboard();
+ hterm.copySelectionToClipboard(this.document_);
return;
}
@@ -2398,18 +2420,7 @@
this.scrollBlockerNode_.style.top = '-99px';
}
- if (!e.processedByTerminalHandler_) {
- // We register our event handlers on the document, as well as the cursor
- // and the scroll blocker. Mouse events that occur on the cursor or
- // scroll blocker will also appear on the document, but we don't want to
- // process them twice.
- //
- // We can't just prevent bubbling because that has other side effects, so
- // we decorate the event object with this property instead.
- e.processedByTerminalHandler_ = true;
-
- this.onMouse(e);
- }
+ this.onMouse(e);
};
/**
@@ -2446,7 +2457,7 @@
*/
hterm.Terminal.prototype.onCopy_ = function(e) {
e.preventDefault();
- setTimeout(this.copySelectionToClipboard.bind(this), 200);
+ this.copySelectionToClipboard();
};
/**