Merge pull request #5106 from Tyriar/tyriar/lifecycle

Move to vs/base disposables
This commit is contained in:
Daniel Imms
2024-07-15 10:11:12 -07:00
committed by GitHub
50 changed files with 365 additions and 645 deletions
+3 -4
View File
@@ -6,8 +6,7 @@
import { toRGBA8888 } from 'sixel/lib/Colors'; import { toRGBA8888 } from 'sixel/lib/Colors';
import { IDisposable } from '@xterm/xterm'; import { IDisposable } from '@xterm/xterm';
import { ICellSize, ITerminalExt, IImageSpec, IRenderDimensions, IRenderService } from './Types'; import { ICellSize, ITerminalExt, IImageSpec, IRenderDimensions, IRenderService } from './Types';
import { Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle'; import { Disposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
const PLACEHOLDER_LENGTH = 4096; const PLACEHOLDER_LENGTH = 4096;
const PLACEHOLDER_HEIGHT = 24; const PLACEHOLDER_HEIGHT = 24;
@@ -23,7 +22,7 @@ export class ImageRenderer extends Disposable implements IDisposable {
private _ctx: CanvasRenderingContext2D | null | undefined; private _ctx: CanvasRenderingContext2D | null | undefined;
private _placeholder: HTMLCanvasElement | undefined; private _placeholder: HTMLCanvasElement | undefined;
private _placeholderBitmap: ImageBitmap | undefined; private _placeholderBitmap: ImageBitmap | undefined;
private _optionsRefresh = this.register(new MutableDisposable()); private _optionsRefresh = this._register(new MutableDisposable());
private _oldOpen: ((parent: HTMLElement) => void) | undefined; private _oldOpen: ((parent: HTMLElement) => void) | undefined;
private _renderService: IRenderService | undefined; private _renderService: IRenderService | undefined;
private _oldSetRenderer: ((renderer: any) => void) | undefined; private _oldSetRenderer: ((renderer: any) => void) | undefined;
@@ -85,7 +84,7 @@ export class ImageRenderer extends Disposable implements IDisposable {
this._renderService?.refreshRows(0, this._terminal.rows); this._renderService?.refreshRows(0, this._terminal.rows);
} }
}); });
this.register(toDisposable(() => { this._register(toDisposable(() => {
this.removeLayerFromDom(); this.removeLayerFromDom();
if (this._terminal._core && this._oldOpen) { if (this._terminal._core && this._oldOpen) {
this._terminal._core.open = this._oldOpen; this._terminal._core.open = this._oldOpen;
+3 -1
View File
@@ -15,6 +15,7 @@
"paths": { "paths": {
"browser/*": [ "../../../src/browser/*" ], "browser/*": [ "../../../src/browser/*" ],
"common/*": [ "../../../src/common/*" ], "common/*": [ "../../../src/common/*" ],
"vs/*": [ "../../../src/vs/*" ],
"@xterm/addon-image": [ "../typings/addon-image.d.ts" ] "@xterm/addon-image": [ "../typings/addon-image.d.ts" ]
} }
}, },
@@ -24,6 +25,7 @@
], ],
"references": [ "references": [
{ "path": "../../../src/browser" }, { "path": "../../../src/browser" },
{ "path": "../../../src/common" } { "path": "../../../src/common" },
{ "path": "../../../src/vs" }
] ]
} }
+2 -1
View File
@@ -26,7 +26,8 @@ const addon = {
extensions: [ '.js' ], extensions: [ '.js' ],
alias: { alias: {
common: path.resolve('../../out/common'), common: path.resolve('../../out/common'),
browser: path.resolve('../../out/browser') browser: path.resolve('../../out/browser'),
vs: path.resolve('../../out/vs')
} }
}, },
output: { output: {
+11 -11
View File
@@ -5,8 +5,8 @@
import type { Terminal, IDisposable, ITerminalAddon, IDecoration } from '@xterm/xterm'; import type { Terminal, IDisposable, ITerminalAddon, IDecoration } from '@xterm/xterm';
import type { SearchAddon as ISearchApi } from '@xterm/addon-search'; import type { SearchAddon as ISearchApi } from '@xterm/addon-search';
import { Disposable, toDisposable, disposeArray, MutableDisposable, getDisposeArrayDisposable } from 'common/Lifecycle';
import { Emitter } from 'vs/base/common/event'; import { Emitter } from 'vs/base/common/event';
import { combinedDisposable, Disposable, dispose, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
export interface ISearchOptions { export interface ISearchOptions {
regex?: boolean; regex?: boolean;
@@ -67,7 +67,7 @@ export class SearchAddon extends Disposable implements ITerminalAddon , ISearchA
private _cachedSearchTerm: string | undefined; private _cachedSearchTerm: string | undefined;
private _highlightedLines: Set<number> = new Set(); private _highlightedLines: Set<number> = new Set();
private _highlightDecorations: IHighlight[] = []; private _highlightDecorations: IHighlight[] = [];
private _selectedDecoration: MutableDisposable<IHighlight> = this.register(new MutableDisposable()); private _selectedDecoration: MutableDisposable<IHighlight> = this._register(new MutableDisposable());
private _highlightLimit: number; private _highlightLimit: number;
private _lastSearchOptions: ISearchOptions | undefined; private _lastSearchOptions: ISearchOptions | undefined;
private _highlightTimeout: number | undefined; private _highlightTimeout: number | undefined;
@@ -80,7 +80,7 @@ export class SearchAddon extends Disposable implements ITerminalAddon , ISearchA
private _linesCacheTimeoutId = 0; private _linesCacheTimeoutId = 0;
private _linesCacheDisposables = new MutableDisposable(); private _linesCacheDisposables = new MutableDisposable();
private readonly _onDidChangeResults = this.register(new Emitter<{ resultIndex: number, resultCount: number }>()); private readonly _onDidChangeResults = this._register(new Emitter<{ resultIndex: number, resultCount: number }>());
public readonly onDidChangeResults = this._onDidChangeResults.event; public readonly onDidChangeResults = this._onDidChangeResults.event;
constructor(options?: Partial<ISearchAddonOptions>) { constructor(options?: Partial<ISearchAddonOptions>) {
@@ -91,9 +91,9 @@ export class SearchAddon extends Disposable implements ITerminalAddon , ISearchA
public activate(terminal: Terminal): void { public activate(terminal: Terminal): void {
this._terminal = terminal; this._terminal = terminal;
this.register(this._terminal.onWriteParsed(() => this._updateMatches())); this._register(this._terminal.onWriteParsed(() => this._updateMatches()));
this.register(this._terminal.onResize(() => this._updateMatches())); this._register(this._terminal.onResize(() => this._updateMatches()));
this.register(toDisposable(() => this.clearDecorations())); this._register(toDisposable(() => this.clearDecorations()));
} }
private _updateMatches(): void { private _updateMatches(): void {
@@ -111,7 +111,7 @@ export class SearchAddon extends Disposable implements ITerminalAddon , ISearchA
public clearDecorations(retainCachedSearchTerm?: boolean): void { public clearDecorations(retainCachedSearchTerm?: boolean): void {
this._selectedDecoration.clear(); this._selectedDecoration.clear();
disposeArray(this._highlightDecorations); dispose(this._highlightDecorations);
this._highlightDecorations = []; this._highlightDecorations = [];
this._highlightedLines.clear(); this._highlightedLines.clear();
if (!retainCachedSearchTerm) { if (!retainCachedSearchTerm) {
@@ -426,11 +426,11 @@ export class SearchAddon extends Disposable implements ITerminalAddon , ISearchA
const terminal = this._terminal!; const terminal = this._terminal!;
if (!this._linesCache) { if (!this._linesCache) {
this._linesCache = new Array(terminal.buffer.active.length); this._linesCache = new Array(terminal.buffer.active.length);
this._linesCacheDisposables.value = getDisposeArrayDisposable([ this._linesCacheDisposables.value = combinedDisposable(
terminal.onLineFeed(() => this._destroyLinesCache()), terminal.onLineFeed(() => this._destroyLinesCache()),
terminal.onCursorMove(() => this._destroyLinesCache()), terminal.onCursorMove(() => this._destroyLinesCache()),
terminal.onResize(() => this._destroyLinesCache()) terminal.onResize(() => this._destroyLinesCache())
]); );
} }
window.clearTimeout(this._linesCacheTimeoutId); window.clearTimeout(this._linesCacheTimeoutId);
@@ -678,7 +678,7 @@ export class SearchAddon extends Disposable implements ITerminalAddon , ISearchA
const disposables: IDisposable[] = []; const disposables: IDisposable[] = [];
disposables.push(marker); disposables.push(marker);
disposables.push(decoration.onRender((e) => this._applyStyles(e, options.activeMatchBorder, true))); disposables.push(decoration.onRender((e) => this._applyStyles(e, options.activeMatchBorder, true)));
disposables.push(decoration.onDispose(() => disposeArray(disposables))); disposables.push(decoration.onDispose(() => dispose(disposables)));
this._selectedDecoration.value = { decoration, match: result, dispose() { decoration.dispose(); } }; this._selectedDecoration.value = { decoration, match: result, dispose() { decoration.dispose(); } };
} }
} }
@@ -740,7 +740,7 @@ export class SearchAddon extends Disposable implements ITerminalAddon , ISearchA
const disposables: IDisposable[] = []; const disposables: IDisposable[] = [];
disposables.push(marker); disposables.push(marker);
disposables.push(findResultDecoration.onRender((e) => this._applyStyles(e, options.matchBorder, false))); disposables.push(findResultDecoration.onRender((e) => this._applyStyles(e, options.matchBorder, false)));
disposables.push(findResultDecoration.onDispose(() => disposeArray(disposables))); disposables.push(findResultDecoration.onDispose(() => dispose(disposables)));
} }
return findResultDecoration; return findResultDecoration;
} }
+6 -6
View File
@@ -7,7 +7,7 @@ import { allowRescaling, throwIfFalsy } from 'browser/renderer/shared/RendererUt
import { TextureAtlas } from 'browser/renderer/shared/TextureAtlas'; import { TextureAtlas } from 'browser/renderer/shared/TextureAtlas';
import { IRasterizedGlyph, IRenderDimensions, ITextureAtlas } from 'browser/renderer/shared/Types'; import { IRasterizedGlyph, IRenderDimensions, ITextureAtlas } from 'browser/renderer/shared/Types';
import { NULL_CELL_CODE } from 'common/buffer/Constants'; import { NULL_CELL_CODE } from 'common/buffer/Constants';
import { Disposable, toDisposable } from 'common/Lifecycle'; import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { Terminal } from '@xterm/xterm'; import { Terminal } from '@xterm/xterm';
import { IRenderModel, IWebGL2RenderingContext, IWebGLVertexArrayObject } from './Types'; import { IRenderModel, IWebGL2RenderingContext, IWebGLVertexArrayObject } from './Types';
import { createProgram, GLTexture, PROJECTION_MATRIX } from './WebglUtils'; import { createProgram, GLTexture, PROJECTION_MATRIX } from './WebglUtils';
@@ -127,7 +127,7 @@ export class GlyphRenderer extends Disposable {
} }
this._program = throwIfFalsy(createProgram(gl, vertexShaderSource, createFragmentShaderSource(TextureAtlas.maxAtlasPages))); this._program = throwIfFalsy(createProgram(gl, vertexShaderSource, createFragmentShaderSource(TextureAtlas.maxAtlasPages)));
this.register(toDisposable(() => gl.deleteProgram(this._program))); this._register(toDisposable(() => gl.deleteProgram(this._program)));
// Uniform locations // Uniform locations
this._projectionLocation = throwIfFalsy(gl.getUniformLocation(this._program, 'u_projection')); this._projectionLocation = throwIfFalsy(gl.getUniformLocation(this._program, 'u_projection'));
@@ -141,7 +141,7 @@ export class GlyphRenderer extends Disposable {
// Setup a_unitquad, this defines the 4 vertices of a rectangle // Setup a_unitquad, this defines the 4 vertices of a rectangle
const unitQuadVertices = new Float32Array([0, 0, 1, 0, 0, 1, 1, 1]); const unitQuadVertices = new Float32Array([0, 0, 1, 0, 0, 1, 1, 1]);
const unitQuadVerticesBuffer = gl.createBuffer(); const unitQuadVerticesBuffer = gl.createBuffer();
this.register(toDisposable(() => gl.deleteBuffer(unitQuadVerticesBuffer))); this._register(toDisposable(() => gl.deleteBuffer(unitQuadVerticesBuffer)));
gl.bindBuffer(gl.ARRAY_BUFFER, unitQuadVerticesBuffer); gl.bindBuffer(gl.ARRAY_BUFFER, unitQuadVerticesBuffer);
gl.bufferData(gl.ARRAY_BUFFER, unitQuadVertices, gl.STATIC_DRAW); gl.bufferData(gl.ARRAY_BUFFER, unitQuadVertices, gl.STATIC_DRAW);
gl.enableVertexAttribArray(VertexAttribLocations.UNIT_QUAD); gl.enableVertexAttribArray(VertexAttribLocations.UNIT_QUAD);
@@ -152,13 +152,13 @@ export class GlyphRenderer extends Disposable {
// triangle strip // triangle strip
const unitQuadElementIndices = new Uint8Array([0, 1, 2, 3]); const unitQuadElementIndices = new Uint8Array([0, 1, 2, 3]);
const elementIndicesBuffer = gl.createBuffer(); const elementIndicesBuffer = gl.createBuffer();
this.register(toDisposable(() => gl.deleteBuffer(elementIndicesBuffer))); this._register(toDisposable(() => gl.deleteBuffer(elementIndicesBuffer)));
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementIndicesBuffer); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementIndicesBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, unitQuadElementIndices, gl.STATIC_DRAW); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, unitQuadElementIndices, gl.STATIC_DRAW);
// Setup attributes // Setup attributes
this._attributesBuffer = throwIfFalsy(gl.createBuffer()); this._attributesBuffer = throwIfFalsy(gl.createBuffer());
this.register(toDisposable(() => gl.deleteBuffer(this._attributesBuffer))); this._register(toDisposable(() => gl.deleteBuffer(this._attributesBuffer)));
gl.bindBuffer(gl.ARRAY_BUFFER, this._attributesBuffer); gl.bindBuffer(gl.ARRAY_BUFFER, this._attributesBuffer);
gl.enableVertexAttribArray(VertexAttribLocations.OFFSET); gl.enableVertexAttribArray(VertexAttribLocations.OFFSET);
gl.vertexAttribPointer(VertexAttribLocations.OFFSET, 2, gl.FLOAT, false, BYTES_PER_CELL, 0); gl.vertexAttribPointer(VertexAttribLocations.OFFSET, 2, gl.FLOAT, false, BYTES_PER_CELL, 0);
@@ -193,7 +193,7 @@ export class GlyphRenderer extends Disposable {
this._atlasTextures = []; this._atlasTextures = [];
for (let i = 0; i < TextureAtlas.maxAtlasPages; i++) { for (let i = 0; i < TextureAtlas.maxAtlasPages; i++) {
const glTexture = new GLTexture(throwIfFalsy(gl.createTexture())); const glTexture = new GLTexture(throwIfFalsy(gl.createTexture()));
this.register(toDisposable(() => gl.deleteTexture(glTexture.texture))); this._register(toDisposable(() => gl.deleteTexture(glTexture.texture)));
gl.activeTexture(gl.TEXTURE0 + i); gl.activeTexture(gl.TEXTURE0 + i);
gl.bindTexture(gl.TEXTURE_2D, glTexture.texture); gl.bindTexture(gl.TEXTURE_2D, glTexture.texture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+6 -6
View File
@@ -8,7 +8,7 @@ import { IRenderDimensions } from 'browser/renderer/shared/Types';
import { IThemeService } from 'browser/services/Services'; import { IThemeService } from 'browser/services/Services';
import { ReadonlyColorSet } from 'browser/Types'; import { ReadonlyColorSet } from 'browser/Types';
import { Attributes, FgFlags } from 'common/buffer/Constants'; import { Attributes, FgFlags } from 'common/buffer/Constants';
import { Disposable, toDisposable } from 'common/Lifecycle'; import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { IColor } from 'common/Types'; import { IColor } from 'common/Types';
import { Terminal } from '@xterm/xterm'; import { Terminal } from '@xterm/xterm';
import { RENDER_MODEL_BG_OFFSET, RENDER_MODEL_FG_OFFSET, RENDER_MODEL_INDICIES_PER_CELL } from './RenderModel'; import { RENDER_MODEL_BG_OFFSET, RENDER_MODEL_FG_OFFSET, RENDER_MODEL_INDICIES_PER_CELL } from './RenderModel';
@@ -96,7 +96,7 @@ export class RectangleRenderer extends Disposable {
const gl = this._gl; const gl = this._gl;
this._program = throwIfFalsy(createProgram(gl, vertexShaderSource, fragmentShaderSource)); this._program = throwIfFalsy(createProgram(gl, vertexShaderSource, fragmentShaderSource));
this.register(toDisposable(() => gl.deleteProgram(this._program))); this._register(toDisposable(() => gl.deleteProgram(this._program)));
// Uniform locations // Uniform locations
this._projectionLocation = throwIfFalsy(gl.getUniformLocation(this._program, 'u_projection')); this._projectionLocation = throwIfFalsy(gl.getUniformLocation(this._program, 'u_projection'));
@@ -108,7 +108,7 @@ export class RectangleRenderer extends Disposable {
// Setup a_unitquad, this defines the 4 vertices of a rectangle // Setup a_unitquad, this defines the 4 vertices of a rectangle
const unitQuadVertices = new Float32Array([0, 0, 1, 0, 0, 1, 1, 1]); const unitQuadVertices = new Float32Array([0, 0, 1, 0, 0, 1, 1, 1]);
const unitQuadVerticesBuffer = gl.createBuffer(); const unitQuadVerticesBuffer = gl.createBuffer();
this.register(toDisposable(() => gl.deleteBuffer(unitQuadVerticesBuffer))); this._register(toDisposable(() => gl.deleteBuffer(unitQuadVerticesBuffer)));
gl.bindBuffer(gl.ARRAY_BUFFER, unitQuadVerticesBuffer); gl.bindBuffer(gl.ARRAY_BUFFER, unitQuadVerticesBuffer);
gl.bufferData(gl.ARRAY_BUFFER, unitQuadVertices, gl.STATIC_DRAW); gl.bufferData(gl.ARRAY_BUFFER, unitQuadVertices, gl.STATIC_DRAW);
gl.enableVertexAttribArray(VertexAttribLocations.UNIT_QUAD); gl.enableVertexAttribArray(VertexAttribLocations.UNIT_QUAD);
@@ -119,13 +119,13 @@ export class RectangleRenderer extends Disposable {
// triangle strip // triangle strip
const unitQuadElementIndices = new Uint8Array([0, 1, 2, 3]); const unitQuadElementIndices = new Uint8Array([0, 1, 2, 3]);
const elementIndicesBuffer = gl.createBuffer(); const elementIndicesBuffer = gl.createBuffer();
this.register(toDisposable(() => gl.deleteBuffer(elementIndicesBuffer))); this._register(toDisposable(() => gl.deleteBuffer(elementIndicesBuffer)));
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementIndicesBuffer); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementIndicesBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, unitQuadElementIndices, gl.STATIC_DRAW); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, unitQuadElementIndices, gl.STATIC_DRAW);
// Setup attributes // Setup attributes
this._attributesBuffer = throwIfFalsy(gl.createBuffer()); this._attributesBuffer = throwIfFalsy(gl.createBuffer());
this.register(toDisposable(() => gl.deleteBuffer(this._attributesBuffer))); this._register(toDisposable(() => gl.deleteBuffer(this._attributesBuffer)));
gl.bindBuffer(gl.ARRAY_BUFFER, this._attributesBuffer); gl.bindBuffer(gl.ARRAY_BUFFER, this._attributesBuffer);
gl.enableVertexAttribArray(VertexAttribLocations.POSITION); gl.enableVertexAttribArray(VertexAttribLocations.POSITION);
gl.vertexAttribPointer(VertexAttribLocations.POSITION, 2, gl.FLOAT, false, BYTES_PER_RECTANGLE, 0); gl.vertexAttribPointer(VertexAttribLocations.POSITION, 2, gl.FLOAT, false, BYTES_PER_RECTANGLE, 0);
@@ -138,7 +138,7 @@ export class RectangleRenderer extends Disposable {
gl.vertexAttribDivisor(VertexAttribLocations.COLOR, 1); gl.vertexAttribDivisor(VertexAttribLocations.COLOR, 1);
this._updateCachedColors(_themeService.colors); this._updateCachedColors(_themeService.colors);
this.register(this._themeService.onChangeColors(e => { this._register(this._themeService.onChangeColors(e => {
this._updateCachedColors(e); this._updateCachedColors(e);
this._updateViewportRectangle(); this._updateViewportRectangle();
})); }));
+12 -12
View File
@@ -7,7 +7,7 @@ import type { ITerminalAddon, Terminal } from '@xterm/xterm';
import type { WebglAddon as IWebglApi } from '@xterm/addon-webgl'; import type { WebglAddon as IWebglApi } from '@xterm/addon-webgl';
import { ICharacterJoinerService, ICharSizeService, ICoreBrowserService, IRenderService, IThemeService } from 'browser/services/Services'; import { ICharacterJoinerService, ICharSizeService, ICoreBrowserService, IRenderService, IThemeService } from 'browser/services/Services';
import { ITerminal } from 'browser/Types'; import { ITerminal } from 'browser/Types';
import { Disposable, toDisposable } from 'common/Lifecycle'; import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { getSafariVersion, isSafari } from 'common/Platform'; import { getSafariVersion, isSafari } from 'common/Platform';
import { ICoreService, IDecorationService, ILogService, IOptionsService } from 'common/services/Services'; import { ICoreService, IDecorationService, ILogService, IOptionsService } from 'common/services/Services';
import { IWebGL2RenderingContext } from './Types'; import { IWebGL2RenderingContext } from './Types';
@@ -19,13 +19,13 @@ export class WebglAddon extends Disposable implements ITerminalAddon , IWebglApi
private _terminal?: Terminal; private _terminal?: Terminal;
private _renderer?: WebglRenderer; private _renderer?: WebglRenderer;
private readonly _onChangeTextureAtlas = this.register(new Emitter<HTMLCanvasElement>()); private readonly _onChangeTextureAtlas = this._register(new Emitter<HTMLCanvasElement>());
public readonly onChangeTextureAtlas = this._onChangeTextureAtlas.event; public readonly onChangeTextureAtlas = this._onChangeTextureAtlas.event;
private readonly _onAddTextureAtlasCanvas = this.register(new Emitter<HTMLCanvasElement>()); private readonly _onAddTextureAtlasCanvas = this._register(new Emitter<HTMLCanvasElement>());
public readonly onAddTextureAtlasCanvas = this._onAddTextureAtlasCanvas.event; public readonly onAddTextureAtlasCanvas = this._onAddTextureAtlasCanvas.event;
private readonly _onRemoveTextureAtlasCanvas = this.register(new Emitter<HTMLCanvasElement>()); private readonly _onRemoveTextureAtlasCanvas = this._register(new Emitter<HTMLCanvasElement>());
public readonly onRemoveTextureAtlasCanvas = this._onRemoveTextureAtlasCanvas.event; public readonly onRemoveTextureAtlasCanvas = this._onRemoveTextureAtlasCanvas.event;
private readonly _onContextLoss = this.register(new Emitter<void>()); private readonly _onContextLoss = this._register(new Emitter<void>());
public readonly onContextLoss = this._onContextLoss.event; public readonly onContextLoss = this._onContextLoss.event;
constructor( constructor(
@@ -49,7 +49,7 @@ export class WebglAddon extends Disposable implements ITerminalAddon , IWebglApi
public activate(terminal: Terminal): void { public activate(terminal: Terminal): void {
const core = (terminal as any)._core as ITerminal; const core = (terminal as any)._core as ITerminal;
if (!terminal.element) { if (!terminal.element) {
this.register(core.onWillOpen(() => this.activate(terminal))); this._register(core.onWillOpen(() => this.activate(terminal)));
return; return;
} }
@@ -70,7 +70,7 @@ export class WebglAddon extends Disposable implements ITerminalAddon , IWebglApi
// bundled separately to the core module // bundled separately to the core module
setTraceLogger(logService); setTraceLogger(logService);
this._renderer = this.register(new WebglRenderer( this._renderer = this._register(new WebglRenderer(
terminal, terminal,
characterJoinerService, characterJoinerService,
charSizeService, charSizeService,
@@ -81,13 +81,13 @@ export class WebglAddon extends Disposable implements ITerminalAddon , IWebglApi
themeService, themeService,
this._preserveDrawingBuffer this._preserveDrawingBuffer
)); ));
this.register(Event.forward(this._renderer.onContextLoss, this._onContextLoss)); this._register(Event.forward(this._renderer.onContextLoss, this._onContextLoss));
this.register(Event.forward(this._renderer.onChangeTextureAtlas, this._onChangeTextureAtlas)); this._register(Event.forward(this._renderer.onChangeTextureAtlas, this._onChangeTextureAtlas));
this.register(Event.forward(this._renderer.onAddTextureAtlasCanvas, this._onAddTextureAtlasCanvas)); this._register(Event.forward(this._renderer.onAddTextureAtlasCanvas, this._onAddTextureAtlasCanvas));
this.register(Event.forward(this._renderer.onRemoveTextureAtlasCanvas, this._onRemoveTextureAtlasCanvas)); this._register(Event.forward(this._renderer.onRemoveTextureAtlasCanvas, this._onRemoveTextureAtlasCanvas));
renderService.setRenderer(this._renderer); renderService.setRenderer(this._renderer);
this.register(toDisposable(() => { this._register(toDisposable(() => {
const renderService: IRenderService = (this._terminal as any)._core._renderService; const renderService: IRenderService = (this._terminal as any)._core._renderService;
renderService.setRenderer((this._terminal as any)._core._createRenderer()); renderService.setRenderer((this._terminal as any)._core._createRenderer());
renderService.handleResize(terminal.cols, terminal.rows); renderService.handleResize(terminal.cols, terminal.rows);
+19 -19
View File
@@ -3,7 +3,6 @@
* @license MIT * @license MIT
*/ */
import { addDisposableDomListener } from 'browser/Lifecycle';
import { ITerminal } from 'browser/Types'; import { ITerminal } from 'browser/Types';
import { CellColorResolver } from 'browser/renderer/shared/CellColorResolver'; import { CellColorResolver } from 'browser/renderer/shared/CellColorResolver';
import { acquireTextureAtlas, removeTerminalFromCache } from 'browser/renderer/shared/CharAtlasCache'; import { acquireTextureAtlas, removeTerminalFromCache } from 'browser/renderer/shared/CharAtlasCache';
@@ -12,7 +11,6 @@ import { observeDevicePixelDimensions } from 'browser/renderer/shared/DevicePixe
import { createRenderDimensions } from 'browser/renderer/shared/RendererUtils'; import { createRenderDimensions } from 'browser/renderer/shared/RendererUtils';
import { IRenderDimensions, IRenderer, IRequestRedrawEvent, ITextureAtlas } from 'browser/renderer/shared/Types'; import { IRenderDimensions, IRenderer, IRequestRedrawEvent, ITextureAtlas } from 'browser/renderer/shared/Types';
import { ICharSizeService, ICharacterJoinerService, ICoreBrowserService, IThemeService } from 'browser/services/Services'; import { ICharSizeService, ICharacterJoinerService, ICoreBrowserService, IThemeService } from 'browser/services/Services';
import { Disposable, MutableDisposable, getDisposeArrayDisposable, toDisposable } from 'common/Lifecycle';
import { CharData, IBufferLine, ICellData } from 'common/Types'; import { CharData, IBufferLine, ICellData } from 'common/Types';
import { AttributeData } from 'common/buffer/AttributeData'; import { AttributeData } from 'common/buffer/AttributeData';
import { CellData } from 'common/buffer/CellData'; import { CellData } from 'common/buffer/CellData';
@@ -26,14 +24,16 @@ import { IWebGL2RenderingContext } from './Types';
import { LinkRenderLayer } from './renderLayer/LinkRenderLayer'; import { LinkRenderLayer } from './renderLayer/LinkRenderLayer';
import { IRenderLayer } from './renderLayer/Types'; import { IRenderLayer } from './renderLayer/Types';
import { Emitter, Event } from 'vs/base/common/event'; import { Emitter, Event } from 'vs/base/common/event';
import { addDisposableListener } from 'vs/base/browser/dom';
import { combinedDisposable, Disposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
export class WebglRenderer extends Disposable implements IRenderer { export class WebglRenderer extends Disposable implements IRenderer {
private _renderLayers: IRenderLayer[]; private _renderLayers: IRenderLayer[];
private _cursorBlinkStateManager: MutableDisposable<CursorBlinkStateManager> = new MutableDisposable(); private _cursorBlinkStateManager: MutableDisposable<CursorBlinkStateManager> = new MutableDisposable();
private _charAtlasDisposable = this.register(new MutableDisposable()); private _charAtlasDisposable = this._register(new MutableDisposable());
private _charAtlas: ITextureAtlas | undefined; private _charAtlas: ITextureAtlas | undefined;
private _devicePixelRatio: number; private _devicePixelRatio: number;
private _observerDisposable = this.register(new MutableDisposable()); private _observerDisposable = this._register(new MutableDisposable());
private _model: RenderModel = new RenderModel(); private _model: RenderModel = new RenderModel();
private _workCell: ICellData = new CellData(); private _workCell: ICellData = new CellData();
@@ -42,8 +42,8 @@ export class WebglRenderer extends Disposable implements IRenderer {
private _canvas: HTMLCanvasElement; private _canvas: HTMLCanvasElement;
private _gl: IWebGL2RenderingContext; private _gl: IWebGL2RenderingContext;
private _rectangleRenderer: MutableDisposable<RectangleRenderer> = this.register(new MutableDisposable()); private _rectangleRenderer: MutableDisposable<RectangleRenderer> = this._register(new MutableDisposable());
private _glyphRenderer: MutableDisposable<GlyphRenderer> = this.register(new MutableDisposable()); private _glyphRenderer: MutableDisposable<GlyphRenderer> = this._register(new MutableDisposable());
public readonly dimensions: IRenderDimensions; public readonly dimensions: IRenderDimensions;
@@ -51,15 +51,15 @@ export class WebglRenderer extends Disposable implements IRenderer {
private _isAttached: boolean; private _isAttached: boolean;
private _contextRestorationTimeout: number | undefined; private _contextRestorationTimeout: number | undefined;
private readonly _onChangeTextureAtlas = this.register(new Emitter<HTMLCanvasElement>()); private readonly _onChangeTextureAtlas = this._register(new Emitter<HTMLCanvasElement>());
public readonly onChangeTextureAtlas = this._onChangeTextureAtlas.event; public readonly onChangeTextureAtlas = this._onChangeTextureAtlas.event;
private readonly _onAddTextureAtlasCanvas = this.register(new Emitter<HTMLCanvasElement>()); private readonly _onAddTextureAtlasCanvas = this._register(new Emitter<HTMLCanvasElement>());
public readonly onAddTextureAtlasCanvas = this._onAddTextureAtlasCanvas.event; public readonly onAddTextureAtlasCanvas = this._onAddTextureAtlasCanvas.event;
private readonly _onRemoveTextureAtlasCanvas = this.register(new Emitter<HTMLCanvasElement>()); private readonly _onRemoveTextureAtlasCanvas = this._register(new Emitter<HTMLCanvasElement>());
public readonly onRemoveTextureAtlasCanvas = this._onRemoveTextureAtlasCanvas.event; public readonly onRemoveTextureAtlasCanvas = this._onRemoveTextureAtlasCanvas.event;
private readonly _onRequestRedraw = this.register(new Emitter<IRequestRedrawEvent>()); private readonly _onRequestRedraw = this._register(new Emitter<IRequestRedrawEvent>());
public readonly onRequestRedraw = this._onRequestRedraw.event; public readonly onRequestRedraw = this._onRequestRedraw.event;
private readonly _onContextLoss = this.register(new Emitter<void>()); private readonly _onContextLoss = this._register(new Emitter<void>());
public readonly onContextLoss = this._onContextLoss.event; public readonly onContextLoss = this._onContextLoss.event;
constructor( constructor(
@@ -75,7 +75,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
) { ) {
super(); super();
this.register(this._themeService.onChangeColors(() => this._handleColorChange())); this._register(this._themeService.onChangeColors(() => this._handleColorChange()));
this._cellColorResolver = new CellColorResolver(this._terminal, this._optionsService, this._model.selection, this._decorationService, this._coreBrowserService, this._themeService); this._cellColorResolver = new CellColorResolver(this._terminal, this._optionsService, this._model.selection, this._decorationService, this._coreBrowserService, this._themeService);
@@ -88,7 +88,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
this._devicePixelRatio = this._coreBrowserService.dpr; this._devicePixelRatio = this._coreBrowserService.dpr;
this._updateDimensions(); this._updateDimensions();
this._updateCursorBlink(); this._updateCursorBlink();
this.register(_optionsService.onOptionChange(() => this._handleOptionsChanged())); this._register(_optionsService.onOptionChange(() => this._handleOptionsChanged()));
this._canvas = this._coreBrowserService.mainDocument.createElement('canvas'); this._canvas = this._coreBrowserService.mainDocument.createElement('canvas');
@@ -102,7 +102,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
throw new Error('WebGL2 not supported ' + this._gl); throw new Error('WebGL2 not supported ' + this._gl);
} }
this.register(addDisposableDomListener(this._canvas, 'webglcontextlost', (e) => { this._register(addDisposableListener(this._canvas, 'webglcontextlost', (e) => {
console.log('webglcontextlost event received'); console.log('webglcontextlost event received');
// Prevent the default behavior in order to enable WebGL context restoration. // Prevent the default behavior in order to enable WebGL context restoration.
e.preventDefault(); e.preventDefault();
@@ -114,7 +114,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
this._onContextLoss.fire(e); this._onContextLoss.fire(e);
}, 3000 /* ms */); }, 3000 /* ms */);
})); }));
this.register(addDisposableDomListener(this._canvas, 'webglcontextrestored', (e) => { this._register(addDisposableListener(this._canvas, 'webglcontextrestored', (e) => {
console.warn('webglcontextrestored event received'); console.warn('webglcontextrestored event received');
clearTimeout(this._contextRestorationTimeout); clearTimeout(this._contextRestorationTimeout);
this._contextRestorationTimeout = undefined; this._contextRestorationTimeout = undefined;
@@ -126,7 +126,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
})); }));
this._observerDisposable.value = observeDevicePixelDimensions(this._canvas, this._coreBrowserService.window, (w, h) => this._setCanvasDevicePixelDimensions(w, h)); this._observerDisposable.value = observeDevicePixelDimensions(this._canvas, this._coreBrowserService.window, (w, h) => this._setCanvasDevicePixelDimensions(w, h));
this.register(this._coreBrowserService.onWindowChange(w => { this._register(this._coreBrowserService.onWindowChange(w => {
this._observerDisposable.value = observeDevicePixelDimensions(this._canvas, w, (w, h) => this._setCanvasDevicePixelDimensions(w, h)); this._observerDisposable.value = observeDevicePixelDimensions(this._canvas, w, (w, h) => this._setCanvasDevicePixelDimensions(w, h));
})); }));
@@ -136,7 +136,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
this._isAttached = this._coreBrowserService.window.document.body.contains(this._core.screenElement!); this._isAttached = this._coreBrowserService.window.document.body.contains(this._core.screenElement!);
this.register(toDisposable(() => { this._register(toDisposable(() => {
for (const l of this._renderLayers) { for (const l of this._renderLayers) {
l.dispose(); l.dispose();
} }
@@ -276,10 +276,10 @@ export class WebglRenderer extends Disposable implements IRenderer {
); );
if (this._charAtlas !== atlas) { if (this._charAtlas !== atlas) {
this._onChangeTextureAtlas.fire(atlas.pages[0].canvas); this._onChangeTextureAtlas.fire(atlas.pages[0].canvas);
this._charAtlasDisposable.value = getDisposeArrayDisposable([ this._charAtlasDisposable.value = combinedDisposable(
Event.forward(atlas.onAddTextureAtlasCanvas, this._onAddTextureAtlasCanvas), Event.forward(atlas.onAddTextureAtlasCanvas, this._onAddTextureAtlasCanvas),
Event.forward(atlas.onRemoveTextureAtlasCanvas, this._onRemoveTextureAtlasCanvas) Event.forward(atlas.onRemoveTextureAtlasCanvas, this._onRemoveTextureAtlasCanvas)
]); );
} }
this._charAtlas = atlas; this._charAtlas = atlas;
this._charAtlas.warmUp(); this._charAtlas.warmUp();
@@ -9,7 +9,7 @@ import { TEXT_BASELINE } from 'browser/renderer/shared/Constants';
import { throwIfFalsy } from 'browser/renderer/shared/RendererUtils'; import { throwIfFalsy } from 'browser/renderer/shared/RendererUtils';
import { IRenderDimensions, ITextureAtlas } from 'browser/renderer/shared/Types'; import { IRenderDimensions, ITextureAtlas } from 'browser/renderer/shared/Types';
import { ICoreBrowserService, IThemeService } from 'browser/services/Services'; import { ICoreBrowserService, IThemeService } from 'browser/services/Services';
import { Disposable, toDisposable } from 'common/Lifecycle'; import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { CellData } from 'common/buffer/CellData'; import { CellData } from 'common/buffer/CellData';
import { IOptionsService } from 'common/services/Services'; import { IOptionsService } from 'common/services/Services';
import { Terminal } from '@xterm/xterm'; import { Terminal } from '@xterm/xterm';
@@ -43,11 +43,11 @@ export abstract class BaseRenderLayer extends Disposable implements IRenderLayer
this._canvas.style.zIndex = zIndex.toString(); this._canvas.style.zIndex = zIndex.toString();
this._initCanvas(); this._initCanvas();
this._container.appendChild(this._canvas); this._container.appendChild(this._canvas);
this.register(this._themeService.onChangeColors(e => { this._register(this._themeService.onChangeColors(e => {
this._refreshCharAtlas(terminal, e); this._refreshCharAtlas(terminal, e);
this.reset(terminal); this.reset(terminal);
})); }));
this.register(toDisposable(() => { this._register(toDisposable(() => {
this._canvas.remove(); this._canvas.remove();
})); }));
} }
@@ -26,8 +26,8 @@ export class LinkRenderLayer extends BaseRenderLayer {
) { ) {
super(terminal, container, 'link', zIndex, true, coreBrowserService, optionsService, themeService); super(terminal, container, 'link', zIndex, true, coreBrowserService, optionsService, themeService);
this.register(linkifier2.onShowLinkUnderline(e => this._handleShowLinkUnderline(e))); this._register(linkifier2.onShowLinkUnderline(e => this._handleShowLinkUnderline(e)));
this.register(linkifier2.onHideLinkUnderline(e => this._handleHideLinkUnderline(e))); this._register(linkifier2.onHideLinkUnderline(e => this._handleHideLinkUnderline(e)));
} }
public resize(terminal: Terminal, dim: IRenderDimensions): void { public resize(terminal: Terminal, dim: IRenderDimensions): void {
+2 -1
View File
@@ -29,7 +29,8 @@
"downlevelIteration": true, "downlevelIteration": true,
"experimentalDecorators": true, "experimentalDecorators": true,
"types": [ "types": [
"../../../node_modules/@types/mocha" "../../../node_modules/@types/mocha",
"../../../src/vs/typings/thenable"
] ]
}, },
"include": [ "include": [
+1 -4
View File
@@ -12,10 +12,7 @@ const COVERAGE_LINES_THRESHOLD = 40;
const env = { ...process.env }; const env = { ...process.env };
env.NODE_PATH = path.resolve(__dirname, '../out-esbuild'); env.NODE_PATH = path.resolve(__dirname, '../out-esbuild');
let testFiles = [ let testFiles = ['**/out-esbuild/**/*.test.js'];
'./out-esbuild/**/*test.js',
'./addons/**/out-esbuild/*test.js',
];
let flagArgs = []; let flagArgs = [];
+1 -1
View File
@@ -694,7 +694,7 @@ function updateFindResults(e: { resultIndex: number, resultCount: number } | und
function addDomListener(element: HTMLElement, type: string, handler: (...args: any[]) => any): void { function addDomListener(element: HTMLElement, type: string, handler: (...args: any[]) => any): void {
element.addEventListener(type, handler); element.addEventListener(type, handler);
term._core.register({ dispose: () => element.removeEventListener(type, handler) }); term._core._register({ dispose: () => element.removeEventListener(type, handler) });
} }
function updateTerminalSize(): void { function updateTerminalSize(): void {
+15 -15
View File
@@ -6,11 +6,11 @@
import * as Strings from 'browser/LocalizableStrings'; import * as Strings from 'browser/LocalizableStrings';
import { ITerminal, IRenderDebouncer } from 'browser/Types'; import { ITerminal, IRenderDebouncer } from 'browser/Types';
import { TimeBasedDebouncer } from 'browser/TimeBasedDebouncer'; import { TimeBasedDebouncer } from 'browser/TimeBasedDebouncer';
import { Disposable, toDisposable } from 'common/Lifecycle'; import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { ICoreBrowserService, IRenderService } from 'browser/services/Services'; import { ICoreBrowserService, IRenderService } from 'browser/services/Services';
import { IBuffer } from 'common/buffer/Types'; import { IBuffer } from 'common/buffer/Types';
import { IInstantiationService } from 'common/services/Services'; import { IInstantiationService } from 'common/services/Services';
import { addDisposableDomListener } from 'browser/Lifecycle'; import { addDisposableListener } from 'vs/base/browser/dom';
const MAX_ROWS_TO_READ = 20; const MAX_ROWS_TO_READ = 20;
@@ -82,7 +82,7 @@ export class AccessibilityManager extends Disposable {
this._liveRegion.classList.add('live-region'); this._liveRegion.classList.add('live-region');
this._liveRegion.setAttribute('aria-live', 'assertive'); this._liveRegion.setAttribute('aria-live', 'assertive');
this._accessibilityContainer.appendChild(this._liveRegion); this._accessibilityContainer.appendChild(this._liveRegion);
this._liveRegionDebouncer = this.register(new TimeBasedDebouncer(this._renderRows.bind(this))); this._liveRegionDebouncer = this._register(new TimeBasedDebouncer(this._renderRows.bind(this)));
if (!this._terminal.element) { if (!this._terminal.element) {
throw new Error('Cannot enable accessibility before Terminal.open'); throw new Error('Cannot enable accessibility before Terminal.open');
@@ -105,22 +105,22 @@ export class AccessibilityManager extends Disposable {
this._terminal.element.insertAdjacentElement('afterbegin', this._accessibilityContainer); this._terminal.element.insertAdjacentElement('afterbegin', this._accessibilityContainer);
} }
this.register(this._terminal.onResize(e => this._handleResize(e.rows))); this._register(this._terminal.onResize(e => this._handleResize(e.rows)));
this.register(this._terminal.onRender(e => this._refreshRows(e.start, e.end))); this._register(this._terminal.onRender(e => this._refreshRows(e.start, e.end)));
this.register(this._terminal.onScroll(() => this._refreshRows())); this._register(this._terminal.onScroll(() => this._refreshRows()));
// Line feed is an issue as the prompt won't be read out after a command is run // Line feed is an issue as the prompt won't be read out after a command is run
this.register(this._terminal.onA11yChar(char => this._handleChar(char))); this._register(this._terminal.onA11yChar(char => this._handleChar(char)));
this.register(this._terminal.onLineFeed(() => this._handleChar('\n'))); this._register(this._terminal.onLineFeed(() => this._handleChar('\n')));
this.register(this._terminal.onA11yTab(spaceCount => this._handleTab(spaceCount))); this._register(this._terminal.onA11yTab(spaceCount => this._handleTab(spaceCount)));
this.register(this._terminal.onKey(e => this._handleKey(e.key))); this._register(this._terminal.onKey(e => this._handleKey(e.key)));
this.register(this._terminal.onBlur(() => this._clearLiveRegion())); this._register(this._terminal.onBlur(() => this._clearLiveRegion()));
this.register(this._renderService.onDimensionsChange(() => this._refreshRowsDimensions())); this._register(this._renderService.onDimensionsChange(() => this._refreshRowsDimensions()));
this.register(addDisposableDomListener(doc, 'selectionchange', () => this._handleSelectionChange())); this._register(addDisposableListener(doc, 'selectionchange', () => this._handleSelectionChange()));
this.register(this._coreBrowserService.onDprChange(() => this._refreshRowsDimensions())); this._register(this._coreBrowserService.onDprChange(() => this._refreshRowsDimensions()));
this._refreshRowsDimensions(); this._refreshRowsDimensions();
this._refreshRows(); this._refreshRows();
this.register(toDisposable(() => { this._register(toDisposable(() => {
if (DEBUG) { if (DEBUG) {
this._debugRootContainer!.remove(); this._debugRootContainer!.remove();
} else { } else {
+68 -68
View File
@@ -23,7 +23,6 @@
import { IDecoration, IDecorationOptions, IDisposable, ILinkProvider, IMarker } from '@xterm/xterm'; import { IDecoration, IDecorationOptions, IDisposable, ILinkProvider, IMarker } from '@xterm/xterm';
import { copyHandler, handlePasteEvent, moveTextAreaUnderMouseCursor, paste, rightClickHandler } from 'browser/Clipboard'; import { copyHandler, handlePasteEvent, moveTextAreaUnderMouseCursor, paste, rightClickHandler } from 'browser/Clipboard';
import { addDisposableDomListener } from 'browser/Lifecycle';
import * as Strings from 'browser/LocalizableStrings'; import * as Strings from 'browser/LocalizableStrings';
import { OscLinkProvider } from 'browser/OscLinkProvider'; import { OscLinkProvider } from 'browser/OscLinkProvider';
import { CharacterJoinerHandler, CustomKeyEventHandler, CustomWheelEventHandler, IBrowser, IBufferRange, ICompositionHelper, ILinkifier2, ITerminal } from 'browser/Types'; import { CharacterJoinerHandler, CustomKeyEventHandler, CustomWheelEventHandler, IBrowser, IBufferRange, ICompositionHelper, ILinkifier2, ITerminal } from 'browser/Types';
@@ -44,7 +43,6 @@ import { ICharSizeService, ICharacterJoinerService, ICoreBrowserService, ILinkPr
import { ThemeService } from 'browser/services/ThemeService'; import { ThemeService } from 'browser/services/ThemeService';
import { channels, color } from 'common/Color'; import { channels, color } from 'common/Color';
import { CoreTerminal } from 'common/CoreTerminal'; import { CoreTerminal } from 'common/CoreTerminal';
import { MutableDisposable, toDisposable } from 'common/Lifecycle';
import * as Browser from 'common/Platform'; import * as Browser from 'common/Platform';
import { ColorRequestType, CoreMouseAction, CoreMouseButton, CoreMouseEventType, IColorEvent, ITerminalOptions, KeyboardResultType, SpecialColorIndex } from 'common/Types'; import { ColorRequestType, CoreMouseAction, CoreMouseButton, CoreMouseEventType, IColorEvent, ITerminalOptions, KeyboardResultType, SpecialColorIndex } from 'common/Types';
import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine'; import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';
@@ -58,6 +56,8 @@ import { WindowsOptionsReportType } from '../common/InputHandler';
import { AccessibilityManager } from './AccessibilityManager'; import { AccessibilityManager } from './AccessibilityManager';
import { Linkifier } from './Linkifier'; import { Linkifier } from './Linkifier';
import { Emitter, Event } from 'vs/base/common/event'; import { Emitter, Event } from 'vs/base/common/event';
import { addDisposableListener } from 'vs/base/browser/dom';
import { MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
export class CoreBrowserTerminal extends CoreTerminal implements ITerminal { export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
public textarea: HTMLTextAreaElement | undefined; public textarea: HTMLTextAreaElement | undefined;
@@ -119,30 +119,30 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
private _unprocessedDeadKey: boolean = false; private _unprocessedDeadKey: boolean = false;
private _compositionHelper: ICompositionHelper | undefined; private _compositionHelper: ICompositionHelper | undefined;
private _accessibilityManager: MutableDisposable<AccessibilityManager> = this.register(new MutableDisposable()); private _accessibilityManager: MutableDisposable<AccessibilityManager> = this._register(new MutableDisposable());
private readonly _onCursorMove = this.register(new Emitter<void>()); private readonly _onCursorMove = this._register(new Emitter<void>());
public readonly onCursorMove = this._onCursorMove.event; public readonly onCursorMove = this._onCursorMove.event;
private readonly _onKey = this.register(new Emitter<{ key: string, domEvent: KeyboardEvent }>()); private readonly _onKey = this._register(new Emitter<{ key: string, domEvent: KeyboardEvent }>());
public readonly onKey = this._onKey.event; public readonly onKey = this._onKey.event;
private readonly _onRender = this.register(new Emitter<{ start: number, end: number }>()); private readonly _onRender = this._register(new Emitter<{ start: number, end: number }>());
public readonly onRender = this._onRender.event; public readonly onRender = this._onRender.event;
private readonly _onSelectionChange = this.register(new Emitter<void>()); private readonly _onSelectionChange = this._register(new Emitter<void>());
public readonly onSelectionChange = this._onSelectionChange.event; public readonly onSelectionChange = this._onSelectionChange.event;
private readonly _onTitleChange = this.register(new Emitter<string>()); private readonly _onTitleChange = this._register(new Emitter<string>());
public readonly onTitleChange = this._onTitleChange.event; public readonly onTitleChange = this._onTitleChange.event;
private readonly _onBell = this.register(new Emitter<void>()); private readonly _onBell = this._register(new Emitter<void>());
public readonly onBell = this._onBell.event; public readonly onBell = this._onBell.event;
private _onFocus = this.register(new Emitter<void>()); private _onFocus = this._register(new Emitter<void>());
public get onFocus(): Event<void> { return this._onFocus.event; } public get onFocus(): Event<void> { return this._onFocus.event; }
private _onBlur = this.register(new Emitter<void>()); private _onBlur = this._register(new Emitter<void>());
public get onBlur(): Event<void> { return this._onBlur.event; } public get onBlur(): Event<void> { return this._onBlur.event; }
private _onA11yCharEmitter = this.register(new Emitter<string>()); private _onA11yCharEmitter = this._register(new Emitter<string>());
public get onA11yChar(): Event<string> { return this._onA11yCharEmitter.event; } public get onA11yChar(): Event<string> { return this._onA11yCharEmitter.event; }
private _onA11yTabEmitter = this.register(new Emitter<number>()); private _onA11yTabEmitter = this._register(new Emitter<number>());
public get onA11yTab(): Event<number> { return this._onA11yTabEmitter.event; } public get onA11yTab(): Event<number> { return this._onA11yTabEmitter.event; }
private _onWillOpen = this.register(new Emitter<HTMLElement>()); private _onWillOpen = this._register(new Emitter<HTMLElement>());
public get onWillOpen(): Event<HTMLElement> { return this._onWillOpen.event; } public get onWillOpen(): Event<HTMLElement> { return this._onWillOpen.event; }
constructor( constructor(
@@ -159,21 +159,21 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
this._linkProviderService.registerLinkProvider(this._instantiationService.createInstance(OscLinkProvider)); this._linkProviderService.registerLinkProvider(this._instantiationService.createInstance(OscLinkProvider));
// Setup InputHandler listeners // Setup InputHandler listeners
this.register(this._inputHandler.onRequestBell(() => this._onBell.fire())); this._register(this._inputHandler.onRequestBell(() => this._onBell.fire()));
this.register(this._inputHandler.onRequestRefreshRows((e) => this.refresh(e?.start ?? 0, e?.end ?? (this.rows - 1)))); this._register(this._inputHandler.onRequestRefreshRows((e) => this.refresh(e?.start ?? 0, e?.end ?? (this.rows - 1))));
this.register(this._inputHandler.onRequestSendFocus(() => this._reportFocus())); this._register(this._inputHandler.onRequestSendFocus(() => this._reportFocus()));
this.register(this._inputHandler.onRequestReset(() => this.reset())); this._register(this._inputHandler.onRequestReset(() => this.reset()));
this.register(this._inputHandler.onRequestWindowsOptionsReport(type => this._reportWindowsOptions(type))); this._register(this._inputHandler.onRequestWindowsOptionsReport(type => this._reportWindowsOptions(type)));
this.register(this._inputHandler.onColor((event) => this._handleColorEvent(event))); this._register(this._inputHandler.onColor((event) => this._handleColorEvent(event)));
this.register(Event.forward(this._inputHandler.onCursorMove, this._onCursorMove)); this._register(Event.forward(this._inputHandler.onCursorMove, this._onCursorMove));
this.register(Event.forward(this._inputHandler.onTitleChange, this._onTitleChange)); this._register(Event.forward(this._inputHandler.onTitleChange, this._onTitleChange));
this.register(Event.forward(this._inputHandler.onA11yChar, this._onA11yCharEmitter)); this._register(Event.forward(this._inputHandler.onA11yChar, this._onA11yCharEmitter));
this.register(Event.forward(this._inputHandler.onA11yTab, this._onA11yTabEmitter)); this._register(Event.forward(this._inputHandler.onA11yTab, this._onA11yTabEmitter));
// Setup listeners // Setup listeners
this.register(this._bufferService.onResize(e => this._afterResize(e.cols, e.rows))); this._register(this._bufferService.onResize(e => this._afterResize(e.cols, e.rows)));
this.register(toDisposable(() => { this._register(toDisposable(() => {
this._customKeyEventHandler = undefined; this._customKeyEventHandler = undefined;
this.element?.parentNode?.removeChild(this.element); this.element?.parentNode?.removeChild(this.element);
})); }));
@@ -330,7 +330,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
this._bindKeys(); this._bindKeys();
// Bind clipboard functionality // Bind clipboard functionality
this.register(addDisposableDomListener(this.element!, 'copy', (event: ClipboardEvent) => { this._register(addDisposableListener(this.element!, 'copy', (event: ClipboardEvent) => {
// If mouse events are active it means the selection manager is disabled and // If mouse events are active it means the selection manager is disabled and
// copy should be handled by the host program. // copy should be handled by the host program.
if (!this.hasSelection()) { if (!this.hasSelection()) {
@@ -339,19 +339,19 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
copyHandler(event, this._selectionService!); copyHandler(event, this._selectionService!);
})); }));
const pasteHandlerWrapper = (event: ClipboardEvent): void => handlePasteEvent(event, this.textarea!, this.coreService, this.optionsService); const pasteHandlerWrapper = (event: ClipboardEvent): void => handlePasteEvent(event, this.textarea!, this.coreService, this.optionsService);
this.register(addDisposableDomListener(this.textarea!, 'paste', pasteHandlerWrapper)); this._register(addDisposableListener(this.textarea!, 'paste', pasteHandlerWrapper));
this.register(addDisposableDomListener(this.element!, 'paste', pasteHandlerWrapper)); this._register(addDisposableListener(this.element!, 'paste', pasteHandlerWrapper));
// Handle right click context menus // Handle right click context menus
if (Browser.isFirefox) { if (Browser.isFirefox) {
// Firefox doesn't appear to fire the contextmenu event on right click // Firefox doesn't appear to fire the contextmenu event on right click
this.register(addDisposableDomListener(this.element!, 'mousedown', (event: MouseEvent) => { this._register(addDisposableListener(this.element!, 'mousedown', (event: MouseEvent) => {
if (event.button === 2) { if (event.button === 2) {
rightClickHandler(event, this.textarea!, this.screenElement!, this._selectionService!, this.options.rightClickSelectsWord); rightClickHandler(event, this.textarea!, this.screenElement!, this._selectionService!, this.options.rightClickSelectsWord);
} }
})); }));
} else { } else {
this.register(addDisposableDomListener(this.element!, 'contextmenu', (event: MouseEvent) => { this._register(addDisposableListener(this.element!, 'contextmenu', (event: MouseEvent) => {
rightClickHandler(event, this.textarea!, this.screenElement!, this._selectionService!, this.options.rightClickSelectsWord); rightClickHandler(event, this.textarea!, this.screenElement!, this._selectionService!, this.options.rightClickSelectsWord);
})); }));
} }
@@ -362,7 +362,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
if (Browser.isLinux) { if (Browser.isLinux) {
// Use auxclick event over mousedown the latter doesn't seem to work. Note // Use auxclick event over mousedown the latter doesn't seem to work. Note
// that the regular click event doesn't fire for the middle mouse button. // that the regular click event doesn't fire for the middle mouse button.
this.register(addDisposableDomListener(this.element!, 'auxclick', (event: MouseEvent) => { this._register(addDisposableListener(this.element!, 'auxclick', (event: MouseEvent) => {
if (event.button === 1) { if (event.button === 1) {
moveTextAreaUnderMouseCursor(event, this.textarea!, this.screenElement!); moveTextAreaUnderMouseCursor(event, this.textarea!, this.screenElement!);
} }
@@ -374,14 +374,14 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
* Apply key handling to the terminal * Apply key handling to the terminal
*/ */
private _bindKeys(): void { private _bindKeys(): void {
this.register(addDisposableDomListener(this.textarea!, 'keyup', (ev: KeyboardEvent) => this._keyUp(ev), true)); this._register(addDisposableListener(this.textarea!, 'keyup', (ev: KeyboardEvent) => this._keyUp(ev), true));
this.register(addDisposableDomListener(this.textarea!, 'keydown', (ev: KeyboardEvent) => this._keyDown(ev), true)); this._register(addDisposableListener(this.textarea!, 'keydown', (ev: KeyboardEvent) => this._keyDown(ev), true));
this.register(addDisposableDomListener(this.textarea!, 'keypress', (ev: KeyboardEvent) => this._keyPress(ev), true)); this._register(addDisposableListener(this.textarea!, 'keypress', (ev: KeyboardEvent) => this._keyPress(ev), true));
this.register(addDisposableDomListener(this.textarea!, 'compositionstart', () => this._compositionHelper!.compositionstart())); this._register(addDisposableListener(this.textarea!, 'compositionstart', () => this._compositionHelper!.compositionstart()));
this.register(addDisposableDomListener(this.textarea!, 'compositionupdate', (e: CompositionEvent) => this._compositionHelper!.compositionupdate(e))); this._register(addDisposableListener(this.textarea!, 'compositionupdate', (e: CompositionEvent) => this._compositionHelper!.compositionupdate(e)));
this.register(addDisposableDomListener(this.textarea!, 'compositionend', () => this._compositionHelper!.compositionend())); this._register(addDisposableListener(this.textarea!, 'compositionend', () => this._compositionHelper!.compositionend()));
this.register(addDisposableDomListener(this.textarea!, 'input', (ev: InputEvent) => this._inputEvent(ev), true)); this._register(addDisposableListener(this.textarea!, 'input', (ev: InputEvent) => this._inputEvent(ev), true));
this.register(this.onRender(() => this._compositionHelper!.updateCompositionElements())); this._register(this.onRender(() => this._compositionHelper!.updateCompositionElements()));
} }
/** /**
@@ -428,7 +428,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
this.screenElement = this._document.createElement('div'); this.screenElement = this._document.createElement('div');
this.screenElement.classList.add('xterm-screen'); this.screenElement.classList.add('xterm-screen');
this.register(addDisposableDomListener(this.screenElement, 'mousemove', (ev: MouseEvent) => this.updateCursorStyle(ev))); this._register(addDisposableListener(this.screenElement, 'mousemove', (ev: MouseEvent) => this.updateCursorStyle(ev)));
// Create the container that will hold helpers like the textarea for // Create the container that will hold helpers like the textarea for
// capturing DOM Events. Then produce the helpers. // capturing DOM Events. Then produce the helpers.
this._helperContainer = this._document.createElement('div'); this._helperContainer = this._document.createElement('div');
@@ -451,7 +451,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
// Register the core browser service before the generic textarea handlers are registered so it // Register the core browser service before the generic textarea handlers are registered so it
// handles them first. Otherwise the renderers may use the wrong focus state. // handles them first. Otherwise the renderers may use the wrong focus state.
this._coreBrowserService = this.register(this._instantiationService.createInstance(CoreBrowserService, this._coreBrowserService = this._register(this._instantiationService.createInstance(CoreBrowserService,
this.textarea, this.textarea,
parent.ownerDocument.defaultView ?? window, parent.ownerDocument.defaultView ?? window,
// Force unsafe null in node.js environment for tests // Force unsafe null in node.js environment for tests
@@ -459,8 +459,8 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
)); ));
this._instantiationService.setService(ICoreBrowserService, this._coreBrowserService); this._instantiationService.setService(ICoreBrowserService, this._coreBrowserService);
this.register(addDisposableDomListener(this.textarea, 'focus', (ev: FocusEvent) => this._handleTextAreaFocus(ev))); this._register(addDisposableListener(this.textarea, 'focus', (ev: FocusEvent) => this._handleTextAreaFocus(ev)));
this.register(addDisposableDomListener(this.textarea, 'blur', () => this._handleTextAreaBlur())); this._register(addDisposableListener(this.textarea, 'blur', () => this._handleTextAreaBlur()));
this._helperContainer.appendChild(this.textarea); this._helperContainer.appendChild(this.textarea);
this._charSizeService = this._instantiationService.createInstance(CharSizeService, this._document, this._helperContainer); this._charSizeService = this._instantiationService.createInstance(CharSizeService, this._document, this._helperContainer);
@@ -472,9 +472,9 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
this._characterJoinerService = this._instantiationService.createInstance(CharacterJoinerService); this._characterJoinerService = this._instantiationService.createInstance(CharacterJoinerService);
this._instantiationService.setService(ICharacterJoinerService, this._characterJoinerService); this._instantiationService.setService(ICharacterJoinerService, this._characterJoinerService);
this._renderService = this.register(this._instantiationService.createInstance(RenderService, this.rows, this.screenElement)); this._renderService = this._register(this._instantiationService.createInstance(RenderService, this.rows, this.screenElement));
this._instantiationService.setService(IRenderService, this._renderService); this._instantiationService.setService(IRenderService, this._renderService);
this.register(this._renderService.onRenderedViewportChange(e => this._onRender.fire(e))); this._register(this._renderService.onRenderedViewportChange(e => this._onRender.fire(e)));
this.onResize(e => this._renderService!.resize(e.cols, e.rows)); this.onResize(e => this._renderService!.resize(e.cols, e.rows));
this._compositionView = this._document.createElement('div'); this._compositionView = this._document.createElement('div');
@@ -485,7 +485,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
this._mouseService = this._instantiationService.createInstance(MouseService); this._mouseService = this._instantiationService.createInstance(MouseService);
this._instantiationService.setService(IMouseService, this._mouseService); this._instantiationService.setService(IMouseService, this._mouseService);
this.linkifier = this.register(this._instantiationService.createInstance(Linkifier, this.screenElement)); this.linkifier = this._register(this._instantiationService.createInstance(Linkifier, this.screenElement));
// Performance: Add viewport and helper elements from the fragment // Performance: Add viewport and helper elements from the fragment
this.element.appendChild(fragment); this.element.appendChild(fragment);
@@ -498,30 +498,30 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
this._renderService.setRenderer(this._createRenderer()); this._renderService.setRenderer(this._createRenderer());
} }
this.register(this.onCursorMove(() => { this._register(this.onCursorMove(() => {
this._renderService!.handleCursorMove(); this._renderService!.handleCursorMove();
this._syncTextArea(); this._syncTextArea();
})); }));
this.register(this.onResize(() => this._renderService!.handleResize(this.cols, this.rows))); this._register(this.onResize(() => this._renderService!.handleResize(this.cols, this.rows)));
this.register(this.onBlur(() => this._renderService!.handleBlur())); this._register(this.onBlur(() => this._renderService!.handleBlur()));
this.register(this.onFocus(() => this._renderService!.handleFocus())); this._register(this.onFocus(() => this._renderService!.handleFocus()));
this._viewport = this.register(this._instantiationService.createInstance(Viewport, this.element, this.screenElement)); this._viewport = this._register(this._instantiationService.createInstance(Viewport, this.element, this.screenElement));
this.register(this._viewport.onRequestScrollLines(e => { this._register(this._viewport.onRequestScrollLines(e => {
super.scrollLines(e, false); super.scrollLines(e, false);
this.refresh(0, this.rows - 1); this.refresh(0, this.rows - 1);
})); }));
this._selectionService = this.register(this._instantiationService.createInstance(SelectionService, this._selectionService = this._register(this._instantiationService.createInstance(SelectionService,
this.element, this.element,
this.screenElement, this.screenElement,
this.linkifier this.linkifier
)); ));
this._instantiationService.setService(ISelectionService, this._selectionService); this._instantiationService.setService(ISelectionService, this._selectionService);
this.register(this._selectionService.onRequestScrollLines(e => this.scrollLines(e.amount, e.suppressScrollEvent))); this._register(this._selectionService.onRequestScrollLines(e => this.scrollLines(e.amount, e.suppressScrollEvent)));
this.register(this._selectionService.onSelectionChange(() => this._onSelectionChange.fire())); this._register(this._selectionService.onSelectionChange(() => this._onSelectionChange.fire()));
this.register(this._selectionService.onRequestRedraw(e => this._renderService!.handleSelectionChanged(e.start, e.end, e.columnSelectMode))); this._register(this._selectionService.onRequestRedraw(e => this._renderService!.handleSelectionChanged(e.start, e.end, e.columnSelectMode)));
this.register(this._selectionService.onLinuxMouseSelection(text => { this._register(this._selectionService.onLinuxMouseSelection(text => {
// If there's a new selection, put it into the textarea, focus and select it // If there's a new selection, put it into the textarea, focus and select it
// in order to register it as a selection on the OS. This event is fired // in order to register it as a selection on the OS. This event is fired
// only on Linux to enable middle click to paste selection. // only on Linux to enable middle click to paste selection.
@@ -529,10 +529,10 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
this.textarea!.focus(); this.textarea!.focus();
this.textarea!.select(); this.textarea!.select();
})); }));
this.register(this._onScroll.event(() => this._selectionService!.refresh())); this._register(this._onScroll.event(() => this._selectionService!.refresh()));
this.register(this._instantiationService.createInstance(BufferDecorationRenderer, this.screenElement)); this._register(this._instantiationService.createInstance(BufferDecorationRenderer, this.screenElement));
this.register(addDisposableDomListener(this.element, 'mousedown', (e: MouseEvent) => this._selectionService!.handleMouseDown(e))); this._register(addDisposableListener(this.element, 'mousedown', (e: MouseEvent) => this._selectionService!.handleMouseDown(e)));
// apply mouse event classes set by escape codes before terminal was attached // apply mouse event classes set by escape codes before terminal was attached
if (this.coreMouseService.areMouseEventsActive) { if (this.coreMouseService.areMouseEventsActive) {
@@ -547,14 +547,14 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
// ensure the correct order of the dprchange event // ensure the correct order of the dprchange event
this._accessibilityManager.value = this._instantiationService.createInstance(AccessibilityManager, this); this._accessibilityManager.value = this._instantiationService.createInstance(AccessibilityManager, this);
} }
this.register(this.optionsService.onSpecificOptionChange('screenReaderMode', e => this._handleScreenReaderModeOptionChange(e))); this._register(this.optionsService.onSpecificOptionChange('screenReaderMode', e => this._handleScreenReaderModeOptionChange(e)));
if (this.options.overviewRuler.width) { if (this.options.overviewRuler.width) {
this._overviewRulerRenderer = this.register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement)); this._overviewRulerRenderer = this._register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement));
} }
this.optionsService.onSpecificOptionChange('overviewRuler', value => { this.optionsService.onSpecificOptionChange('overviewRuler', value => {
if (!this._overviewRulerRenderer && value.width && this._viewportElement && this.screenElement) { if (!this._overviewRulerRenderer && value && this._viewportElement && this.screenElement) {
this._overviewRulerRenderer = this.register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement)); this._overviewRulerRenderer = this._register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement));
} }
}); });
// Measure the character size // Measure the character size
@@ -707,7 +707,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
} }
} }
}; };
this.register(this.coreMouseService.onProtocolChange(events => { this._register(this.coreMouseService.onProtocolChange(events => {
// apply global changes on events // apply global changes on events
if (events) { if (events) {
if (this.optionsService.rawOptions.logLevel === 'debug') { if (this.optionsService.rawOptions.logLevel === 'debug') {
@@ -759,7 +759,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
/** /**
* "Always on" event listeners. * "Always on" event listeners.
*/ */
this.register(addDisposableDomListener(el, 'mousedown', (ev: MouseEvent) => { this._register(addDisposableListener(el, 'mousedown', (ev: MouseEvent) => {
ev.preventDefault(); ev.preventDefault();
this.focus(); this.focus();
@@ -786,7 +786,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
return this.cancel(ev); return this.cancel(ev);
})); }));
this.register(addDisposableDomListener(el, 'wheel', (ev: WheelEvent) => { this._register(addDisposableListener(el, 'wheel', (ev: WheelEvent) => {
// do nothing, if app side handles wheel itself // do nothing, if app side handles wheel itself
if (requestedEvents.wheel) return; if (requestedEvents.wheel) return;
-40
View File
@@ -1,40 +0,0 @@
/**
* Copyright (c) 2020 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { assert } from 'chai';
import { addDisposableDomListener } from './Lifecycle';
import jsdom = require('jsdom');
describe('addDisposableDomListener', () => {
const dom = new jsdom.JSDOM();
const document = dom.window.document;
function createEvent(type: string): Event {
const event = document.createEvent('Event');
event.initEvent(type);
return event;
}
it('dispose', () => {
let calledTimes = 0;
const div = document.createElement('div');
const disposable = addDisposableDomListener(div, 'test', () => { calledTimes++; });
assert.equal(calledTimes, 0);
div.dispatchEvent(createEvent('test'));
assert.equal(calledTimes, 1);
disposable.dispose();
div.dispatchEvent(createEvent('test'));
assert.equal(calledTimes, 1);
disposable.dispose(); // double disposing
div.dispatchEvent(createEvent('test'));
assert.equal(calledTimes, 1);
});
});
-33
View File
@@ -1,33 +0,0 @@
/**
* Copyright (c) 2018 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { IDisposable } from 'common/Types';
/**
* Adds a disposable listener to a node in the DOM, returning the disposable.
* @param node The node to add a listener to.
* @param type The event type.
* @param handler The handler for the listener.
* @param options The boolean or options object to pass on to the event
* listener.
*/
export function addDisposableDomListener(
node: Element | Window | Document,
type: string,
handler: (e: any) => void,
options?: boolean | AddEventListenerOptions
): IDisposable {
node.addEventListener(type, handler, options);
let disposed = false;
return {
dispose: () => {
if (disposed) {
return;
}
disposed = true;
node.removeEventListener(type, handler, options);
}
};
}
+14 -12
View File
@@ -3,13 +3,13 @@
* @license MIT * @license MIT
*/ */
import { addDisposableDomListener } from 'browser/Lifecycle';
import { IBufferCellPosition, ILink, ILinkDecorations, ILinkWithState, ILinkifier2, ILinkifierEvent } from 'browser/Types'; import { IBufferCellPosition, ILink, ILinkDecorations, ILinkWithState, ILinkifier2, ILinkifierEvent } from 'browser/Types';
import { Disposable, disposeArray, getDisposeArrayDisposable, toDisposable } from 'common/Lifecycle'; import { Disposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
import { IDisposable } from 'common/Types'; import { IDisposable } from 'common/Types';
import { IBufferService } from 'common/services/Services'; import { IBufferService } from 'common/services/Services';
import { ILinkProviderService, IMouseService, IRenderService } from './services/Services'; import { ILinkProviderService, IMouseService, IRenderService } from './services/Services';
import { Emitter } from 'vs/base/common/event'; import { Emitter } from 'vs/base/common/event';
import { addDisposableListener } from 'vs/base/browser/dom';
export class Linkifier extends Disposable implements ILinkifier2 { export class Linkifier extends Disposable implements ILinkifier2 {
public get currentLink(): ILinkWithState | undefined { return this._currentLink; } public get currentLink(): ILinkWithState | undefined { return this._currentLink; }
@@ -23,9 +23,9 @@ export class Linkifier extends Disposable implements ILinkifier2 {
private _activeProviderReplies: Map<Number, ILinkWithState[] | undefined> | undefined; private _activeProviderReplies: Map<Number, ILinkWithState[] | undefined> | undefined;
private _activeLine: number = -1; private _activeLine: number = -1;
private readonly _onShowLinkUnderline = this.register(new Emitter<ILinkifierEvent>()); private readonly _onShowLinkUnderline = this._register(new Emitter<ILinkifierEvent>());
public readonly onShowLinkUnderline = this._onShowLinkUnderline.event; public readonly onShowLinkUnderline = this._onShowLinkUnderline.event;
private readonly _onHideLinkUnderline = this.register(new Emitter<ILinkifierEvent>()); private readonly _onHideLinkUnderline = this._register(new Emitter<ILinkifierEvent>());
public readonly onHideLinkUnderline = this._onHideLinkUnderline.event; public readonly onHideLinkUnderline = this._onHideLinkUnderline.event;
constructor( constructor(
@@ -36,24 +36,25 @@ export class Linkifier extends Disposable implements ILinkifier2 {
@ILinkProviderService private readonly _linkProviderService: ILinkProviderService @ILinkProviderService private readonly _linkProviderService: ILinkProviderService
) { ) {
super(); super();
this.register(getDisposeArrayDisposable(this._linkCacheDisposables)); this._register(toDisposable(() => {
this.register(toDisposable(() => { dispose(this._linkCacheDisposables);
this._linkCacheDisposables.length = 0;
this._lastMouseEvent = undefined; this._lastMouseEvent = undefined;
// Clear out link providers as they could easily cause an embedder memory leak // Clear out link providers as they could easily cause an embedder memory leak
this._activeProviderReplies?.clear(); this._activeProviderReplies?.clear();
})); }));
// Listen to resize to catch the case where it's resized and the cursor is out of the viewport. // Listen to resize to catch the case where it's resized and the cursor is out of the viewport.
this.register(this._bufferService.onResize(() => { this._register(this._bufferService.onResize(() => {
this._clearCurrentLink(); this._clearCurrentLink();
this._wasResized = true; this._wasResized = true;
})); }));
this.register(addDisposableDomListener(this._element, 'mouseleave', () => { this._register(addDisposableListener(this._element, 'mouseleave', () => {
this._isMouseOut = true; this._isMouseOut = true;
this._clearCurrentLink(); this._clearCurrentLink();
})); }));
this.register(addDisposableDomListener(this._element, 'mousemove', this._handleMouseMove.bind(this))); this._register(addDisposableListener(this._element, 'mousemove', this._handleMouseMove.bind(this)));
this.register(addDisposableDomListener(this._element, 'mousedown', this._handleMouseDown.bind(this))); this._register(addDisposableListener(this._element, 'mousedown', this._handleMouseDown.bind(this)));
this.register(addDisposableDomListener(this._element, 'mouseup', this._handleMouseUp.bind(this))); this._register(addDisposableListener(this._element, 'mouseup', this._handleMouseUp.bind(this)));
} }
private _handleMouseMove(event: MouseEvent): void { private _handleMouseMove(event: MouseEvent): void {
@@ -240,7 +241,8 @@ export class Linkifier extends Disposable implements ILinkifier2 {
if (!startRow || !endRow || (this._currentLink.link.range.start.y >= startRow && this._currentLink.link.range.end.y <= endRow)) { if (!startRow || !endRow || (this._currentLink.link.range.start.y >= startRow && this._currentLink.link.range.end.y <= endRow)) {
this._linkLeave(this._element, this._currentLink.link, this._lastMouseEvent); this._linkLeave(this._element, this._currentLink.link, this._lastMouseEvent);
this._currentLink = undefined; this._currentLink = undefined;
disposeArray(this._linkCacheDisposables); dispose(this._linkCacheDisposables);
this._linkCacheDisposables.length = 0;
} }
} }
+14 -14
View File
@@ -5,7 +5,7 @@
import { ICoreBrowserService, IRenderService, IThemeService } from 'browser/services/Services'; import { ICoreBrowserService, IRenderService, IThemeService } from 'browser/services/Services';
import { ViewportConstants } from 'browser/shared/Constants'; import { ViewportConstants } from 'browser/shared/Constants';
import { Disposable, toDisposable } from 'common/Lifecycle'; import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { IBufferService, ICoreMouseService, IOptionsService } from 'common/services/Services'; import { IBufferService, ICoreMouseService, IOptionsService } from 'common/services/Services';
import { CoreMouseEventType } from 'common/Types'; import { CoreMouseEventType } from 'common/Types';
import { scheduleAtNextAnimationFrame } from 'vs/base/browser/dom'; import { scheduleAtNextAnimationFrame } from 'vs/base/browser/dom';
@@ -16,7 +16,7 @@ import { Scrollable, ScrollbarVisibility, type ScrollEvent } from 'vs/base/commo
export class Viewport extends Disposable { export class Viewport extends Disposable {
protected _onRequestScrollLines = this.register(new Emitter<number>()); protected _onRequestScrollLines = this._register(new Emitter<number>());
public readonly onRequestScrollLines = this._onRequestScrollLines.event; public readonly onRequestScrollLines = this._onRequestScrollLines.event;
private _scrollableElement: SmoothScrollableElement; private _scrollableElement: SmoothScrollableElement;
@@ -40,46 +40,46 @@ export class Viewport extends Disposable {
) { ) {
super(); super();
const scrollable = this.register(new Scrollable({ const scrollable = this._register(new Scrollable({
forceIntegerValues: false, forceIntegerValues: false,
smoothScrollDuration: this._optionsService.rawOptions.smoothScrollDuration, smoothScrollDuration: this._optionsService.rawOptions.smoothScrollDuration,
// This is used over `IRenderService.addRefreshCallback` since it can be canceled // This is used over `IRenderService.addRefreshCallback` since it can be canceled
scheduleAtNextAnimationFrame: cb => scheduleAtNextAnimationFrame(coreBrowserService.window, cb) scheduleAtNextAnimationFrame: cb => scheduleAtNextAnimationFrame(coreBrowserService.window, cb)
})); }));
this.register(this._optionsService.onSpecificOptionChange('smoothScrollDuration', () => { this._register(this._optionsService.onSpecificOptionChange('smoothScrollDuration', () => {
scrollable.setSmoothScrollDuration(this._optionsService.rawOptions.smoothScrollDuration); scrollable.setSmoothScrollDuration(this._optionsService.rawOptions.smoothScrollDuration);
})); }));
this._scrollableElement = this.register(new SmoothScrollableElement(screenElement, { this._scrollableElement = this._register(new SmoothScrollableElement(screenElement, {
vertical: ScrollbarVisibility.Auto, vertical: ScrollbarVisibility.Auto,
horizontal: ScrollbarVisibility.Hidden, horizontal: ScrollbarVisibility.Hidden,
useShadows: false, useShadows: false,
mouseWheelSmoothScroll: true, mouseWheelSmoothScroll: true,
...this._getChangeOptions() ...this._getChangeOptions()
}, scrollable)); }, scrollable));
this.register(this._optionsService.onMultipleOptionChange([ this._register(this._optionsService.onMultipleOptionChange([
'scrollSensitivity', 'scrollSensitivity',
'fastScrollSensitivity', 'fastScrollSensitivity',
'overviewRuler' 'overviewRuler'
], () => this._scrollableElement.updateOptions(this._getChangeOptions()))); ], () => this._scrollableElement.updateOptions(this._getChangeOptions())));
// Don't handle mouse wheel if wheel events are supported by the current mouse prototcol // Don't handle mouse wheel if wheel events are supported by the current mouse prototcol
this.register(coreMouseService.onProtocolChange(type => { this._register(coreMouseService.onProtocolChange(type => {
this._scrollableElement.updateOptions({ this._scrollableElement.updateOptions({
handleMouseWheel: !(type & CoreMouseEventType.WHEEL) handleMouseWheel: !(type & CoreMouseEventType.WHEEL)
}); });
})); }));
this._scrollableElement.setScrollDimensions({ height: 0, scrollHeight: 0 }); this._scrollableElement.setScrollDimensions({ height: 0, scrollHeight: 0 });
this.register(Event.runAndSubscribe(themeService.onChangeColors, () => { this._register(Event.runAndSubscribe(themeService.onChangeColors, () => {
this._scrollableElement.getDomNode().style.backgroundColor = themeService.colors.background.css; this._scrollableElement.getDomNode().style.backgroundColor = themeService.colors.background.css;
})); }));
element.appendChild(this._scrollableElement.getDomNode()); element.appendChild(this._scrollableElement.getDomNode());
this.register(toDisposable(() => this._scrollableElement.getDomNode().remove())); this._register(toDisposable(() => this._scrollableElement.getDomNode().remove()));
this._styleElement = coreBrowserService.window.document.createElement('style'); this._styleElement = coreBrowserService.window.document.createElement('style');
screenElement.appendChild(this._styleElement); screenElement.appendChild(this._styleElement);
this.register(toDisposable(() => this._styleElement.remove())); this._register(toDisposable(() => this._styleElement.remove()));
this.register(Event.runAndSubscribe(themeService.onChangeColors, () => { this._register(Event.runAndSubscribe(themeService.onChangeColors, () => {
this._styleElement.textContent = [ this._styleElement.textContent = [
`.xterm .xterm-scrollable-element > .scrollbar > .slider {`, `.xterm .xterm-scrollable-element > .scrollbar > .slider {`,
` background: ${themeService.colors.scrollbarSliderBackground.css};`, ` background: ${themeService.colors.scrollbarSliderBackground.css};`,
@@ -93,10 +93,10 @@ export class Viewport extends Disposable {
].join('\n'); ].join('\n');
})); }));
this.register(this._bufferService.onResize(() => this._queueSync())); this._register(this._bufferService.onResize(() => this._queueSync()));
this.register(this._bufferService.onScroll(() => this._sync())); this._register(this._bufferService.onScroll(() => this._sync()));
this.register(this._scrollableElement.onScroll(e => this._handleScroll(e))); this._register(this._scrollableElement.onScroll(e => this._handleScroll(e)));
} }
public scrollLines(disp: number): void { public scrollLines(disp: number): void {
@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { ICoreBrowserService, IRenderService } from 'browser/services/Services'; import { ICoreBrowserService, IRenderService } from 'browser/services/Services';
import { Disposable, toDisposable } from 'common/Lifecycle'; import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { IBufferService, IDecorationService, IInternalDecoration } from 'common/services/Services'; import { IBufferService, IDecorationService, IInternalDecoration } from 'common/services/Services';
export class BufferDecorationRenderer extends Disposable { export class BufferDecorationRenderer extends Disposable {
@@ -28,18 +28,18 @@ export class BufferDecorationRenderer extends Disposable {
this._container.classList.add('xterm-decoration-container'); this._container.classList.add('xterm-decoration-container');
this._screenElement.appendChild(this._container); this._screenElement.appendChild(this._container);
this.register(this._renderService.onRenderedViewportChange(() => this._doRefreshDecorations())); this._register(this._renderService.onRenderedViewportChange(() => this._doRefreshDecorations()));
this.register(this._renderService.onDimensionsChange(() => { this._register(this._renderService.onDimensionsChange(() => {
this._dimensionsChanged = true; this._dimensionsChanged = true;
this._queueRefresh(); this._queueRefresh();
})); }));
this.register(this._coreBrowserService.onDprChange(() => this._queueRefresh())); this._register(this._coreBrowserService.onDprChange(() => this._queueRefresh()));
this.register(this._bufferService.buffers.onBufferActivate(() => { this._register(this._bufferService.buffers.onBufferActivate(() => {
this._altBufferIsActive = this._bufferService.buffer === this._bufferService.buffers.alt; this._altBufferIsActive = this._bufferService.buffer === this._bufferService.buffers.alt;
})); }));
this.register(this._decorationService.onDecorationRegistered(() => this._queueRefresh())); this._register(this._decorationService.onDecorationRegistered(() => this._queueRefresh()));
this.register(this._decorationService.onDecorationRemoved(decoration => this._removeDecoration(decoration))); this._register(this._decorationService.onDecorationRemoved(decoration => this._removeDecoration(decoration)));
this.register(toDisposable(() => { this._register(toDisposable(() => {
this._container.remove(); this._container.remove();
this._decorationElements.clear(); this._decorationElements.clear();
})); }));
@@ -5,7 +5,7 @@
import { ColorZoneStore, IColorZone, IColorZoneStore } from 'browser/decorations/ColorZoneStore'; import { ColorZoneStore, IColorZone, IColorZoneStore } from 'browser/decorations/ColorZoneStore';
import { ICoreBrowserService, IRenderService, IThemeService } from 'browser/services/Services'; import { ICoreBrowserService, IRenderService, IThemeService } from 'browser/services/Services';
import { Disposable, toDisposable } from 'common/Lifecycle'; import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { IBufferService, IDecorationService, IOptionsService } from 'common/services/Services'; import { IBufferService, IDecorationService, IOptionsService } from 'common/services/Services';
const enum Constants { const enum Constants {
@@ -63,7 +63,7 @@ export class OverviewRulerRenderer extends Disposable {
this._canvas.classList.add('xterm-decoration-overview-ruler'); this._canvas.classList.add('xterm-decoration-overview-ruler');
this._refreshCanvasDimensions(); this._refreshCanvasDimensions();
this._viewportElement.parentElement?.insertBefore(this._canvas, this._viewportElement); this._viewportElement.parentElement?.insertBefore(this._canvas, this._viewportElement);
this.register(toDisposable(() => this._canvas?.remove())); this._register(toDisposable(() => this._canvas?.remove()));
const ctx = this._canvas.getContext('2d'); const ctx = this._canvas.getContext('2d');
if (!ctx) { if (!ctx) {
@@ -72,14 +72,14 @@ export class OverviewRulerRenderer extends Disposable {
this._ctx = ctx; this._ctx = ctx;
} }
this.register(this._decorationService.onDecorationRegistered(() => this._queueRefresh(undefined, true))); this._register(this._decorationService.onDecorationRegistered(() => this._queueRefresh(undefined, true)));
this.register(this._decorationService.onDecorationRemoved(() => this._queueRefresh(undefined, true))); this._register(this._decorationService.onDecorationRemoved(() => this._queueRefresh(undefined, true)));
this.register(this._renderService.onRenderedViewportChange(() => this._queueRefresh())); this._register(this._renderService.onRenderedViewportChange(() => this._queueRefresh()));
this.register(this._bufferService.buffers.onBufferActivate(() => { this._register(this._bufferService.buffers.onBufferActivate(() => {
this._canvas!.style.display = this._bufferService.buffer === this._bufferService.buffers.alt ? 'none' : 'block'; this._canvas!.style.display = this._bufferService.buffer === this._bufferService.buffers.alt ? 'none' : 'block';
})); }));
this.register(this._bufferService.onScroll(() => { this._register(this._bufferService.onScroll(() => {
if (this._lastKnownBufferLength !== this._bufferService.buffers.normal.lines.length) { if (this._lastKnownBufferLength !== this._bufferService.buffers.normal.lines.length) {
this._refreshDrawHeightConstants(); this._refreshDrawHeightConstants();
this._refreshColorZonePadding(); this._refreshColorZonePadding();
@@ -87,16 +87,16 @@ export class OverviewRulerRenderer extends Disposable {
})); }));
// Container height changed // Container height changed
this.register(this._renderService.onRender((): void => { this._register(this._renderService.onRender((): void => {
if (!this._containerHeight || this._containerHeight !== this._screenElement.clientHeight) { if (!this._containerHeight || this._containerHeight !== this._screenElement.clientHeight) {
this._queueRefresh(true); this._queueRefresh(true);
this._containerHeight = this._screenElement.clientHeight; this._containerHeight = this._screenElement.clientHeight;
} }
})); }));
this.register(this._coreBrowserService.onDprChange(() => this._queueRefresh(true))); this._register(this._coreBrowserService.onDprChange(() => this._queueRefresh(true)));
this.register(this._optionsService.onSpecificOptionChange('overviewRuler', () => this._queueRefresh(true))); this._register(this._optionsService.onSpecificOptionChange('overviewRuler', () => this._queueRefresh(true)));
this.register(this._themeService.onChangeColors(() => this._queueRefresh())); this._register(this._themeService.onChangeColors(() => this._queueRefresh()));
this._queueRefresh(true); this._queueRefresh(true);
} }
+4 -4
View File
@@ -6,7 +6,7 @@
import * as Strings from 'browser/LocalizableStrings'; import * as Strings from 'browser/LocalizableStrings';
import { CoreBrowserTerminal as TerminalCore } from 'browser/CoreBrowserTerminal'; import { CoreBrowserTerminal as TerminalCore } from 'browser/CoreBrowserTerminal';
import { IBufferRange, ITerminal } from 'browser/Types'; import { IBufferRange, ITerminal } from 'browser/Types';
import { Disposable } from 'common/Lifecycle'; import { Disposable } from 'vs/base/common/lifecycle';
import { ITerminalOptions } from 'common/Types'; import { ITerminalOptions } from 'common/Types';
import { AddonManager } from 'common/public/AddonManager'; import { AddonManager } from 'common/public/AddonManager';
import { BufferNamespaceApi } from 'common/public/BufferNamespaceApi'; import { BufferNamespaceApi } from 'common/public/BufferNamespaceApi';
@@ -32,8 +32,8 @@ export class Terminal extends Disposable implements ITerminalApi {
constructor(options?: ITerminalOptions & ITerminalInitOnlyOptions) { constructor(options?: ITerminalOptions & ITerminalInitOnlyOptions) {
super(); super();
this._core = this.register(new TerminalCore(options)); this._core = this._register(new TerminalCore(options));
this._addonManager = this.register(new AddonManager()); this._addonManager = this._register(new AddonManager());
this._publicOptions = { ... this._core.options }; this._publicOptions = { ... this._core.options };
const getter = (propName: string): any => { const getter = (propName: string): any => {
@@ -97,7 +97,7 @@ export class Terminal extends Disposable implements ITerminalApi {
public get cols(): number { return this._core.cols; } public get cols(): number { return this._core.cols; }
public get buffer(): IBufferNamespaceApi { public get buffer(): IBufferNamespaceApi {
if (!this._buffer) { if (!this._buffer) {
this._buffer = this.register(new BufferNamespaceApi(this._core)); this._buffer = this._register(new BufferNamespaceApi(this._core));
} }
return this._buffer; return this._buffer;
} }
+7 -7
View File
@@ -12,7 +12,7 @@ import { IRenderDimensions, IRenderer, IRequestRedrawEvent, ISelectionRenderMode
import { ICharSizeService, ICoreBrowserService, IThemeService } from 'browser/services/Services'; import { ICharSizeService, ICoreBrowserService, IThemeService } from 'browser/services/Services';
import { ILinkifier2, ILinkifierEvent, ITerminal, ReadonlyColorSet } from 'browser/Types'; import { ILinkifier2, ILinkifierEvent, ITerminal, ReadonlyColorSet } from 'browser/Types';
import { color } from 'common/Color'; import { color } from 'common/Color';
import { Disposable, toDisposable } from 'common/Lifecycle'; import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { IBufferService, IInstantiationService, IOptionsService } from 'common/services/Services'; import { IBufferService, IInstantiationService, IOptionsService } from 'common/services/Services';
import { Emitter } from 'vs/base/common/event'; import { Emitter } from 'vs/base/common/event';
@@ -45,7 +45,7 @@ export class DomRenderer extends Disposable implements IRenderer {
public dimensions: IRenderDimensions; public dimensions: IRenderDimensions;
public readonly onRequestRedraw = this.register(new Emitter<IRequestRedrawEvent>()).event; public readonly onRequestRedraw = this._register(new Emitter<IRequestRedrawEvent>()).event;
constructor( constructor(
private readonly _terminal: ITerminal, private readonly _terminal: ITerminal,
@@ -74,9 +74,9 @@ export class DomRenderer extends Disposable implements IRenderer {
this.dimensions = createRenderDimensions(); this.dimensions = createRenderDimensions();
this._updateDimensions(); this._updateDimensions();
this.register(this._optionsService.onOptionChange(() => this._handleOptionsChanged())); this._register(this._optionsService.onOptionChange(() => this._handleOptionsChanged()));
this.register(this._themeService.onChangeColors(e => this._injectCss(e))); this._register(this._themeService.onChangeColors(e => this._injectCss(e)));
this._injectCss(this._themeService.colors); this._injectCss(this._themeService.colors);
this._rowFactory = instantiationService.createInstance(DomRendererRowFactory, document); this._rowFactory = instantiationService.createInstance(DomRendererRowFactory, document);
@@ -85,10 +85,10 @@ export class DomRenderer extends Disposable implements IRenderer {
this._screenElement.appendChild(this._rowContainer); this._screenElement.appendChild(this._rowContainer);
this._screenElement.appendChild(this._selectionContainer); this._screenElement.appendChild(this._selectionContainer);
this.register(this._linkifier2.onShowLinkUnderline(e => this._handleLinkHover(e))); this._register(this._linkifier2.onShowLinkUnderline(e => this._handleLinkHover(e)));
this.register(this._linkifier2.onHideLinkUnderline(e => this._handleLinkLeave(e))); this._register(this._linkifier2.onHideLinkUnderline(e => this._handleLinkLeave(e)));
this.register(toDisposable(() => { this._register(toDisposable(() => {
this._element.classList.remove(TERMINAL_CLASS_PREFIX + this._terminalClass); this._element.classList.remove(TERMINAL_CLASS_PREFIX + this._terminalClass);
// Outside influences such as React unmounts may manipulate the DOM before our disposal. // Outside influences such as React unmounts may manipulate the DOM before our disposal.
@@ -3,8 +3,7 @@
* @license MIT * @license MIT
*/ */
import { toDisposable } from 'common/Lifecycle'; import { toDisposable, IDisposable } from 'vs/base/common/lifecycle';
import { IDisposable } from 'common/Types';
export function observeDevicePixelDimensions(element: HTMLElement, parentWindow: Window & typeof globalThis, callback: (deviceWidth: number, deviceHeight: number) => void): IDisposable { export function observeDevicePixelDimensions(element: HTMLElement, parentWindow: Window & typeof globalThis, callback: (deviceWidth: number, deviceHeight: number) => void): IDisposable {
// Observe any resizes to the element and extract the actual pixel size of the element if the // Observe any resizes to the element and extract the actual pixel size of the element if the
+5 -5
View File
@@ -5,7 +5,7 @@
import { IOptionsService } from 'common/services/Services'; import { IOptionsService } from 'common/services/Services';
import { ICharSizeService } from 'browser/services/Services'; import { ICharSizeService } from 'browser/services/Services';
import { Disposable } from 'common/Lifecycle'; import { Disposable } from 'vs/base/common/lifecycle';
import { Emitter } from 'vs/base/common/event'; import { Emitter } from 'vs/base/common/event';
export class CharSizeService extends Disposable implements ICharSizeService { export class CharSizeService extends Disposable implements ICharSizeService {
@@ -17,7 +17,7 @@ export class CharSizeService extends Disposable implements ICharSizeService {
public get hasValidSize(): boolean { return this.width > 0 && this.height > 0; } public get hasValidSize(): boolean { return this.width > 0 && this.height > 0; }
private readonly _onCharSizeChange = this.register(new Emitter<void>()); private readonly _onCharSizeChange = this._register(new Emitter<void>());
public readonly onCharSizeChange = this._onCharSizeChange.event; public readonly onCharSizeChange = this._onCharSizeChange.event;
constructor( constructor(
@@ -27,11 +27,11 @@ export class CharSizeService extends Disposable implements ICharSizeService {
) { ) {
super(); super();
try { try {
this._measureStrategy = this.register(new TextMetricsMeasureStrategy(this._optionsService)); this._measureStrategy = this._register(new TextMetricsMeasureStrategy(this._optionsService));
} catch { } catch {
this._measureStrategy = this.register(new DomMeasureStrategy(document, parentElement, this._optionsService)); this._measureStrategy = this._register(new DomMeasureStrategy(document, parentElement, this._optionsService));
} }
this.register(this._optionsService.onMultipleOptionChange(['fontFamily', 'fontSize'], () => this.measure())); this._register(this._optionsService.onMultipleOptionChange(['fontFamily', 'fontSize'], () => this.measure()));
} }
public measure(): void { public measure(): void {
+14 -18
View File
@@ -3,21 +3,21 @@
* @license MIT * @license MIT
*/ */
import { Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle';
import { ICoreBrowserService } from './Services'; import { ICoreBrowserService } from './Services';
import { addDisposableDomListener } from 'browser/Lifecycle';
import { Emitter, Event } from 'vs/base/common/event'; import { Emitter, Event } from 'vs/base/common/event';
import { addDisposableListener } from 'vs/base/browser/dom';
import { Disposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
export class CoreBrowserService extends Disposable implements ICoreBrowserService { export class CoreBrowserService extends Disposable implements ICoreBrowserService {
public serviceBrand: undefined; public serviceBrand: undefined;
private _isFocused = false; private _isFocused = false;
private _cachedIsFocused: boolean | undefined = undefined; private _cachedIsFocused: boolean | undefined = undefined;
private _screenDprMonitor = this.register(new ScreenDprMonitor(this._window)); private _screenDprMonitor = this._register(new ScreenDprMonitor(this._window));
private readonly _onDprChange = this.register(new Emitter<number>()); private readonly _onDprChange = this._register(new Emitter<number>());
public readonly onDprChange = this._onDprChange.event; public readonly onDprChange = this._onDprChange.event;
private readonly _onWindowChange = this.register(new Emitter<Window & typeof globalThis>()); private readonly _onWindowChange = this._register(new Emitter<Window & typeof globalThis>());
public readonly onWindowChange = this._onWindowChange.event; public readonly onWindowChange = this._onWindowChange.event;
constructor( constructor(
@@ -28,15 +28,11 @@ export class CoreBrowserService extends Disposable implements ICoreBrowserServic
super(); super();
// Monitor device pixel ratio // Monitor device pixel ratio
this.register(this.onWindowChange(w => this._screenDprMonitor.setWindow(w))); this._register(this.onWindowChange(w => this._screenDprMonitor.setWindow(w)));
this.register(Event.forward(this._screenDprMonitor.onDprChange, this._onDprChange)); this._register(Event.forward(this._screenDprMonitor.onDprChange, this._onDprChange));
this.register( this._register(addDisposableListener(this._textarea, 'focus', () => this._isFocused = true));
addDisposableDomListener(this._textarea, 'focus', () => (this._isFocused = true)) this._register(addDisposableListener(this._textarea, 'blur', () => this._isFocused = false));
);
this.register(
addDisposableDomListener(this._textarea, 'blur', () => (this._isFocused = false))
);
} }
public get window(): Window & typeof globalThis { public get window(): Window & typeof globalThis {
@@ -69,7 +65,7 @@ export class CoreBrowserService extends Disposable implements ICoreBrowserServic
* window.devicePixelRatio value changes. This is done not with polling but with * 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 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 * the listener will be reattached using a different media query to ensure that
* any further changes will register. * any further changes will _register.
* *
* The listener should fire on both window zoom changes and switching to a * The listener should fire on both window zoom changes and switching to a
* monitor with a different DPI. * monitor with a different DPI.
@@ -78,9 +74,9 @@ class ScreenDprMonitor extends Disposable {
private _currentDevicePixelRatio: number; private _currentDevicePixelRatio: number;
private _outerListener: ((this: MediaQueryList, ev: MediaQueryListEvent) => any) | undefined; private _outerListener: ((this: MediaQueryList, ev: MediaQueryListEvent) => any) | undefined;
private _resolutionMediaMatchList: MediaQueryList | undefined; private _resolutionMediaMatchList: MediaQueryList | undefined;
private _windowResizeListener = this.register(new MutableDisposable()); private _windowResizeListener = this._register(new MutableDisposable());
private readonly _onDprChange = this.register(new Emitter<number>()); private readonly _onDprChange = this._register(new Emitter<number>());
public readonly onDprChange = this._onDprChange.event; public readonly onDprChange = this._onDprChange.event;
constructor(private _parentWindow: Window) { constructor(private _parentWindow: Window) {
@@ -95,7 +91,7 @@ class ScreenDprMonitor extends Disposable {
this._setWindowResizeListener(); this._setWindowResizeListener();
// Setup additional disposables // Setup additional disposables
this.register(toDisposable(() => this.clearListener())); this._register(toDisposable(() => this.clearListener()));
} }
@@ -106,7 +102,7 @@ class ScreenDprMonitor extends Disposable {
} }
private _setWindowResizeListener(): void { private _setWindowResizeListener(): void {
this._windowResizeListener.value = addDisposableDomListener(this._parentWindow, 'resize', () => this._setDprAndFireIfDiffers()); this._windowResizeListener.value = addDisposableListener(this._parentWindow, 'resize', () => this._setDprAndFireIfDiffers());
} }
private _setDprAndFireIfDiffers(): void { private _setDprAndFireIfDiffers(): void {
+2 -2
View File
@@ -1,5 +1,5 @@
import { ILinkProvider, ILinkProviderService } from 'browser/services/Services'; import { ILinkProvider, ILinkProviderService } from 'browser/services/Services';
import { Disposable, toDisposable } from 'common/Lifecycle'; import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { IDisposable } from 'common/Types'; import { IDisposable } from 'common/Types';
export class LinkProviderService extends Disposable implements ILinkProviderService { export class LinkProviderService extends Disposable implements ILinkProviderService {
@@ -9,7 +9,7 @@ export class LinkProviderService extends Disposable implements ILinkProviderServ
constructor() { constructor() {
super(); super();
this.register(toDisposable(() => this.linkProviders.length = 0)); this._register(toDisposable(() => this.linkProviders.length = 0));
} }
public registerLinkProvider(linkProvider: ILinkProvider): IDisposable { public registerLinkProvider(linkProvider: ILinkProvider): IDisposable {
+19 -19
View File
@@ -7,7 +7,7 @@ import { RenderDebouncer } from 'browser/RenderDebouncer';
import { IRenderDebouncerWithCallback } from 'browser/Types'; import { IRenderDebouncerWithCallback } from 'browser/Types';
import { IRenderDimensions, IRenderer } from 'browser/renderer/shared/Types'; import { IRenderDimensions, IRenderer } from 'browser/renderer/shared/Types';
import { ICharSizeService, ICoreBrowserService, IRenderService, IThemeService } from 'browser/services/Services'; import { ICharSizeService, ICoreBrowserService, IRenderService, IThemeService } from 'browser/services/Services';
import { Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle'; import { Disposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { DebouncedIdleTask } from 'common/TaskQueue'; import { DebouncedIdleTask } from 'common/TaskQueue';
import { IBufferService, IDecorationService, IOptionsService } from 'common/services/Services'; import { IBufferService, IDecorationService, IOptionsService } from 'common/services/Services';
import { Emitter } from 'vs/base/common/event'; import { Emitter } from 'vs/base/common/event';
@@ -21,10 +21,10 @@ interface ISelectionState {
export class RenderService extends Disposable implements IRenderService { export class RenderService extends Disposable implements IRenderService {
public serviceBrand: undefined; public serviceBrand: undefined;
private _renderer: MutableDisposable<IRenderer> = this.register(new MutableDisposable()); private _renderer: MutableDisposable<IRenderer> = this._register(new MutableDisposable());
private _renderDebouncer: IRenderDebouncerWithCallback; private _renderDebouncer: IRenderDebouncerWithCallback;
private _pausedResizeTask = new DebouncedIdleTask(); private _pausedResizeTask = new DebouncedIdleTask();
private _observerDisposable = this.register(new MutableDisposable()); private _observerDisposable = this._register(new MutableDisposable());
private _isPaused: boolean = false; private _isPaused: boolean = false;
private _needsFullRefresh: boolean = false; private _needsFullRefresh: boolean = false;
@@ -38,13 +38,13 @@ export class RenderService extends Disposable implements IRenderService {
columnSelectMode: false columnSelectMode: false
}; };
private readonly _onDimensionsChange = this.register(new Emitter<IRenderDimensions>()); private readonly _onDimensionsChange = this._register(new Emitter<IRenderDimensions>());
public readonly onDimensionsChange = this._onDimensionsChange.event; public readonly onDimensionsChange = this._onDimensionsChange.event;
private readonly _onRenderedViewportChange = this.register(new Emitter<{ start: number, end: number }>()); private readonly _onRenderedViewportChange = this._register(new Emitter<{ start: number, end: number }>());
public readonly onRenderedViewportChange = this._onRenderedViewportChange.event; public readonly onRenderedViewportChange = this._onRenderedViewportChange.event;
private readonly _onRender = this.register(new Emitter<{ start: number, end: number }>()); private readonly _onRender = this._register(new Emitter<{ start: number, end: number }>());
public readonly onRender = this._onRender.event; public readonly onRender = this._onRender.event;
private readonly _onRefreshRequest = this.register(new Emitter<{ start: number, end: number }>()); private readonly _onRefreshRequest = this._register(new Emitter<{ start: number, end: number }>());
public readonly onRefreshRequest = this._onRefreshRequest.event; public readonly onRefreshRequest = this._onRefreshRequest.event;
public get dimensions(): IRenderDimensions { return this._renderer.value!.dimensions; } public get dimensions(): IRenderDimensions { return this._renderer.value!.dimensions; }
@@ -62,23 +62,23 @@ export class RenderService extends Disposable implements IRenderService {
super(); super();
this._renderDebouncer = new RenderDebouncer((start, end) => this._renderRows(start, end), coreBrowserService); this._renderDebouncer = new RenderDebouncer((start, end) => this._renderRows(start, end), coreBrowserService);
this.register(this._renderDebouncer); this._register(this._renderDebouncer);
this.register(coreBrowserService.onDprChange(() => this.handleDevicePixelRatioChange())); this._register(coreBrowserService.onDprChange(() => this.handleDevicePixelRatioChange()));
this.register(bufferService.onResize(() => this._fullRefresh())); this._register(bufferService.onResize(() => this._fullRefresh()));
this.register(bufferService.buffers.onBufferActivate(() => this._renderer.value?.clear())); this._register(bufferService.buffers.onBufferActivate(() => this._renderer.value?.clear()));
this.register(optionsService.onOptionChange(() => this._handleOptionsChanged())); this._register(optionsService.onOptionChange(() => this._handleOptionsChanged()));
this.register(this._charSizeService.onCharSizeChange(() => this.handleCharSizeChanged())); this._register(this._charSizeService.onCharSizeChange(() => this.handleCharSizeChanged()));
// Do a full refresh whenever any decoration is added or removed. This may not actually result // Do a full refresh whenever any decoration is added or removed. This may not actually result
// in changes but since decorations should be used sparingly or added/removed all in the same // in changes but since decorations should be used sparingly or added/removed all in the same
// frame this should have minimal performance impact. // frame this should have minimal performance impact.
this.register(decorationService.onDecorationRegistered(() => this._fullRefresh())); this._register(decorationService.onDecorationRegistered(() => this._fullRefresh()));
this.register(decorationService.onDecorationRemoved(() => this._fullRefresh())); this._register(decorationService.onDecorationRemoved(() => this._fullRefresh()));
// Clear the renderer when the a change that could affect glyphs occurs // Clear the renderer when the a change that could affect glyphs occurs
this.register(optionsService.onMultipleOptionChange([ this._register(optionsService.onMultipleOptionChange([
'customGlyphs', 'customGlyphs',
'drawBoldTextInBrightColors', 'drawBoldTextInBrightColors',
'letterSpacing', 'letterSpacing',
@@ -96,15 +96,15 @@ export class RenderService extends Disposable implements IRenderService {
})); }));
// Refresh the cursor line when the cursor changes // Refresh the cursor line when the cursor changes
this.register(optionsService.onMultipleOptionChange([ this._register(optionsService.onMultipleOptionChange([
'cursorBlink', 'cursorBlink',
'cursorStyle' 'cursorStyle'
], () => this.refreshRows(bufferService.buffer.y, bufferService.buffer.y, true))); ], () => this.refreshRows(bufferService.buffer.y, bufferService.buffer.y, true)));
this.register(themeService.onChangeColors(() => this._fullRefresh())); this._register(themeService.onChangeColors(() => this._fullRefresh()));
this._registerIntersectionObserver(coreBrowserService.window, screenElement); this._registerIntersectionObserver(coreBrowserService.window, screenElement);
this.register(coreBrowserService.onWindowChange((w) => this._registerIntersectionObserver(w, screenElement))); this._register(coreBrowserService.onWindowChange((w) => this._registerIntersectionObserver(w, screenElement)));
} }
private _registerIntersectionObserver(w: Window & typeof globalThis, screenElement: HTMLElement): void { private _registerIntersectionObserver(w: Window & typeof globalThis, screenElement: HTMLElement): void {
+7 -7
View File
@@ -9,7 +9,7 @@ import { moveToCellSequence } from 'browser/input/MoveToCell';
import { SelectionModel } from 'browser/selection/SelectionModel'; import { SelectionModel } from 'browser/selection/SelectionModel';
import { ISelectionRedrawRequestEvent, ISelectionRequestScrollLinesEvent } from 'browser/selection/Types'; import { ISelectionRedrawRequestEvent, ISelectionRequestScrollLinesEvent } from 'browser/selection/Types';
import { ICoreBrowserService, IMouseService, IRenderService, ISelectionService } from 'browser/services/Services'; import { ICoreBrowserService, IMouseService, IRenderService, ISelectionService } from 'browser/services/Services';
import { Disposable, toDisposable } from 'common/Lifecycle'; import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import * as Browser from 'common/Platform'; import * as Browser from 'common/Platform';
import { IBufferLine, IDisposable } from 'common/Types'; import { IBufferLine, IDisposable } from 'common/Types';
import { getRangeLength } from 'common/buffer/BufferRange'; import { getRangeLength } from 'common/buffer/BufferRange';
@@ -111,13 +111,13 @@ export class SelectionService extends Disposable implements ISelectionService {
private _oldSelectionStart: [number, number] | undefined = undefined; private _oldSelectionStart: [number, number] | undefined = undefined;
private _oldSelectionEnd: [number, number] | undefined = undefined; private _oldSelectionEnd: [number, number] | undefined = undefined;
private readonly _onLinuxMouseSelection = this.register(new Emitter<string>()); private readonly _onLinuxMouseSelection = this._register(new Emitter<string>());
public readonly onLinuxMouseSelection = this._onLinuxMouseSelection.event; public readonly onLinuxMouseSelection = this._onLinuxMouseSelection.event;
private readonly _onRedrawRequest = this.register(new Emitter<ISelectionRedrawRequestEvent>()); private readonly _onRedrawRequest = this._register(new Emitter<ISelectionRedrawRequestEvent>());
public readonly onRequestRedraw = this._onRedrawRequest.event; public readonly onRequestRedraw = this._onRedrawRequest.event;
private readonly _onSelectionChange = this.register(new Emitter<void>()); private readonly _onSelectionChange = this._register(new Emitter<void>());
public readonly onSelectionChange = this._onSelectionChange.event; public readonly onSelectionChange = this._onSelectionChange.event;
private readonly _onRequestScrollLines = this.register(new Emitter<ISelectionRequestScrollLinesEvent>()); private readonly _onRequestScrollLines = this._register(new Emitter<ISelectionRequestScrollLinesEvent>());
public readonly onRequestScrollLines = this._onRequestScrollLines.event; public readonly onRequestScrollLines = this._onRequestScrollLines.event;
constructor( constructor(
@@ -142,14 +142,14 @@ export class SelectionService extends Disposable implements ISelectionService {
} }
}); });
this._trimListener = this._bufferService.buffer.lines.onTrim(amount => this._handleTrim(amount)); this._trimListener = this._bufferService.buffer.lines.onTrim(amount => this._handleTrim(amount));
this.register(this._bufferService.buffers.onBufferActivate(e => this._handleBufferActivate(e))); this._register(this._bufferService.buffers.onBufferActivate(e => this._handleBufferActivate(e)));
this.enable(); this.enable();
this._model = new SelectionModel(this._bufferService); this._model = new SelectionModel(this._bufferService);
this._activeSelectionMode = SelectionMode.NORMAL; this._activeSelectionMode = SelectionMode.NORMAL;
this.register(toDisposable(() => { this._register(toDisposable(() => {
this._removeMouseDownListeners(); this._removeMouseDownListeners();
})); }));
} }
+4 -4
View File
@@ -7,7 +7,7 @@ import { ColorContrastCache } from 'browser/ColorContrastCache';
import { IThemeService } from 'browser/services/Services'; import { IThemeService } from 'browser/services/Services';
import { DEFAULT_ANSI_COLORS, IColorContrastCache, IColorSet, ReadonlyColorSet } from 'browser/Types'; import { DEFAULT_ANSI_COLORS, IColorContrastCache, IColorSet, ReadonlyColorSet } from 'browser/Types';
import { color, css, NULL_COLOR } from 'common/Color'; import { color, css, NULL_COLOR } from 'common/Color';
import { Disposable } from 'common/Lifecycle'; import { Disposable } from 'vs/base/common/lifecycle';
import { IOptionsService, ITheme } from 'common/services/Services'; import { IOptionsService, ITheme } from 'common/services/Services';
import { AllColorIndex, IColor, SpecialColorIndex } from 'common/Types'; import { AllColorIndex, IColor, SpecialColorIndex } from 'common/Types';
import { Emitter } from 'vs/base/common/event'; import { Emitter } from 'vs/base/common/event';
@@ -40,7 +40,7 @@ export class ThemeService extends Disposable implements IThemeService {
public get colors(): ReadonlyColorSet { return this._colors; } public get colors(): ReadonlyColorSet { return this._colors; }
private readonly _onChangeColors = this.register(new Emitter<ReadonlyColorSet>()); private readonly _onChangeColors = this._register(new Emitter<ReadonlyColorSet>());
public readonly onChangeColors = this._onChangeColors.event; public readonly onChangeColors = this._onChangeColors.event;
constructor( constructor(
@@ -69,8 +69,8 @@ export class ThemeService extends Disposable implements IThemeService {
this._updateRestoreColors(); this._updateRestoreColors();
this._setTheme(this._optionsService.rawOptions.theme); this._setTheme(this._optionsService.rawOptions.theme);
this.register(this._optionsService.onSpecificOptionChange('minimumContrastRatio', () => this._contrastCache.clear())); this._register(this._optionsService.onSpecificOptionChange('minimumContrastRatio', () => this._contrastCache.clear()));
this.register(this._optionsService.onSpecificOptionChange('theme', () => this._setTheme(this._optionsService.rawOptions.theme))); this._register(this._optionsService.onSpecificOptionChange('theme', () => this._setTheme(this._optionsService.rawOptions.theme)));
} }
/** /**
+4 -4
View File
@@ -4,7 +4,7 @@
*/ */
import { ICircularList } from 'common/Types'; import { ICircularList } from 'common/Types';
import { Disposable } from 'common/Lifecycle'; import { Disposable } from 'vs/base/common/lifecycle';
import { Emitter } from 'vs/base/common/event'; import { Emitter } from 'vs/base/common/event';
export interface IInsertEvent { export interface IInsertEvent {
@@ -26,11 +26,11 @@ export class CircularList<T> extends Disposable implements ICircularList<T> {
private _startIndex: number; private _startIndex: number;
private _length: number; private _length: number;
public readonly onDeleteEmitter = this.register(new Emitter<IDeleteEvent>()); public readonly onDeleteEmitter = this._register(new Emitter<IDeleteEvent>());
public readonly onDelete = this.onDeleteEmitter.event; public readonly onDelete = this.onDeleteEmitter.event;
public readonly onInsertEmitter = this.register(new Emitter<IInsertEvent>()); public readonly onInsertEmitter = this._register(new Emitter<IInsertEvent>());
public readonly onInsert = this.onInsertEmitter.event; public readonly onInsert = this.onInsertEmitter.event;
public readonly onTrimEmitter = this.register(new Emitter<number>()); public readonly onTrimEmitter = this._register(new Emitter<number>());
public readonly onTrim = this.onTrimEmitter.event; public readonly onTrim = this.onTrimEmitter.event;
constructor( constructor(
+27 -27
View File
@@ -21,7 +21,6 @@
* http://linux.die.net/man/7/urxvt * http://linux.die.net/man/7/urxvt
*/ */
import { Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle';
import { IInstantiationService, IOptionsService, IBufferService, ILogService, ICharsetService, ICoreService, ICoreMouseService, IUnicodeService, LogLevelEnum, ITerminalOptions, IOscLinkService } from 'common/services/Services'; import { IInstantiationService, IOptionsService, IBufferService, ILogService, ICharsetService, ICoreService, ICoreMouseService, IUnicodeService, LogLevelEnum, ITerminalOptions, IOscLinkService } from 'common/services/Services';
import { InstantiationService } from 'common/services/InstantiationService'; import { InstantiationService } from 'common/services/InstantiationService';
import { LogService } from 'common/services/LogService'; import { LogService } from 'common/services/LogService';
@@ -39,6 +38,7 @@ import { InputHandler } from 'common/InputHandler';
import { WriteBuffer } from 'common/input/WriteBuffer'; import { WriteBuffer } from 'common/input/WriteBuffer';
import { OscLinkService } from 'common/services/OscLinkService'; import { OscLinkService } from 'common/services/OscLinkService';
import { Emitter, Event } from 'vs/base/common/event'; import { Emitter, Event } from 'vs/base/common/event';
import { Disposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
// Only trigger this warning a single time per session // Only trigger this warning a single time per session
let hasWriteSyncWarnHappened = false; let hasWriteSyncWarnHappened = false;
@@ -57,17 +57,17 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
protected _inputHandler: InputHandler; protected _inputHandler: InputHandler;
private _writeBuffer: WriteBuffer; private _writeBuffer: WriteBuffer;
private _windowsWrappingHeuristics = this.register(new MutableDisposable()); private _windowsWrappingHeuristics = this._register(new MutableDisposable());
private readonly _onBinary = this.register(new Emitter<string>()); private readonly _onBinary = this._register(new Emitter<string>());
public readonly onBinary = this._onBinary.event; public readonly onBinary = this._onBinary.event;
private readonly _onData = this.register(new Emitter<string>()); private readonly _onData = this._register(new Emitter<string>());
public readonly onData = this._onData.event; public readonly onData = this._onData.event;
protected _onLineFeed = this.register(new Emitter<void>()); protected _onLineFeed = this._register(new Emitter<void>());
public readonly onLineFeed = this._onLineFeed.event; public readonly onLineFeed = this._onLineFeed.event;
private readonly _onResize = this.register(new Emitter<{ cols: number, rows: number }>()); private readonly _onResize = this._register(new Emitter<{ cols: number, rows: number }>());
public readonly onResize = this._onResize.event; public readonly onResize = this._onResize.event;
protected readonly _onWriteParsed = this.register(new Emitter<void>()); protected readonly _onWriteParsed = this._register(new Emitter<void>());
public readonly onWriteParsed = this._onWriteParsed.event; public readonly onWriteParsed = this._onWriteParsed.event;
/** /**
@@ -75,10 +75,10 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
* it's filtered out. * it's filtered out.
*/ */
protected _onScrollApi?: Emitter<number>; protected _onScrollApi?: Emitter<number>;
protected _onScroll = this.register(new Emitter<IScrollEvent>()); protected _onScroll = this._register(new Emitter<IScrollEvent>());
public get onScroll(): Event<number> { public get onScroll(): Event<number> {
if (!this._onScrollApi) { if (!this._onScrollApi) {
this._onScrollApi = this.register(new Emitter<number>()); this._onScrollApi = this._register(new Emitter<number>());
this._onScroll.event(ev => { this._onScroll.event(ev => {
this._onScrollApi?.fire(ev.position); this._onScrollApi?.fire(ev.position);
}); });
@@ -103,17 +103,17 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
// Setup and initialize services // Setup and initialize services
this._instantiationService = new InstantiationService(); this._instantiationService = new InstantiationService();
this.optionsService = this.register(new OptionsService(options)); this.optionsService = this._register(new OptionsService(options));
this._instantiationService.setService(IOptionsService, this.optionsService); this._instantiationService.setService(IOptionsService, this.optionsService);
this._bufferService = this.register(this._instantiationService.createInstance(BufferService)); this._bufferService = this._register(this._instantiationService.createInstance(BufferService));
this._instantiationService.setService(IBufferService, this._bufferService); this._instantiationService.setService(IBufferService, this._bufferService);
this._logService = this.register(this._instantiationService.createInstance(LogService)); this._logService = this._register(this._instantiationService.createInstance(LogService));
this._instantiationService.setService(ILogService, this._logService); this._instantiationService.setService(ILogService, this._logService);
this.coreService = this.register(this._instantiationService.createInstance(CoreService)); this.coreService = this._register(this._instantiationService.createInstance(CoreService));
this._instantiationService.setService(ICoreService, this.coreService); this._instantiationService.setService(ICoreService, this.coreService);
this.coreMouseService = this.register(this._instantiationService.createInstance(CoreMouseService)); this.coreMouseService = this._register(this._instantiationService.createInstance(CoreMouseService));
this._instantiationService.setService(ICoreMouseService, this.coreMouseService); this._instantiationService.setService(ICoreMouseService, this.coreMouseService);
this.unicodeService = this.register(this._instantiationService.createInstance(UnicodeService)); this.unicodeService = this._register(this._instantiationService.createInstance(UnicodeService));
this._instantiationService.setService(IUnicodeService, this.unicodeService); this._instantiationService.setService(IUnicodeService, this.unicodeService);
this._charsetService = this._instantiationService.createInstance(CharsetService); this._charsetService = this._instantiationService.createInstance(CharsetService);
this._instantiationService.setService(ICharsetService, this._charsetService); this._instantiationService.setService(ICharsetService, this._charsetService);
@@ -122,24 +122,24 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
// Register input handler and handle/forward events // Register input handler and handle/forward events
this._inputHandler = this.register(new InputHandler(this._bufferService, this._charsetService, this.coreService, this._logService, this.optionsService, this._oscLinkService, this.coreMouseService, this.unicodeService)); this._inputHandler = this._register(new InputHandler(this._bufferService, this._charsetService, this.coreService, this._logService, this.optionsService, this._oscLinkService, this.coreMouseService, this.unicodeService));
this.register(Event.forward(this._inputHandler.onLineFeed, this._onLineFeed)); this._register(Event.forward(this._inputHandler.onLineFeed, this._onLineFeed));
this.register(this._inputHandler); this._register(this._inputHandler);
// Setup listeners // Setup listeners
this.register(Event.forward(this._bufferService.onResize, this._onResize)); this._register(Event.forward(this._bufferService.onResize, this._onResize));
this.register(Event.forward(this.coreService.onData, this._onData)); this._register(Event.forward(this.coreService.onData, this._onData));
this.register(Event.forward(this.coreService.onBinary, this._onBinary)); this._register(Event.forward(this.coreService.onBinary, this._onBinary));
this.register(this.coreService.onRequestScrollToBottom(() => this.scrollToBottom(true))); this._register(this.coreService.onRequestScrollToBottom(() => this.scrollToBottom(true)));
this.register(this.coreService.onUserInput(() => this._writeBuffer.handleUserInput())); this._register(this.coreService.onUserInput(() => this._writeBuffer.handleUserInput()));
this.register(this.optionsService.onMultipleOptionChange(['windowsMode', 'windowsPty'], () => this._handleWindowsPtyOptionChange())); this._register(this.optionsService.onMultipleOptionChange(['windowsMode', 'windowsPty'], () => this._handleWindowsPtyOptionChange()));
this.register(this._bufferService.onScroll(() => { this._register(this._bufferService.onScroll(() => {
this._onScroll.fire({ position: this._bufferService.buffer.ydisp }); this._onScroll.fire({ position: this._bufferService.buffer.ydisp });
this._inputHandler.markRangeDirty(this._bufferService.buffer.scrollTop, this._bufferService.buffer.scrollBottom); this._inputHandler.markRangeDirty(this._bufferService.buffer.scrollTop, this._bufferService.buffer.scrollBottom);
})); }));
// Setup WriteBuffer // Setup WriteBuffer
this._writeBuffer = this.register(new WriteBuffer((data, promiseResult) => this._inputHandler.parse(data, promiseResult))); this._writeBuffer = this._register(new WriteBuffer((data, promiseResult) => this._inputHandler.parse(data, promiseResult)));
this.register(Event.forward(this._writeBuffer.onWriteParsed, this._onWriteParsed)); this._register(Event.forward(this._writeBuffer.onWriteParsed, this._onWriteParsed));
} }
public write(data: string | Uint8Array, callback?: () => void): void { public write(data: string | Uint8Array, callback?: () => void): void {
+16 -16
View File
@@ -8,7 +8,7 @@ import { IInputHandler, IAttributeData, IDisposable, IWindowOptions, IColorEvent
import { C0, C1 } from 'common/data/EscapeSequences'; import { C0, C1 } from 'common/data/EscapeSequences';
import { CHARSETS, DEFAULT_CHARSET } from 'common/data/Charsets'; import { CHARSETS, DEFAULT_CHARSET } from 'common/data/Charsets';
import { EscapeSequenceParser } from 'common/parser/EscapeSequenceParser'; import { EscapeSequenceParser } from 'common/parser/EscapeSequenceParser';
import { Disposable } from 'common/Lifecycle'; import { Disposable } from 'vs/base/common/lifecycle';
import { StringToUtf32, stringFromCodePoint, Utf8ToUtf32 } from 'common/input/TextDecoder'; import { StringToUtf32, stringFromCodePoint, Utf8ToUtf32 } from 'common/input/TextDecoder';
import { BufferLine, DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine'; import { BufferLine, DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';
import { IParsingState, IEscapeSequenceParser, IParams, IFunctionIdentifier } from 'common/parser/Types'; import { IParsingState, IEscapeSequenceParser, IParams, IFunctionIdentifier } from 'common/parser/Types';
@@ -131,32 +131,32 @@ export class InputHandler extends Disposable implements IInputHandler {
private _activeBuffer: IBuffer; private _activeBuffer: IBuffer;
private readonly _onRequestBell = this.register(new Emitter<void>()); private readonly _onRequestBell = this._register(new Emitter<void>());
public readonly onRequestBell = this._onRequestBell.event; public readonly onRequestBell = this._onRequestBell.event;
private readonly _onRequestRefreshRows = this.register(new Emitter<{ start: number, end: number } | undefined>()); private readonly _onRequestRefreshRows = this._register(new Emitter<{ start: number, end: number } | undefined>());
public readonly onRequestRefreshRows = this._onRequestRefreshRows.event; public readonly onRequestRefreshRows = this._onRequestRefreshRows.event;
private readonly _onRequestReset = this.register(new Emitter<void>()); private readonly _onRequestReset = this._register(new Emitter<void>());
public readonly onRequestReset = this._onRequestReset.event; public readonly onRequestReset = this._onRequestReset.event;
private readonly _onRequestSendFocus = this.register(new Emitter<void>()); private readonly _onRequestSendFocus = this._register(new Emitter<void>());
public readonly onRequestSendFocus = this._onRequestSendFocus.event; public readonly onRequestSendFocus = this._onRequestSendFocus.event;
private readonly _onRequestSyncScrollBar = this.register(new Emitter<void>()); private readonly _onRequestSyncScrollBar = this._register(new Emitter<void>());
public readonly onRequestSyncScrollBar = this._onRequestSyncScrollBar.event; public readonly onRequestSyncScrollBar = this._onRequestSyncScrollBar.event;
private readonly _onRequestWindowsOptionsReport = this.register(new Emitter<WindowsOptionsReportType>()); private readonly _onRequestWindowsOptionsReport = this._register(new Emitter<WindowsOptionsReportType>());
public readonly onRequestWindowsOptionsReport = this._onRequestWindowsOptionsReport.event; public readonly onRequestWindowsOptionsReport = this._onRequestWindowsOptionsReport.event;
private readonly _onA11yChar = this.register(new Emitter<string>()); private readonly _onA11yChar = this._register(new Emitter<string>());
public readonly onA11yChar = this._onA11yChar.event; public readonly onA11yChar = this._onA11yChar.event;
private readonly _onA11yTab = this.register(new Emitter<number>()); private readonly _onA11yTab = this._register(new Emitter<number>());
public readonly onA11yTab = this._onA11yTab.event; public readonly onA11yTab = this._onA11yTab.event;
private readonly _onCursorMove = this.register(new Emitter<void>()); private readonly _onCursorMove = this._register(new Emitter<void>());
public readonly onCursorMove = this._onCursorMove.event; public readonly onCursorMove = this._onCursorMove.event;
private readonly _onLineFeed = this.register(new Emitter<void>()); private readonly _onLineFeed = this._register(new Emitter<void>());
public readonly onLineFeed = this._onLineFeed.event; public readonly onLineFeed = this._onLineFeed.event;
private readonly _onScroll = this.register(new Emitter<number>()); private readonly _onScroll = this._register(new Emitter<number>());
public readonly onScroll = this._onScroll.event; public readonly onScroll = this._onScroll.event;
private readonly _onTitleChange = this.register(new Emitter<string>()); private readonly _onTitleChange = this._register(new Emitter<string>());
public readonly onTitleChange = this._onTitleChange.event; public readonly onTitleChange = this._onTitleChange.event;
private readonly _onColor = this.register(new Emitter<IColorEvent>()); private readonly _onColor = this._register(new Emitter<IColorEvent>());
public readonly onColor = this._onColor.event; public readonly onColor = this._onColor.event;
private _parseStack: IParseStack = { private _parseStack: IParseStack = {
@@ -179,12 +179,12 @@ export class InputHandler extends Disposable implements IInputHandler {
private readonly _parser: IEscapeSequenceParser = new EscapeSequenceParser() private readonly _parser: IEscapeSequenceParser = new EscapeSequenceParser()
) { ) {
super(); super();
this.register(this._parser); this._register(this._parser);
this._dirtyRowTracker = new DirtyRowTracker(this._bufferService); this._dirtyRowTracker = new DirtyRowTracker(this._bufferService);
// Track properties used in performance critical code manually to avoid using slow getters // Track properties used in performance critical code manually to avoid using slow getters
this._activeBuffer = this._bufferService.buffer; this._activeBuffer = this._bufferService.buffer;
this.register(this._bufferService.buffers.onBufferActivate(e => this._activeBuffer = e.activeBuffer)); this._register(this._bufferService.buffers.onBufferActivate(e => this._activeBuffer = e.activeBuffer));
/** /**
* custom fallback handlers * custom fallback handlers
-95
View File
@@ -1,95 +0,0 @@
/**
* Copyright (c) 2018 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { assert } from 'chai';
import { Disposable, MutableDisposable } from 'common/Lifecycle';
import { IDisposable } from 'common/Types';
class TestDisposable extends Disposable {
public get isDisposed(): boolean {
return this._isDisposed;
}
}
describe('Disposable', () => {
describe('register', () => {
it('should register disposables', () => {
const d = new TestDisposable();
const d2 = {
dispose: () => { throw new Error(); }
};
d.register(d2);
assert.throws(() => d.dispose());
});
});
describe('unregister', () => {
it('should unregister disposables', () => {
const d = new TestDisposable();
const d2 = {
dispose: () => { throw new Error(); }
};
d.register(d2);
d.unregister(d2);
assert.doesNotThrow(() => d.dispose());
});
});
describe('dispose', () => {
it('should set is disposed flag', () => {
const d = new TestDisposable();
assert.isFalse(d.isDisposed);
d.dispose();
assert.isTrue(d.isDisposed);
});
});
});
describe('MutableDisposable', () => {
const mutable = new MutableDisposable();
class TrackedDisposable extends Disposable {
public get isDisposed(): boolean { return this._isDisposed; }
}
describe('value', () => {
it('should set the value', () => {
const d1 = new TrackedDisposable();
mutable.value = d1;
assert.strictEqual(mutable.value, d1);
assert.isFalse(d1.isDisposed);
});
it('should dispose of any previous value', () => {
const d1 = new TrackedDisposable();
const d2 = new TrackedDisposable();
mutable.value = d1;
mutable.value = d2;
assert.strictEqual(mutable.value, d2);
assert.isTrue(d1.isDisposed);
assert.isFalse(d2.isDisposed);
});
});
describe('clear', () => {
it('should clear and dispose of the object', () => {
const d1 = new TrackedDisposable();
mutable.value = d1;
mutable.clear();
assert.strictEqual(mutable.value, undefined);
assert.isTrue(d1.isDisposed);
});
});
it('dispose', () => {
it('should dispose of the object', () => {
const d1 = new TrackedDisposable();
mutable.value = d1;
mutable.dispose();
assert.strictEqual(mutable.value, undefined);
assert.isTrue(d1.isDisposed);
});
it('should prevent using the MutableDisposable again', () => {
const d1 = new TrackedDisposable();
mutable.value = d1;
mutable.dispose();
mutable.value = new TrackedDisposable();
assert.strictEqual(mutable.value, undefined);
});
});
});
-108
View File
@@ -1,108 +0,0 @@
/**
* Copyright (c) 2018 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { IDisposable } from 'common/Types';
/**
* A base class that can be extended to provide convenience methods for managing the lifecycle of an
* object and its components.
*/
export abstract class Disposable implements IDisposable {
protected _disposables: IDisposable[] = [];
protected _isDisposed: boolean = false;
/**
* Disposes the object, triggering the `dispose` method on all registered IDisposables.
*/
public dispose(): void {
this._isDisposed = true;
for (const d of this._disposables) {
d.dispose();
}
this._disposables.length = 0;
}
/**
* Registers a disposable object.
* @param d The disposable to register.
* @returns The disposable.
*/
public register<T extends IDisposable>(d: T): T {
this._disposables.push(d);
return d;
}
/**
* Unregisters a disposable object if it has been registered, if not do
* nothing.
* @param d The disposable to unregister.
*/
public unregister<T extends IDisposable>(d: T): void {
const index = this._disposables.indexOf(d);
if (index !== -1) {
this._disposables.splice(index, 1);
}
}
}
export class MutableDisposable<T extends IDisposable> implements IDisposable {
private _value?: T;
private _isDisposed = false;
/**
* Gets the value if it exists.
*/
public get value(): T | undefined {
return this._isDisposed ? undefined : this._value;
}
/**
* Sets the value, disposing of the old value if it exists.
*/
public set value(value: T | undefined) {
if (this._isDisposed || value === this._value) {
return;
}
this._value?.dispose();
this._value = value;
}
/**
* Resets the stored value and disposes of the previously stored value.
*/
public clear(): void {
this.value = undefined;
}
public dispose(): void {
this._isDisposed = true;
this._value?.dispose();
this._value = undefined;
}
}
/**
* Wrap a function in a disposable.
*/
export function toDisposable(f: () => void): IDisposable {
return { dispose: f };
}
/**
* Dispose of all disposables in an array and set its length to 0.
*/
export function disposeArray(disposables: IDisposable[]): void {
for (const d of disposables) {
d.dispose();
}
disposables.length = 0;
}
/**
* Creates a disposable that will dispose of an array of disposables when disposed.
*/
export function getDisposeArrayDisposable(array: IDisposable[]): IDisposable {
return { dispose: () => disposeArray(array) };
}
+4 -4
View File
@@ -3,7 +3,7 @@
* @license MIT * @license MIT
*/ */
import { Disposable } from 'common/Lifecycle'; import { Disposable } from 'vs/base/common/lifecycle';
import { IAttributeData } from 'common/Types'; import { IAttributeData } from 'common/Types';
import { Buffer } from 'common/buffer/Buffer'; import { Buffer } from 'common/buffer/Buffer';
import { IBuffer, IBufferSet } from 'common/buffer/Types'; import { IBuffer, IBufferSet } from 'common/buffer/Types';
@@ -19,7 +19,7 @@ export class BufferSet extends Disposable implements IBufferSet {
private _alt!: Buffer; private _alt!: Buffer;
private _activeBuffer!: Buffer; private _activeBuffer!: Buffer;
private readonly _onBufferActivate = this.register(new Emitter<{ activeBuffer: IBuffer, inactiveBuffer: IBuffer }>()); private readonly _onBufferActivate = this._register(new Emitter<{ activeBuffer: IBuffer, inactiveBuffer: IBuffer }>());
public readonly onBufferActivate = this._onBufferActivate.event; public readonly onBufferActivate = this._onBufferActivate.event;
/** /**
@@ -31,8 +31,8 @@ export class BufferSet extends Disposable implements IBufferSet {
) { ) {
super(); super();
this.reset(); this.reset();
this.register(this._optionsService.onSpecificOptionChange('scrollback', () => this.resize(this._bufferService.cols, this._bufferService.rows))); this._register(this._optionsService.onSpecificOptionChange('scrollback', () => this.resize(this._bufferService.cols, this._bufferService.rows)));
this.register(this._optionsService.onSpecificOptionChange('tabStopWidth', () => this.setupTabStops())); this._register(this._optionsService.onSpecificOptionChange('tabStopWidth', () => this.setupTabStops()));
} }
public reset(): void { public reset(): void {
+2 -2
View File
@@ -3,9 +3,9 @@
* @license MIT * @license MIT
*/ */
import { disposeArray } from 'common/Lifecycle';
import { IDisposable, IMarker } from 'common/Types'; import { IDisposable, IMarker } from 'common/Types';
import { Emitter } from 'vs/base/common/event'; import { Emitter } from 'vs/base/common/event';
import { dispose } from 'vs/base/common/lifecycle';
export class Marker implements IMarker { export class Marker implements IMarker {
private static _nextId = 1; private static _nextId = 1;
@@ -32,7 +32,7 @@ export class Marker implements IMarker {
this.line = -1; this.line = -1;
// Emit before super.dispose such that dispose listeners get a change to react // Emit before super.dispose such that dispose listeners get a change to react
this._onDispose.fire(); this._onDispose.fire();
disposeArray(this._disposables); dispose(this._disposables);
this._disposables.length = 0; this._disposables.length = 0;
} }
+2 -2
View File
@@ -4,7 +4,7 @@
* @license MIT * @license MIT
*/ */
import { Disposable } from 'common/Lifecycle'; import { Disposable } from 'vs/base/common/lifecycle';
import { Emitter } from 'vs/base/common/event'; import { Emitter } from 'vs/base/common/event';
declare const setTimeout: (handler: () => void, timeout?: number) => void; declare const setTimeout: (handler: () => void, timeout?: number) => void;
@@ -43,7 +43,7 @@ export class WriteBuffer extends Disposable {
private _syncCalls = 0; private _syncCalls = 0;
private _didUserInput = false; private _didUserInput = false;
private readonly _onWriteParsed = this.register(new Emitter<void>()); private readonly _onWriteParsed = this._register(new Emitter<void>());
public readonly onWriteParsed = this._onWriteParsed.event; public readonly onWriteParsed = this._onWriteParsed.event;
constructor(private _action: (data: string | Uint8Array, promiseResult?: boolean) => void | Promise<boolean>) { constructor(private _action: (data: string | Uint8Array, promiseResult?: boolean) => void | Promise<boolean>) {
+4 -4
View File
@@ -5,7 +5,7 @@
import { IParsingState, IDcsHandler, IEscapeSequenceParser, IParams, IOscHandler, IHandlerCollection, CsiHandlerType, OscFallbackHandlerType, IOscParser, EscHandlerType, IDcsParser, DcsFallbackHandlerType, IFunctionIdentifier, ExecuteFallbackHandlerType, CsiFallbackHandlerType, EscFallbackHandlerType, PrintHandlerType, PrintFallbackHandlerType, ExecuteHandlerType, IParserStackState, ParserStackType, ResumableHandlersType } from 'common/parser/Types'; import { IParsingState, IDcsHandler, IEscapeSequenceParser, IParams, IOscHandler, IHandlerCollection, CsiHandlerType, OscFallbackHandlerType, IOscParser, EscHandlerType, IDcsParser, DcsFallbackHandlerType, IFunctionIdentifier, ExecuteFallbackHandlerType, CsiFallbackHandlerType, EscFallbackHandlerType, PrintHandlerType, PrintFallbackHandlerType, ExecuteHandlerType, IParserStackState, ParserStackType, ResumableHandlersType } from 'common/parser/Types';
import { ParserState, ParserAction } from 'common/parser/Constants'; import { ParserState, ParserAction } from 'common/parser/Constants';
import { Disposable, toDisposable } from 'common/Lifecycle'; import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { IDisposable } from 'common/Types'; import { IDisposable } from 'common/Types';
import { Params } from 'common/parser/Params'; import { Params } from 'common/parser/Params';
import { OscParser } from 'common/parser/OscParser'; import { OscParser } from 'common/parser/OscParser';
@@ -283,13 +283,13 @@ export class EscapeSequenceParser extends Disposable implements IEscapeSequenceP
this._executeHandlers = Object.create(null); this._executeHandlers = Object.create(null);
this._csiHandlers = Object.create(null); this._csiHandlers = Object.create(null);
this._escHandlers = Object.create(null); this._escHandlers = Object.create(null);
this.register(toDisposable(() => { this._register(toDisposable(() => {
this._csiHandlers = Object.create(null); this._csiHandlers = Object.create(null);
this._executeHandlers = Object.create(null); this._executeHandlers = Object.create(null);
this._escHandlers = Object.create(null); this._escHandlers = Object.create(null);
})); }));
this._oscParser = this.register(new OscParser()); this._oscParser = this._register(new OscParser());
this._dcsParser = this.register(new DcsParser()); this._dcsParser = this._register(new DcsParser());
this._errorHandler = this._errorHandlerFb; this._errorHandler = this._errorHandlerFb;
// swallow 7bit ST (ESC+\) // swallow 7bit ST (ESC+\)
+2 -2
View File
@@ -6,14 +6,14 @@
import { IBuffer as IBufferApi, IBufferNamespace as IBufferNamespaceApi } from '@xterm/xterm'; import { IBuffer as IBufferApi, IBufferNamespace as IBufferNamespaceApi } from '@xterm/xterm';
import { BufferApiView } from 'common/public/BufferApiView'; import { BufferApiView } from 'common/public/BufferApiView';
import { ICoreTerminal } from 'common/Types'; import { ICoreTerminal } from 'common/Types';
import { Disposable } from 'common/Lifecycle'; import { Disposable } from 'vs/base/common/lifecycle';
import { Emitter } from 'vs/base/common/event'; import { Emitter } from 'vs/base/common/event';
export class BufferNamespaceApi extends Disposable implements IBufferNamespaceApi { export class BufferNamespaceApi extends Disposable implements IBufferNamespaceApi {
private _normal: BufferApiView; private _normal: BufferApiView;
private _alternate: BufferApiView; private _alternate: BufferApiView;
private readonly _onBufferChange = this.register(new Emitter<IBufferApi>()); private readonly _onBufferChange = this._register(new Emitter<IBufferApi>());
public readonly onBufferChange = this._onBufferChange.event; public readonly onBufferChange = this._onBufferChange.event;
constructor(private _core: ICoreTerminal) { constructor(private _core: ICoreTerminal) {
+4 -4
View File
@@ -3,7 +3,7 @@
* @license MIT * @license MIT
*/ */
import { Disposable } from 'common/Lifecycle'; import { Disposable } from 'vs/base/common/lifecycle';
import { IAttributeData, IBufferLine } from 'common/Types'; import { IAttributeData, IBufferLine } from 'common/Types';
import { BufferSet } from 'common/buffer/BufferSet'; import { BufferSet } from 'common/buffer/BufferSet';
import { IBuffer, IBufferSet } from 'common/buffer/Types'; import { IBuffer, IBufferSet } from 'common/buffer/Types';
@@ -22,9 +22,9 @@ export class BufferService extends Disposable implements IBufferService {
/** Whether the user is scrolling (locks the scroll position) */ /** Whether the user is scrolling (locks the scroll position) */
public isUserScrolling: boolean = false; public isUserScrolling: boolean = false;
private readonly _onResize = this.register(new Emitter<{ cols: number, rows: number }>()); private readonly _onResize = this._register(new Emitter<{ cols: number, rows: number }>());
public readonly onResize = this._onResize.event; public readonly onResize = this._onResize.event;
private readonly _onScroll = this.register(new Emitter<number>()); private readonly _onScroll = this._register(new Emitter<number>());
public readonly onScroll = this._onScroll.event; public readonly onScroll = this._onScroll.event;
public get buffer(): IBuffer { return this.buffers.active; } public get buffer(): IBuffer { return this.buffers.active; }
@@ -36,7 +36,7 @@ export class BufferService extends Disposable implements IBufferService {
super(); super();
this.cols = Math.max(optionsService.rawOptions.cols || 0, MINIMUM_COLS); this.cols = Math.max(optionsService.rawOptions.cols || 0, MINIMUM_COLS);
this.rows = Math.max(optionsService.rawOptions.rows || 0, MINIMUM_ROWS); this.rows = Math.max(optionsService.rawOptions.rows || 0, MINIMUM_ROWS);
this.buffers = this.register(new BufferSet(optionsService, this)); this.buffers = this._register(new BufferSet(optionsService, this));
} }
public resize(cols: number, rows: number): void { public resize(cols: number, rows: number): void {
+2 -2
View File
@@ -4,7 +4,7 @@
*/ */
import { IBufferService, ICoreService, ICoreMouseService } from 'common/services/Services'; import { IBufferService, ICoreService, ICoreMouseService } from 'common/services/Services';
import { ICoreMouseProtocol, ICoreMouseEvent, CoreMouseEncoding, CoreMouseEventType, CoreMouseButton, CoreMouseAction } from 'common/Types'; import { ICoreMouseProtocol, ICoreMouseEvent, CoreMouseEncoding, CoreMouseEventType, CoreMouseButton, CoreMouseAction } from 'common/Types';
import { Disposable } from 'common/Lifecycle'; import { Disposable } from 'vs/base/common/lifecycle';
import { Emitter } from 'vs/base/common/event'; import { Emitter } from 'vs/base/common/event';
/** /**
@@ -175,7 +175,7 @@ export class CoreMouseService extends Disposable implements ICoreMouseService {
private _activeEncoding: string = ''; private _activeEncoding: string = '';
private _lastEvent: ICoreMouseEvent | null = null; private _lastEvent: ICoreMouseEvent | null = null;
private readonly _onProtocolChange = this.register(new Emitter<CoreMouseEventType>()); private readonly _onProtocolChange = this._register(new Emitter<CoreMouseEventType>());
public readonly onProtocolChange = this._onProtocolChange.event; public readonly onProtocolChange = this._onProtocolChange.event;
constructor( constructor(
+5 -5
View File
@@ -4,7 +4,7 @@
*/ */
import { clone } from 'common/Clone'; import { clone } from 'common/Clone';
import { Disposable } from 'common/Lifecycle'; import { Disposable } from 'vs/base/common/lifecycle';
import { IDecPrivateModes, IModes } from 'common/Types'; import { IDecPrivateModes, IModes } from 'common/Types';
import { IBufferService, ICoreService, ILogService, IOptionsService } from 'common/services/Services'; import { IBufferService, ICoreService, ILogService, IOptionsService } from 'common/services/Services';
import { Emitter } from 'vs/base/common/event'; import { Emitter } from 'vs/base/common/event';
@@ -31,13 +31,13 @@ export class CoreService extends Disposable implements ICoreService {
public modes: IModes; public modes: IModes;
public decPrivateModes: IDecPrivateModes; public decPrivateModes: IDecPrivateModes;
private readonly _onData = this.register(new Emitter<string>()); private readonly _onData = this._register(new Emitter<string>());
public readonly onData = this._onData.event; public readonly onData = this._onData.event;
private readonly _onUserInput = this.register(new Emitter<void>()); private readonly _onUserInput = this._register(new Emitter<void>());
public readonly onUserInput = this._onUserInput.event; public readonly onUserInput = this._onUserInput.event;
private readonly _onBinary = this.register(new Emitter<string>()); private readonly _onBinary = this._register(new Emitter<string>());
public readonly onBinary = this._onBinary.event; public readonly onBinary = this._onBinary.event;
private readonly _onRequestScrollToBottom = this.register(new Emitter<void>()); private readonly _onRequestScrollToBottom = this._register(new Emitter<void>());
public readonly onRequestScrollToBottom = this._onRequestScrollToBottom.event; public readonly onRequestScrollToBottom = this._onRequestScrollToBottom.event;
constructor( constructor(
@@ -6,7 +6,7 @@
import { assert } from 'chai'; import { assert } from 'chai';
import { DecorationService } from './DecorationService'; import { DecorationService } from './DecorationService';
import { IMarker } from 'common/Types'; import { IMarker } from 'common/Types';
import { Disposable } from 'common/Lifecycle'; import { Disposable } from 'vs/base/common/lifecycle';
import { Emitter } from 'vs/base/common/event'; import { Emitter } from 'vs/base/common/event';
const fakeMarker: IMarker = Object.freeze(new class extends Disposable { const fakeMarker: IMarker = Object.freeze(new class extends Disposable {
+7 -8
View File
@@ -4,7 +4,7 @@
*/ */
import { css } from 'common/Color'; import { css } from 'common/Color';
import { Disposable, toDisposable } from 'common/Lifecycle'; import { Disposable, DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
import { IDecorationService, IInternalDecoration } from 'common/services/Services'; import { IDecorationService, IInternalDecoration } from 'common/services/Services';
import { SortedList } from 'common/SortedList'; import { SortedList } from 'common/SortedList';
import { IColor } from 'common/Types'; import { IColor } from 'common/Types';
@@ -25,9 +25,9 @@ export class DecorationService extends Disposable implements IDecorationService
*/ */
private readonly _decorations: SortedList<IInternalDecoration> = new SortedList(e => e?.marker.line); private readonly _decorations: SortedList<IInternalDecoration> = new SortedList(e => e?.marker.line);
private readonly _onDecorationRegistered = this.register(new Emitter<IInternalDecoration>()); private readonly _onDecorationRegistered = this._register(new Emitter<IInternalDecoration>());
public readonly onDecorationRegistered = this._onDecorationRegistered.event; public readonly onDecorationRegistered = this._onDecorationRegistered.event;
private readonly _onDecorationRemoved = this.register(new Emitter<IInternalDecoration>()); private readonly _onDecorationRemoved = this._register(new Emitter<IInternalDecoration>());
public readonly onDecorationRemoved = this._onDecorationRemoved.event; public readonly onDecorationRemoved = this._onDecorationRemoved.event;
public get decorations(): IterableIterator<IInternalDecoration> { return this._decorations.values(); } public get decorations(): IterableIterator<IInternalDecoration> { return this._decorations.values(); }
@@ -35,7 +35,7 @@ export class DecorationService extends Disposable implements IDecorationService
constructor() { constructor() {
super(); super();
this.register(toDisposable(() => this.reset())); this._register(toDisposable(() => this.reset()));
} }
public registerDecoration(options: IDecorationOptions): IDecoration | undefined { public registerDecoration(options: IDecorationOptions): IDecoration | undefined {
@@ -90,14 +90,13 @@ export class DecorationService extends Disposable implements IDecorationService
} }
} }
class Decoration extends Disposable implements IInternalDecoration { class Decoration extends DisposableStore implements IInternalDecoration {
public readonly marker: IMarker; public readonly marker: IMarker;
public element: HTMLElement | undefined; public element: HTMLElement | undefined;
public get isDisposed(): boolean { return this._isDisposed; }
public readonly onRenderEmitter = this.register(new Emitter<HTMLElement>()); public readonly onRenderEmitter = this.add(new Emitter<HTMLElement>());
public readonly onRender = this.onRenderEmitter.event; public readonly onRender = this.onRenderEmitter.event;
private readonly _onDispose = this.register(new Emitter<void>()); private readonly _onDispose = this.add(new Emitter<void>());
public readonly onDispose = this._onDispose.event; public readonly onDispose = this._onDispose.event;
private _cachedBg: IColor | undefined | null = null; private _cachedBg: IColor | undefined | null = null;
+2 -2
View File
@@ -3,7 +3,7 @@
* @license MIT * @license MIT
*/ */
import { Disposable } from 'common/Lifecycle'; import { Disposable } from 'vs/base/common/lifecycle';
import { ILogService, IOptionsService, LogLevelEnum } from 'common/services/Services'; import { ILogService, IOptionsService, LogLevelEnum } from 'common/services/Services';
type LogType = (message?: any, ...optionalParams: any[]) => void; type LogType = (message?: any, ...optionalParams: any[]) => void;
@@ -42,7 +42,7 @@ export class LogService extends Disposable implements ILogService {
) { ) {
super(); super();
this._updateLogLevel(); this._updateLogLevel();
this.register(this._optionsService.onSpecificOptionChange('logLevel', () => this._updateLogLevel())); this._register(this._optionsService.onSpecificOptionChange('logLevel', () => this._updateLogLevel()));
// For trace logging, assume the latest created log service is valid // For trace logging, assume the latest created log service is valid
traceLogger = this; traceLogger = this;
+3 -3
View File
@@ -3,7 +3,7 @@
* @license MIT * @license MIT
*/ */
import { Disposable, toDisposable } from 'common/Lifecycle'; import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { isMac } from 'common/Platform'; import { isMac } from 'common/Platform';
import { CursorStyle, IDisposable } from 'common/Types'; import { CursorStyle, IDisposable } from 'common/Types';
import { FontWeight, IOptionsService, ITerminalOptions } from 'common/services/Services'; import { FontWeight, IOptionsService, ITerminalOptions } from 'common/services/Services';
@@ -65,7 +65,7 @@ export class OptionsService extends Disposable implements IOptionsService {
public readonly rawOptions: Required<ITerminalOptions>; public readonly rawOptions: Required<ITerminalOptions>;
public options: Required<ITerminalOptions>; public options: Required<ITerminalOptions>;
private readonly _onOptionChange = this.register(new Emitter<keyof ITerminalOptions>()); private readonly _onOptionChange = this._register(new Emitter<keyof ITerminalOptions>());
public readonly onOptionChange = this._onOptionChange.event; public readonly onOptionChange = this._onOptionChange.event;
constructor(options: Partial<ITerminalOptions>) { constructor(options: Partial<ITerminalOptions>) {
@@ -90,7 +90,7 @@ export class OptionsService extends Disposable implements IOptionsService {
// Clear out options that could link outside xterm.js as they could easily cause an embedder // Clear out options that could link outside xterm.js as they could easily cause an embedder
// memory leak // memory leak
this.register(toDisposable(() => { this._register(toDisposable(() => {
this.rawOptions.linkHandler = null; this.rawOptions.linkHandler = null;
this.rawOptions.documentOverride = null; this.rawOptions.documentOverride = null;
})); }));
+11 -11
View File
@@ -28,15 +28,15 @@ import { IMarker, ITerminalOptions } from 'common/Types';
import { Emitter, Event } from 'vs/base/common/event'; import { Emitter, Event } from 'vs/base/common/event';
export class Terminal extends CoreTerminal { export class Terminal extends CoreTerminal {
private readonly _onBell = this.register(new Emitter<void>()); private readonly _onBell = this._register(new Emitter<void>());
public readonly onBell = this._onBell.event; public readonly onBell = this._onBell.event;
private readonly _onCursorMove = this.register(new Emitter<void>()); private readonly _onCursorMove = this._register(new Emitter<void>());
public readonly onCursorMove = this._onCursorMove.event; public readonly onCursorMove = this._onCursorMove.event;
private readonly _onTitleChange = this.register(new Emitter<string>()); private readonly _onTitleChange = this._register(new Emitter<string>());
public readonly onTitleChange = this._onTitleChange.event; public readonly onTitleChange = this._onTitleChange.event;
private readonly _onA11yCharEmitter = this.register(new Emitter<string>()); private readonly _onA11yCharEmitter = this._register(new Emitter<string>());
public readonly onA11yChar = this._onA11yCharEmitter.event; public readonly onA11yChar = this._onA11yCharEmitter.event;
private readonly _onA11yTabEmitter = this.register(new Emitter<number>()); private readonly _onA11yTabEmitter = this._register(new Emitter<number>());
public readonly onA11yTab = this._onA11yTabEmitter.event; public readonly onA11yTab = this._onA11yTabEmitter.event;
constructor( constructor(
@@ -47,12 +47,12 @@ export class Terminal extends CoreTerminal {
this._setup(); this._setup();
// Setup InputHandler listeners // Setup InputHandler listeners
this.register(this._inputHandler.onRequestBell(() => this.bell())); this._register(this._inputHandler.onRequestBell(() => this.bell()));
this.register(this._inputHandler.onRequestReset(() => this.reset())); this._register(this._inputHandler.onRequestReset(() => this.reset()));
this.register(Event.forward(this._inputHandler.onCursorMove, this._onCursorMove)); this._register(Event.forward(this._inputHandler.onCursorMove, this._onCursorMove));
this.register(Event.forward(this._inputHandler.onTitleChange, this._onTitleChange)); this._register(Event.forward(this._inputHandler.onTitleChange, this._onTitleChange));
this.register(Event.forward(this._inputHandler.onA11yChar, this._onA11yCharEmitter)); this._register(Event.forward(this._inputHandler.onA11yChar, this._onA11yCharEmitter));
this.register(Event.forward(this._inputHandler.onA11yTab, this._onA11yTabEmitter)); this._register(Event.forward(this._inputHandler.onA11yTab, this._onA11yTabEmitter));
} }
/** /**
+1 -1
View File
@@ -473,7 +473,7 @@ describe('Headless API Tests', function (): void {
it('dispose', async () => { it('dispose', async () => {
term.dispose(); term.dispose();
strictEqual((term as any)._core._isDisposed, true); strictEqual((term as any)._core._store.isDisposed, true);
}); });
}); });
+4 -4
View File
@@ -10,7 +10,7 @@ import { IBufferNamespace as IBufferNamespaceApi, IMarker, IModes, IParser, ITer
import { Terminal as TerminalCore } from 'headless/Terminal'; import { Terminal as TerminalCore } from 'headless/Terminal';
import { AddonManager } from 'common/public/AddonManager'; import { AddonManager } from 'common/public/AddonManager';
import { ITerminalOptions } from 'common/Types'; import { ITerminalOptions } from 'common/Types';
import { Disposable } from 'common/Lifecycle'; import { Disposable } from 'vs/base/common/lifecycle';
import type { Event } from 'vs/base/common/event'; import type { Event } from 'vs/base/common/event';
/** /**
* The set of options that only have an effect when set in the Terminal constructor. * The set of options that only have an effect when set in the Terminal constructor.
@@ -27,8 +27,8 @@ export class Terminal extends Disposable implements ITerminalApi {
constructor(options?: ITerminalOptions & ITerminalInitOnlyOptions) { constructor(options?: ITerminalOptions & ITerminalInitOnlyOptions) {
super(); super();
this._core = this.register(new TerminalCore(options)); this._core = this._register(new TerminalCore(options));
this._addonManager = this.register(new AddonManager()); this._addonManager = this._register(new AddonManager());
this._publicOptions = { ... this._core.options }; this._publicOptions = { ... this._core.options };
const getter = (propName: string): any => { const getter = (propName: string): any => {
@@ -98,7 +98,7 @@ export class Terminal extends Disposable implements ITerminalApi {
public get buffer(): IBufferNamespaceApi { public get buffer(): IBufferNamespaceApi {
this._checkProposedApi(); this._checkProposedApi();
if (!this._buffer) { if (!this._buffer) {
this._buffer = this.register(new BufferNamespaceApi(this._core)); this._buffer = this._register(new BufferNamespaceApi(this._core));
} }
return this._buffer; return this._buffer;
} }