Merge commit 'd261862' into webgl2

This commit is contained in:
Daniel Imms
2019-05-18 14:27:22 -07:00
43 changed files with 267 additions and 118 deletions
+1
View File
@@ -42,6 +42,7 @@ lib/test/
docs/
/.idea/
.vscode/
bin/
build/
fixtures/
coverage/
+3
View File
@@ -0,0 +1,3 @@
{
"typescript.preferences.quoteStyle": "single"
}
+10
View File
@@ -168,6 +168,16 @@ Xterm.js follows a monthly release cycle roughly.
All current and past releases are available on this repo's [Releases page](https://github.com/sourcelair/xterm.js/releases), you can view the [high-level roadmap on the wiki](https://github.com/xtermjs/xterm.js/wiki/Roadmap) and see what we're working on now by looking through [Milestones](https://github.com/sourcelair/xterm.js/milestones).
### Beta builds
Our CI releases beta builds to npm for every change that goes into master, install the latest beta build with:
```
npm install -S xterm@beta
```
These should generally be stable but some bugs may slip in, we recommend using the beta build primarily to test out new features and for verifying bug fixes.
## Contributing
You can read the [guide on the wiki](https://github.com/xtermjs/xterm.js/wiki/Contributing) to learn how to contribute and setup xterm.js for development.
+25
View File
@@ -66,3 +66,28 @@ jobs:
- script: |
yarn lint
displayName: 'Lint'
- job: Release
dependsOn:
- Linux
- macOS
- Windows
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
pool:
vmImage: 'ubuntu-16.04'
steps:
- task: NodeTool@0
inputs:
versionSpec: '8.x'
displayName: 'Install Node.js'
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
inputs:
versionSpec: "1.9.4"
displayName: 'Install Yarn'
- script: |
yarn
BUILD_DIR=dist npm run build
displayName: 'Install dependencies and build'
- script: |
NPM_AUTH_TOKEN="$(NPM_AUTH_TOKEN)" node ./bin/publish.js
displayName: 'Publish to npm'
+50
View File
@@ -0,0 +1,50 @@
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/
const cp = require('child_process');
const fs = require('fs');
const path = require('path');
const packageJson = require('../package.json');
// Setup auth
fs.writeFileSync(`${process.env['HOME']}/.npmrc`, `//registry.npmjs.org/:_authToken=${process.env['NPM_AUTH_TOKEN']}`);
// Get the version
const tag = 'beta'
const nextVersion = getNextVersion(tag);
console.log(`Publishing version: ${nextVersion}`);
// Set the version in package.json
const packageJsonFile = path.resolve(__dirname, '..', 'package.json');
packageJson.version = nextVersion;
fs.writeFileSync(packageJsonFile, JSON.stringify(packageJson, null, 2));
// Publish
const result = cp.spawn('npm', ['publish', '--tag', tag], {
stdio: 'inherit'
});
result.on('exit', code => process.exit(code));
function getNextVersion(tag) {
if (!/^[0-9]+\.[0-9]+\.[0-9]+$/.exec(packageJson.version)) {
console.error('The package.json version must be of the form x.y.z');
process.exit(1);
}
const stableVersion = packageJson.version.split('.');
const nextStableVersion = `${stableVersion[0]}.${parseInt(stableVersion[1]) + 1}.${stableVersion[2]}`;
const publishedVersions = getPublishedVersions(nextStableVersion, tag);
if (publishedVersions.length === 0) {
return `${packageJson.version}-${tag}1`;
}
const latestPublishedVersion = publishedVersions.sort((a, b) => b.localeCompare(a))[0];
const latestTagVersion = parseInt(latestPublishedVersion.substr(latestPublishedVersion.search(/[0-9]+$/)), 10);
return `${nextStableVersion}-${tag}${latestTagVersion + 1}`;
}
function getPublishedVersions(version, tag) {
const versionsProcess = cp.spawnSync('npm', ['view', 'xterm', 'versions', '--json']);
const versionsJson = JSON.parse(versionsProcess.stdout);
return versionsJson.filter(v => !v.search(new RegExp(`${version}-${tag}[0-9]+`)));
}
+1 -1
View File
@@ -61,4 +61,4 @@
"coveralls": "nyc report --reporter=text-lcov | coveralls",
"watch": "tsc -b -w ./src/tsconfig.all.json --preserveWatchOutput"
}
}
}
+2 -2
View File
@@ -61,7 +61,7 @@ export class AccessibilityManager extends Disposable {
this._refreshRowsDimensions();
this._accessibilityTreeRoot.appendChild(this._rowContainer);
this._renderRowsDebouncer = new RenderDebouncer(this._terminal, this._renderRows.bind(this));
this._renderRowsDebouncer = new RenderDebouncer(this._renderRows.bind(this));
this._refreshRows();
this._liveRegion = document.createElement('div');
@@ -239,7 +239,7 @@ export class AccessibilityManager extends Disposable {
}
private _refreshRows(start?: number, end?: number): void {
this._renderRowsDebouncer.refresh(start, end);
this._renderRowsDebouncer.refresh(start, end, this._terminal.rows);
}
private _renderRows(start: number, end: number): void {
+1 -1
View File
@@ -7,7 +7,7 @@ import { assert, expect } from 'chai';
import { ITerminal } from './Types';
import { Buffer, DEFAULT_ATTR_DATA } from './Buffer';
import { CircularList } from './common/CircularList';
import { MockTerminal, TestTerminal } from './ui/TestUtils.test';
import { MockTerminal, TestTerminal } from './TestUtils.test';
import { BufferLine, CellData } from './BufferLine';
const INIT_COLS = 80;
+1 -1
View File
@@ -7,7 +7,7 @@ import { assert } from 'chai';
import { ITerminal } from './Types';
import { BufferSet } from './BufferSet';
import { Buffer } from './Buffer';
import { MockTerminal } from './ui/TestUtils.test';
import { MockTerminal } from './TestUtils.test';
describe('BufferSet', () => {
let terminal: ITerminal;
@@ -4,7 +4,7 @@
*/
import jsdom = require('jsdom');
import { ICharMeasure } from '../Types';
import { ICharMeasure } from './Types';
import { assert } from 'chai';
import { CharMeasure } from './CharMeasure';
+2 -2
View File
@@ -3,8 +3,8 @@
* @license MIT
*/
import { ICharMeasure, ITerminalOptions } from '../Types';
import { EventEmitter2, IEvent } from '../common/EventEmitter2';
import { ICharMeasure, ITerminalOptions } from './Types';
import { EventEmitter2, IEvent } from './common/EventEmitter2';
/**
* Utility class that measures the size of a character. Measurements are done in
+1 -1
View File
@@ -3,7 +3,7 @@
* @license MIT
*/
import { TestTerminal } from './ui/TestUtils.test';
import { TestTerminal } from './TestUtils.test';
import { assert } from 'chai';
import { getStringCellWidth, wcwidth } from './CharWidth';
import { IBuffer } from './Types';
+1 -1
View File
@@ -3,7 +3,7 @@
* @license MIT
*/
import { ITerminal, ISelectionManager } from '../Types';
import { ITerminal, ISelectionManager } from './Types';
interface IWindow extends Window {
clipboardData?: {
+1 -1
View File
@@ -5,7 +5,7 @@
import { assert, expect } from 'chai';
import { InputHandler } from './InputHandler';
import { MockInputHandlingTerminal, TestTerminal } from './ui/TestUtils.test';
import { MockInputHandlingTerminal, TestTerminal } from './TestUtils.test';
import { DEFAULT_ATTR_DATA } from './Buffer';
import { Terminal } from './Terminal';
import { IBufferLine } from './Types';
+2 -3
View File
@@ -4,10 +4,9 @@
*/
import { assert } from 'chai';
import { IMouseZoneManager, IMouseZone } from './ui/Types';
import { ILinkMatcher, ITerminal, IBufferLine } from './Types';
import { IMouseZoneManager, IMouseZone, ILinkMatcher, ITerminal, IBufferLine } from './Types';
import { Linkifier } from './Linkifier';
import { MockBuffer, MockTerminal, TestTerminal } from './ui/TestUtils.test';
import { MockBuffer, MockTerminal, TestTerminal } from './TestUtils.test';
import { CircularList } from './common/CircularList';
import { BufferLine, CellData } from './BufferLine';
+2 -3
View File
@@ -3,9 +3,8 @@
* @license MIT
*/
import { IMouseZoneManager } from './ui/Types';
import { ILinkifierEvent, ILinkMatcher, LinkMatcherHandler, ILinkMatcherOptions, ILinkifier, ITerminal, IBufferStringIteratorResult } from './Types';
import { MouseZone } from './ui/MouseZoneManager';
import { ILinkifierEvent, ILinkMatcher, LinkMatcherHandler, ILinkMatcherOptions, ILinkifier, ITerminal, IBufferStringIteratorResult, IMouseZoneManager } from './Types';
import { MouseZone } from './MouseZoneManager';
import { getStringCellWidth } from './CharWidth';
import { EventEmitter2, IEvent } from './common/EventEmitter2';
+2 -2
View File
@@ -3,8 +3,8 @@
* @license MIT
*/
import { ICharMeasure, IMouseHelper } from '../Types';
import { IRenderer } from '../renderer/Types';
import { ICharMeasure, IMouseHelper } from './Types';
import { IRenderer } from './renderer/Types';
export class MouseHelper implements IMouseHelper {
constructor(private _renderer: IRenderer) {}
@@ -3,10 +3,9 @@
* @license MIT
*/
import { ITerminal } from '../Types';
import { IMouseZoneManager, IMouseZone } from './Types';
import { Disposable } from '../common/Lifecycle';
import { addDisposableDomListener } from './Lifecycle';
import { ITerminal, IMouseZoneManager, IMouseZone } from './Types';
import { Disposable } from './common/Lifecycle';
import { addDisposableDomListener } from './ui/Lifecycle';
const HOVER_DURATION = 500;
+2 -2
View File
@@ -4,12 +4,12 @@
*/
import { assert } from 'chai';
import { CharMeasure } from './ui/CharMeasure';
import { CharMeasure } from './CharMeasure';
import { SelectionManager, SelectionMode } from './SelectionManager';
import { SelectionModel } from './SelectionModel';
import { BufferSet } from './BufferSet';
import { ITerminal, IBuffer, IBufferLine } from './Types';
import { MockTerminal } from './ui/TestUtils.test';
import { MockTerminal } from './TestUtils.test';
import { BufferLine, CellData } from './BufferLine';
class TestMockTerminal extends MockTerminal {
+2 -2
View File
@@ -4,9 +4,9 @@
*/
import { ITerminal, ISelectionManager, IBuffer, IBufferLine, ISelectionRedrawRequestEvent } from './Types';
import { MouseHelper } from './ui/MouseHelper';
import { MouseHelper } from './MouseHelper';
import * as Browser from './common/Platform';
import { CharMeasure } from './ui/CharMeasure';
import { CharMeasure } from './CharMeasure';
import { SelectionModel } from './SelectionModel';
import { AltClickHandler } from './handlers/AltClickHandler';
import { CellData } from './BufferLine';
+1 -1
View File
@@ -7,7 +7,7 @@ import { assert } from 'chai';
import { ITerminal } from './Types';
import { SelectionModel } from './SelectionModel';
import { BufferSet } from './BufferSet';
import { MockTerminal } from './ui/TestUtils.test';
import { MockTerminal } from './TestUtils.test';
class TestSelectionModel extends SelectionModel {
constructor(
+1 -1
View File
@@ -5,7 +5,7 @@
import { assert, expect } from 'chai';
import { Terminal } from './Terminal';
import { MockViewport, MockCompositionHelper, MockRenderer } from './ui/TestUtils.test';
import { MockViewport, MockCompositionHelper, MockRenderer } from './TestUtils.test';
import { DEFAULT_ATTR_DATA } from './Buffer';
import { CellData } from './BufferLine';
+5 -6
View File
@@ -21,27 +21,26 @@
* http://linux.die.net/man/7/urxvt
*/
import { IInputHandlingTerminal, IViewport, ICompositionHelper, ITerminalOptions, ITerminal, IBrowser, ILinkifier, ILinkMatcherOptions, CustomKeyEventHandler, LinkMatcherHandler, CharacterJoinerHandler, IBufferLine, IAttributeData } from './Types';
import { IMouseZoneManager } from './ui/Types';
import { IInputHandlingTerminal, IViewport, ICompositionHelper, ITerminalOptions, ITerminal, IBrowser, ILinkifier, ILinkMatcherOptions, CustomKeyEventHandler, LinkMatcherHandler, CharacterJoinerHandler, IBufferLine, IAttributeData, IMouseZoneManager } from './Types';
import { IRenderer } from './renderer/Types';
import { BufferSet } from './BufferSet';
import { Buffer, MAX_BUFFER_SIZE, DEFAULT_ATTR_DATA } from './Buffer';
import { CompositionHelper } from './CompositionHelper';
import { EventEmitter } from './common/EventEmitter';
import { Viewport } from './Viewport';
import { rightClickHandler, moveTextAreaUnderMouseCursor, pasteHandler, copyHandler } from './ui/Clipboard';
import { rightClickHandler, moveTextAreaUnderMouseCursor, pasteHandler, copyHandler } from './Clipboard';
import { C0 } from './common/data/EscapeSequences';
import { InputHandler } from './InputHandler';
import { Renderer } from './renderer/Renderer';
import { Linkifier } from './Linkifier';
import { SelectionManager } from './SelectionManager';
import { CharMeasure } from './ui/CharMeasure';
import { CharMeasure } from './CharMeasure';
import * as Browser from './common/Platform';
import { addDisposableDomListener } from './ui/Lifecycle';
import * as Strings from './Strings';
import { MouseHelper } from './ui/MouseHelper';
import { MouseHelper } from './MouseHelper';
import { DEFAULT_BELL_SOUND, SoundManager } from './SoundManager';
import { MouseZoneManager } from './ui/MouseZoneManager';
import { MouseZoneManager } from './MouseZoneManager';
import { AccessibilityManager } from './AccessibilityManager';
import { ScreenDprMonitor } from './ui/ScreenDprMonitor';
import { ITheme, IMarker, IDisposable } from 'xterm';
@@ -3,14 +3,14 @@
* @license MIT
*/
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, IAttributeData } from '../Types';
import { ICircularList, XtermListener } from '../common/Types';
import { Buffer } from '../Buffer';
import * as Browser from '../common/Platform';
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, IAttributeData } from './Types';
import { ICircularList, XtermListener } from './common/Types';
import { Buffer } from './Buffer';
import * as Browser from './common/Platform';
import { ITheme, IDisposable, IMarker, IEvent } from 'xterm';
import { Terminal } from '../Terminal';
import { AttributeData } from '../BufferLine';
import { Terminal } from './Terminal';
import { AttributeData } from './BufferLine';
export class TestTerminal extends Terminal {
writeSync(data: string): void {
+17 -1
View File
@@ -5,7 +5,6 @@
import { Terminal as PublicTerminal, ITerminalOptions as IPublicTerminalOptions, IEventEmitter, IDisposable } from 'xterm';
import { IColorSet, IRenderer } from './renderer/Types';
import { IMouseZoneManager } from './ui/Types';
import { ICharset } from './core/Types';
import { ICircularList } from './common/Types';
import { IEvent } from './common/EventEmitter2';
@@ -605,3 +604,20 @@ export interface IBufferLine {
isCombined(index: number): number;
getString(index: number): string;
}
export interface IMouseZoneManager extends IDisposable {
add(zone: IMouseZone): void;
clearAll(start?: number, end?: number): void;
}
export interface IMouseZone {
x1: number;
x2: number;
y1: number;
y2: number;
clickCallback: (e: MouseEvent) => any;
hoverCallback: (e: MouseEvent) => any | undefined;
tooltipCallback: (e: MouseEvent) => any | undefined;
leaveCallback: () => any | undefined;
willLinkActivate: (e: MouseEvent) => boolean;
}
+1 -1
View File
@@ -5,7 +5,7 @@
import { IColorSet } from './renderer/Types';
import { ITerminal, IViewport } from './Types';
import { CharMeasure } from './ui/CharMeasure';
import { CharMeasure } from './CharMeasure';
import { Disposable } from './common/Lifecycle';
import { addDisposableDomListener } from './ui/Lifecycle';
+6
View File
@@ -21,6 +21,7 @@ export class SearchHelper implements ISearchHelper {
private _linesCache: string[] = null;
private _linesCacheTimeoutId = 0;
private _cursorMoveListener: IDisposable | undefined;
private _resizeListener: IDisposable | undefined;
constructor(private _terminal: ISearchAddonTerminal) {
this._destroyLinesCache = this._destroyLinesCache.bind(this);
@@ -185,6 +186,7 @@ export class SearchHelper implements ISearchHelper {
if (!this._linesCache) {
this._linesCache = new Array(this._terminal._core.buffer.length);
this._cursorMoveListener = this._terminal.onCursorMove(() => this._destroyLinesCache());
this._resizeListener = this._terminal.onResize(() => this._destroyLinesCache());
}
window.clearTimeout(this._linesCacheTimeoutId);
@@ -197,6 +199,10 @@ export class SearchHelper implements ISearchHelper {
this._cursorMoveListener.dispose();
this._cursorMoveListener = undefined;
}
if (this._resizeListener) {
this._resizeListener.dispose();
this._resizeListener = undefined;
}
if (this._linesCacheTimeoutId) {
window.clearTimeout(this._linesCacheTimeoutId);
this._linesCacheTimeoutId = 0;
+11 -7
View File
@@ -322,14 +322,18 @@ export abstract class BaseRenderLayer implements IRenderLayer {
} else {
this._ctx.fillStyle = this._colors.ansi[cell.getBgColor()].css;
}
} else if (cell.isFgRGB()) {
this._ctx.fillStyle = `rgb(${AttributeData.toColorRGB(cell.getFgColor()).join(',')})`;
} else if (cell.isFgPalette()) {
let fg = cell.getFgColor();
if (terminal.options.drawBoldTextInBrightColors && cell.isBold() && fg < 8) {
fg += 8;
} else {
if (cell.isFgDefault()) {
this._ctx.fillStyle = this._colors.foreground.css;
} else if (cell.isFgRGB()) {
this._ctx.fillStyle = `rgb(${AttributeData.toColorRGB(cell.getFgColor()).join(',')})`;
} else {
let fg = cell.getFgColor();
if (terminal.options.drawBoldTextInBrightColors && cell.isBold() && fg < 8) {
fg += 8;
}
this._ctx.fillStyle = this._colors.ansi[fg].css;
}
this._ctx.fillStyle = this._colors.ansi[fg].css;
}
this._clipRow(terminal, y);
+1 -1
View File
@@ -1,6 +1,6 @@
import { assert } from 'chai';
import { MockTerminal, MockBuffer } from '../ui/TestUtils.test';
import { MockTerminal, MockBuffer } from '../TestUtils.test';
import { CircularList } from '../common/CircularList';
import { ICharacterJoinerRegistry } from './Types';
+2 -2
View File
@@ -68,7 +68,7 @@ export class Renderer extends Disposable implements IRenderer {
this._updateDimensions();
this.onOptionsChanged();
this._renderDebouncer = new RenderDebouncer(this._terminal, this._renderRows.bind(this));
this._renderDebouncer = new RenderDebouncer(this._renderRows.bind(this));
this._screenDprMonitor = new ScreenDprMonitor();
this._screenDprMonitor.setListener(() => this.onWindowResize(window.devicePixelRatio));
this.register(this._screenDprMonitor);
@@ -194,7 +194,7 @@ export class Renderer extends Disposable implements IRenderer {
this._needsFullRefresh = true;
return;
}
this._renderDebouncer.refresh(start, end);
this._renderDebouncer.refresh(start, end, this._terminal.rows);
}
/**
+12 -4
View File
@@ -217,10 +217,18 @@ export class TextRenderLayer extends BaseRenderLayer {
} else {
this._ctx.fillStyle = this._colors.ansi[cell.getBgColor()].css;
}
} else if (cell.isFgRGB()) {
this._ctx.fillStyle = `rgb(${AttributeData.toColorRGB(cell.getFgColor()).join(',')})`;
} else if (cell.isFgPalette()) {
this._ctx.fillStyle = this._colors.ansi[cell.getFgColor()].css;
} else {
if (cell.isFgDefault()) {
this._ctx.fillStyle = this._colors.foreground.css;
} else if (cell.isFgRGB()) {
this._ctx.fillStyle = `rgb(${AttributeData.toColorRGB(cell.getFgColor()).join(',')})`;
} else {
let fg = cell.getFgColor();
if (terminal.options.drawBoldTextInBrightColors && cell.isBold() && fg < 8) {
fg += 8;
}
this._ctx.fillStyle = this._colors.ansi[fg].css;
}
}
this.fillBottomLineAtCells(x, y, cell.getWidth());
+2 -2
View File
@@ -80,7 +80,7 @@ export class DomRenderer extends Disposable implements IRenderer {
};
this._updateDimensions();
this._renderDebouncer = new RenderDebouncer(this._terminal, this._renderRows.bind(this));
this._renderDebouncer = new RenderDebouncer(this._renderRows.bind(this));
this._rowFactory = new DomRendererRowFactory(_terminal.options, document);
this._terminal.element.classList.add(TERMINAL_CLASS_PREFIX + this._terminalClass);
@@ -340,7 +340,7 @@ export class DomRenderer extends Disposable implements IRenderer {
}
public refreshRows(start: number, end: number): void {
this._renderDebouncer.refresh(start, end);
this._renderDebouncer.refresh(start, end, this._terminal.rows);
}
private _renderRows(start: number, end: number): void {
@@ -100,6 +100,16 @@ describe('DomRendererRowFactory', () => {
);
});
it('should add class for underline', () => {
const cell = CellData.fromCharData([0, 'a', 1, 'a'.charCodeAt(0)]);
cell.fg = DEFAULT_ATTR_DATA.fg | FgFlags.UNDERLINE;
lineData.setCell(0, cell);
const fragment = rowFactory.createRow(lineData, false, undefined, 0, false, 5, 20);
assert.equal(getFragmentHtml(fragment),
'<span class="xterm-underline">a</span>'
);
});
it('should add classes for 256 foreground colors', () => {
const cell = CellData.fromCharData([0, 'a', 1, 'a'.charCodeAt(0)]);
cell.fg |= Attributes.CM_P256;
@@ -11,6 +11,7 @@ import { CellData, AttributeData } from '../../BufferLine';
export const BOLD_CLASS = 'xterm-bold';
export const DIM_CLASS = 'xterm-dim';
export const ITALIC_CLASS = 'xterm-italic';
export const UNDERLINE_CLASS = 'xterm-underline';
export const CURSOR_CLASS = 'xterm-cursor';
export const CURSOR_BLINK_CLASS = 'xterm-cursor-blink';
export const CURSOR_STYLE_BLOCK_CLASS = 'xterm-cursor-block';
@@ -88,6 +89,10 @@ export class DomRendererRowFactory {
charElement.classList.add(DIM_CLASS);
}
if (this._workCell.isUnderline()) {
charElement.classList.add(UNDERLINE_CLASS);
}
charElement.textContent = this._workCell.getChars() || WHITESPACE_CELL_CHAR;
const swapColor = this._workCell.isInverse();
+2 -1
View File
@@ -24,6 +24,7 @@
],
"references": [
{ "path": "./common" },
{ "path": "./core" }
{ "path": "./core" },
{ "path": "./ui" }
]
}
+1 -3
View File
@@ -3,7 +3,7 @@
* @license MIT
*/
import { IDisposable } from 'xterm';
import { IDisposable } from '../common/Types';
/**
* Adds a disposable listener to a node in the DOM, returning the disposable.
@@ -24,8 +24,6 @@ export function addDisposableDomListener(
return;
}
node.removeEventListener(type, handler, useCapture);
node = null;
handler = null;
}
};
}
+28 -21
View File
@@ -1,37 +1,39 @@
import { ITerminal } from '../Types';
import { IDisposable } from 'xterm';
/**
* Copyright (c) 2018 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { IDisposable } from '../common/Types';
/**
* Debounces calls to render terminal rows using animation frames.
*/
export class RenderDebouncer implements IDisposable {
private _rowStart: number;
private _rowEnd: number;
private _animationFrame: number = null;
private _rowStart: number | undefined;
private _rowEnd: number | undefined;
private _rowCount: number | undefined;
private _animationFrame: number | undefined;
constructor(
private _terminal: ITerminal,
private _callback: (start: number, end: number) => void
private _renderCallback: (start: number, end: number) => void
) {
}
public dispose(): void {
if (this._animationFrame) {
window.cancelAnimationFrame(this._animationFrame);
this._animationFrame = null;
this._animationFrame = undefined;
}
}
public refresh(rowStart: number, rowEnd: number): void {
public refresh(rowStart: number, rowEnd: number, rowCount: number): void {
this._rowCount = rowCount;
// Get the min/max row start/end for the arg values
rowStart = rowStart !== null && rowStart !== undefined ? rowStart : 0;
rowEnd = rowEnd !== null && rowEnd !== undefined ? rowEnd : this._terminal.rows - 1;
// Check whether the row start/end values have already been set
const isRowStartSet = this._rowStart !== undefined && this._rowStart !== null;
const isRowEndSet = this._rowEnd !== undefined && this._rowEnd !== null;
rowStart = rowStart !== undefined ? rowStart : 0;
rowEnd = rowEnd !== undefined ? rowEnd : this._rowCount - 1;
// Set the properties to the updated values
this._rowStart = isRowStartSet ? Math.min(this._rowStart, rowStart) : rowStart;
this._rowEnd = isRowEndSet ? Math.max(this._rowEnd, rowEnd) : rowEnd;
this._rowStart = this._rowStart !== undefined ? Math.min(this._rowStart, rowStart) : rowStart;
this._rowEnd = this._rowEnd !== undefined ? Math.max(this._rowEnd, rowEnd) : rowEnd;
if (this._animationFrame) {
return;
@@ -41,16 +43,21 @@ export class RenderDebouncer implements IDisposable {
}
private _innerRefresh(): void {
// Make sure values are set
if (this._rowStart === undefined || this._rowEnd === undefined || this._rowCount === undefined) {
return;
}
// Clamp values
this._rowStart = Math.max(this._rowStart, 0);
this._rowEnd = Math.min(this._rowEnd, this._terminal.rows - 1);
this._rowEnd = Math.min(this._rowEnd, this._rowCount - 1);
// Run render callback
this._callback(this._rowStart, this._rowEnd);
this._renderCallback(this._rowStart, this._rowEnd);
// Reset debouncer
this._rowStart = null;
this._rowEnd = null;
this._animationFrame = null;
this._rowStart = undefined;
this._rowEnd = undefined;
this._animationFrame = undefined;
}
}
+17 -10
View File
@@ -18,10 +18,10 @@ export type ScreenDprListener = (newDevicePixelRatio?: number, oldDevicePixelRat
* monitor with a different DPI.
*/
export class ScreenDprMonitor extends Disposable {
private _currentDevicePixelRatio: number;
private _outerListener: (this: MediaQueryList, ev: MediaQueryListEvent) => any;
private _listener: ScreenDprListener;
private _resolutionMediaMatchList: MediaQueryList;
private _currentDevicePixelRatio: number = window.devicePixelRatio;
private _outerListener: ((this: MediaQueryList, ev: MediaQueryListEvent) => any) | undefined;
private _listener: ScreenDprListener | undefined;
private _resolutionMediaMatchList: MediaQueryList | undefined;
public setListener(listener: ScreenDprListener): void {
if (this._listener) {
@@ -29,6 +29,9 @@ export class ScreenDprMonitor extends Disposable {
}
this._listener = listener;
this._outerListener = () => {
if (!this._listener) {
return;
}
this._listener(window.devicePixelRatio, this._currentDevicePixelRatio);
this._updateDpr();
};
@@ -41,10 +44,13 @@ export class ScreenDprMonitor extends Disposable {
}
private _updateDpr(): void {
// Clear listeners for old DPR
if (this._resolutionMediaMatchList) {
this._resolutionMediaMatchList.removeListener(this._outerListener);
if (!this._resolutionMediaMatchList || !this._outerListener) {
return;
}
// Clear listeners for old DPR
this._resolutionMediaMatchList.removeListener(this._outerListener);
// Add listeners for new DPR
this._currentDevicePixelRatio = window.devicePixelRatio;
this._resolutionMediaMatchList = window.matchMedia(`screen and (resolution: ${window.devicePixelRatio}dppx)`);
@@ -52,11 +58,12 @@ export class ScreenDprMonitor extends Disposable {
}
public clearListener(): void {
if (!this._listener) {
if (!this._resolutionMediaMatchList || !this._listener || !this._outerListener) {
return;
}
this._resolutionMediaMatchList.removeListener(this._outerListener);
this._listener = null;
this._outerListener = null;
this._resolutionMediaMatchList = undefined;
this._listener = undefined;
this._outerListener = undefined;
}
}
-23
View File
@@ -1,23 +0,0 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { IDisposable } from 'xterm';
export interface IMouseZoneManager extends IDisposable {
add(zone: IMouseZone): void;
clearAll(start?: number, end?: number): void;
}
export interface IMouseZone {
x1: number;
x2: number;
y1: number;
y2: number;
clickCallback: (e: MouseEvent) => any;
hoverCallback: (e: MouseEvent) => any | undefined;
tooltipCallback: (e: MouseEvent) => any | undefined;
leaveCallback: () => any | undefined;
willLinkActivate: (e: MouseEvent) => boolean;
}
+21
View File
@@ -0,0 +1,21 @@
{
"extends": "../tsconfig-library-base",
"compilerOptions": {
"lib": [
"dom",
"es5",
],
"outDir": "../../lib",
"types": [
"../../node_modules/@types/mocha"
]
},
"include": [
"./Lifecycle.ts",
"./RenderDebouncer.ts",
"./ScreenDprMonitor.ts"
],
"references": [
{ "path": "../common" }
]
}
+4
View File
@@ -165,3 +165,7 @@
.xterm-dim {
opacity: 0.5;
}
.xterm-underline {
text-decoration: underline;
}