Merge pull request #810 from Tyriar/809_onSingleClick_null_check

Make SelectionManager more resilient
This commit is contained in:
Daniel Imms 2017-07-21 06:30:56 -07:00 committed by GitHub
commit 2e9177a032
2 changed files with 34 additions and 8 deletions

View File

@ -277,6 +277,10 @@ export class SelectionManager extends EventEmitter {
*/ */
private _getMouseBufferCoords(event: MouseEvent): [number, number] { private _getMouseBufferCoords(event: MouseEvent): [number, number] {
const coords = Mouse.getCoords(event, this._rowContainer, this._charMeasure, this._terminal.cols, this._terminal.rows, true); const coords = Mouse.getCoords(event, this._rowContainer, this._charMeasure, this._terminal.cols, this._terminal.rows, true);
if (!coords) {
return null;
}
// Convert to 0-based // Convert to 0-based
coords[0]--; coords[0]--;
coords[1]--; coords[1]--;
@ -377,15 +381,25 @@ export class SelectionManager extends EventEmitter {
this._model.selectionStartLength = 0; this._model.selectionStartLength = 0;
this._model.isSelectAllActive = false; this._model.isSelectAllActive = false;
this._activeSelectionMode = SelectionMode.NORMAL; this._activeSelectionMode = SelectionMode.NORMAL;
// Initialize the new selection
this._model.selectionStart = this._getMouseBufferCoords(event); this._model.selectionStart = this._getMouseBufferCoords(event);
if (this._model.selectionStart) { if (!this._model.selectionStart) {
this._model.selectionEnd = null; return;
// If the mouse is over the second half of a wide character, adjust the }
// selection to cover the whole character this._model.selectionEnd = null;
const char = this._buffer.get(this._model.selectionStart[1])[this._model.selectionStart[0]];
if (char[LINE_DATA_WIDTH_INDEX] === 0) { // Ensure the line exists
this._model.selectionStart[0]++; const line = this._buffer.get(this._model.selectionStart[1]);
} if (!line) {
return;
}
// If the mouse is over the second half of a wide character, adjust the
// selection to cover the whole character
const char = line[this._model.selectionStart[0]];
if (char[LINE_DATA_WIDTH_INDEX] === 0) {
this._model.selectionStart[0]++;
} }
} }
@ -426,6 +440,10 @@ export class SelectionManager extends EventEmitter {
// Set the initial selection end based on the mouse coordinates // Set the initial selection end based on the mouse coordinates
this._model.selectionEnd = this._getMouseBufferCoords(event); this._model.selectionEnd = this._getMouseBufferCoords(event);
if (!this._model.selectionEnd) {
this.refresh(true);
return;
}
// Select the entire line if line select mode is active. // Select the entire line if line select mode is active.
if (this._activeSelectionMode === SelectionMode.LINE) { if (this._activeSelectionMode === SelectionMode.LINE) {

View File

@ -37,7 +37,15 @@ export function getCoordsRelativeToElement(event: MouseEvent, element: HTMLEleme
* select that cell and the right half will select the next cell. * select that cell and the right half will select the next cell.
*/ */
export function getCoords(event: MouseEvent, rowContainer: HTMLElement, charMeasure: CharMeasure, colCount: number, rowCount: number, isSelection?: boolean): [number, number] { export function getCoords(event: MouseEvent, rowContainer: HTMLElement, charMeasure: CharMeasure, colCount: number, rowCount: number, isSelection?: boolean): [number, number] {
// Coordinates cannot be measured if charMeasure has not been initialized
if (!charMeasure.width || !charMeasure.height) {
return null;
}
const coords = getCoordsRelativeToElement(event, rowContainer); const coords = getCoordsRelativeToElement(event, rowContainer);
if (!coords) {
return null;
}
// Convert to cols/rows. // Convert to cols/rows.
coords[0] = Math.ceil((coords[0] + (isSelection ? charMeasure.width / 2 : 0)) / charMeasure.width); coords[0] = Math.ceil((coords[0] + (isSelection ? charMeasure.width / 2 : 0)) / charMeasure.width);