Merge branch 'master' into webgl2

This commit is contained in:
Daniel Imms
2019-06-16 00:13:15 -07:00
committed by GitHub
37 changed files with 291 additions and 304 deletions
+1
View File
@@ -18,6 +18,7 @@ describe('InputHandler', () => {
const terminal = new MockInputHandlingTerminal();
terminal.buffer.x = 1;
terminal.buffer.y = 2;
terminal.buffer.ybase = 0;
terminal.curAttrData.fg = 3;
const inputHandler = new InputHandler(terminal);
// Save cursor position
+4 -2
View File
@@ -6,6 +6,7 @@
import { ITerminal, IMouseZoneManager, IMouseZone } from './Types';
import { Disposable } from 'common/Lifecycle';
import { addDisposableDomListener } from 'browser/Lifecycle';
import { IMouseService } from 'browser/services/Services';
const HOVER_DURATION = 500;
@@ -31,7 +32,8 @@ export class MouseZoneManager extends Disposable implements IMouseZoneManager {
private _initialSelectionLength: number;
constructor(
private _terminal: ITerminal
private _terminal: ITerminal,
private _mouseService: IMouseService
) {
super();
@@ -203,7 +205,7 @@ export class MouseZoneManager extends Disposable implements IMouseZoneManager {
}
private _findZoneEventAt(e: MouseEvent): IMouseZone {
const coords = this._terminal.mouseHelper.getCoords(e, this._terminal.screenElement, this._terminal.cols, this._terminal.rows);
const coords = this._mouseService.getCoords(e, this._terminal.screenElement, this._terminal.cols, this._terminal.rows);
if (!coords) {
return null;
}
+6 -11
View File
@@ -5,16 +5,15 @@
import { assert } from 'chai';
import { SelectionManager, SelectionMode } from './SelectionManager';
import { SelectionModel } from './SelectionModel';
import { BufferSet } from 'common/buffer/BufferSet';
import { SelectionModel } from 'browser/selection/SelectionModel';
import { ITerminal } from './Types';
import { IBuffer } from 'common/buffer/Types';
import { IBufferLine } from 'common/Types';
import { MockTerminal } from './TestUtils.test';
import { MockOptionsService, MockBufferService } from 'common/TestUtils.test';
import { MockBufferService } from 'common/TestUtils.test';
import { BufferLine } from 'common/buffer/BufferLine';
import { IBufferService } from 'common/services/Services';
import { MockCharSizeService } from 'browser/TestUtils.test';
import { MockCharSizeService, MockMouseService } from 'browser/TestUtils.test';
import { CellData } from 'common/buffer/CellData';
class TestMockTerminal extends MockTerminal {
@@ -26,7 +25,7 @@ class TestSelectionManager extends SelectionManager {
terminal: ITerminal,
bufferService: IBufferService
) {
super(terminal, new MockCharSizeService(10, 10), bufferService);
super(terminal, new MockCharSizeService(10, 10), bufferService, new MockMouseService());
}
public get model(): SelectionModel { return this._model; }
@@ -52,10 +51,7 @@ describe('SelectionManager', () => {
beforeEach(() => {
terminal = new TestMockTerminal();
bufferService = new MockBufferService(20, 20);
terminal.buffers = new BufferSet(
new MockOptionsService({ scrollback: 100 }),
bufferService
);
terminal.buffers = bufferService.buffers;
terminal.cols = 20;
terminal.rows = 20;
terminal.buffer = terminal.buffers.active;
@@ -366,14 +362,13 @@ describe('SelectionManager', () => {
describe('selectAll', () => {
it('should select the entire buffer, beyond the viewport', () => {
buffer.lines.length = 5;
bufferService.resize(20, 5);
buffer.lines.set(0, stringToRow('1'));
buffer.lines.set(1, stringToRow('2'));
buffer.lines.set(2, stringToRow('3'));
buffer.lines.set(3, stringToRow('4'));
buffer.lines.set(4, stringToRow('5'));
selectionManager.selectAll();
terminal.buffer.ybase = buffer.lines.length - bufferService.rows;
assert.equal(selectionManager.selectionText, '1\n2\n3\n4\n5');
});
});
+11 -10
View File
@@ -6,15 +6,15 @@
import { ITerminal, ISelectionManager, ISelectionRedrawRequestEvent } from './Types';
import { IBuffer } from 'common/buffer/Types';
import { IBufferLine } from 'common/Types';
import { MouseHelper } from 'browser/input/MouseHelper';
import * as Browser from 'common/Platform';
import { SelectionModel } from './SelectionModel';
import { SelectionModel } from 'browser/selection/SelectionModel';
import { AltClickHandler } from './handlers/AltClickHandler';
import { CellData } from 'common/buffer/CellData';
import { IDisposable } from 'xterm';
import { EventEmitter, IEvent } from 'common/EventEmitter';
import { ICharSizeService } from 'browser/services/Services';
import { ICharSizeService, IMouseService } from 'browser/services/Services';
import { IBufferService } from 'common/services/Services';
import { getCoordsRelativeToElement } from 'browser/input/Mouse';
/**
* The number of pixels the mouse needs to be above or below the viewport in
@@ -118,14 +118,15 @@ export class SelectionManager implements ISelectionManager {
public get onSelectionChange(): IEvent<void> { return this._onSelectionChange.event; }
constructor(
private _terminal: ITerminal,
private _charSizeService: ICharSizeService,
bufferService: IBufferService
private readonly _terminal: ITerminal,
private readonly _charSizeService: ICharSizeService,
readonly bufferService: IBufferService,
private readonly _mouseService: IMouseService
) {
this._initListeners();
this.enable();
this._model = new SelectionModel(_terminal, bufferService);
this._model = new SelectionModel(bufferService);
this._activeSelectionMode = SelectionMode.NORMAL;
}
@@ -357,7 +358,7 @@ export class SelectionManager implements ISelectionManager {
* @param event The mouse event.
*/
private _getMouseBufferCoords(event: MouseEvent): [number, number] {
const coords = this._terminal.mouseHelper.getCoords(event, this._terminal.screenElement, this._terminal.cols, this._terminal.rows, true);
const coords = this._mouseService.getCoords(event, this._terminal.screenElement, this._terminal.cols, this._terminal.rows, true);
if (!coords) {
return null;
}
@@ -377,7 +378,7 @@ export class SelectionManager implements ISelectionManager {
* @param event The mouse event.
*/
private _getMouseEventScrollAmount(event: MouseEvent): number {
let offset = MouseHelper.getCoordsRelativeToElement(event, this._terminal.screenElement)[1];
let offset = getCoordsRelativeToElement(event, this._terminal.screenElement)[1];
const terminalHeight = this._terminal.rows * Math.ceil(this._charSizeService.height * this._terminal.options.lineHeight);
if (offset >= 0 && offset <= terminalHeight) {
return 0;
@@ -654,7 +655,7 @@ export class SelectionManager implements ISelectionManager {
this._removeMouseDownListeners();
if (this.selectionText.length <= 1 && timeElapsed < ALT_CLICK_MOVE_CURSOR_TIME) {
(new AltClickHandler(event, this._terminal)).move();
(new AltClickHandler(event, this._terminal, this._mouseService)).move();
} else if (this.hasSelection) {
this._onSelectionChange.fire();
}
+15 -14
View File
@@ -34,7 +34,6 @@ import { SelectionManager } from './SelectionManager';
import * as Browser from 'common/Platform';
import { addDisposableDomListener } from 'browser/Lifecycle';
import * as Strings from './browser/LocalizableStrings';
import { MouseHelper } from 'browser/input/MouseHelper';
import { SoundManager } from './SoundManager';
import { MouseZoneManager } from './MouseZoneManager';
import { AccessibilityManager } from './AccessibilityManager';
@@ -50,12 +49,13 @@ import { ColorManager } from 'browser/ColorManager';
import { RenderService } from 'browser/services/RenderService';
import { IOptionsService, IBufferService } from 'common/services/Services';
import { OptionsService } from 'common/services/OptionsService';
import { ICharSizeService } from 'browser/services/Services';
import { ICharSizeService, IRenderService, IMouseService } from 'browser/services/Services';
import { CharSizeService } from 'browser/services/CharSizeService';
import { BufferService, MINIMUM_COLS, MINIMUM_ROWS } from 'common/services/BufferService';
import { Disposable } from 'common/Lifecycle';
import { IBufferSet, IBuffer } from 'common/buffer/Types';
import { Attributes } from 'common/buffer/Constants';
import { MouseService } from 'browser/services/MouseService';
// Let it work inside Node.js for automated testing purposes.
const document = (typeof window !== 'undefined') ? window.document : null;
@@ -111,7 +111,8 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
// browser services
private _charSizeService: ICharSizeService;
private _renderService: RenderService;
private _renderService: IRenderService;
private _mouseService: IMouseService;
// modes
public applicationKeypad: boolean;
@@ -177,7 +178,6 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
public viewport: IViewport;
private _compositionHelper: ICompositionHelper;
private _mouseZoneManager: IMouseZoneManager;
public mouseHelper: MouseHelper;
private _accessibilityManager: AccessibilityManager;
private _colorManager: ColorManager;
private _theme: ITheme;
@@ -591,11 +591,6 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
this.screenElement.appendChild(this._helperContainer);
fragment.appendChild(this.screenElement);
this._mouseZoneManager = new MouseZoneManager(this);
this.register(this._mouseZoneManager);
this.register(this.onScroll(() => this._mouseZoneManager.clearAll()));
this.linkifier.attachToDom(this._mouseZoneManager);
this.textarea = document.createElement('textarea');
this.textarea.classList.add('xterm-helper-textarea');
this.textarea.setAttribute('aria-label', Strings.promptLabel);
@@ -628,6 +623,13 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
this._renderService.onRender(e => this._onRender.fire(e));
this.onResize(e => this._renderService.resize(e.cols, e.rows));
this._mouseService = new MouseService(this._renderService, this._charSizeService);
this._mouseZoneManager = new MouseZoneManager(this, this._mouseService);
this.register(this._mouseZoneManager);
this.register(this.onScroll(() => this._mouseZoneManager.clearAll()));
this.linkifier.attachToDom(this._mouseZoneManager);
this.viewport = new Viewport(this, this._viewportElement, this._viewportScrollArea, this._renderService.dimensions, this._charSizeService);
this.viewport.onThemeChange(this._colorManager.colors);
this.register(this.viewport);
@@ -638,7 +640,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
this.register(this.onFocus(() => this._renderService.onFocus()));
this.register(this._renderService.onDimensionsChange(() => this.viewport.syncScrollArea()));
this.selectionManager = new SelectionManager(this, this._charSizeService, this._bufferService);
this.selectionManager = new SelectionManager(this, this._charSizeService, this._bufferService, this._mouseService);
this.register(this.selectionManager.onSelectionChange(() => this._onSelectionChange.fire()));
this.register(addDisposableDomListener(this.element, 'mousedown', (e: MouseEvent) => this.selectionManager.onMouseDown(e)));
this.register(this.selectionManager.onRedrawRequest(e => this._renderService.onSelectionChanged(e.start, e.end, e.columnSelectMode)));
@@ -656,7 +658,6 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
}));
this.register(addDisposableDomListener(this._viewportElement, 'scroll', () => this.selectionManager.refresh()));
this.mouseHelper = new MouseHelper(this._renderService, this._charSizeService);
// apply mouse event classes set by escape codes before terminal was attached
this.element.classList.toggle('enable-mouse-events', this.mouseEvents);
if (this.mouseEvents) {
@@ -690,7 +691,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
private _createRenderer(): IRenderer {
switch (this.options.rendererType) {
case 'canvas': return new Renderer(this, this._colorManager.colors, this._charSizeService); break;
case 'dom': return new DomRenderer(this, this._colorManager.colors, this._charSizeService); break;
case 'dom': return new DomRenderer(this, this._colorManager.colors, this._charSizeService, this.optionsService); break;
default: throw new Error(`Unrecognized rendererType "${this.options.rendererType}"`);
}
}
@@ -738,7 +739,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
button = getButton(ev);
// get mouse coordinates
pos = self.mouseHelper.getRawByteCoords(ev, self.screenElement, self.cols, self.rows);
pos = self._mouseService.getRawByteCoords(ev, self.screenElement, self.cols, self.rows);
if (!pos) return;
sendEvent(button, pos);
@@ -764,7 +765,7 @@ export class Terminal extends Disposable implements ITerminal, IDisposable, IInp
// ^[[M 3<^[[M@4<^[[M@5<^[[M@6<^[[M@7<^[[M#7<
function sendMove(ev: MouseEvent): void {
let button = pressed;
const pos = self.mouseHelper.getRawByteCoords(ev, self.screenElement, self.cols, self.rows);
const pos = self._mouseService.getRawByteCoords(ev, self.screenElement, self.cols, self.rows);
if (!pos) return;
// buttons marked as motions
+1 -2
View File
@@ -12,7 +12,7 @@ import * as Browser from 'common/Platform';
import { IDisposable, IMarker, IEvent, ISelectionPosition } from 'xterm';
import { Terminal } from './Terminal';
import { AttributeData } from 'common/buffer/AttributeData';
import { IColorManager, IColorSet, IMouseHelper } from 'browser/Types';
import { IColorManager, IColorSet } from 'browser/Types';
import { IOptionsService } from 'common/services/Services';
import { EventEmitter } from 'common/EventEmitter';
@@ -122,7 +122,6 @@ export class MockTerminal implements ITerminal {
throw new Error('Method not implemented.');
}
bracketedPasteMode: boolean;
mouseHelper: IMouseHelper;
renderer: IRenderer;
linkifier: ILinkifier;
isFocused: boolean;
+1 -2
View File
@@ -6,7 +6,7 @@
import { ITerminalOptions as IPublicTerminalOptions, IDisposable, IMarker, ISelectionPosition } from 'xterm';
import { ICharset, IAttributeData, CharData } from 'common/Types';
import { IEvent, IEventEmitter } from 'common/EventEmitter';
import { IColorSet, IMouseHelper } from 'browser/Types';
import { IColorSet } from 'browser/Types';
import { IOptionsService } from 'common/services/Services';
import { IBuffer, IBufferSet } from 'common/buffer/Types';
@@ -204,7 +204,6 @@ export interface ITerminal extends IPublicTerminal, IElementAccessor, IBufferAcc
buffer: IBuffer;
buffers: IBufferSet;
isFocused: boolean;
mouseHelper: IMouseHelper;
viewport: IViewport;
bracketedPasteMode: boolean;
applicationCursor: boolean;
+11 -1
View File
@@ -4,7 +4,7 @@
*/
import { IEvent, EventEmitter } from 'common/EventEmitter';
import { ICharSizeService } from 'browser/services/Services';
import { ICharSizeService, IMouseService } from 'browser/services/Services';
export class MockCharSizeService implements ICharSizeService {
get hasValidSize(): boolean { return this.width > 0 && this.height > 0; }
@@ -12,3 +12,13 @@ export class MockCharSizeService implements ICharSizeService {
constructor(public width: number, public height: number) {}
measure(): void {}
}
export class MockMouseService implements IMouseService {
public getCoords(event: {clientX: number, clientY: number}, element: HTMLElement, colCount: number, rowCount: number, isSelection?: boolean): [number, number] | undefined {
throw new Error('Not implemented');
}
public getRawByteCoords(event: MouseEvent, element: HTMLElement, colCount: number, rowCount: number): { x: number, y: number } | undefined {
throw new Error('Not implemented');
}
}
-5
View File
@@ -20,8 +20,3 @@ export interface IColorSet {
selection: IColor;
ansi: IColor[];
}
export interface IMouseHelper {
getCoords(event: { clientX: number, clientY: number }, element: HTMLElement, colCount: number, rowCount: number, isSelection?: boolean): [number, number] | undefined;
getRawByteCoords(event: MouseEvent, element: HTMLElement, colCount: number, rowCount: number): { x: number | undefined, y: number | undefined };
}
+40
View File
@@ -0,0 +1,40 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
import jsdom = require('jsdom');
import { assert } from 'chai';
import { getCoords } from 'browser/input/Mouse';
const CHAR_WIDTH = 10;
const CHAR_HEIGHT = 20;
describe('Mouse getCoords', () => {
let document: Document;
beforeEach(() => {
document = new jsdom.JSDOM('').window.document;
});
it('should return the cell that was clicked', () => {
let coords: [number, number] | undefined;
coords = getCoords({ clientX: CHAR_WIDTH / 2, clientY: CHAR_HEIGHT / 2 }, document.createElement('div'), 10, 10, true, CHAR_WIDTH, CHAR_HEIGHT);
assert.deepEqual(coords, [1, 1]);
coords = getCoords({ clientX: CHAR_WIDTH, clientY: CHAR_HEIGHT }, document.createElement('div'), 10, 10, true, CHAR_WIDTH, CHAR_HEIGHT);
assert.deepEqual(coords, [1, 1]);
coords = getCoords({ clientX: CHAR_WIDTH, clientY: CHAR_HEIGHT + 1 }, document.createElement('div'), 10, 10, true, CHAR_WIDTH, CHAR_HEIGHT);
assert.deepEqual(coords, [1, 2]);
coords = getCoords({ clientX: CHAR_WIDTH + 1, clientY: CHAR_HEIGHT }, document.createElement('div'), 10, 10, true, CHAR_WIDTH, CHAR_HEIGHT);
assert.deepEqual(coords, [2, 1]);
});
it('should ensure the coordinates are returned within the terminal bounds', () => {
let coords: [number, number] | undefined;
coords = getCoords({ clientX: -1, clientY: -1 }, document.createElement('div'), 10, 10, true, CHAR_WIDTH, CHAR_HEIGHT);
assert.deepEqual(coords, [1, 1]);
// Event are double the cols/rows
coords = getCoords({ clientX: CHAR_WIDTH * 20, clientY: CHAR_HEIGHT * 20 }, document.createElement('div'), 10, 10, true, CHAR_WIDTH, CHAR_HEIGHT);
assert.deepEqual(coords, [10, 10], 'coordinates should never come back as larger than the terminal');
});
});
+58
View File
@@ -0,0 +1,58 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
export function getCoordsRelativeToElement(event: {clientX: number, clientY: number}, element: HTMLElement): [number, number] {
const rect = element.getBoundingClientRect();
return [event.clientX - rect.left, event.clientY - rect.top];
}
/**
* Gets coordinates within the terminal for a particular mouse event. The result
* is returned as an array in the form [x, y] instead of an object as it's a
* little faster and this function is used in some low level code.
* @param event The mouse event.
* @param element The terminal's container element.
* @param colCount The number of columns in the terminal.
* @param rowCount The number of rows n the terminal.
* @param isSelection Whether the request is for the selection or not. This will
* apply an offset to the x value such that the left half of the cell will
* select that cell and the right half will select the next cell.
*/
export function getCoords(event: {clientX: number, clientY: number}, element: HTMLElement, colCount: number, rowCount: number, hasValidCharSize: boolean, actualCellWidth: number, actualCellHeight: number, isSelection?: boolean): [number, number] | undefined {
// Coordinates cannot be measured if there are no valid
if (!hasValidCharSize) {
return undefined;
}
const coords = getCoordsRelativeToElement(event, element);
if (!coords) {
return undefined;
}
coords[0] = Math.ceil((coords[0] + (isSelection ? actualCellWidth / 2 : 0)) / actualCellWidth);
coords[1] = Math.ceil(coords[1] / actualCellHeight);
// Ensure coordinates are within the terminal viewport. Note that selections
// need an addition point of precision to cover the end point (as characters
// cover half of one char and half of the next).
coords[0] = Math.min(Math.max(coords[0], 1), colCount + (isSelection ? 1 : 0));
coords[1] = Math.min(Math.max(coords[1], 1), rowCount);
return coords;
}
/**
* Gets coordinates within the terminal for a particular mouse event, wrapping
* them to the bounds of the terminal and adding 32 to both the x and y values
* as expected by xterm.
*/
export function getRawByteCoords(coords: [number, number] | undefined): { x: number, y: number } | undefined {
if (!coords) {
return undefined;
}
// xterm sends raw bytes and starts at 32 (SP) for each.
return { x: coords[0] + 32, y: coords[1] + 32 };
}
-49
View File
@@ -1,49 +0,0 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
import jsdom = require('jsdom');
import { assert } from 'chai';
import { MouseHelper } from 'browser/input/MouseHelper';
import { MockCharSizeService } from 'browser/TestUtils.test';
const CHAR_WIDTH = 10;
const CHAR_HEIGHT = 20;
describe('MouseHelper.getCoords', () => {
let document: Document;
let mouseHelper: MouseHelper;
beforeEach(() => {
document = new jsdom.JSDOM('').window.document;
const mockRenderService = {
dimensions: {
actualCellWidth: CHAR_WIDTH,
actualCellHeight: CHAR_HEIGHT
}
};
mouseHelper = new MouseHelper(mockRenderService as any, new MockCharSizeService(CHAR_WIDTH, CHAR_HEIGHT));
});
it('should return the cell that was clicked', () => {
let coords: [number, number] | undefined;
coords = mouseHelper.getCoords({ clientX: CHAR_WIDTH / 2, clientY: CHAR_HEIGHT / 2 }, document.createElement('div'), 10, 10);
assert.deepEqual(coords, [1, 1]);
coords = mouseHelper.getCoords({ clientX: CHAR_WIDTH, clientY: CHAR_HEIGHT }, document.createElement('div'), 10, 10);
assert.deepEqual(coords, [1, 1]);
coords = mouseHelper.getCoords({ clientX: CHAR_WIDTH, clientY: CHAR_HEIGHT + 1 }, document.createElement('div'), 10, 10);
assert.deepEqual(coords, [1, 2]);
coords = mouseHelper.getCoords({ clientX: CHAR_WIDTH + 1, clientY: CHAR_HEIGHT }, document.createElement('div'), 10, 10);
assert.deepEqual(coords, [2, 1]);
});
it('should ensure the coordinates are returned within the terminal bounds', () => {
let coords: [number, number] | undefined;
coords = mouseHelper.getCoords({ clientX: -1, clientY: -1 }, document.createElement('div'), 10, 10);
assert.deepEqual(coords, [1, 1]);
// Event are double the cols/rows
coords = mouseHelper.getCoords({ clientX: CHAR_WIDTH * 20, clientY: CHAR_HEIGHT * 20 }, document.createElement('div'), 10, 10);
assert.deepEqual(coords, [10, 10], 'coordinates should never come back as larger than the terminal');
});
});
-75
View File
@@ -1,75 +0,0 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { IMouseHelper } from 'browser/Types';
import { RenderService } from 'browser/services/RenderService';
import { ICharSizeService } from 'browser/services/Services';
export class MouseHelper implements IMouseHelper {
constructor(
private _renderService: RenderService,
private _charSizeService: ICharSizeService
) {
}
public static getCoordsRelativeToElement(event: {clientX: number, clientY: number}, element: HTMLElement): [number, number] {
const rect = element.getBoundingClientRect();
return [event.clientX - rect.left, event.clientY - rect.top];
}
/**
* Gets coordinates within the terminal for a particular mouse event. The result
* is returned as an array in the form [x, y] instead of an object as it's a
* little faster and this function is used in some low level code.
* @param event The mouse event.
* @param element The terminal's container element.
* @param colCount The number of columns in the terminal.
* @param rowCount The number of rows n the terminal.
* @param isSelection Whether the request is for the selection or not. This will
* apply an offset to the x value such that the left half of the cell will
* select that cell and the right half will select the next cell.
*/
public getCoords(event: {clientX: number, clientY: number}, element: HTMLElement, colCount: number, rowCount: number, isSelection?: boolean): [number, number] | undefined {
// Coordinates cannot be measured if there are no valid
if (!this._charSizeService.hasValidSize) {
return undefined;
}
const coords = MouseHelper.getCoordsRelativeToElement(event, element);
if (!coords) {
return undefined;
}
coords[0] = Math.ceil((coords[0] + (isSelection ? this._renderService.dimensions.actualCellWidth / 2 : 0)) / this._renderService.dimensions.actualCellWidth);
coords[1] = Math.ceil(coords[1] / this._renderService.dimensions.actualCellHeight);
// Ensure coordinates are within the terminal viewport. Note that selections
// need an addition point of precision to cover the end point (as characters
// cover half of one char and half of the next).
coords[0] = Math.min(Math.max(coords[0], 1), colCount + (isSelection ? 1 : 0));
coords[1] = Math.min(Math.max(coords[1], 1), rowCount);
return coords;
}
/**
* Gets coordinates within the terminal for a particular mouse event, wrapping
* them to the bounds of the terminal and adding 32 to both the x and y values
* as expected by xterm.
* @param event The mouse event.
* @param element The terminal's container element.
* @param colCount The number of columns in the terminal.
* @param rowCount The number of rows in the terminal.
*/
public getRawByteCoords(event: MouseEvent, element: HTMLElement, colCount: number, rowCount: number): { x: number | undefined, y: number | undefined } {
const coords = this.getCoords(event, element, colCount, rowCount);
// xterm sends raw bytes and starts at 32 (SP) for each.
const x = coords ? coords[0] + 32 : undefined;
const y = coords ? coords[1] + 32 : undefined;
return { x, y };
}
}
@@ -4,24 +4,19 @@
*/
import { assert } from 'chai';
import { MockTerminal, MockBuffer } from '../TestUtils.test';
import { CircularList } from 'common/CircularList';
import { ICharacterJoinerRegistry } from './Types';
import { CharacterJoinerRegistry } from './CharacterJoinerRegistry';
import { ICharacterJoinerRegistry } from 'browser/renderer/Types';
import { CharacterJoinerRegistry } from 'browser/renderer/CharacterJoinerRegistry';
import { BufferLine } from 'common/buffer/BufferLine';
import { IBufferLine } from 'common/Types';
import { CellData } from 'common/buffer/CellData';
import { MockBufferService } from 'common/TestUtils.test';
describe('CharacterJoinerRegistry', () => {
let registry: ICharacterJoinerRegistry;
beforeEach(() => {
const terminal = new MockTerminal();
terminal.cols = 16;
terminal.buffer = new MockBuffer();
const lines = new CircularList<IBufferLine>(7);
const bufferService = new MockBufferService(16, 10);
const lines = bufferService.buffer.lines;
lines.set(0, lineData([['a -> b -> c -> d']]));
lines.set(1, lineData([['a -> b => c -> d']]));
lines.set(2, lineData([['a -> b -', 0xFFFFFFFF], ['> c -> d', 0]]));
@@ -31,7 +26,7 @@ describe('CharacterJoinerRegistry', () => {
lines.set(5, lineData([['a', 0x11111111], [' -> b -> c -> '], ['d', 0x22222222]]));
const line6 = lineData([['wi']]);
line6.resize(line6.length + 1, CellData.fromCharData([0, '¥', 2, '¥'.charCodeAt(0)]));
line6.resize(line6.length + 1, CellData.fromCharData([0, '', 0, null]));
line6.resize(line6.length + 1, CellData.fromCharData([0, '', 0, 0]));
let sub = lineData([['deemo']]);
let oldSize = line6.length;
line6.resize(oldSize + sub.length, CellData.fromCharData([0, '', 0, 0]));
@@ -44,9 +39,7 @@ describe('CharacterJoinerRegistry', () => {
for (let i = 0; i < sub.length; ++i) line6.setCell(i + oldSize, sub.loadCell(i, new CellData()));
lines.set(6, line6);
(<MockBuffer>terminal.buffer).setLines(lines);
terminal.buffer.ydisp = 0;
registry = new CharacterJoinerRegistry(terminal);
registry = new CharacterJoinerRegistry(bufferService);
});
it('has no joiners upon creation', () => {
@@ -3,12 +3,12 @@
* @license MIT
*/
import { ITerminal } from '../Types';
import { IBufferLine, ICellData, CharData } from 'common/Types';
import { ICharacterJoinerRegistry, ICharacterJoiner } from './Types';
import { ICharacterJoinerRegistry, ICharacterJoiner } from 'browser/renderer/Types';
import { AttributeData } from 'common/buffer/AttributeData';
import { WHITESPACE_CELL_CHAR, Content } from 'common/buffer/Constants';
import { CellData } from 'common/buffer/CellData';
import { IBufferService } from 'common/services/Services';
export class JoinedCellData extends AttributeData implements ICellData {
private _width: number;
@@ -61,8 +61,7 @@ export class CharacterJoinerRegistry implements ICharacterJoinerRegistry {
private _nextCharacterJoinerId: number = 0;
private _workCell: CellData = new CellData();
constructor(private _terminal: ITerminal) {
}
constructor(private _bufferService: IBufferService) { }
public registerCharacterJoiner(handler: (text: string) => [number, number][]): number {
const joiner: ICharacterJoiner = {
@@ -90,8 +89,8 @@ export class CharacterJoinerRegistry implements ICharacterJoinerRegistry {
return [];
}
const line = this._terminal.buffer.lines.get(row);
if (line.length === 0) {
const line = this._bufferService.buffer.lines.get(row);
if (!line || line.length === 0) {
return [];
}
@@ -144,7 +143,7 @@ export class CharacterJoinerRegistry implements ICharacterJoinerRegistry {
}
// Process any trailing ranges.
if (this._terminal.cols - rangeStartColumn > 1) {
if (this._bufferService.cols - rangeStartColumn > 1) {
const joinedRanges = this._getJoinedRanges(
lineStr,
rangeStartStringIndex,
@@ -204,7 +203,7 @@ export class CharacterJoinerRegistry implements ICharacterJoinerRegistry {
return;
}
for (let x = startCol; x < this._terminal.cols; x++) {
for (let x = startCol; x < this._bufferService.cols; x++) {
const width = line.getWidth(x);
const length = line.getString(x).length || WHITESPACE_CELL_CHAR.length;
@@ -252,7 +251,7 @@ export class CharacterJoinerRegistry implements ICharacterJoinerRegistry {
// If there is still a range left at the end, it must extend all the way to
// the end of the line.
if (currentRange) {
currentRange[1] = this._terminal.cols;
currentRange[1] = this._bufferService.cols;
}
}
@@ -4,7 +4,7 @@
*/
import { assert } from 'chai';
import { GridCache } from './GridCache';
import { GridCache } from 'browser/renderer/GridCache';
describe('GridCache', () => {
let grid: GridCache<number>;
@@ -4,7 +4,7 @@
*/
export class GridCache<T> {
public cache: T[][];
public cache: (T | undefined)[][];
public constructor() {
this.cache = [];
@@ -16,7 +16,7 @@ export class GridCache<T> {
this.cache.push([]);
}
for (let y = this.cache[x].length; y < height; y++) {
this.cache[x].push(null);
this.cache[x].push(undefined);
}
this.cache[x].length = height;
}
@@ -26,7 +26,7 @@ export class GridCache<T> {
public clear(): void {
for (let x = 0; x < this.cache.length; x++) {
for (let y = 0; y < this.cache[x].length; y++) {
this.cache[x][y] = null;
this.cache[x][y] = undefined;
}
}
}
+11
View File
@@ -45,3 +45,14 @@ export interface IRenderer extends IDisposable {
registerCharacterJoiner(handler: CharacterJoinerHandler): number;
deregisterCharacterJoiner(joinerId: number): boolean;
}
export interface ICharacterJoiner {
id: number;
handler: CharacterJoinerHandler;
}
export interface ICharacterJoinerRegistry {
registerCharacterJoiner(handler: (text: string) => [number, number][]): number;
deregisterCharacterJoiner(joinerId: number): boolean;
getJoinedCharacters(row: number): [number, number][];
}
@@ -4,7 +4,7 @@
*/
import { assert } from 'chai';
import { LRUMap } from './LRUMap';
import { LRUMap } from 'browser/renderer/atlas/LRUMap';
describe('LRUMap', () => {
it('can be used to store and retrieve values', () => {
@@ -4,16 +4,16 @@
*/
interface ILinkedListNode<T> {
prev: ILinkedListNode<T>;
next: ILinkedListNode<T>;
key: number;
value: T;
prev: ILinkedListNode<T> | null;
next: ILinkedListNode<T> | null;
key: number | null;
value: T | null;
}
export class LRUMap<T> {
private _map: { [key: number]: ILinkedListNode<T> } = {};
private _head: ILinkedListNode<T> = null;
private _tail: ILinkedListNode<T> = null;
private _head: ILinkedListNode<T> | null = null;
private _tail: ILinkedListNode<T> | null = null;
private _nodePool: ILinkedListNode<T>[] = [];
public size: number = 0;
@@ -106,9 +106,9 @@ export class LRUMap<T> {
node.value = value;
} else if (this.size >= this.capacity) {
// we're out of space: recycle the head node, move it to the tail
node = this._head;
node = this._head!;
this._unlinkNode(node);
delete this._map[node.key];
delete this._map[node.key!];
node.key = key;
node.value = value;
this._map[key] = node;
@@ -117,7 +117,7 @@ export class LRUMap<T> {
const nodePool = this._nodePool;
if (nodePool.length > 0) {
// use a preallocated node if we can
node = nodePool.pop();
node = nodePool.pop()!;
node.key = key;
node.value = value;
} else {
@@ -5,25 +5,21 @@
import jsdom = require('jsdom');
import { assert } from 'chai';
import { DomRendererRowFactory } from './DomRendererRowFactory';
import { DomRendererRowFactory } from 'browser/renderer/dom/DomRendererRowFactory';
import { NULL_CELL_CODE, NULL_CELL_WIDTH, NULL_CELL_CHAR, DEFAULT_ATTR, FgFlags, BgFlags, Attributes } from 'common/buffer/Constants';
import { BufferLine, DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';
import { ITerminalOptions } from '../../Types';
import { IBufferLine } from 'common/Types';
import { CellData } from 'common/buffer/CellData';
import { MockOptionsService } from 'common/TestUtils.test';
describe('DomRendererRowFactory', () => {
let dom: jsdom.JSDOM;
const options: ITerminalOptions = {};
let rowFactory: DomRendererRowFactory;
let lineData: IBufferLine;
beforeEach(() => {
dom = new jsdom.JSDOM('');
options.drawBoldTextInBrightColors = true;
rowFactory = new DomRendererRowFactory(options, dom.window.document);
rowFactory = new DomRendererRowFactory(dom.window.document, new MockOptionsService({ drawBoldTextInBrightColors: true }));
lineData = createEmptyLineData(2);
});
@@ -38,7 +34,7 @@ describe('DomRendererRowFactory', () => {
it('should set correct attributes for double width characters', () => {
lineData.setCell(0, CellData.fromCharData([DEFAULT_ATTR, '語', 2, '語'.charCodeAt(0)]));
// There should be no element for the following "empty" cell
lineData.setCell(1, CellData.fromCharData([DEFAULT_ATTR, '', 0, undefined]));
lineData.setCell(1, CellData.fromCharData([DEFAULT_ATTR, '', 0, 0]));
const fragment = rowFactory.createRow(lineData, false, undefined, 0, false, 5, 20);
assert.equal(getFragmentHtml(fragment),
'<span style="width: 10px;">語</span>'
@@ -3,12 +3,12 @@
* @license MIT
*/
import { ITerminalOptions } from '../../Types';
import { IBufferLine } from 'common/Types';
import { INVERTED_DEFAULT_COLOR } from '../atlas/Constants';
import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants';
import { AttributeData } from 'common/buffer/AttributeData';
import { NULL_CELL_CODE, WHITESPACE_CELL_CHAR } from 'common/buffer/Constants';
import { CellData } from 'common/buffer/CellData';
import { ITerminalOptions, IOptionsService } from 'common/services/Services';
export const BOLD_CLASS = 'xterm-bold';
export const DIM_CLASS = 'xterm-dim';
@@ -24,8 +24,8 @@ export class DomRendererRowFactory {
private _workCell: CellData = new CellData();
constructor(
private _terminalOptions: ITerminalOptions,
private _document: Document
private _document: Document,
private _optionsService: IOptionsService
) {
}
@@ -106,7 +106,7 @@ export class DomRendererRowFactory {
charElement.setAttribute('style', style);
} else if (this._workCell.isFgPalette()) {
let fg = this._workCell.getFgColor();
if (this._workCell.isBold() && fg < 8 && !swapColor && this._terminalOptions.drawBoldTextInBrightColors) {
if (this._workCell.isBold() && fg < 8 && !swapColor && this._optionsService.options.drawBoldTextInBrightColors) {
fg += 8;
}
charElement.classList.add(`xterm-${swapColor ? 'b' : 'f'}g-${fg}`);
@@ -4,36 +4,15 @@
*/
import { assert } from 'chai';
import { ITerminal } from './Types';
import { SelectionModel } from './SelectionModel';
import { BufferSet } from 'common/buffer/BufferSet';
import { MockTerminal } from './TestUtils.test';
import { MockOptionsService, MockBufferService } from 'common/TestUtils.test';
import { IBufferService } from 'common/services/Services';
import { MockBufferService } from 'common/TestUtils.test';
class TestSelectionModel extends SelectionModel {
constructor(
terminal: ITerminal,
bufferService: IBufferService
) {
super(terminal, bufferService);
}
}
describe('SelectionManager', () => {
let terminal: ITerminal;
let model: TestSelectionModel;
describe('SelectionModel', () => {
let model: SelectionModel;
beforeEach(() => {
terminal = new MockTerminal();
const bufferService = new MockBufferService(80, 2);
terminal.buffers = new BufferSet(
new MockOptionsService({ scrollback: 10 }),
bufferService
);
terminal.buffer = terminal.buffers.active;
model = new TestSelectionModel(terminal, bufferService);
model = new SelectionModel(bufferService);
});
describe('clearSelection', () => {
@@ -43,8 +22,8 @@ describe('SelectionManager', () => {
assert.deepEqual(model.finalSelectionStart, [0, 0]);
assert.deepEqual(model.finalSelectionEnd, [10, 2]);
model.clearSelection();
assert.deepEqual(model.finalSelectionStart, null);
assert.deepEqual(model.finalSelectionEnd, null);
assert.deepEqual(model.finalSelectionStart, undefined);
assert.deepEqual(model.finalSelectionEnd, undefined);
});
});
@@ -82,8 +61,8 @@ describe('SelectionManager', () => {
model.selectionStart = [0, 0];
model.selectionEnd = [10, 0];
model.onTrim(1);
assert.deepEqual(model.finalSelectionStart, null);
assert.deepEqual(model.finalSelectionEnd, null);
assert.deepEqual(model.finalSelectionStart, undefined);
assert.deepEqual(model.finalSelectionEnd, undefined);
});
});
@@ -111,9 +90,9 @@ describe('SelectionManager', () => {
assert.deepEqual(model.finalSelectionEnd, [80, 1]);
});
it('should return null if there is no selection start', () => {
assert.equal(model.finalSelectionEnd, null);
assert.equal(model.finalSelectionEnd, undefined);
model.selectionEnd = [1, 2];
assert.equal(model.finalSelectionEnd, null);
assert.equal(model.finalSelectionEnd, undefined);
});
it('should return selection start + length if there is no selection end', () => {
model.selectionStart = [2, 2];
@@ -3,7 +3,6 @@
* @license MIT
*/
import { ITerminal } from './Types';
import { IBufferService } from 'common/services/Services';
/**
@@ -14,38 +13,36 @@ export class SelectionModel {
/**
* Whether select all is currently active.
*/
public isSelectAllActive: boolean;
/**
* The [x, y] position the selection starts at.
*/
public selectionStart: [number, number];
public isSelectAllActive: boolean = false;
/**
* The minimal length of the selection from the start position. When double
* clicking on a word, the word will be selected which makes the selection
* start at the start of the word and makes this variable the length.
*/
public selectionStartLength: number;
public selectionStartLength: number = 0;
/**
* The [x, y] position the selection starts at.
*/
public selectionStart: [number, number] | undefined;
/**
* The [x, y] position the selection ends at.
*/
public selectionEnd: [number, number];
public selectionEnd: [number, number] | undefined;
constructor(
private _terminal: ITerminal,
private _bufferService: IBufferService
) {
this.clearSelection();
}
/**
* Clears the current selection.
*/
public clearSelection(): void {
this.selectionStart = null;
this.selectionEnd = null;
this.selectionStart = undefined;
this.selectionEnd = undefined;
this.isSelectAllActive = false;
this.selectionStartLength = 0;
}
@@ -53,7 +50,7 @@ export class SelectionModel {
/**
* The final selection start, taking into consideration select all.
*/
public get finalSelectionStart(): [number, number] {
public get finalSelectionStart(): [number, number] | undefined {
if (this.isSelectAllActive) {
return [0, 0];
}
@@ -69,13 +66,13 @@ export class SelectionModel {
* The final selection end, taking into consideration select all, double click
* word selection and triple click line selection.
*/
public get finalSelectionEnd(): [number, number] {
public get finalSelectionEnd(): [number, number] | undefined {
if (this.isSelectAllActive) {
return [this._bufferService.cols, this._terminal.buffer.ybase + this._bufferService.rows - 1];
return [this._bufferService.cols, this._bufferService.buffer.ybase + this._bufferService.rows - 1];
}
if (!this.selectionStart) {
return null;
return undefined;
}
// Use the selection start + length if the end doesn't exist or they're reversed
+33
View File
@@ -0,0 +1,33 @@
/**
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { ICharSizeService, IRenderService, IMouseService } from './Services';
import { getCoords, getRawByteCoords } from 'browser/input/Mouse';
export class MouseService implements IMouseService {
constructor(
private readonly _renderService: IRenderService,
private readonly _charSizeService: ICharSizeService
) {
}
public getCoords(event: {clientX: number, clientY: number}, element: HTMLElement, colCount: number, rowCount: number, isSelection?: boolean): [number, number] | undefined {
return getCoords(
event,
element,
colCount,
rowCount,
this._charSizeService.hasValidSize,
this._renderService.dimensions.actualCellWidth,
this._renderService.dimensions.actualCellHeight,
isSelection
);
}
public getRawByteCoords(event: MouseEvent, element: HTMLElement, colCount: number, rowCount: number): { x: number, y: number } | undefined {
const coords = this.getCoords(event, element, colCount, rowCount);
return getRawByteCoords(coords);
}
}
+5
View File
@@ -17,6 +17,11 @@ export interface ICharSizeService {
measure(): void;
}
export interface IMouseService {
getCoords(event: {clientX: number, clientY: number}, element: HTMLElement, colCount: number, rowCount: number, isSelection?: boolean): [number, number] | undefined;
getRawByteCoords(event: MouseEvent, element: HTMLElement, colCount: number, rowCount: number): { x: number, y: number } | undefined;
}
export interface IRenderService {
onDimensionsChange: IEvent<IRenderDimensions>;
onRender: IEvent<{ start: number, end: number }>;
+11 -5
View File
@@ -8,14 +8,18 @@ import { IEvent, EventEmitter } from 'common/EventEmitter';
import { clone } from 'common/Clone';
import { DEFAULT_OPTIONS } from 'common/services/OptionsService';
import { IBufferSet, IBuffer } from 'common/buffer/Types';
import { BufferSet } from 'common/buffer/BufferSet';
export class MockBufferService implements IBufferService {
public buffer: IBuffer = {} as any;
public get buffer(): IBuffer { return this.buffers.active; }
public buffers: IBufferSet = {} as any;
constructor(
public cols: number,
public rows: number
) {}
public rows: number,
optionsService: IOptionsService = new MockOptionsService()
) {
this.buffers = new BufferSet(optionsService, this);
}
resize(cols: number, rows: number): void {
this.cols = cols;
this.rows = rows;
@@ -26,8 +30,10 @@ export class MockBufferService implements IBufferService {
export class MockOptionsService implements IOptionsService {
options: ITerminalOptions = clone(DEFAULT_OPTIONS);
onOptionChange: IEvent<string> = new EventEmitter<string>().event;
constructor(testOptions: IPartialTerminalOptions) {
Object.keys(testOptions).forEach(key => this.options[key] = (<any>testOptions)[key]);
constructor(testOptions?: IPartialTerminalOptions) {
if (testOptions) {
Object.keys(testOptions).forEach(key => this.options[key] = (<any>testOptions)[key]);
}
}
setOption<T>(key: string, value: T): void {
throw new Error('Method not implemented.');
-1
View File
@@ -126,7 +126,6 @@ export class Buffer implements IBuffer {
public clear(): void {
this.ydisp = 0;
this.ybase = 0;
this.savedY = 0;
this.y = 0;
this.x = 0;
this.lines = new CircularList<IBufferLine>(this._getCorrectBufferLength(this._rows));
+4 -2
View File
@@ -6,6 +6,7 @@
import { ITerminal } from '../Types';
import { IBufferLine, ICircularList } from 'common/Types';
import { C0 } from 'common/data/EscapeSequences';
import { IMouseService } from 'browser/services/Services';
const enum Direction {
UP = 'A',
@@ -23,13 +24,14 @@ export class AltClickHandler {
constructor(
private _mouseEvent: MouseEvent,
private _terminal: ITerminal
private _terminal: ITerminal,
private readonly _mouseService: IMouseService
) {
this._lines = this._terminal.buffer.lines;
this._startCol = this._terminal.buffer.x;
this._startRow = this._terminal.buffer.y;
const coordinates = this._terminal.mouseHelper.getCoords(
const coordinates = this._mouseService.getCoords(
this._mouseEvent,
this._terminal.element,
this._terminal.cols,
+1 -1
View File
@@ -9,7 +9,7 @@ import { ITerminal } from '../Types';
import { ICellData } from 'common/Types';
import { DEFAULT_COLOR, WHITESPACE_CELL_CHAR, WHITESPACE_CELL_CODE } from 'common/buffer/Constants';
import { IGlyphIdentifier } from './atlas/Types';
import { DIM_OPACITY, INVERTED_DEFAULT_COLOR } from './atlas/Constants';
import { DIM_OPACITY, INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants';
import { BaseCharAtlas } from './atlas/BaseCharAtlas';
import { acquireCharAtlas } from './atlas/CharAtlasCache';
import { AttributeData } from 'common/buffer/AttributeData';
+1 -1
View File
@@ -6,7 +6,7 @@
import { ILinkifierEvent, ITerminal, ILinkifierAccessor } from '../Types';
import { IRenderDimensions } from 'browser/renderer/Types';
import { BaseRenderLayer } from './BaseRenderLayer';
import { INVERTED_DEFAULT_COLOR } from './atlas/Constants';
import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants';
import { is256Color } from './atlas/CharAtlasUtils';
import { IColorSet } from 'browser/Types';
+3 -3
View File
@@ -6,11 +6,11 @@
import { TextRenderLayer } from './TextRenderLayer';
import { SelectionRenderLayer } from './SelectionRenderLayer';
import { CursorRenderLayer } from './CursorRenderLayer';
import { IRenderLayer, ICharacterJoinerRegistry } from './Types';
import { IRenderer, IRenderDimensions, CharacterJoinerHandler } from 'browser/renderer/Types';
import { IRenderLayer } from './Types';
import { IRenderer, IRenderDimensions, CharacterJoinerHandler, ICharacterJoinerRegistry } from 'browser/renderer/Types';
import { ITerminal } from '../Types';
import { LinkRenderLayer } from './LinkRenderLayer';
import { CharacterJoinerRegistry } from '../renderer/CharacterJoinerRegistry';
import { CharacterJoinerRegistry } from 'browser/renderer/CharacterJoinerRegistry';
import { Disposable } from 'common/Lifecycle';
import { IColorSet } from 'browser/Types';
import { ICharSizeService } from 'browser/services/Services';
+3 -4
View File
@@ -3,15 +3,14 @@
* @license MIT
*/
import { ICharacterJoinerRegistry } from './Types';
import { IRenderDimensions } from 'browser/renderer/Types';
import { ICharacterJoinerRegistry, IRenderDimensions } from 'browser/renderer/Types';
import { ITerminal } from '../Types';
import { CharData, ICellData } from 'common/Types';
import { GridCache } from './GridCache';
import { GridCache } from 'browser/renderer/GridCache';
import { BaseRenderLayer } from './BaseRenderLayer';
import { AttributeData } from 'common/buffer/AttributeData';
import { NULL_CELL_CODE, Content } from 'common/buffer/Constants';
import { JoinedCellData } from './CharacterJoinerRegistry';
import { JoinedCellData } from 'browser/renderer/CharacterJoinerRegistry';
import { IColorSet } from 'browser/Types';
import { CellData } from 'common/buffer/CellData';
+1 -12
View File
@@ -6,7 +6,7 @@
import { ITerminal } from '../Types';
import { IDisposable } from 'xterm';
import { IColorSet } from 'browser/Types';
import { IRenderDimensions, CharacterJoinerHandler } from 'browser/renderer/Types';
import { IRenderDimensions, CharacterJoinerHandler, ICharacterJoiner } from 'browser/renderer/Types';
export interface IRenderLayer extends IDisposable {
/**
@@ -65,14 +65,3 @@ export interface IRenderLayer extends IDisposable {
*/
reset(terminal: ITerminal): void;
}
export interface ICharacterJoiner {
id: number;
handler: CharacterJoinerHandler;
}
export interface ICharacterJoinerRegistry {
registerCharacterJoiner(handler: (text: string) => [number, number][]): number;
deregisterCharacterJoiner(joinerId: number): boolean;
getJoinedCharacters(row: number): [number, number][];
}
+2 -2
View File
@@ -4,10 +4,10 @@
*/
import { IGlyphIdentifier, ICharAtlasConfig } from './Types';
import { DIM_OPACITY, INVERTED_DEFAULT_COLOR } from './Constants';
import { DIM_OPACITY, INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants';
import { BaseCharAtlas } from './BaseCharAtlas';
import { DEFAULT_ANSI_COLORS } from 'browser/ColorManager';
import { LRUMap } from './LRUMap';
import { LRUMap } from 'browser/renderer/atlas/LRUMap';
import { isFirefox, isSafari } from 'common/Platform';
import { IColor } from 'browser/Types';
+6 -4
View File
@@ -5,11 +5,12 @@
import { IRenderer, IRenderDimensions, CharacterJoinerHandler } from 'browser/renderer/Types';
import { ILinkifierEvent, ITerminal } from '../../Types';
import { BOLD_CLASS, ITALIC_CLASS, CURSOR_CLASS, CURSOR_STYLE_BLOCK_CLASS, CURSOR_BLINK_CLASS, CURSOR_STYLE_BAR_CLASS, CURSOR_STYLE_UNDERLINE_CLASS, DomRendererRowFactory } from './DomRendererRowFactory';
import { INVERTED_DEFAULT_COLOR } from '../atlas/Constants';
import { BOLD_CLASS, ITALIC_CLASS, CURSOR_CLASS, CURSOR_STYLE_BLOCK_CLASS, CURSOR_BLINK_CLASS, CURSOR_STYLE_BAR_CLASS, CURSOR_STYLE_UNDERLINE_CLASS, DomRendererRowFactory } from 'browser/renderer/dom/DomRendererRowFactory';
import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/atlas/Constants';
import { Disposable } from 'common/Lifecycle';
import { IColorSet } from 'browser/Types';
import { ICharSizeService } from 'browser/services/Services';
import { IOptionsService } from 'common/services/Services';
const TERMINAL_CLASS_PREFIX = 'xterm-dom-renderer-owner-';
const ROW_CONTAINER_CLASS = 'xterm-rows';
@@ -43,7 +44,8 @@ export class DomRenderer extends Disposable implements IRenderer {
constructor(
private _terminal: ITerminal,
private _colors: IColorSet,
private _charSizeService: ICharSizeService
private _charSizeService: ICharSizeService,
private _optionsService: IOptionsService
) {
super();
@@ -73,7 +75,7 @@ export class DomRenderer extends Disposable implements IRenderer {
this._updateDimensions();
this._injectCss();
this._rowFactory = new DomRendererRowFactory(_terminal.options, document);
this._rowFactory = new DomRendererRowFactory(document, this._optionsService);
this._terminal.element.classList.add(TERMINAL_CLASS_PREFIX + this._terminalClass);
this._terminal.screenElement.appendChild(this._rowContainer);