Merge remote-tracking branch 'origin/master' into 731_screen_reader

This commit is contained in:
Daniel Imms
2018-01-05 14:28:08 -08:00
12 changed files with 155 additions and 18 deletions
+18
View File
@@ -19,45 +19,63 @@ Bill Church <billchurch@users.noreply.github.com>
Bob Reid <bobreid@Bobs-MacBook-Pro.local>
bottleofwater <nison.mael+bottleofwater@gmail.com>
Brian Mock <brian@mockbrian.com>
Bruno Ribeito <b.m.fernandes.ribeiro@gmail.com>
Carson Anderson <carson@betterservers.com>
CHaBou <chabup@delean.fr>
Christian Budde Christensen <budde377@gmail.com>
Christof Marti <chrmarti@microsoft.com>
Christopher Jeffrey <chjjeffrey@gmail.com>
coderaiser <mnemonic.enemy@gmail.com>
Dan Brown <jdanbrown@gmail.com>
Daniel Griffen <daniel@griffen.io>
Daniel Imms <daimms@microsoft.com>
Daniel Risacher <drisacher@gmail.com>
Dan Kaplun <dbkaplun@twitch.tv>
Darin Morrison <freebroccolo@users.noreply.github.com>
dcylabs <dcylabs@gmail.com>
Dominik Csapak <d.csapak@proxmox.com>
Edgar Andrés Margffoy Tuay <andfoy@gmail.com>
Elliot Saba <staticfloat@gmail.com>
Exile <exile@chamber.ee>
Felipe Gasper <felipe@felipegasper.com>
ficristo <ficristo.work@gmail.com>
Gary Ritchie <gary@rstudio.com>
hiro-su <h.sugipon@gmail.com>
Ian Lewis <ianlewis@google.com>
imoses <ido@twiggle.com>
InDieTasten <indietasten@gmail.com>
irokas <akasidiari@inf.uth.gr>
Jakob Gillich <jakob@gillich.me>
Jean Bruenn <himself@jeanbruenn.info>
Jeremy Danyow <jedanyow@microsoft.com>
Joao Moreno <jomo@microsoft.com>
Joao Moreno <mail@joaomoreno.com>
Johannes Zellner <johannes@nebulon.de>
Jon Masters <jon.masters@sky.com>
Jörg Breitbart <jerch@rockborn.de>
Justin Mecham <justin@mecham.me>
Kirill Merkushev <lanwen@yandex.ru>
Luca <LucaT1@users.noreply.github.com>
Lucian Buzzo <lucian.buzzo@gmail.com>
Lukas Drgon <lukas.drgon@gmail.com>
Maël Nison <nison.mael@gmail.com>
Marc Dumais <marc.dumais@ericsson.com>
Martin Chloride <i@martincl2.me>
Martin Koppehel <martin.koppehel@st.ovgu.de>
Martin Wang <jiahaow@ca.ibm.com>
Matt Bierner <matb@microsoft.com>
Michael Irwin <mikesir87@gmail.com>
Mikko Karvonen <mikko.karvonen@arm.com>
mofux <t.zilz@mofux.org>
Nicolas Ramz <nicolas.ramz@gmail.com>
npezza93 <npezza93@gmail.com>
Oleksandr Andriienko <oandriie@redhat.com>
Paris Kasidiaris <pariskasidiaris@gmail.com>
Paris Kasidiaris <paris@sourcelair.com>
Peter Baumgarten <me@peterbaumgarten.com>
Rick Baker <rick@ricktbaker.com>
runarberg <runar@greenqloud.com>
Samuel Williams <samuel.williams@oriontransfer.co.nz>
Saswat Das <saswatds@users.noreply.github.com>
Saul Costa <saul@codevolve.com>
Shuanglei Tao <tsl0922@gmail.com>
+6 -1
View File
@@ -1,6 +1,6 @@
# [![xterm.js logo](logo-full.png)](https://xtermjs.org)
[![xterm.js build status](https://api.travis-ci.org/sourcelair/xterm.js.svg)](https://travis-ci.org/sourcelair/xterm.js) [![Coverage Status](https://coveralls.io/repos/github/sourcelair/xterm.js/badge.svg)](https://coveralls.io/github/sourcelair/xterm.js) [![Gitter](https://badges.gitter.im/sourcelair/xterm.js.svg)](https://gitter.im/sourcelair/xterm.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![jsDelivr Hits](https://data.jsdelivr.com/v1/package/npm/xterm/badge?style=rounded)](https://www.jsdelivr.com/package/npm/xterm)
[![xterm.js build status](https://api.travis-ci.org/xtermjs/xterm.js.svg)](https://travis-ci.org/xtermjs/xterm.js) [![Coverage Status](https://coveralls.io/repos/github/sourcelair/xterm.js/badge.svg)](https://coveralls.io/github/sourcelair/xterm.js) [![Gitter](https://badges.gitter.im/sourcelair/xterm.js.svg)](https://gitter.im/sourcelair/xterm.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![jsDelivr Hits](https://data.jsdelivr.com/v1/package/npm/xterm/badge?style=rounded)](https://www.jsdelivr.com/package/npm/xterm)
Xterm.js is a terminal front-end component written in JavaScript that works in the browser.
@@ -115,6 +115,11 @@ computational environment for Jupyter, supporting interactive data science and s
- [**Theia**](https://github.com/theia-ide/theia): Theia is a cloud & desktop IDE framework implemented in TypeScript.
- [**Opshell**](https://github.com/ricktbaker/opshell) Ops Helper tool to make life easier working with AWS instances across multiple organizations.
- [**Proxmox VE**](https://www.proxmox.com/en/proxmox-ve): Proxmox VE is a complete open-source platform for enterprise virtualization. It uses xterm.js for container terminals and the host shell.
- [**Script Runner**](https://github.com/ioquatix/script-runner): Run scripts (or a shell) in Atom.
- [**Whack Whack Terminal**](https://github.com/Microsoft/WhackWhackTerminal): Terminal emulator for Visual Studio 2017.
- [**VTerm**](https://github.com/vterm/vterm): Extensible terminal emulator based on Electron and React.
- [**electerm**](http://electerm.html5beta.com): electerm is a terminal/ssh/sftp client(mac, win, linux) based on electron/node-pty/xterm.
- [**Kubebox**](https://github.com/astefanutti/kubebox): Terminal console for Kubernetes clusters.
Do you use xterm.js in your application as well? Please [open a Pull Request](https://github.com/sourcelair/xterm.js/pulls) to include it here. We would love to have it in our list.
+4 -3
View File
@@ -1,7 +1,7 @@
{
"name": "xterm",
"description": "Full xterm terminal, in your browser",
"version": "2.9.1",
"version": "3.0.0",
"ignore": [
"demo",
"test",
@@ -9,7 +9,7 @@
],
"main": "lib/Terminal.js",
"types": "typings/xterm.d.ts",
"repository": "https://github.com/sourcelair/xterm.js",
"repository": "https://github.com/xtermjs/xterm.js",
"license": "MIT",
"files": [
"*.js",
@@ -35,7 +35,8 @@
"src/*.ts",
"src/**/*.js",
"src/**/*.js.map",
"src/**/*.ts"
"src/**/*.ts",
"typings/*.d.ts"
],
"devDependencies": {
"@types/chai": "^3.4.34",
+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 -1
View File
@@ -647,7 +647,6 @@ export class Terminal extends EventEmitter implements ITerminal, IInputHandlingT
this.on('resize', () => this.renderer.onResize(this.cols, this.rows, false));
this.on('blur', () => this.renderer.onBlur());
this.on('focus', () => this.renderer.onFocus());
window.addEventListener('resize', () => this.renderer.onWindowResize(window.devicePixelRatio));
this.charMeasure.on('charsizechanged', () => this.renderer.onResize(this.cols, this.rows, true));
this.renderer.on('resize', (dimensions) => this.viewport.syncScrollArea());
@@ -1463,6 +1462,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) {
+49 -8
View File
@@ -14,12 +14,16 @@ import { IRenderLayer, IColorSet, IRenderer, IRenderDimensions } from './Interfa
import { LinkRenderLayer } from './LinkRenderLayer';
import { EventEmitter } from '../EventEmitter';
import { RenderDebouncer } from '../utils/RenderDebouncer';
import { ScreenDprMonitor } from '../utils/ScreenDprMonitor';
export class Renderer extends EventEmitter implements IRenderer {
private _renderDebouncer: RenderDebouncer;
private _renderLayers: IRenderLayer[];
private _devicePixelRatio: number;
private _screenDprMonitor: ScreenDprMonitor;
private _isPaused: boolean = false;
private _needsFullRefresh: boolean = false;
public colorManager: ColorManager;
public dimensions: IRenderDimensions;
@@ -53,6 +57,23 @@ export class Renderer extends EventEmitter implements IRenderer {
this._devicePixelRatio = window.devicePixelRatio;
this._updateDimensions();
this._renderDebouncer = new RenderDebouncer(this._terminal, this._renderRows.bind(this));
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 {
@@ -73,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;
}
@@ -86,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,
@@ -99,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));
}
}
/**
@@ -129,6 +166,10 @@ export class Renderer extends EventEmitter implements IRenderer {
* @param {number} end The end row.
*/
public refreshRows(start: number, end: number): void {
if (this._isPaused) {
this._needsFullRefresh = true;
return;
}
this._renderDebouncer.refresh(start, end);
}
+55
View File
@@ -0,0 +1,55 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
export type ScreenDprListener = (newDevicePixelRatio?: number, oldDevicePixelRatio?: number) => void;
/**
* The screen device pixel ratio monitor allows listening for when the
* window.devicePixelRatio value changes. This is done not with polling but with
* the use of window.matchMedia to watch media queries. When the event fires,
* the listener will be reattached using a different media query to ensure that
* any further changes will register.
*
* The listener should fire on both window zoom changes and switching to a
* monitor with a different DPI.
*/
export class ScreenDprMonitor {
private _currentDevicePixelRatio: number;
private _outerListener: MediaQueryListListener;
private _listener: ScreenDprListener;
private _resolutionMediaMatchList: MediaQueryList;
public setListener(listener: ScreenDprListener): void {
if (this._listener) {
this.clearListener();
}
this._listener = listener;
this._outerListener = () => {
this._listener(window.devicePixelRatio, this._currentDevicePixelRatio);
this._updateDpr();
};
this._updateDpr();
}
private _updateDpr(): void {
// Clear listeners for old DPR
if (this._resolutionMediaMatchList) {
this._resolutionMediaMatchList.removeListener(this._outerListener);
}
// Add listeners for new DPR
this._currentDevicePixelRatio = window.devicePixelRatio;
this._resolutionMediaMatchList = window.matchMedia(`screen and (resolution: ${window.devicePixelRatio}dppx)`);
this._resolutionMediaMatchList.addListener(this._outerListener);
}
public clearListener(): void {
if (!this._listener) {
return;
}
this._resolutionMediaMatchList.removeListener(this._outerListener);
this._listener = null;
this._outerListener = null;
}
}
+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 {