Merge remote-tracking branch 'origin/master' into 1118_dpi_change

This commit is contained in:
Daniel Imms
2018-01-05 14:19:21 -08:00
11 changed files with 95 additions and 17 deletions
+7
View File
@@ -286,36 +286,43 @@ export class Parser {
// Single Shift Select of G2 Character Set
// ( SS2 is 0x8e). This affects next character only.
case 'N':
this._state = ParserState.NORMAL;
break;
// ESC O
// Single Shift Select of G3 Character Set
// ( SS3 is 0x8f). This affects next character only.
case 'O':
this._state = ParserState.NORMAL;
break;
// ESC n
// Invoke the G2 Character Set as GL (LS2).
case 'n':
this._terminal.setgLevel(2);
this._state = ParserState.NORMAL;
break;
// ESC o
// Invoke the G3 Character Set as GL (LS3).
case 'o':
this._terminal.setgLevel(3);
this._state = ParserState.NORMAL;
break;
// ESC |
// Invoke the G3 Character Set as GR (LS3R).
case '|':
this._terminal.setgLevel(3);
this._state = ParserState.NORMAL;
break;
// ESC }
// Invoke the G2 Character Set as GR (LS2R).
case '}':
this._terminal.setgLevel(2);
this._state = ParserState.NORMAL;
break;
// ESC ~
// Invoke the G1 Character Set as GR (LS1R).
case '~':
this._terminal.setgLevel(1);
this._state = ParserState.NORMAL;
break;
// ESC 7 Save Cursor (DECSC).
+5 -1
View File
@@ -14,6 +14,10 @@ import { BufferSet } from './BufferSet';
import { MockTerminal } from './utils/TestUtils.test';
import { LineData, CharData } from './Types';
class TestMockTerminal extends MockTerminal {
emit(event: string, data: any): void {}
}
class TestSelectionManager extends SelectionManager {
constructor(
terminal: ITerminal,
@@ -48,7 +52,7 @@ describe('SelectionManager', () => {
dom = new jsdom.JSDOM('');
window = dom.window;
document = window.document;
terminal = new MockTerminal();
terminal = new TestMockTerminal();
terminal.cols = 80;
terminal.rows = 2;
terminal.options.scrollback = 100;
+3 -3
View File
@@ -255,7 +255,7 @@ export class SelectionManager extends EventEmitter implements ISelectionManager
public selectAll(): void {
this._model.isSelectAllActive = true;
this.refresh();
this.emit('selection');
this._terminal.emit('selection');
}
/**
@@ -528,7 +528,7 @@ export class SelectionManager extends EventEmitter implements ISelectionManager
this._terminal.scrollLines(this._dragScrollAmount, false);
// Re-evaluate selection
if (this._dragScrollAmount > 0) {
this._model.selectionEnd = [this._terminal.cols - 1, this._terminal.buffer.ydisp + this._terminal.rows];
this._model.selectionEnd = [this._terminal.cols - 1, Math.min(this._terminal.buffer.ydisp + this._terminal.rows, this._terminal.buffer.lines.length - 1)];
} else {
this._model.selectionEnd = [0, this._terminal.buffer.ydisp];
}
@@ -544,7 +544,7 @@ export class SelectionManager extends EventEmitter implements ISelectionManager
this._removeMouseDownListeners();
if (this.hasSelection)
this.emit('selection');
this._terminal.emit('selection');
}
/**
+3
View File
@@ -1448,6 +1448,9 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
if (ev.shiftKey) {
result.key = C0.BS; // ^H
break;
} else if (ev.altKey) {
result.key = C0.ESC + C0.DEL; // \e ^?
break;
}
result.key = C0.DEL; // ^?
break;
+3
View File
@@ -59,6 +59,9 @@ export function attach(term, socket, bidirectional, buffered) {
};
term._sendData = function(data) {
if (socket.readyState !== 1) {
return;
}
socket.send(data);
};
+1 -1
View File
@@ -34,7 +34,7 @@ export function proposeGeometry(term) {
};
export function fit(term) {
var geometry = exports.proposeGeometry(term);
var geometry = proposeGeometry(term);
if (geometry) {
// Force a full render
if (term.rows !== geometry.rows || term.cols !== geometry.cols) {
+44 -8
View File
@@ -23,6 +23,8 @@ export class Renderer extends EventEmitter implements IRenderer {
private _renderLayers: IRenderLayer[];
private _devicePixelRatio: number;
private _screenDprMonitor: ScreenDprMonitor;
private _isPaused: boolean = false;
private _needsFullRefresh: boolean = false;
public colorManager: ColorManager;
public dimensions: IRenderDimensions;
@@ -58,6 +60,20 @@ export class Renderer extends EventEmitter implements IRenderer {
this._screenDprMonitor = new ScreenDprMonitor();
this._screenDprMonitor.setListener(() => this.onWindowResize(window.devicePixelRatio));
// Detect whether IntersectionObserver is detected and enable renderer pause
// and resume based on terminal visibility if so
if ('IntersectionObserver' in window) {
const observer = new IntersectionObserver(e => this.onIntersectionChange(e[0]), {threshold: 0});
observer.observe(this._terminal.element);
}
}
public onIntersectionChange(entry: IntersectionObserverEntry): void {
this._isPaused = entry.intersectionRatio === 0;
if (!this._isPaused && this._needsFullRefresh) {
this._terminal.refresh(0, this._terminal.rows - 1);
}
}
public onWindowResize(devicePixelRatio: number): void {
@@ -78,7 +94,11 @@ export class Renderer extends EventEmitter implements IRenderer {
l.reset(this._terminal);
});
this._terminal.refresh(0, this._terminal.rows - 1);
if (this._isPaused) {
this._needsFullRefresh = true;
} else {
this._terminal.refresh(0, this._terminal.rows - 1);
}
return this.colorManager.colors;
}
@@ -91,7 +111,11 @@ export class Renderer extends EventEmitter implements IRenderer {
this._renderLayers.forEach(l => l.resize(this._terminal, this.dimensions, didCharSizeChange));
// Force a refresh
this._terminal.refresh(0, this._terminal.rows - 1);
if (this._isPaused) {
this._needsFullRefresh = true;
} else {
this._terminal.refresh(0, this._terminal.rows - 1);
}
this.emit('resize', {
width: this.dimensions.canvasWidth,
@@ -104,27 +128,35 @@ export class Renderer extends EventEmitter implements IRenderer {
}
public onBlur(): void {
this._renderLayers.forEach(l => l.onBlur(this._terminal));
this._runOperation(l => l.onBlur(this._terminal));
}
public onFocus(): void {
this._renderLayers.forEach(l => l.onFocus(this._terminal));
this._runOperation(l => l.onFocus(this._terminal));
}
public onSelectionChanged(start: [number, number], end: [number, number]): void {
this._renderLayers.forEach(l => l.onSelectionChanged(this._terminal, start, end));
this._runOperation(l => l.onSelectionChanged(this._terminal, start, end));
}
public onCursorMove(): void {
this._renderLayers.forEach(l => l.onCursorMove(this._terminal));
this._runOperation(l => l.onCursorMove(this._terminal));
}
public onOptionsChanged(): void {
this._renderLayers.forEach(l => l.onOptionsChanged(this._terminal));
this._runOperation(l => l.onOptionsChanged(this._terminal));
}
public clear(): void {
this._renderLayers.forEach(l => l.reset(this._terminal));
this._runOperation(l => l.reset(this._terminal));
}
private _runOperation(operation: (layer: IRenderLayer) => void): void {
if (this._isPaused) {
this._needsFullRefresh = true;
} else {
this._renderLayers.forEach(l => operation(l));
}
}
/**
@@ -134,6 +166,10 @@ export class Renderer extends EventEmitter implements IRenderer {
* @param {number} end The end row.
*/
public queueRefresh(start: number, end: number): void {
if (this._isPaused) {
this._needsFullRefresh = true;
return;
}
this._refreshRowsQueue.push({ start: start, end: end });
if (!this._refreshAnimationFrame) {
this._refreshAnimationFrame = window.requestAnimationFrame(this._refreshLoop.bind(this));
+1
View File
@@ -95,6 +95,7 @@
/* On OS X this is required in order for the scroll bar to appear fully opaque */
background-color: #000;
overflow-y: scroll;
cursor: default;
}
.xterm canvas {