Merge branch 'master' into 724_fix_hasSelection

This commit is contained in:
Daniel Imms
2017-06-21 08:34:33 -07:00
committed by GitHub
5 changed files with 69 additions and 18 deletions
+17 -4
View File
@@ -2,10 +2,11 @@
* @license MIT
*/
import * as Mouse from './utils/Mouse';
import * as Browser from './utils/Browser';
import { CharMeasure } from './utils/CharMeasure';
import { CircularList } from './utils/CircularList';
import { EventEmitter } from './EventEmitter';
import * as Mouse from './utils/Mouse';
import { ITerminal } from './Interfaces';
import { SelectionModel } from './SelectionModel';
@@ -297,11 +298,23 @@ export class SelectionManager extends EventEmitter {
/**
* Queues a refresh, redrawing the selection on the next opportunity.
* @param isNewSelection Whether the selection should be registered as a new
* selection on Linux.
*/
public refresh(): void {
public refresh(isNewSelection?: boolean): void {
// Queue the refresh for the renderer
if (!this._refreshAnimationFrame) {
this._refreshAnimationFrame = window.requestAnimationFrame(() => this._refresh());
}
// If the platform is Linux and the refresh call comes from a mouse event,
// we need to update the selection for middle click to paste selection.
if (Browser.isLinux && isNewSelection) {
const selectionText = this.selectionText;
if (selectionText.length) {
this.emit('newselection', this.selectionText);
}
}
}
/**
@@ -397,7 +410,7 @@ export class SelectionManager extends EventEmitter {
}
this._addMouseDownListeners();
this.refresh();
this.refresh(true);
}
/**
@@ -552,7 +565,7 @@ export class SelectionManager extends EventEmitter {
if (!previousSelectionEnd ||
previousSelectionEnd[0] !== this._model.selectionEnd[0] ||
previousSelectionEnd[1] !== this._model.selectionEnd[1]) {
this.refresh();
this.refresh(true);
}
}
+18 -8
View File
@@ -75,12 +75,11 @@ export function pasteHandler(ev: ClipboardEvent, term: ITerminal) {
}
/**
* Bind to right-click event and allow right-click copy and paste.
* @param ev The original right click event to be handled
* @param term The terminal on which to apply the handled paste event
* @param selectionManager The terminal's selection manager.
* Moves the textarea under the mouse cursor and focuses it.
* @param ev The original right click event to be handled.
* @param textarea The terminal's textarea.
*/
export function rightClickHandler(ev: MouseEvent, textarea: HTMLTextAreaElement, selectionManager: ISelectionManager) {
export function moveTextAreaUnderMouseCursor(ev: MouseEvent, textarea: HTMLTextAreaElement) {
// Bring textarea at the cursor position
textarea.style.position = 'fixed';
textarea.style.width = '20px';
@@ -89,10 +88,7 @@ export function rightClickHandler(ev: MouseEvent, textarea: HTMLTextAreaElement,
textarea.style.top = (ev.clientY - 10) + 'px';
textarea.style.zIndex = '1000';
// Get textarea ready to copy from the context menu
textarea.value = selectionManager.selectionText;
textarea.focus();
textarea.select();
// Reset the terminal textarea's styling
setTimeout(function () {
@@ -104,3 +100,17 @@ export function rightClickHandler(ev: MouseEvent, textarea: HTMLTextAreaElement,
textarea.style.zIndex = null;
}, 4);
}
/**
* Bind to right-click event and allow right-click copy and paste.
* @param ev The original right click event to be handled.
* @param textarea The terminal's textarea.
* @param selectionManager The terminal's selection manager.
*/
export function rightClickHandler(ev: MouseEvent, textarea: HTMLTextAreaElement, selectionManager: ISelectionManager) {
moveTextAreaUnderMouseCursor(ev, textarea);
// Get textarea ready to copy from the context menu
textarea.value = selectionManager.selectionText;
textarea.select();
}
+1
View File
@@ -20,3 +20,4 @@ export const isMac = contains(['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K'], pla
export const isIpad = platform === 'iPad';
export const isIphone = platform === 'iPhone';
export const isMSWindows = contains(['Windows', 'Win16', 'Win32', 'WinCE'], platform);
export const isLinux = platform.indexOf('Linux') >= 0;
+4 -1
View File
@@ -192,11 +192,14 @@
position: absolute;
top: 0;
left: 0;
z-index: 1;
opacity: 0.3;
pointer-events: none;
}
.terminal .xterm-selection div {
position: absolute;
background-color: #555;
background-color: #fff;
}
/*
+29 -5
View File
@@ -13,7 +13,7 @@
import { CompositionHelper } from './CompositionHelper';
import { EventEmitter } from './EventEmitter';
import { Viewport } from './Viewport';
import { rightClickHandler, pasteHandler, copyHandler } from './handlers/Clipboard';
import { rightClickHandler, moveTextAreaUnderMouseCursor, pasteHandler, copyHandler } from './handlers/Clipboard';
import { CircularList } from './utils/CircularList';
import { C0 } from './EscapeSequences';
import { InputHandler } from './InputHandler';
@@ -537,9 +537,11 @@ Terminal.prototype.initGlobal = function() {
on(this.textarea, 'paste', pasteHandlerWrapper);
on(this.element, 'paste', pasteHandlerWrapper);
// Handle right click context menus
if (term.browser.isFirefox) {
// Firefox doesn't appear to fire the contextmenu event on right click
on(this.element, 'mousedown', event => {
if (ev.button == 2) {
if (event.button == 2) {
rightClickHandler(event, this.textarea, this.selectionManager);
}
});
@@ -548,6 +550,19 @@ Terminal.prototype.initGlobal = function() {
rightClickHandler(event, this.textarea, this.selectionManager);
});
}
// Move the textarea under the cursor when middle clicking on Linux to ensure
// middle click to paste selection works. This only appears to work in Chrome
// at the time is writing.
if (term.browser.isLinux) {
// Use auxclick event over mousedown the latter doesn't seem to work. Note
// that the regular click event doesn't fire for the middle mouse button.
on(this.element, 'auxclick', event => {
if (event.button === 1) {
moveTextAreaUnderMouseCursor(event, this.textarea, this.selectionManager);
}
});
}
};
/**
@@ -647,8 +662,7 @@ Terminal.prototype.open = function(parent, focus) {
this.viewportScrollArea.classList.add('xterm-scroll-area');
this.viewportElement.appendChild(this.viewportScrollArea);
// Create the selection container. This needs to be added before the
// rowContainer as the selection must be below the text.
// Create the selection container.
this.selectionContainer = document.createElement('div');
this.selectionContainer.classList.add('xterm-selection');
this.element.appendChild(this.selectionContainer);
@@ -703,7 +717,17 @@ Terminal.prototype.open = function(parent, focus) {
this.viewport = new Viewport(this, this.viewportElement, this.viewportScrollArea, this.charMeasure);
this.renderer = new Renderer(this);
this.selectionManager = new SelectionManager(this, this.lines, this.rowContainer, this.charMeasure);
this.selectionManager.on('refresh', data => this.renderer.refreshSelection(data.start, data.end));
this.selectionManager.on('refresh', data => {
this.renderer.refreshSelection(data.start, data.end);
});
this.selectionManager.on('newselection', text => {
// If there's a new selection, put it into the textarea, focus and select it
// in order to register it as a selection on the OS. This event is fired
// only on Linux to enable middle click to paste selection.
this.textarea.value = text;
this.textarea.focus();
this.textarea.select();
});
this.on('scroll', () => this.selectionManager.refresh());
this.viewportElement.addEventListener('scroll', () => this.selectionManager.refresh());