Merge branch 'master' into pr/jerch/1904
This commit is contained in:
+25
-19
@@ -85,26 +85,32 @@ export function pasteHandler(ev: ClipboardEvent, term: ITerminal): void {
|
||||
* @param ev The original right click event to be handled.
|
||||
* @param textarea The terminal's textarea.
|
||||
*/
|
||||
export function moveTextAreaUnderMouseCursor(ev: MouseEvent, textarea: HTMLTextAreaElement): void {
|
||||
// Bring textarea at the cursor position
|
||||
textarea.style.position = 'fixed';
|
||||
textarea.style.width = '20px';
|
||||
textarea.style.height = '20px';
|
||||
textarea.style.left = (ev.clientX - 10) + 'px';
|
||||
textarea.style.top = (ev.clientY - 10) + 'px';
|
||||
textarea.style.zIndex = '1000';
|
||||
export function moveTextAreaUnderMouseCursor(ev: MouseEvent, term: ITerminal): void {
|
||||
|
||||
textarea.focus();
|
||||
// Calculate textarea position relative to the screen element
|
||||
const pos = term.screenElement.getBoundingClientRect();
|
||||
const left = ev.clientX - pos.left - 10;
|
||||
const top = ev.clientY - pos.top - 10;
|
||||
|
||||
// Bring textarea at the cursor position
|
||||
term.textarea.style.position = 'absolute';
|
||||
term.textarea.style.width = '20px';
|
||||
term.textarea.style.height = '20px';
|
||||
term.textarea.style.left = `${left}px`;
|
||||
term.textarea.style.top = `${top}px`;
|
||||
term.textarea.style.zIndex = '1000';
|
||||
|
||||
term.textarea.focus();
|
||||
|
||||
// Reset the terminal textarea's styling
|
||||
// Timeout needs to be long enough for click event to be handled.
|
||||
setTimeout(() => {
|
||||
textarea.style.position = null;
|
||||
textarea.style.width = null;
|
||||
textarea.style.height = null;
|
||||
textarea.style.left = null;
|
||||
textarea.style.top = null;
|
||||
textarea.style.zIndex = null;
|
||||
term.textarea.style.position = null;
|
||||
term.textarea.style.width = null;
|
||||
term.textarea.style.height = null;
|
||||
term.textarea.style.left = null;
|
||||
term.textarea.style.top = null;
|
||||
term.textarea.style.zIndex = null;
|
||||
}, 200);
|
||||
}
|
||||
|
||||
@@ -115,14 +121,14 @@ export function moveTextAreaUnderMouseCursor(ev: MouseEvent, textarea: HTMLTextA
|
||||
* @param selectionManager The terminal's selection manager.
|
||||
* @param shouldSelectWord If true and there is no selection the current word will be selected
|
||||
*/
|
||||
export function rightClickHandler(ev: MouseEvent, textarea: HTMLTextAreaElement, selectionManager: ISelectionManager, shouldSelectWord: boolean): void {
|
||||
moveTextAreaUnderMouseCursor(ev, textarea);
|
||||
export function rightClickHandler(ev: MouseEvent, term: ITerminal, selectionManager: ISelectionManager, shouldSelectWord: boolean): void {
|
||||
moveTextAreaUnderMouseCursor(ev, term);
|
||||
|
||||
if (shouldSelectWord && !selectionManager.isClickInSelection(ev)) {
|
||||
selectionManager.selectWordAtCursor(ev);
|
||||
}
|
||||
|
||||
// Get textarea ready to copy from the context menu
|
||||
textarea.value = selectionManager.selectionText;
|
||||
textarea.select();
|
||||
term.textarea.value = selectionManager.selectionText;
|
||||
term.textarea.select();
|
||||
}
|
||||
|
||||
@@ -23,11 +23,13 @@ export class MouseZoneManager extends Disposable implements IMouseZoneManager {
|
||||
|
||||
private _areZonesActive: boolean = false;
|
||||
private _mouseMoveListener: (e: MouseEvent) => any;
|
||||
private _mouseLeaveListener: (e: MouseEvent) => any;
|
||||
private _clickListener: (e: MouseEvent) => any;
|
||||
|
||||
private _tooltipTimeout: number = null;
|
||||
private _currentZone: IMouseZone = null;
|
||||
private _lastHoverCoords: [number, number] = [null, null];
|
||||
private _initialSelectionLength: number;
|
||||
|
||||
constructor(
|
||||
private _terminal: ITerminal
|
||||
@@ -38,6 +40,7 @@ export class MouseZoneManager extends Disposable implements IMouseZoneManager {
|
||||
|
||||
// These events are expensive, only listen to it when mouse zones are active
|
||||
this._mouseMoveListener = e => this._onMouseMove(e);
|
||||
this._mouseLeaveListener = e => this._onMouseLeave(e);
|
||||
this._clickListener = e => this._onClick(e);
|
||||
}
|
||||
|
||||
@@ -89,6 +92,7 @@ export class MouseZoneManager extends Disposable implements IMouseZoneManager {
|
||||
if (!this._areZonesActive) {
|
||||
this._areZonesActive = true;
|
||||
this._terminal.element.addEventListener('mousemove', this._mouseMoveListener);
|
||||
this._terminal.element.addEventListener('mouseleave', this._mouseLeaveListener);
|
||||
this._terminal.element.addEventListener('click', this._clickListener);
|
||||
}
|
||||
}
|
||||
@@ -97,6 +101,7 @@ export class MouseZoneManager extends Disposable implements IMouseZoneManager {
|
||||
if (this._areZonesActive) {
|
||||
this._areZonesActive = false;
|
||||
this._terminal.element.removeEventListener('mousemove', this._mouseMoveListener);
|
||||
this._terminal.element.removeEventListener('mouseleave', this._mouseLeaveListener);
|
||||
this._terminal.element.removeEventListener('click', this._clickListener);
|
||||
}
|
||||
}
|
||||
@@ -153,6 +158,10 @@ export class MouseZoneManager extends Disposable implements IMouseZoneManager {
|
||||
}
|
||||
|
||||
private _onMouseDown(e: MouseEvent): void {
|
||||
// Store current terminal selection length, to check if we're performing
|
||||
// a selection operation
|
||||
this._initialSelectionLength = this._terminal.getSelection().length;
|
||||
|
||||
// Ignore the event if there are no zones active
|
||||
if (!this._areZonesActive) {
|
||||
return;
|
||||
@@ -169,10 +178,25 @@ export class MouseZoneManager extends Disposable implements IMouseZoneManager {
|
||||
}
|
||||
}
|
||||
|
||||
private _onMouseLeave(e: MouseEvent): void {
|
||||
// Fire the hover end callback and cancel any existing timer if the mouse
|
||||
// leaves the terminal element
|
||||
if (this._currentZone) {
|
||||
this._currentZone.leaveCallback();
|
||||
this._currentZone = null;
|
||||
if (this._tooltipTimeout) {
|
||||
clearTimeout(this._tooltipTimeout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private _onClick(e: MouseEvent): void {
|
||||
// Find the active zone and click it if found
|
||||
// Find the active zone and click it if found and no selection was
|
||||
// being performed
|
||||
const zone = this._findZoneEventAt(e);
|
||||
if (zone) {
|
||||
const currentSelectionLength = this._terminal.getSelection().length;
|
||||
|
||||
if (zone && currentSelectionLength === this._initialSelectionLength) {
|
||||
zone.clickCallback(e);
|
||||
e.preventDefault();
|
||||
e.stopImmediatePropagation();
|
||||
|
||||
@@ -4,12 +4,13 @@
|
||||
*/
|
||||
|
||||
import { IColorSet, IRenderer, IRenderDimensions, IColorManager } from '../renderer/Types';
|
||||
import { IInputHandlingTerminal, IViewport, ICompositionHelper, ITerminal, IBuffer, IBufferSet, IBrowser, ICharMeasure, ISelectionManager, ITerminalOptions, ILinkifier, IMouseHelper, ILinkMatcherOptions, CharacterJoinerHandler, IBufferLine, IBufferStringIterator, ICellData } from '../Types';
|
||||
import { IInputHandlingTerminal, IViewport, ICompositionHelper, ITerminal, IBuffer, IBufferSet, IBrowser, ICharMeasure, ISelectionManager, ITerminalOptions, ILinkifier, IMouseHelper, ILinkMatcherOptions, CharacterJoinerHandler, IBufferLine, IBufferStringIterator, ICellData, IAttributeData } from '../Types';
|
||||
import { ICircularList, XtermListener } from '../common/Types';
|
||||
import { Buffer } from '../Buffer';
|
||||
import * as Browser from '../core/Platform';
|
||||
import * as Browser from '../common/Platform';
|
||||
import { ITheme, IDisposable, IMarker } from 'xterm';
|
||||
import { Terminal } from '../Terminal';
|
||||
import { AttributeData } from '../BufferLine';
|
||||
|
||||
export class TestTerminal extends Terminal {
|
||||
writeSync(data: string): void {
|
||||
@@ -190,7 +191,7 @@ export class MockInputHandlingTerminal implements IInputHandlingTerminal {
|
||||
insertMode: boolean;
|
||||
wraparoundMode: boolean;
|
||||
bracketedPasteMode: boolean;
|
||||
curAttr: number;
|
||||
curAttrData = new AttributeData();
|
||||
savedCols: number;
|
||||
x10Mouse: boolean;
|
||||
vt200Mouse: boolean;
|
||||
@@ -225,7 +226,7 @@ export class MockInputHandlingTerminal implements IInputHandlingTerminal {
|
||||
setgLevel(g: number): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
eraseAttr(): number {
|
||||
eraseAttrData(): IAttributeData {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
eraseRight(x: number, y: number): void {
|
||||
@@ -312,7 +313,7 @@ export class MockBuffer implements IBuffer {
|
||||
scrollTop: number;
|
||||
savedY: number;
|
||||
savedX: number;
|
||||
savedCurAttr: number;
|
||||
savedCurAttrData = new AttributeData();
|
||||
translateBufferLineToString(lineIndex: number, trimRight: boolean, startCol?: number, endCol?: number): string {
|
||||
return Buffer.prototype.translateBufferLineToString.apply(this, arguments);
|
||||
}
|
||||
@@ -328,7 +329,7 @@ export class MockBuffer implements IBuffer {
|
||||
setLines(lines: ICircularList<IBufferLine>): void {
|
||||
this.lines = lines;
|
||||
}
|
||||
getBlankLine(attr: number, isWrapped?: boolean): IBufferLine {
|
||||
getBlankLine(attr: IAttributeData, isWrapped?: boolean): IBufferLine {
|
||||
return Buffer.prototype.getBlankLine.apply(this, arguments);
|
||||
}
|
||||
stringIndexToBufferIndex(lineIndex: number, stringIndex: number): number[] {
|
||||
@@ -337,10 +338,10 @@ export class MockBuffer implements IBuffer {
|
||||
iterator(trimRight: boolean, startIndex?: number, endIndex?: number): IBufferStringIterator {
|
||||
return Buffer.prototype.iterator.apply(this, arguments);
|
||||
}
|
||||
getNullCell(fg: number = 0, bg: number = 0): ICellData {
|
||||
getNullCell(attr?: IAttributeData): ICellData {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
getWhitespaceCell(fg: number = 0, bg: number = 0): ICellData {
|
||||
getWhitespaceCell(attr?: IAttributeData): ICellData {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user