diff --git a/addons/xterm-addon-canvas/src/CanvasRenderer.ts b/addons/xterm-addon-canvas/src/CanvasRenderer.ts index fd9629c06a..726ad0803a 100644 --- a/addons/xterm-addon-canvas/src/CanvasRenderer.ts +++ b/addons/xterm-addon-canvas/src/CanvasRenderer.ts @@ -14,7 +14,7 @@ import { IColorSet, ILinkifier2 } from 'browser/Types'; import { ICharacterJoinerService, ICharSizeService, ICoreBrowserService } from 'browser/services/Services'; import { IBufferService, IOptionsService, IDecorationService, ICoreService } from 'common/services/Services'; import { removeTerminalFromCache } from './atlas/CharAtlasCache'; -import { EventEmitter, IEvent } from 'common/EventEmitter'; +import { initEvent, EventEmitter, IEvent } from 'common/EventEmitter'; import { observeDevicePixelDimensions } from 'browser/renderer/DevicePixelObserver'; let nextRendererId = 1; @@ -27,8 +27,7 @@ export class CanvasRenderer extends Disposable implements IRenderer { public dimensions: IRenderDimensions; - private readonly _onRequestRedraw = new EventEmitter(); - public readonly onRequestRedraw = this._onRequestRedraw.event; + public readonly onRequestRedraw = initEvent(); constructor( private _colors: IColorSet, @@ -48,7 +47,7 @@ export class CanvasRenderer extends Disposable implements IRenderer { new TextRenderLayer(this._screenElement, 0, this._colors, allowTransparency, this._id, this._bufferService, this._optionsService, characterJoinerService, decorationService, this._coreBrowserService), new SelectionRenderLayer(this._screenElement, 1, this._colors, this._id, this._bufferService, this._coreBrowserService, decorationService, this._optionsService), new LinkRenderLayer(this._screenElement, 2, this._colors, this._id, linkifier2, this._bufferService, this._optionsService, decorationService, this._coreBrowserService), - new CursorRenderLayer(this._screenElement, 3, this._colors, this._id, this._onRequestRedraw, this._bufferService, this._optionsService, coreService, this._coreBrowserService, decorationService) + new CursorRenderLayer(this._screenElement, 3, this._colors, this._id, this.onRequestRedraw, this._bufferService, this._optionsService, coreService, this._coreBrowserService, decorationService) ]; this.dimensions = { scaledCharWidth: 0, @@ -128,7 +127,7 @@ export class CanvasRenderer extends Disposable implements IRenderer { this._runOperation(l => l.onSelectionChanged(start, end, columnSelectMode)); // Selection foreground requires a full re-render if (this._colors.selectionForeground) { - this._onRequestRedraw.fire({ start: 0, end: this._bufferService.rows - 1 }); + this.onRequestRedraw.fire({ start: 0, end: this._bufferService.rows - 1 }); } } @@ -201,6 +200,6 @@ export class CanvasRenderer extends Disposable implements IRenderer { } private _requestRedrawViewport(): void { - this._onRequestRedraw.fire({ start: 0, end: this._bufferService.rows - 1 }); + this.onRequestRedraw.fire({ start: 0, end: this._bufferService.rows - 1 }); } } diff --git a/addons/xterm-addon-search/src/SearchAddon.ts b/addons/xterm-addon-search/src/SearchAddon.ts index 689899ef19..d14e1fe769 100644 --- a/addons/xterm-addon-search/src/SearchAddon.ts +++ b/addons/xterm-addon-search/src/SearchAddon.ts @@ -4,7 +4,7 @@ */ import { Terminal, IDisposable, ITerminalAddon, IBufferRange, IDecoration } from 'xterm'; -import { EventEmitter } from 'common/EventEmitter'; +import { initEvent } from 'common/EventEmitter'; export interface ISearchOptions { regex?: boolean; @@ -72,8 +72,7 @@ export class SearchAddon implements ITerminalAddon { private _resultIndex: number | undefined; - private readonly _onDidChangeResults = new EventEmitter<{ resultIndex: number, resultCount: number } | undefined>(); - public readonly onDidChangeResults = this._onDidChangeResults.event; + public readonly onDidChangeResults = initEvent<{ resultIndex: number, resultCount: number } | undefined>(); public activate(terminal: Terminal): void { this._terminal = terminal; @@ -89,7 +88,7 @@ export class SearchAddon implements ITerminalAddon { this._highlightTimeout = setTimeout(() => { this.findPrevious(this._cachedSearchTerm!, { ...this._lastSearchOptions, incremental: true, noScroll: true }); this._resultIndex = this._searchResults ? this._searchResults.size - 1 : -1; - this._onDidChangeResults.fire({ resultIndex: this._resultIndex, resultCount: this._searchResults?.size ?? -1 }); + this.onDidChangeResults.fire({ resultIndex: this._resultIndex, resultCount: this._searchResults?.size ?? -1 }); }, 200); } } @@ -325,9 +324,9 @@ export class SearchAddon implements ITerminalAddon { private _fireResults(term: string, found: boolean, searchOptions?: ISearchOptions): boolean { if (searchOptions?.decorations) { if (this._resultIndex !== undefined && this._searchResults?.size !== undefined) { - this._onDidChangeResults.fire({ resultIndex: this._resultIndex, resultCount: this._searchResults.size }); + this.onDidChangeResults.fire({ resultIndex: this._resultIndex, resultCount: this._searchResults.size }); } else { - this._onDidChangeResults.fire(undefined); + this.onDidChangeResults.fire(undefined); } } this._cachedSearchTerm = term; diff --git a/addons/xterm-addon-webgl/src/WebglAddon.ts b/addons/xterm-addon-webgl/src/WebglAddon.ts index 45858e8c88..b26c565c36 100644 --- a/addons/xterm-addon-webgl/src/WebglAddon.ts +++ b/addons/xterm-addon-webgl/src/WebglAddon.ts @@ -7,7 +7,7 @@ import { Terminal, ITerminalAddon, IEvent } from 'xterm'; import { WebglRenderer } from './WebglRenderer'; import { ICharacterJoinerService, ICoreBrowserService, IRenderService } from 'browser/services/Services'; import { IColorSet } from 'browser/Types'; -import { EventEmitter, forwardEvent } from 'common/EventEmitter'; +import { EventEmitter, forwardEvent, initEvent } from 'common/EventEmitter'; import { isSafari } from 'common/Platform'; import { ICoreService, IDecorationService } from 'common/services/Services'; @@ -15,14 +15,12 @@ export class WebglAddon implements ITerminalAddon { private _terminal?: Terminal; private _renderer?: WebglRenderer; - private readonly _onChangeTextureAtlas = new EventEmitter(); - public readonly onChangeTextureAtlas = this._onChangeTextureAtlas.event; - private readonly _onContextLoss = new EventEmitter(); - public readonly onContextLoss = this._onContextLoss.event; + public readonly onChangeTextureAtlas = initEvent(); + public readonly onContextLoss = initEvent(); constructor( private _preserveDrawingBuffer?: boolean - ) {} + ) { } public activate(terminal: Terminal): void { if (!terminal.element) { @@ -39,8 +37,8 @@ export class WebglAddon implements ITerminalAddon { const decorationService: IDecorationService = (terminal as any)._core._decorationService; const colors: IColorSet = (terminal as any)._core._colorManager.colors; this._renderer = new WebglRenderer(terminal, colors, characterJoinerService, coreBrowserService, coreService, decorationService, this._preserveDrawingBuffer); - forwardEvent(this._renderer.onContextLoss, this._onContextLoss); - forwardEvent(this._renderer.onChangeTextureAtlas, this._onChangeTextureAtlas); + forwardEvent(this._renderer.onContextLoss, this.onContextLoss); + forwardEvent(this._renderer.onChangeTextureAtlas, this.onChangeTextureAtlas); renderService.setRenderer(this._renderer); } diff --git a/addons/xterm-addon-webgl/src/WebglRenderer.ts b/addons/xterm-addon-webgl/src/WebglRenderer.ts index 58fbb6ed30..8d8b24f71f 100644 --- a/addons/xterm-addon-webgl/src/WebglRenderer.ts +++ b/addons/xterm-addon-webgl/src/WebglRenderer.ts @@ -18,7 +18,7 @@ import { IRenderLayer } from './renderLayer/Types'; import { IRenderDimensions, IRenderer, IRequestRedrawEvent } from 'browser/renderer/Types'; import { observeDevicePixelDimensions } from 'browser/renderer/DevicePixelObserver'; import { ITerminal, IColorSet } from 'browser/Types'; -import { EventEmitter } from 'common/EventEmitter'; +import { EventEmitter, initEvent } from 'common/EventEmitter'; import { CellData } from 'common/buffer/CellData'; import { addDisposableDomListener } from 'browser/Lifecycle'; import { ICharacterJoinerService, ICoreBrowserService } from 'browser/services/Services'; @@ -53,12 +53,9 @@ export class WebglRenderer extends Disposable implements IRenderer { private _isAttached: boolean; private _contextRestorationTimeout: number | undefined; - private readonly _onChangeTextureAtlas = new EventEmitter(); - public readonly onChangeTextureAtlas = this._onChangeTextureAtlas.event; - private readonly _onRequestRedraw = new EventEmitter(); - public readonly onRequestRedraw = this._onRequestRedraw.event; - private readonly _onContextLoss = new EventEmitter(); - public readonly onContextLoss = this._onContextLoss.event; + public readonly onChangeTextureAtlas = initEvent(); + public readonly onRequestRedraw = initEvent(); + public readonly onContextLoss = initEvent(); constructor( private _terminal: Terminal, @@ -75,7 +72,7 @@ export class WebglRenderer extends Disposable implements IRenderer { this._renderLayers = [ new LinkRenderLayer(this._core.screenElement!, 2, this._colors, this._core, this._coreBrowserService), - new CursorRenderLayer(_terminal, this._core.screenElement!, 3, this._colors, this._onRequestRedraw, this._coreBrowserService, coreService) + new CursorRenderLayer(_terminal, this._core.screenElement!, 3, this._colors, this.onRequestRedraw, this._coreBrowserService, coreService) ]; this.dimensions = { scaledCharWidth: 0, @@ -115,7 +112,7 @@ export class WebglRenderer extends Disposable implements IRenderer { this._contextRestorationTimeout = setTimeout(() => { this._contextRestorationTimeout = undefined; console.warn('webgl context not restored; firing onContextLoss'); - this._onContextLoss.fire(e); + this.onContextLoss.fire(e); }, 3000 /* ms */); })); this.register(addDisposableDomListener(this._canvas, 'webglcontextrestored', (e) => { @@ -283,7 +280,7 @@ export class WebglRenderer extends Disposable implements IRenderer { throw new Error('The webgl renderer only works with the webgl char atlas'); } if (this._charAtlas !== atlas) { - this._onChangeTextureAtlas.fire(atlas.cacheCanvas); + this.onChangeTextureAtlas.fire(atlas.cacheCanvas); } this._charAtlas = atlas; this._charAtlas.warmUp(); @@ -422,9 +419,9 @@ export class WebglRenderer extends Disposable implements IRenderer { // Nothing has changed, no updates needed if (this._model.cells[i] === code && - this._model.cells[i + RENDER_MODEL_BG_OFFSET] === this._workColors.bg && - this._model.cells[i + RENDER_MODEL_FG_OFFSET] === this._workColors.fg && - this._model.cells[i + RENDER_MODEL_EXT_OFFSET] === this._workColors.ext) { + this._model.cells[i + RENDER_MODEL_BG_OFFSET] === this._workColors.bg && + this._model.cells[i + RENDER_MODEL_FG_OFFSET] === this._workColors.fg && + this._model.cells[i + RENDER_MODEL_EXT_OFFSET] === this._workColors.ext) { continue; } @@ -676,7 +673,7 @@ export class WebglRenderer extends Disposable implements IRenderer { } private _requestRedrawViewport(): void { - this._onRequestRedraw.fire({ start: 0, end: this._terminal.rows - 1 }); + this.onRequestRedraw.fire({ start: 0, end: this._terminal.rows - 1 }); } } diff --git a/src/browser/Linkifier2.ts b/src/browser/Linkifier2.ts index cf5b9dd2e1..844b64f82c 100644 --- a/src/browser/Linkifier2.ts +++ b/src/browser/Linkifier2.ts @@ -7,7 +7,7 @@ import { ILinkifier2, ILinkProvider, IBufferCellPosition, ILink, ILinkifierEvent import { IDisposable } from 'common/Types'; import { IMouseService, IRenderService } from './services/Services'; import { IBufferService } from 'common/services/Services'; -import { EventEmitter, IEvent } from 'common/EventEmitter'; +import { EventEmitter, IEvent, initEvent } from 'common/EventEmitter'; import { Disposable, getDisposeArrayDisposable, disposeArray } from 'common/Lifecycle'; import { addDisposableDomListener } from 'browser/Lifecycle'; @@ -26,10 +26,8 @@ export class Linkifier2 extends Disposable implements ILinkifier2 { private _activeProviderReplies: Map | undefined; private _activeLine: number = -1; - private readonly _onShowLinkUnderline = this.register(new EventEmitter()); - public readonly onShowLinkUnderline = this._onShowLinkUnderline.event; - private readonly _onHideLinkUnderline = this.register(new EventEmitter()); - public readonly onHideLinkUnderline = this._onHideLinkUnderline.event; + public readonly onShowLinkUnderline = this.register(initEvent()); + public readonly onHideLinkUnderline = this.register(initEvent()); constructor( @IBufferService private readonly _bufferService: IBufferService @@ -343,7 +341,7 @@ export class Linkifier2 extends Disposable implements ILinkifier2 { const range = link.range; const scrollOffset = this._bufferService.buffer.ydisp; const event = this._createLinkUnderlineEvent(range.start.x - 1, range.start.y - scrollOffset - 1, range.end.x, range.end.y - scrollOffset - 1, undefined); - const emitter = showEvent ? this._onShowLinkUnderline : this._onHideLinkUnderline; + const emitter = showEvent ? this.onShowLinkUnderline : this.onHideLinkUnderline; emitter.fire(event); } diff --git a/src/browser/Terminal.ts b/src/browser/Terminal.ts index 9c10fc16ef..90c1b13454 100644 --- a/src/browser/Terminal.ts +++ b/src/browser/Terminal.ts @@ -37,7 +37,7 @@ import { ITheme, IMarker, IDisposable, ILinkProvider, IDecorationOptions, IDecor import { DomRenderer } from 'browser/renderer/dom/DomRenderer'; import { KeyboardResultType, CoreMouseEventType, CoreMouseButton, CoreMouseAction, ITerminalOptions, ScrollSource, IColorEvent, ColorIndex, ColorRequestType } from 'common/Types'; import { evaluateKeyboardEvent } from 'common/input/Keyboard'; -import { EventEmitter, IEvent, forwardEvent } from 'common/EventEmitter'; +import { EventEmitter, IEvent, forwardEvent, initEvent } from 'common/EventEmitter'; import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine'; import { ColorManager } from 'browser/ColorManager'; import { RenderService } from 'browser/services/RenderService'; @@ -122,27 +122,16 @@ export class Terminal extends CoreTerminal implements ITerminal { private _colorManager: ColorManager | undefined; private _theme: ITheme | undefined; - private readonly _onCursorMove = new EventEmitter(); - public readonly onCursorMove = this._onCursorMove.event; - private readonly _onKey = new EventEmitter<{ key: string, domEvent: KeyboardEvent }>(); - public readonly onKey = this._onKey.event; - private readonly _onRender = new EventEmitter<{ start: number, end: number }>(); - public readonly onRender = this._onRender.event; - private readonly _onSelectionChange = new EventEmitter(); - public readonly onSelectionChange = this._onSelectionChange.event; - private readonly _onTitleChange = new EventEmitter(); - public readonly onTitleChange = this._onTitleChange.event; - private readonly _onBell = new EventEmitter(); - public readonly onBell = this._onBell.event; - - private readonly _onFocus = new EventEmitter(); - public readonly onFocus = this._onFocus.event; - private readonly _onBlur = new EventEmitter(); - public readonly onBlur = this._onBlur.event; - private readonly _onA11yCharEmitter = new EventEmitter(); - public readonly onA11yChar = this._onA11yCharEmitter.event; - private readonly _onA11yTabEmitter = new EventEmitter(); - public readonly onA11yTab = this._onA11yTabEmitter.event; + public readonly onCursorMove = initEvent(); + public readonly onKey = initEvent<{ key: string, domEvent: KeyboardEvent }>(); + public readonly onRender = initEvent<{ start: number, end: number }>(); + public readonly onSelectionChange = initEvent(); + public readonly onTitleChange = initEvent(); + public readonly onBell = initEvent(); + public readonly onFocus = initEvent(); + public readonly onBlur = initEvent(); + public readonly onA11yChar = initEvent(); + public readonly onA11yTab = initEvent(); /** * Creates a new `Terminal` object. @@ -169,16 +158,16 @@ export class Terminal extends CoreTerminal implements ITerminal { this._instantiationService.setService(IDecorationService, this._decorationService); // Setup InputHandler listeners - this.register(this._inputHandler.onRequestBell(() => this._onBell.fire())); + this.register(this._inputHandler.onRequestBell(() => this.onBell.fire())); this.register(this._inputHandler.onRequestRefreshRows((start, end) => this.refresh(start, end))); this.register(this._inputHandler.onRequestSendFocus(() => this._reportFocus())); this.register(this._inputHandler.onRequestReset(() => this.reset())); this.register(this._inputHandler.onRequestWindowsOptionsReport(type => this._reportWindowsOptions(type))); this.register(this._inputHandler.onColor((event) => this._handleColorEvent(event))); - this.register(forwardEvent(this._inputHandler.onCursorMove, this._onCursorMove)); - this.register(forwardEvent(this._inputHandler.onTitleChange, this._onTitleChange)); - this.register(forwardEvent(this._inputHandler.onA11yChar, this._onA11yCharEmitter)); - this.register(forwardEvent(this._inputHandler.onA11yTab, this._onA11yTabEmitter)); + this.register(forwardEvent(this._inputHandler.onCursorMove, this.onCursorMove)); + this.register(forwardEvent(this._inputHandler.onTitleChange, this.onTitleChange)); + this.register(forwardEvent(this._inputHandler.onA11yChar, this.onA11yChar)); + this.register(forwardEvent(this._inputHandler.onA11yTab, this.onA11yTab)); // Setup listeners this.register(this._bufferService.onResize(e => this._afterResize(e.cols, e.rows))); @@ -326,7 +315,7 @@ export class Terminal extends CoreTerminal implements ITerminal { this.updateCursorStyle(ev); this.element!.classList.add('focus'); this._showCursor(); - this._onFocus.fire(); + this.onFocus.fire(); } /** @@ -349,7 +338,7 @@ export class Terminal extends CoreTerminal implements ITerminal { this.coreService.triggerDataEvent(C0.ESC + '[O'); } this.element!.classList.remove('focus'); - this._onBlur.fire(); + this.onBlur.fire(); } private _syncTextArea(): void { @@ -512,7 +501,7 @@ export class Terminal extends CoreTerminal implements ITerminal { const renderer = this._createRenderer(); this._renderService = this.register(this._instantiationService.createInstance(RenderService, renderer, this.rows, this.screenElement)); 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._compositionView = document.createElement('div'); @@ -552,7 +541,7 @@ export class Terminal extends CoreTerminal implements ITerminal { )); this._instantiationService.setService(ISelectionService, this._selectionService); 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!.onSelectionChanged(e.start, e.end, e.columnSelectMode))); this.register(this._selectionService.onLinuxMouseSelection(text => { // If there's a new selection, put it into the textarea, focus and select it @@ -1101,7 +1090,7 @@ export class Terminal extends CoreTerminal implements ITerminal { this.textarea!.value = ''; } - this._onKey.fire({ key: result.key, domEvent: event }); + this.onKey.fire({ key: result.key, domEvent: event }); this._showCursor(); this.coreService.triggerDataEvent(result.key, true); @@ -1184,7 +1173,7 @@ export class Terminal extends CoreTerminal implements ITerminal { key = String.fromCharCode(key); - this._onKey.fire({ key, domEvent: ev }); + this.onKey.fire({ key, domEvent: ev }); this._showCursor(); this.coreService.triggerDataEvent(key, true); diff --git a/src/browser/TestUtils.test.ts b/src/browser/TestUtils.test.ts index 0b5e00c173..959203756f 100644 --- a/src/browser/TestUtils.test.ts +++ b/src/browser/TestUtils.test.ts @@ -4,7 +4,7 @@ */ import { IDisposable, IMarker, ILinkProvider, IDecorationOptions, IDecoration } from 'xterm'; -import { IEvent, EventEmitter } from 'common/EventEmitter'; +import { IEvent, EventEmitter, initEvent } from 'common/EventEmitter'; import { ICharacterJoinerService, ICharSizeService, ICoreBrowserService, IMouseService, IRenderService, ISelectionService } from 'browser/services/Services'; import { IRenderDimensions, IRenderer, IRequestRedrawEvent } from 'browser/renderer/Types'; import { IColorSet, ITerminal, ILinkifier2, IBrowser, IViewport, IColorManager, ICompositionHelper, CharacterJoinerHandler, IBufferRange } from 'browser/Types'; @@ -352,7 +352,7 @@ export class MockCoreBrowserService implements ICoreBrowserService { export class MockCharSizeService implements ICharSizeService { public serviceBrand: undefined; public get hasValidSize(): boolean { return this.width > 0 && this.height > 0; } - public onCharSizeChange: IEvent = new EventEmitter().event; + public onCharSizeChange: IEvent = initEvent(); constructor(public width: number, public height: number) {} public measure(): void {} } @@ -370,10 +370,10 @@ export class MockMouseService implements IMouseService { export class MockRenderService implements IRenderService { public serviceBrand: undefined; - public onDimensionsChange: IEvent = new EventEmitter().event; - public onRenderedViewportChange: IEvent<{ start: number, end: number }, void> = new EventEmitter<{ start: number, end: number }>().event; - public onRender: IEvent<{ start: number, end: number }, void> = new EventEmitter<{ start: number, end: number }>().event; - public onRefreshRequest: IEvent<{ start: number, end: number}, void> = new EventEmitter<{ start: number, end: number }>().event; + public onDimensionsChange: IEvent = initEvent(); + public onRenderedViewportChange: IEvent<{ start: number, end: number }, void> = initEvent<{ start: number, end: number }>(); + public onRender: IEvent<{ start: number, end: number }, void> = initEvent<{ start: number, end: number }>(); + public onRefreshRequest: IEvent<{ start: number, end: number}, void> = initEvent<{ start: number, end: number }>(); public dimensions: IRenderDimensions = { scaledCharWidth: 0, scaledCharHeight: 0, @@ -457,10 +457,10 @@ export class MockSelectionService implements ISelectionService { public hasSelection: boolean = false; public selectionStart: [number, number] | undefined; public selectionEnd: [number, number] | undefined; - public onLinuxMouseSelection = new EventEmitter().event; - public onRequestRedraw = new EventEmitter().event; - public onRequestScrollLines = new EventEmitter().event; - public onSelectionChange = new EventEmitter().event; + public onLinuxMouseSelection = initEvent(); + public onRequestRedraw = initEvent(); + public onRequestScrollLines = initEvent(); + public onSelectionChange = initEvent(); public disable(): void { throw new Error('Method not implemented.'); } diff --git a/src/browser/decorations/BufferDecorationRenderer.ts b/src/browser/decorations/BufferDecorationRenderer.ts index 7fcc5ea954..23ba174f89 100644 --- a/src/browser/decorations/BufferDecorationRenderer.ts +++ b/src/browser/decorations/BufferDecorationRenderer.ts @@ -95,7 +95,7 @@ export class BufferDecorationRenderer extends Disposable { // outside of viewport if (decoration.element) { decoration.element.style.display = 'none'; - decoration.onRenderEmitter.fire(decoration.element); + decoration.onRender.fire(decoration.element); } } else { let element = this._decorationElements.get(decoration); @@ -108,7 +108,7 @@ export class BufferDecorationRenderer extends Disposable { } element.style.top = `${line * this._renderService.dimensions.actualCellHeight}px`; element.style.display = this._altBufferIsActive ? 'none' : 'block'; - decoration.onRenderEmitter.fire(element); + decoration.onRender.fire(element); } } diff --git a/src/browser/renderer/dom/DomRenderer.ts b/src/browser/renderer/dom/DomRenderer.ts index 223e24705e..39de7b2cfe 100644 --- a/src/browser/renderer/dom/DomRenderer.ts +++ b/src/browser/renderer/dom/DomRenderer.ts @@ -10,7 +10,7 @@ import { Disposable } from 'common/Lifecycle'; import { IColorSet, ILinkifierEvent, ILinkifier2 } from 'browser/Types'; import { ICharSizeService, ICoreBrowserService } from 'browser/services/Services'; import { IOptionsService, IBufferService, IInstantiationService } from 'common/services/Services'; -import { EventEmitter, IEvent } from 'common/EventEmitter'; +import { EventEmitter, IEvent, initEvent } from 'common/EventEmitter'; import { color } from 'common/Color'; import { removeElementFromParent } from 'browser/Dom'; @@ -40,7 +40,7 @@ export class DomRenderer extends Disposable implements IRenderer { public dimensions: IRenderDimensions; - public readonly onRequestRedraw = new EventEmitter().event; + public readonly onRequestRedraw = initEvent(); constructor( private _colors: IColorSet, diff --git a/src/browser/services/CharSizeService.ts b/src/browser/services/CharSizeService.ts index 7062deecef..583006d614 100644 --- a/src/browser/services/CharSizeService.ts +++ b/src/browser/services/CharSizeService.ts @@ -4,7 +4,7 @@ */ import { IOptionsService } from 'common/services/Services'; -import { IEvent, EventEmitter } from 'common/EventEmitter'; +import { IEvent, EventEmitter, initEvent } from 'common/EventEmitter'; import { ICharSizeService } from 'browser/services/Services'; export class CharSizeService implements ICharSizeService { @@ -16,8 +16,7 @@ export class CharSizeService implements ICharSizeService { public get hasValidSize(): boolean { return this.width > 0 && this.height > 0; } - private readonly _onCharSizeChange = new EventEmitter(); - public readonly onCharSizeChange = this._onCharSizeChange.event; + public readonly onCharSizeChange = initEvent(); constructor( document: Document, @@ -32,7 +31,7 @@ export class CharSizeService implements ICharSizeService { if (result.width !== this.width || result.height !== this.height) { this.width = result.width; this.height = result.height; - this._onCharSizeChange.fire(); + this.onCharSizeChange.fire(); } } } diff --git a/src/browser/services/RenderService.ts b/src/browser/services/RenderService.ts index 66dbb7aa28..dfb4df80b7 100644 --- a/src/browser/services/RenderService.ts +++ b/src/browser/services/RenderService.ts @@ -5,7 +5,7 @@ import { IRenderer, IRenderDimensions } from 'browser/renderer/Types'; import { RenderDebouncer } from 'browser/RenderDebouncer'; -import { EventEmitter, IEvent } from 'common/EventEmitter'; +import { EventEmitter, IEvent, initEvent } from 'common/EventEmitter'; import { Disposable } from 'common/Lifecycle'; import { ScreenDprMonitor } from 'browser/ScreenDprMonitor'; import { addDisposableDomListener } from 'browser/Lifecycle'; @@ -39,14 +39,10 @@ export class RenderService extends Disposable implements IRenderService { columnSelectMode: false }; - private readonly _onDimensionsChange = new EventEmitter(); - public readonly onDimensionsChange = this._onDimensionsChange.event; - private readonly _onRenderedViewportChange = new EventEmitter<{ start: number, end: number }>(); - public readonly onRenderedViewportChange = this._onRenderedViewportChange.event; - private readonly _onRender = new EventEmitter<{ start: number, end: number }>(); - public readonly onRender = this._onRender.event; - private readonly _onRefreshRequest = new EventEmitter<{ start: number, end: number }>(); - public readonly onRefreshRequest = this._onRefreshRequest.event; + public readonly onDimensionsChange = initEvent(); + public readonly onRenderedViewportChange = initEvent<{ start: number, end: number }>(); + public readonly onRender = initEvent<{ start: number, end: number }>(); + public readonly onRefreshRequest = initEvent<{ start: number, end: number }>(); public get dimensions(): IRenderDimensions { return this._renderer.dimensions; } @@ -135,9 +131,9 @@ export class RenderService extends Disposable implements IRenderService { // Fire render event only if it was not a redraw if (!this._isNextRenderRedrawOnly) { - this._onRenderedViewportChange.fire({ start, end }); + this.onRenderedViewportChange.fire({ start, end }); } - this._onRender.fire({ start, end }); + this.onRender.fire({ start, end }); this._isNextRenderRedrawOnly = true; } @@ -157,7 +153,7 @@ export class RenderService extends Disposable implements IRenderService { if (this._renderer.dimensions.canvasWidth === this._canvasWidth && this._renderer.dimensions.canvasHeight === this._canvasHeight) { return; } - this._onDimensionsChange.fire(this._renderer.dimensions); + this.onDimensionsChange.fire(this._renderer.dimensions); } public dispose(): void { diff --git a/src/browser/services/SelectionService.ts b/src/browser/services/SelectionService.ts index 3780c7ee8f..5da197b13a 100644 --- a/src/browser/services/SelectionService.ts +++ b/src/browser/services/SelectionService.ts @@ -9,7 +9,7 @@ import { IBufferLine, IDisposable } from 'common/Types'; import * as Browser from 'common/Platform'; import { SelectionModel } from 'browser/selection/SelectionModel'; import { CellData } from 'common/buffer/CellData'; -import { EventEmitter, IEvent } from 'common/EventEmitter'; +import { EventEmitter, IEvent, initEvent } from 'common/EventEmitter'; import { IMouseService, ISelectionService, IRenderService, ICoreBrowserService } from 'browser/services/Services'; import { IBufferRange, ILinkifier2 } from 'browser/Types'; import { IBufferService, IOptionsService, ICoreService } from 'common/services/Services'; @@ -111,14 +111,10 @@ export class SelectionService extends Disposable implements ISelectionService { private _oldSelectionStart: [number, number] | undefined = undefined; private _oldSelectionEnd: [number, number] | undefined = undefined; - private readonly _onLinuxMouseSelection = this.register(new EventEmitter()); - public readonly onLinuxMouseSelection = this._onLinuxMouseSelection.event; - private readonly _onRedrawRequest = this.register(new EventEmitter()); - public readonly onRequestRedraw = this._onRedrawRequest.event; - private readonly _onSelectionChange = this.register(new EventEmitter()); - public readonly onSelectionChange = this._onSelectionChange.event; - private readonly _onRequestScrollLines = this.register(new EventEmitter()); - public readonly onRequestScrollLines = this._onRequestScrollLines.event; + public readonly onLinuxMouseSelection = this.register(initEvent()); + public readonly onRequestRedraw = this.register(initEvent()); + public readonly onSelectionChange = this.register(initEvent()); + public readonly onRequestScrollLines = this.register(initEvent()); constructor( private readonly _element: HTMLElement, @@ -260,7 +256,7 @@ export class SelectionService extends Disposable implements ISelectionService { this._model.clearSelection(); this._removeMouseDownListeners(); this.refresh(); - this._onSelectionChange.fire(); + this.onSelectionChange.fire(); } /** @@ -279,7 +275,7 @@ export class SelectionService extends Disposable implements ISelectionService { if (Browser.isLinux && isLinuxMouseSelection) { const selectionText = this.selectionText; if (selectionText.length) { - this._onLinuxMouseSelection.fire(this.selectionText); + this.onLinuxMouseSelection.fire(this.selectionText); } } } @@ -290,7 +286,7 @@ export class SelectionService extends Disposable implements ISelectionService { */ private _refresh(): void { this._refreshAnimationFrame = undefined; - this._onRedrawRequest.fire({ + this.onRequestRedraw.fire({ start: this._model.finalSelectionStart, end: this._model.finalSelectionEnd, columnSelectMode: this._activeSelectionMode === SelectionMode.COLUMN @@ -358,7 +354,7 @@ export class SelectionService extends Disposable implements ISelectionService { public selectAll(): void { this._model.isSelectAllActive = true; this.refresh(); - this._onSelectionChange.fire(); + this.onSelectionChange.fire(); } public selectLines(start: number, end: number): void { @@ -368,7 +364,7 @@ export class SelectionService extends Disposable implements ISelectionService { this._model.selectionStart = [0, start]; this._model.selectionEnd = [this._bufferService.cols, end]; this.refresh(); - this._onSelectionChange.fire(); + this.onSelectionChange.fire(); } /** @@ -665,7 +661,7 @@ export class SelectionService extends Disposable implements ISelectionService { return; } if (this._dragScrollAmount) { - this._onRequestScrollLines.fire({ amount: this._dragScrollAmount, suppressScrollEvent: false }); + this.onRequestScrollLines.fire({ amount: this._dragScrollAmount, suppressScrollEvent: false }); // Re-evaluate selection // If the cursor was above or below the viewport, make sure it's at the // start or end of the viewport respectively. This should only happen when @@ -743,7 +739,7 @@ export class SelectionService extends Disposable implements ISelectionService { this._oldSelectionStart = start; this._oldSelectionEnd = end; this._oldHasSelection = hasSelection; - this._onSelectionChange.fire(); + this.onSelectionChange.fire(); } private _onBufferActivate(e: {activeBuffer: IBuffer, inactiveBuffer: IBuffer}): void { diff --git a/src/common/CircularList.ts b/src/common/CircularList.ts index 599db1aba8..5374344947 100644 --- a/src/common/CircularList.ts +++ b/src/common/CircularList.ts @@ -4,7 +4,7 @@ */ import { ICircularList } from 'common/Types'; -import { EventEmitter, IEvent } from 'common/EventEmitter'; +import { initEvent } from 'common/EventEmitter'; export interface IInsertEvent { index: number; @@ -25,12 +25,9 @@ export class CircularList implements ICircularList { private _startIndex: number; private _length: number; - public readonly onDeleteEmitter = new EventEmitter(); - public readonly onDelete = this.onDeleteEmitter.event; - public readonly onInsertEmitter = new EventEmitter(); - public readonly onInsert = this.onInsertEmitter.event; - public readonly onTrimEmitter = new EventEmitter(); - public readonly onTrim = this.onTrimEmitter.event; + public readonly onDelete = initEvent(); + public readonly onInsert = initEvent(); + public readonly onTrim = initEvent(); constructor( private _maxLength: number @@ -107,7 +104,7 @@ export class CircularList implements ICircularList { this._array[this._getCyclicIndex(this._length)] = value; if (this._length === this._maxLength) { this._startIndex = ++this._startIndex % this._maxLength; - this.onTrimEmitter.fire(1); + this.onTrim.fire(1); } else { this._length++; } @@ -123,7 +120,7 @@ export class CircularList implements ICircularList { throw new Error('Can only recycle when the buffer is full'); } this._startIndex = ++this._startIndex % this._maxLength; - this.onTrimEmitter.fire(1); + this.onTrim.fire(1); return this._array[this._getCyclicIndex(this._length - 1)]!; } @@ -158,7 +155,7 @@ export class CircularList implements ICircularList { this._array[this._getCyclicIndex(i)] = this._array[this._getCyclicIndex(i + deleteCount)]; } this._length -= deleteCount; - this.onDeleteEmitter.fire({ index: start, amount: deleteCount }); + this.onDelete.fire({ index: start, amount: deleteCount }); } // Add items @@ -169,7 +166,7 @@ export class CircularList implements ICircularList { this._array[this._getCyclicIndex(start + i)] = items[i]; } if (items.length) { - this.onInsertEmitter.fire({ index: start, amount: items.length }); + this.onInsert.fire({ index: start, amount: items.length }); } // Adjust length as needed @@ -177,7 +174,7 @@ export class CircularList implements ICircularList { const countToTrim = (this._length + items.length) - this._maxLength; this._startIndex += countToTrim; this._length = this._maxLength; - this.onTrimEmitter.fire(countToTrim); + this.onTrim.fire(countToTrim); } else { this._length += items.length; } @@ -193,7 +190,7 @@ export class CircularList implements ICircularList { } this._startIndex += count; this._length -= count; - this.onTrimEmitter.fire(count); + this.onTrim.fire(count); } public shiftElements(start: number, count: number, offset: number): void { @@ -217,7 +214,7 @@ export class CircularList implements ICircularList { while (this._length > this._maxLength) { this._length--; this._startIndex++; - this.onTrimEmitter.fire(1); + this.onTrim.fire(1); } } } else { diff --git a/src/common/CoreTerminal.ts b/src/common/CoreTerminal.ts index 2ad6f73515..dd6953bbe0 100644 --- a/src/common/CoreTerminal.ts +++ b/src/common/CoreTerminal.ts @@ -29,7 +29,7 @@ import { BufferService, MINIMUM_COLS, MINIMUM_ROWS } from 'common/services/Buffe import { OptionsService } from 'common/services/OptionsService'; import { IDisposable, IAttributeData, ICoreTerminal, IScrollEvent, ScrollSource } from 'common/Types'; import { CoreService } from 'common/services/CoreService'; -import { EventEmitter, IEvent, forwardEvent } from 'common/EventEmitter'; +import { EventEmitter, IEvent, forwardEvent, initEvent } from 'common/EventEmitter'; import { CoreMouseService } from 'common/services/CoreMouseService'; import { UnicodeService } from 'common/services/UnicodeService'; import { CharsetService } from 'common/services/CharsetService'; @@ -59,16 +59,11 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal { private _writeBuffer: WriteBuffer; private _windowsMode: IDisposable | undefined; - private readonly _onBinary = new EventEmitter(); - public readonly onBinary = this._onBinary.event; - private readonly _onData = new EventEmitter(); - public readonly onData = this._onData.event; - protected _onLineFeed = new EventEmitter(); - public readonly onLineFeed = this._onLineFeed.event; - private readonly _onResize = new EventEmitter<{ cols: number, rows: number }>(); - public readonly onResize = this._onResize.event; - protected readonly _onWriteParsed = new EventEmitter(); - public readonly onWriteParsed = this._onWriteParsed.event; + public readonly onBinary = initEvent(); + public readonly onData = initEvent(); + public readonly onLineFeed = initEvent(); + public readonly onResize = initEvent<{ cols: number, rows: number }>(); + public readonly onWriteParsed = initEvent(); /** * Internally we track the source of the scroll but this is meaningless outside the library so @@ -122,13 +117,13 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal { // Register input handler and handle/forward events this._inputHandler = new InputHandler(this._bufferService, this._charsetService, this.coreService, this._logService, this.optionsService, this._oscLinkService, this.coreMouseService, this.unicodeService); - this.register(forwardEvent(this._inputHandler.onLineFeed, this._onLineFeed)); + this.register(forwardEvent(this._inputHandler.onLineFeed, this.onLineFeed)); this.register(this._inputHandler); // Setup listeners - this.register(forwardEvent(this._bufferService.onResize, this._onResize)); - this.register(forwardEvent(this.coreService.onData, this._onData)); - this.register(forwardEvent(this.coreService.onBinary, this._onBinary)); + this.register(forwardEvent(this._bufferService.onResize, this.onResize)); + this.register(forwardEvent(this.coreService.onData, this.onData)); + this.register(forwardEvent(this.coreService.onBinary, this.onBinary)); this.register(this.coreService.onUserInput(() => this._writeBuffer.handleUserInput())); this.register(this.optionsService.onOptionChange(key => this._updateOptions(key))); this.register(this._bufferService.onScroll(event => { @@ -142,7 +137,7 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal { // Setup WriteBuffer this._writeBuffer = new WriteBuffer((data, promiseResult) => this._inputHandler.parse(data, promiseResult)); - this.register(forwardEvent(this._writeBuffer.onWriteParsed, this._onWriteParsed)); + this.register(forwardEvent(this._writeBuffer.onWriteParsed, this.onWriteParsed)); } public dispose(): void { diff --git a/src/common/EventEmitter.ts b/src/common/EventEmitter.ts index 4684809f33..29e931d221 100644 --- a/src/common/EventEmitter.ts +++ b/src/common/EventEmitter.ts @@ -14,13 +14,15 @@ export interface IEvent { } export interface IEventEmitter { - event: IEvent; fire(arg1: T, arg2: U): void; dispose(): void; } +export interface IEventWithEmitter extends IEventEmitter, IEvent { +} + export class EventEmitter implements IEventEmitter { - private _listeners: IListener[] = []; + private readonly _listeners: IListener[] = []; private _event?: IEvent; private _disposed: boolean = false; @@ -64,6 +66,34 @@ export class EventEmitter implements IEventEmitter { } } +/** + * Creates an object that implements both the {@link IEvent} and {@link IEmitter} interfaces. This + * allows more concise instantiation. The idea is to internally use the combined + * {@link IEventWithEmitter} interface and only expose {@link IEvent} externally. + * + * @example + * ```ts + * public readonly onFoo = initEvent(); + * // ... + * onFoo(e => handle(e)); + * onFoo.fire('bar'); + * ``` + */ +export function initEvent(): IEventWithEmitter { + const emitter = new EventEmitter(); + const event = emitter.event; + Object.defineProperty(event, '_listeners', { + value: (emitter as any)._listeners + }); + Object.defineProperty(event, 'fire', { + value: emitter.fire.bind(emitter) + }); + Object.defineProperty(event, 'dispose', { + value: emitter.dispose.bind(emitter) + }); + return event as any; +} + export function forwardEvent(from: IEvent, to: IEventEmitter): IDisposable { return from(e => to.fire(e)); } diff --git a/src/common/InputHandler.ts b/src/common/InputHandler.ts index 7f0879efc3..d4711c1f02 100644 --- a/src/common/InputHandler.ts +++ b/src/common/InputHandler.ts @@ -11,7 +11,7 @@ import { EscapeSequenceParser } from 'common/parser/EscapeSequenceParser'; import { Disposable } from 'common/Lifecycle'; import { StringToUtf32, stringFromCodePoint, Utf8ToUtf32 } from 'common/input/TextDecoder'; import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine'; -import { EventEmitter, IEvent } from 'common/EventEmitter'; +import { EventEmitter, IEvent, initEvent } from 'common/EventEmitter'; import { IParsingState, IEscapeSequenceParser, IParams, IFunctionIdentifier } from 'common/parser/Types'; import { NULL_CELL_CODE, NULL_CELL_WIDTH, Attributes, FgFlags, BgFlags, Content, UnderlineStyle } from 'common/buffer/Constants'; import { CellData } from 'common/buffer/CellData'; @@ -132,33 +132,20 @@ export class InputHandler extends Disposable implements IInputHandler { private _activeBuffer: IBuffer; - private readonly _onRequestBell = new EventEmitter(); - public readonly onRequestBell = this._onRequestBell.event; - private readonly _onRequestRefreshRows = new EventEmitter(); - public readonly onRequestRefreshRows = this._onRequestRefreshRows.event; - private readonly _onRequestReset = new EventEmitter(); - public readonly onRequestReset = this._onRequestReset.event; - private readonly _onRequestSendFocus = new EventEmitter(); - public readonly onRequestSendFocus = this._onRequestSendFocus.event; - private readonly _onRequestSyncScrollBar = new EventEmitter(); - public readonly onRequestSyncScrollBar = this._onRequestSyncScrollBar.event; - private readonly _onRequestWindowsOptionsReport = new EventEmitter(); - public readonly onRequestWindowsOptionsReport = this._onRequestWindowsOptionsReport.event; - - private readonly _onA11yChar = new EventEmitter(); - public readonly onA11yChar = this._onA11yChar.event; - private readonly _onA11yTab = new EventEmitter(); - public readonly onA11yTab = this._onA11yTab.event; - private readonly _onCursorMove = new EventEmitter(); - public readonly onCursorMove = this._onCursorMove.event; - private readonly _onLineFeed = new EventEmitter(); - public readonly onLineFeed = this._onLineFeed.event; - private readonly _onScroll = new EventEmitter(); - public readonly onScroll = this._onScroll.event; - private readonly _onTitleChange = new EventEmitter(); - public readonly onTitleChange = this._onTitleChange.event; - private readonly _onColor = new EventEmitter(); - public readonly onColor = this._onColor.event; + public readonly onRequestBell = initEvent(); + public readonly onRequestRefreshRows = initEvent(); + public readonly onRequestReset = initEvent(); + public readonly onRequestSendFocus = initEvent(); + public readonly onRequestSyncScrollBar = initEvent(); + public readonly onRequestWindowsOptionsReport = initEvent(); + + public readonly onA11yChar = initEvent(); + public readonly onA11yTab = initEvent(); + public readonly onCursorMove = initEvent(); + public readonly onLineFeed = initEvent(); + public readonly onScroll = initEvent(); + public readonly onTitleChange = initEvent(); + public readonly onColor = initEvent(); private _parseStack: IParseStack = { paused: false, @@ -492,11 +479,11 @@ export class InputHandler extends Disposable implements IInputHandler { } if (this._activeBuffer.x !== cursorStartX || this._activeBuffer.y !== cursorStartY) { - this._onCursorMove.fire(); + this.onCursorMove.fire(); } // Refresh any dirty rows accumulated as part of parsing - this._onRequestRefreshRows.fire(this._dirtyRowTracker.start, this._dirtyRowTracker.end); + this.onRequestRefreshRows.fire(this._dirtyRowTracker.start, this._dirtyRowTracker.end); } public print(data: Uint32Array, start: number, end: number): void { @@ -535,7 +522,7 @@ export class InputHandler extends Disposable implements IInputHandler { } if (screenReaderMode) { - this._onA11yChar.fire(stringFromCodePoint(code)); + this.onA11yChar.fire(stringFromCodePoint(code)); } if (this._currentLinkId !== undefined) { this._oscLinkService.addLineToLink(this._currentLinkId, this._activeBuffer.ybase + this._activeBuffer.y); @@ -687,7 +674,7 @@ export class InputHandler extends Disposable implements IInputHandler { * and `ITerminalOptions.bellSound`. */ public bell(): boolean { - this._onRequestBell.fire(); + this.onRequestBell.fire(); return true; } @@ -719,7 +706,7 @@ export class InputHandler extends Disposable implements IInputHandler { } this._dirtyRowTracker.markDirty(this._activeBuffer.y); - this._onLineFeed.fire(); + this.onLineFeed.fire(); return true; } @@ -808,7 +795,7 @@ export class InputHandler extends Disposable implements IInputHandler { const originalX = this._activeBuffer.x; this._activeBuffer.x = this._activeBuffer.nextStop(); if (this._optionsService.rawOptions.screenReaderMode) { - this._onA11yTab.fire(this._activeBuffer.x - originalX); + this.onA11yTab.fire(this._activeBuffer.x - originalX); } return true; } @@ -1218,7 +1205,7 @@ export class InputHandler extends Disposable implements IInputHandler { this._activeBuffer.ybase = Math.max(this._activeBuffer.ybase - scrollBackSize, 0); this._activeBuffer.ydisp = Math.max(this._activeBuffer.ydisp - scrollBackSize, 0); // Force a scroll event to refresh viewport - this._onScroll.fire(0); + this.onScroll.fire(0); } break; } @@ -1849,7 +1836,7 @@ export class InputHandler extends Disposable implements IInputHandler { */ if (this._optionsService.rawOptions.windowOptions.setWinLines) { this._bufferService.resize(132, this._bufferService.rows); - this._onRequestReset.fire(); + this.onRequestReset.fire(); } break; case 6: @@ -1868,7 +1855,7 @@ export class InputHandler extends Disposable implements IInputHandler { case 66: this._logService.debug('Serial port requested application keypad.'); this._coreService.decPrivateModes.applicationKeypad = true; - this._onRequestSyncScrollBar.fire(); + this.onRequestSyncScrollBar.fire(); break; case 9: // X10 Mouse // no release, no motion, no wheel, no modifiers. @@ -1890,7 +1877,7 @@ export class InputHandler extends Disposable implements IInputHandler { // focusin: ^[[I // focusout: ^[[O this._coreService.decPrivateModes.sendFocus = true; - this._onRequestSendFocus.fire(); + this.onRequestSendFocus.fire(); break; case 1005: // utf8 ext mode mouse - removed in #2507 this._logService.debug('DECSET 1005 not supported (see #2507)'); @@ -1917,8 +1904,8 @@ export class InputHandler extends Disposable implements IInputHandler { case 1047: // alt screen buffer this._bufferService.buffers.activateAltBuffer(this._eraseAttrData()); this._coreService.isCursorInitialized = true; - this._onRequestRefreshRows.fire(0, this._bufferService.rows - 1); - this._onRequestSyncScrollBar.fire(); + this.onRequestRefreshRows.fire(0, this._bufferService.rows - 1); + this.onRequestSyncScrollBar.fire(); break; case 2004: // bracketed paste mode (https://cirw.in/blog/bracketed-paste) this._coreService.decPrivateModes.bracketedPasteMode = true; @@ -2087,7 +2074,7 @@ export class InputHandler extends Disposable implements IInputHandler { */ if (this._optionsService.rawOptions.windowOptions.setWinLines) { this._bufferService.resize(80, this._bufferService.rows); - this._onRequestReset.fire(); + this.onRequestReset.fire(); } break; case 6: @@ -2106,7 +2093,7 @@ export class InputHandler extends Disposable implements IInputHandler { case 66: this._logService.debug('Switching back to normal keypad.'); this._coreService.decPrivateModes.applicationKeypad = false; - this._onRequestSyncScrollBar.fire(); + this.onRequestSyncScrollBar.fire(); break; case 9: // X10 Mouse case 1000: // vt200 mouse @@ -2145,8 +2132,8 @@ export class InputHandler extends Disposable implements IInputHandler { this.restoreCursor(); } this._coreService.isCursorInitialized = true; - this._onRequestRefreshRows.fire(0, this._bufferService.rows - 1); - this._onRequestSyncScrollBar.fire(); + this.onRequestRefreshRows.fire(0, this._bufferService.rows - 1); + this.onRequestSyncScrollBar.fire(); break; case 2004: // bracketed paste mode (https://cirw.in/blog/bracketed-paste) this._coreService.decPrivateModes.bracketedPasteMode = false; @@ -2645,7 +2632,7 @@ export class InputHandler extends Disposable implements IInputHandler { */ public softReset(params: IParams): boolean { this._coreService.isCursorHidden = false; - this._onRequestSyncScrollBar.fire(); + this.onRequestSyncScrollBar.fire(); this._activeBuffer.scrollTop = 0; this._activeBuffer.scrollBottom = this._bufferService.rows - 1; this._curAttrData = DEFAULT_ATTR_DATA.clone(); @@ -2765,11 +2752,11 @@ export class InputHandler extends Disposable implements IInputHandler { switch (params.params[0]) { case 14: // GetWinSizePixels, returns CSI 4 ; height ; width t if (second !== 2) { - this._onRequestWindowsOptionsReport.fire(WindowsOptionsReportType.GET_WIN_SIZE_PIXELS); + this.onRequestWindowsOptionsReport.fire(WindowsOptionsReportType.GET_WIN_SIZE_PIXELS); } break; case 16: // GetCellSizePixels, returns CSI 6 ; height ; width t - this._onRequestWindowsOptionsReport.fire(WindowsOptionsReportType.GET_CELL_SIZE_PIXELS); + this.onRequestWindowsOptionsReport.fire(WindowsOptionsReportType.GET_CELL_SIZE_PIXELS); break; case 18: // GetWinSizeChars, returns CSI 8 ; height ; width t if (this._bufferService) { @@ -2859,7 +2846,7 @@ export class InputHandler extends Disposable implements IInputHandler { */ public setTitle(data: string): boolean { this._windowTitle = data; - this._onTitleChange.fire(data); + this.onTitleChange.fire(data); return true; } @@ -2901,7 +2888,7 @@ export class InputHandler extends Disposable implements IInputHandler { } } if (event.length) { - this._onColor.fire(event); + this.onColor.fire(event); } return true; } @@ -2975,11 +2962,11 @@ export class InputHandler extends Disposable implements IInputHandler { for (let i = 0; i < slots.length; ++i, ++offset) { if (offset >= this._specialColors.length) break; if (slots[i] === '?') { - this._onColor.fire([{ type: ColorRequestType.REPORT, index: this._specialColors[offset] }]); + this.onColor.fire([{ type: ColorRequestType.REPORT, index: this._specialColors[offset] }]); } else { const color = parseColor(slots[i]); if (color) { - this._onColor.fire([{ type: ColorRequestType.SET, index: this._specialColors[offset], color }]); + this.onColor.fire([{ type: ColorRequestType.SET, index: this._specialColors[offset], color }]); } } } @@ -3040,7 +3027,7 @@ export class InputHandler extends Disposable implements IInputHandler { */ public restoreIndexedColor(data: string): boolean { if (!data) { - this._onColor.fire([{ type: ColorRequestType.RESTORE }]); + this.onColor.fire([{ type: ColorRequestType.RESTORE }]); return true; } const event: IColorEvent = []; @@ -3054,7 +3041,7 @@ export class InputHandler extends Disposable implements IInputHandler { } } if (event.length) { - this._onColor.fire(event); + this.onColor.fire(event); } return true; } @@ -3065,7 +3052,7 @@ export class InputHandler extends Disposable implements IInputHandler { * @vt: #Y OSC 110 "Restore default foreground color" "OSC 110 BEL" "Restore default foreground to themed color." */ public restoreFgColor(data: string): boolean { - this._onColor.fire([{ type: ColorRequestType.RESTORE, index: ColorIndex.FOREGROUND }]); + this.onColor.fire([{ type: ColorRequestType.RESTORE, index: ColorIndex.FOREGROUND }]); return true; } @@ -3075,7 +3062,7 @@ export class InputHandler extends Disposable implements IInputHandler { * @vt: #Y OSC 111 "Restore default background color" "OSC 111 BEL" "Restore default background to themed color." */ public restoreBgColor(data: string): boolean { - this._onColor.fire([{ type: ColorRequestType.RESTORE, index: ColorIndex.BACKGROUND }]); + this.onColor.fire([{ type: ColorRequestType.RESTORE, index: ColorIndex.BACKGROUND }]); return true; } @@ -3085,7 +3072,7 @@ export class InputHandler extends Disposable implements IInputHandler { * @vt: #Y OSC 112 "Restore default cursor color" "OSC 112 BEL" "Restore default cursor to themed color." */ public restoreCursorColor(data: string): boolean { - this._onColor.fire([{ type: ColorRequestType.RESTORE, index: ColorIndex.CURSOR }]); + this.onColor.fire([{ type: ColorRequestType.RESTORE, index: ColorIndex.CURSOR }]); return true; } @@ -3112,7 +3099,7 @@ export class InputHandler extends Disposable implements IInputHandler { public keypadApplicationMode(): boolean { this._logService.debug('Serial port requested application keypad.'); this._coreService.decPrivateModes.applicationKeypad = true; - this._onRequestSyncScrollBar.fire(); + this.onRequestSyncScrollBar.fire(); return true; } @@ -3124,7 +3111,7 @@ export class InputHandler extends Disposable implements IInputHandler { public keypadNumericMode(): boolean { this._logService.debug('Switching back to normal keypad.'); this._coreService.decPrivateModes.applicationKeypad = false; - this._onRequestSyncScrollBar.fire(); + this.onRequestSyncScrollBar.fire(); return true; } @@ -3238,7 +3225,7 @@ export class InputHandler extends Disposable implements IInputHandler { */ public fullReset(): boolean { this._parser.reset(); - this._onRequestReset.fire(); + this.onRequestReset.fire(); return true; } diff --git a/src/common/TestUtils.test.ts b/src/common/TestUtils.test.ts index e302d3e4bd..2ac70a5e8a 100644 --- a/src/common/TestUtils.test.ts +++ b/src/common/TestUtils.test.ts @@ -4,7 +4,7 @@ */ import { IBufferService, ICoreService, ILogService, IOptionsService, ITerminalOptions, ICoreMouseService, ICharsetService, IUnicodeService, IUnicodeVersionProvider, LogLevelEnum, IDecorationService, IInternalDecoration, IOscLinkService } from 'common/services/Services'; -import { IEvent, EventEmitter } from 'common/EventEmitter'; +import { IEvent, EventEmitter, initEvent } from 'common/EventEmitter'; import { clone } from 'common/Clone'; import { DEFAULT_OPTIONS } from 'common/services/OptionsService'; import { IBufferSet, IBuffer } from 'common/buffer/Types'; @@ -17,8 +17,8 @@ export class MockBufferService implements IBufferService { public serviceBrand: any; public get buffer(): IBuffer { return this.buffers.active; } public buffers: IBufferSet = {} as any; - public onResize: IEvent<{ cols: number, rows: number }> = new EventEmitter<{ cols: number, rows: number }>().event; - public onScroll: IEvent = new EventEmitter().event; + public onResize: IEvent<{ cols: number, rows: number }> = initEvent<{ cols: number, rows: number }>(); + public onScroll: IEvent = initEvent(); public isUserScrolling: boolean = false; constructor( public cols: number, @@ -60,7 +60,7 @@ export class MockCoreMouseService implements ICoreMouseService { public addProtocol(name: string): void { } public reset(): void { } public triggerMouseEvent(event: ICoreMouseEvent): boolean { return false; } - public onProtocolChange: IEvent = new EventEmitter().event; + public onProtocolChange: IEvent = initEvent(); public explainEvents(events: CoreMouseEventType): { [event: string]: boolean } { throw new Error('Method not implemented.'); } @@ -92,9 +92,9 @@ export class MockCoreService implements ICoreService { sendFocus: false, wraparound: true }; - public onData: IEvent = new EventEmitter().event; - public onUserInput: IEvent = new EventEmitter().event; - public onBinary: IEvent = new EventEmitter().event; + public onData: IEvent = initEvent(); + public onUserInput: IEvent = initEvent(); + public onBinary: IEvent = initEvent(); public reset(): void { } public triggerDataEvent(data: string, wasUserInput?: boolean): void { } public triggerBinaryEvent(data: string): void { } @@ -113,7 +113,7 @@ export class MockOptionsService implements IOptionsService { public serviceBrand: any; public readonly rawOptions: Required = clone(DEFAULT_OPTIONS); public options: Required = this.rawOptions; - public onOptionChange: IEvent = new EventEmitter().event; + public onOptionChange: IEvent = initEvent(); constructor(testOptions?: Partial) { if (testOptions) { for (const key of Object.keys(testOptions)) { @@ -149,7 +149,7 @@ export class MockUnicodeService implements IUnicodeService { } public versions: string[] = []; public activeVersion: string = ''; - public onChange: IEvent = new EventEmitter().event; + public onChange: IEvent = initEvent(); public wcwidth = (codepoint: number): number => this._provider.wcwidth(codepoint); public getStringCellWidth(s: string): number { throw new Error('Method not implemented.'); @@ -159,8 +159,8 @@ export class MockUnicodeService implements IUnicodeService { export class MockDecorationService implements IDecorationService { public serviceBrand: any; public get decorations(): IterableIterator { return [].values(); } - public onDecorationRegistered = new EventEmitter().event; - public onDecorationRemoved = new EventEmitter().event; + public onDecorationRegistered = initEvent(); + public onDecorationRemoved = initEvent(); public registerDecoration(decorationOptions: IDecorationOptions): IDecoration | undefined { return undefined; } public reset(): void { } public forEachDecorationAtCell(x: number, line: number, layer: 'bottom' | 'top' | undefined, callback: (decoration: IInternalDecoration) => void): void { } diff --git a/src/common/Types.d.ts b/src/common/Types.d.ts index d44bb19772..6e6e93e7eb 100644 --- a/src/common/Types.d.ts +++ b/src/common/Types.d.ts @@ -4,7 +4,7 @@ */ import { IFunctionIdentifier, ITerminalOptions as IPublicTerminalOptions } from 'xterm'; -import { IEvent, IEventEmitter } from 'common/EventEmitter'; +import { IEvent, IEventEmitter, IEventWithEmitter } from 'common/EventEmitter'; import { IDeleteEvent, IInsertEvent } from 'common/CircularList'; import { IParams } from 'common/parser/Types'; import { ICoreMouseService, ICoreService, IOptionsService, IUnicodeService } from 'common/services/Services'; @@ -71,12 +71,9 @@ export interface ICircularList { maxLength: number; isFull: boolean; - onDeleteEmitter: IEventEmitter; - onDelete: IEvent; - onInsertEmitter: IEventEmitter; - onInsert: IEvent; - onTrimEmitter: IEventEmitter; - onTrim: IEvent; + onDelete: IEventWithEmitter; + onInsert: IEventWithEmitter; + onTrim: IEventWithEmitter; get(index: number): T | undefined; set(index: number, value: T): void; diff --git a/src/common/buffer/Buffer.test.ts b/src/common/buffer/Buffer.test.ts index e5ea7f5ec1..03297ba62e 100644 --- a/src/common/buffer/Buffer.test.ts +++ b/src/common/buffer/Buffer.test.ts @@ -1071,7 +1071,7 @@ describe('Buffer', () => { buffer.fillViewportRows(); const marker = buffer.addMarker(buffer.lines.length - 1); assert.equal(marker.line, buffer.lines.length - 1); - buffer.lines.onTrimEmitter.fire(1); + buffer.lines.onTrim.fire(1); assert.equal(marker.line, buffer.lines.length - 2); }); it('should dispose of a marker if it is trimmed off the buffer', () => { @@ -1081,7 +1081,7 @@ describe('Buffer', () => { const marker = buffer.addMarker(0); assert.equal(marker.isDisposed, false); assert.equal(buffer.markers.length, 1); - buffer.lines.onTrimEmitter.fire(1); + buffer.lines.onTrim.fire(1); assert.equal(marker.isDisposed, true); assert.equal(buffer.markers.length, 0); }); @@ -1094,7 +1094,7 @@ describe('Buffer', () => { marker.onDispose(() => eventStack.push('disposed')); assert.equal(marker.isDisposed, false); assert.equal(buffer.markers.length, 1); - buffer.lines.onTrimEmitter.fire(1); + buffer.lines.onTrim.fire(1); assert.equal(marker.isDisposed, true); assert.equal(buffer.markers.length, 0); assert.deepEqual(eventStack, ['disposed']); diff --git a/src/common/buffer/Buffer.ts b/src/common/buffer/Buffer.ts index c8b0d1b250..ec3b9fcd5b 100644 --- a/src/common/buffer/Buffer.ts +++ b/src/common/buffer/Buffer.ts @@ -463,12 +463,12 @@ export class Buffer implements IBuffer { let insertCountEmitted = 0; for (let i = insertEvents.length - 1; i >= 0; i--) { insertEvents[i].index += insertCountEmitted; - this.lines.onInsertEmitter.fire(insertEvents[i]); + this.lines.onInsert.fire(insertEvents[i]); insertCountEmitted += insertEvents[i].amount; } const amountToTrim = Math.max(0, originalLinesLength + countToInsert - this.lines.maxLength); if (amountToTrim > 0) { - this.lines.onTrimEmitter.fire(amountToTrim); + this.lines.onTrim.fire(amountToTrim); } } } diff --git a/src/common/buffer/BufferReflow.ts b/src/common/buffer/BufferReflow.ts index ece9a96ed1..e496cbbb68 100644 --- a/src/common/buffer/BufferReflow.ts +++ b/src/common/buffer/BufferReflow.ts @@ -118,7 +118,7 @@ export function reflowLargerCreateNewLayout(lines: CircularList, to const countToRemove = toRemove[++nextToRemoveIndex]; // Tell markers that there was a deletion - lines.onDeleteEmitter.fire({ + lines.onDelete.fire({ index: i - countRemovedSoFar, amount: countToRemove }); diff --git a/src/common/buffer/BufferSet.ts b/src/common/buffer/BufferSet.ts index 46fcb09796..1fa6fc2757 100644 --- a/src/common/buffer/BufferSet.ts +++ b/src/common/buffer/BufferSet.ts @@ -6,7 +6,7 @@ import { IBuffer, IBufferSet } from 'common/buffer/Types'; import { IAttributeData } from 'common/Types'; import { Buffer } from 'common/buffer/Buffer'; -import { EventEmitter, IEvent } from 'common/EventEmitter'; +import { EventEmitter, IEvent, initEvent } from 'common/EventEmitter'; import { IOptionsService, IBufferService } from 'common/services/Services'; import { Disposable } from 'common/Lifecycle'; @@ -19,8 +19,7 @@ export class BufferSet extends Disposable implements IBufferSet { private _alt!: Buffer; private _activeBuffer!: Buffer; - private readonly _onBufferActivate = this.register(new EventEmitter<{activeBuffer: IBuffer, inactiveBuffer: IBuffer}>()); - public readonly onBufferActivate = this._onBufferActivate.event; + public readonly onBufferActivate = this.register(initEvent<{activeBuffer: IBuffer, inactiveBuffer: IBuffer}>()); /** * Create a new BufferSet for the given terminal. @@ -42,7 +41,7 @@ export class BufferSet extends Disposable implements IBufferSet { // See http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-The-Alternate-Screen-Buffer this._alt = new Buffer(false, this._optionsService, this._bufferService); this._activeBuffer = this._normal; - this._onBufferActivate.fire({ + this.onBufferActivate.fire({ activeBuffer: this._normal, inactiveBuffer: this._alt }); @@ -86,7 +85,7 @@ export class BufferSet extends Disposable implements IBufferSet { this._alt.clearAllMarkers(); this._alt.clear(); this._activeBuffer = this._normal; - this._onBufferActivate.fire({ + this.onBufferActivate.fire({ activeBuffer: this._normal, inactiveBuffer: this._alt }); @@ -105,7 +104,7 @@ export class BufferSet extends Disposable implements IBufferSet { this._alt.x = this._normal.x; this._alt.y = this._normal.y; this._activeBuffer = this._alt; - this._onBufferActivate.fire({ + this.onBufferActivate.fire({ activeBuffer: this._alt, inactiveBuffer: this._normal }); diff --git a/src/common/buffer/Marker.ts b/src/common/buffer/Marker.ts index 56d64a7262..958bd9edf1 100644 --- a/src/common/buffer/Marker.ts +++ b/src/common/buffer/Marker.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { EventEmitter, IEvent } from 'common/EventEmitter'; +import { initEvent } from 'common/EventEmitter'; import { Disposable } from 'common/Lifecycle'; import { IMarker } from 'common/Types'; @@ -15,8 +15,7 @@ export class Marker extends Disposable implements IMarker { public get id(): number { return this._id; } - private readonly _onDispose = new EventEmitter(); - public readonly onDispose = this._onDispose.event; + public readonly onDispose = initEvent(); constructor( public line: number @@ -31,7 +30,7 @@ export class Marker extends Disposable implements IMarker { this.isDisposed = true; this.line = -1; // Emit before super.dispose such that dispose listeners get a change to react - this._onDispose.fire(); + this.onDispose.fire(); super.dispose(); } } diff --git a/src/common/input/WriteBuffer.ts b/src/common/input/WriteBuffer.ts index cb40ffa1f3..4a9c85554c 100644 --- a/src/common/input/WriteBuffer.ts +++ b/src/common/input/WriteBuffer.ts @@ -4,7 +4,7 @@ * @license MIT */ -import { EventEmitter, IEvent } from 'common/EventEmitter'; +import { initEvent, EventEmitter, IEvent } from 'common/EventEmitter'; declare const setTimeout: (handler: () => void, timeout?: number) => void; @@ -42,8 +42,7 @@ export class WriteBuffer { private _syncCalls = 0; private _didUserInput = false; - private readonly _onWriteParsed = new EventEmitter(); - public readonly onWriteParsed = this._onWriteParsed.event; + public readonly onWriteParsed = initEvent(); constructor(private _action: (data: string | Uint8Array, promiseResult?: boolean) => void | Promise) { } @@ -237,6 +236,6 @@ export class WriteBuffer { this._pendingData = 0; this._bufferOffset = 0; } - this._onWriteParsed.fire(); + this.onWriteParsed.fire(); } } diff --git a/src/common/public/BufferNamespaceApi.ts b/src/common/public/BufferNamespaceApi.ts index 033f5955d9..a00962acd8 100644 --- a/src/common/public/BufferNamespaceApi.ts +++ b/src/common/public/BufferNamespaceApi.ts @@ -5,20 +5,19 @@ import { IBuffer as IBufferApi, IBufferNamespace as IBufferNamespaceApi } from 'xterm'; import { BufferApiView } from 'common/public/BufferApiView'; -import { IEvent, EventEmitter } from 'common/EventEmitter'; +import { IEvent, EventEmitter, initEvent } from 'common/EventEmitter'; import { ICoreTerminal } from 'common/Types'; export class BufferNamespaceApi implements IBufferNamespaceApi { private _normal: BufferApiView; private _alternate: BufferApiView; - private readonly _onBufferChange = new EventEmitter(); - public readonly onBufferChange = this._onBufferChange.event; + public readonly onBufferChange = initEvent(); constructor(private _core: ICoreTerminal) { this._normal = new BufferApiView(this._core.buffers.normal, 'normal'); this._alternate = new BufferApiView(this._core.buffers.alt, 'alternate'); - this._core.buffers.onBufferActivate(() => this._onBufferChange.fire(this.active)); + this._core.buffers.onBufferActivate(() => this.onBufferChange.fire(this.active)); } public get active(): IBufferApi { if (this._core.buffers.active === this._core.buffers.normal) { return this.normal; } diff --git a/src/common/services/BufferService.ts b/src/common/services/BufferService.ts index 1bc93041c9..3614fcfad7 100644 --- a/src/common/services/BufferService.ts +++ b/src/common/services/BufferService.ts @@ -6,7 +6,7 @@ import { IBufferService, IOptionsService } from 'common/services/Services'; import { BufferSet } from 'common/buffer/BufferSet'; import { IBufferSet, IBuffer } from 'common/buffer/Types'; -import { EventEmitter, IEventEmitter, IEvent } from 'common/EventEmitter'; +import { EventEmitter, IEventEmitter, IEvent, initEvent } from 'common/EventEmitter'; import { Disposable } from 'common/Lifecycle'; import { IAttributeData, IBufferLine, ScrollSource } from 'common/Types'; @@ -22,10 +22,8 @@ export class BufferService extends Disposable implements IBufferService { /** Whether the user is scrolling (locks the scroll position) */ public isUserScrolling: boolean = false; - private readonly _onResize = new EventEmitter<{ cols: number, rows: number }>(); - public readonly onResize = this._onResize.event; - private readonly _onScroll = new EventEmitter(); - public readonly onScroll = this._onScroll.event; + public readonly onResize = initEvent<{ cols: number, rows: number }>(); + public readonly onScroll = initEvent(); public get buffer(): IBuffer { return this.buffers.active; } @@ -49,7 +47,7 @@ export class BufferService extends Disposable implements IBufferService { this.rows = rows; this.buffers.resize(cols, rows); this.buffers.setupTabStops(this.cols); - this._onResize.fire({ cols, rows }); + this.onResize.fire({ cols, rows }); } public reset(): void { @@ -118,7 +116,7 @@ export class BufferService extends Disposable implements IBufferService { buffer.ydisp = buffer.ybase; } - this._onScroll.fire(buffer.ydisp); + this.onScroll.fire(buffer.ydisp); } /** @@ -148,7 +146,7 @@ export class BufferService extends Disposable implements IBufferService { } if (!suppressScrollEvent) { - this._onScroll.fire(buffer.ydisp); + this.onScroll.fire(buffer.ydisp); } } diff --git a/src/common/services/CoreMouseService.ts b/src/common/services/CoreMouseService.ts index 8c2a24def6..a5f1528a8d 100644 --- a/src/common/services/CoreMouseService.ts +++ b/src/common/services/CoreMouseService.ts @@ -3,7 +3,7 @@ * @license MIT */ import { IBufferService, ICoreService, ICoreMouseService } from 'common/services/Services'; -import { EventEmitter, IEvent } from 'common/EventEmitter'; +import { EventEmitter, IEvent, initEvent } from 'common/EventEmitter'; import { ICoreMouseProtocol, ICoreMouseEvent, CoreMouseEncoding, CoreMouseEventType, CoreMouseButton, CoreMouseAction } from 'common/Types'; /** @@ -172,8 +172,7 @@ export class CoreMouseService implements ICoreMouseService { private _activeEncoding: string = ''; private _lastEvent: ICoreMouseEvent | null = null; - private readonly _onProtocolChange = new EventEmitter(); - public readonly onProtocolChange = this._onProtocolChange.event; + public readonly onProtocolChange = initEvent(); constructor( @IBufferService private readonly _bufferService: IBufferService, @@ -207,7 +206,7 @@ export class CoreMouseService implements ICoreMouseService { throw new Error(`unknown protocol "${name}"`); } this._activeProtocol = name; - this._onProtocolChange.fire(this._protocols[name].events); + this.onProtocolChange.fire(this._protocols[name].events); } public get activeEncoding(): string { diff --git a/src/common/services/CoreService.ts b/src/common/services/CoreService.ts index 9282197b39..35c7591937 100644 --- a/src/common/services/CoreService.ts +++ b/src/common/services/CoreService.ts @@ -4,7 +4,7 @@ */ import { ICoreService, ILogService, IOptionsService, IBufferService } from 'common/services/Services'; -import { EventEmitter, IEvent } from 'common/EventEmitter'; +import { EventEmitter, IEvent, initEvent } from 'common/EventEmitter'; import { IDecPrivateModes, IModes } from 'common/Types'; import { clone } from 'common/Clone'; import { Disposable } from 'common/Lifecycle'; @@ -34,12 +34,9 @@ export class CoreService extends Disposable implements ICoreService { // Circular dependency, this must be unset or memory will leak after Terminal.dispose private _scrollToBottom: (() => void) | undefined; - private readonly _onData = this.register(new EventEmitter()); - public readonly onData = this._onData.event; - private readonly _onUserInput = this.register(new EventEmitter()); - public readonly onUserInput = this._onUserInput.event; - private readonly _onBinary = this.register(new EventEmitter()); - public readonly onBinary = this._onBinary.event; + public readonly onData = this.register(initEvent()); + public readonly onUserInput = this.register(initEvent()); + public readonly onBinary = this.register(initEvent()); constructor( // TODO: Move this into a service @@ -74,12 +71,12 @@ export class CoreService extends Disposable implements ICoreService { // Fire onUserInput so listeners can react as well (eg. clear selection) if (wasUserInput) { - this._onUserInput.fire(); + this.onUserInput.fire(); } // Fire onData API this._logService.debug(`sending data "${data}"`, () => data.split('').map(e => e.charCodeAt(0))); - this._onData.fire(data); + this.onData.fire(data); } public triggerBinaryEvent(data: string): void { @@ -87,6 +84,6 @@ export class CoreService extends Disposable implements ICoreService { return; } this._logService.debug(`sending binary "${data}"`, () => data.split('').map(e => e.charCodeAt(0))); - this._onBinary.fire(data); + this.onBinary.fire(data); } } diff --git a/src/common/services/DecorationService.ts b/src/common/services/DecorationService.ts index 522b04deae..5efeb77d8c 100644 --- a/src/common/services/DecorationService.ts +++ b/src/common/services/DecorationService.ts @@ -4,7 +4,7 @@ */ import { css } from 'common/Color'; -import { EventEmitter } from 'common/EventEmitter'; +import { EventEmitter, initEvent } from 'common/EventEmitter'; import { Disposable } from 'common/Lifecycle'; import { IDecorationService, IInternalDecoration } from 'common/services/Services'; import { SortedList } from 'common/SortedList'; @@ -25,10 +25,8 @@ export class DecorationService extends Disposable implements IDecorationService */ private readonly _decorations: SortedList = new SortedList(e => e?.marker.line); - private readonly _onDecorationRegistered = this.register(new EventEmitter()); - public readonly onDecorationRegistered = this._onDecorationRegistered.event; - private readonly _onDecorationRemoved = this.register(new EventEmitter()); - public readonly onDecorationRemoved = this._onDecorationRemoved.event; + public readonly onDecorationRegistered = this.register(initEvent()); + public readonly onDecorationRemoved = this.register(initEvent()); public get decorations(): IterableIterator { return this._decorations.values(); } @@ -42,13 +40,13 @@ export class DecorationService extends Disposable implements IDecorationService decoration.onDispose(() => { if (decoration) { if (this._decorations.delete(decoration)) { - this._onDecorationRemoved.fire(decoration); + this.onDecorationRemoved.fire(decoration); } markerDispose.dispose(); } }); this._decorations.insert(decoration); - this._onDecorationRegistered.fire(decoration); + this.onDecorationRegistered.fire(decoration); } return decoration; } @@ -84,7 +82,7 @@ export class DecorationService extends Disposable implements IDecorationService public dispose(): void { for (const d of this._decorations.values()) { - this._onDecorationRemoved.fire(d); + this.onDecorationRemoved.fire(d); } this.reset(); } @@ -95,10 +93,8 @@ class Decoration extends Disposable implements IInternalDecoration { public element: HTMLElement | undefined; public isDisposed: boolean = false; - public readonly onRenderEmitter = this.register(new EventEmitter()); - public readonly onRender = this.onRenderEmitter.event; - private readonly _onDispose = this.register(new EventEmitter()); - public readonly onDispose = this._onDispose.event; + public readonly onRender = this.register(initEvent()); + public readonly onDispose = this.register(initEvent()); private _cachedBg: IColor | undefined | null = null; public get backgroundColorRGB(): IColor | undefined { @@ -139,7 +135,7 @@ class Decoration extends Disposable implements IInternalDecoration { return; } this._isDisposed = true; - this._onDispose.fire(); + this.onDispose.fire(); super.dispose(); } } diff --git a/src/common/services/OptionsService.ts b/src/common/services/OptionsService.ts index 33aa3ee239..16beddbab4 100644 --- a/src/common/services/OptionsService.ts +++ b/src/common/services/OptionsService.ts @@ -4,9 +4,9 @@ */ import { IOptionsService, ITerminalOptions, FontWeight } from 'common/services/Services'; -import { EventEmitter, IEvent } from 'common/EventEmitter'; import { isMac } from 'common/Platform'; import { CursorStyle } from 'common/Types'; +import { initEvent } from 'common/EventEmitter'; export const DEFAULT_OPTIONS: Readonly> = { cols: 80, @@ -57,8 +57,7 @@ export class OptionsService implements IOptionsService { public readonly rawOptions: Required; public options: Required; - private readonly _onOptionChange = new EventEmitter(); - public readonly onOptionChange = this._onOptionChange.event; + public readonly onOptionChange = initEvent(); constructor(options: Partial) { // set the default value of each option @@ -97,7 +96,7 @@ export class OptionsService implements IOptionsService { // Don't fire an option change event if they didn't change if (this.rawOptions[propName] !== value) { this.rawOptions[propName] = value; - this._onOptionChange.fire(propName); + this.onOptionChange.fire(propName); } }; diff --git a/src/common/services/Services.ts b/src/common/services/Services.ts index e2b517cde3..c47b1c2a96 100644 --- a/src/common/services/Services.ts +++ b/src/common/services/Services.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { IEvent, IEventEmitter } from 'common/EventEmitter'; +import { IEvent, IEventEmitter, IEventWithEmitter } from 'common/EventEmitter'; import { IBuffer, IBufferSet } from 'common/buffer/Types'; import { IDecPrivateModes, ICoreMouseEvent, CoreMouseEncoding, ICoreMouseProtocol, CoreMouseEventType, ICharset, IWindowOptions, IModes, IAttributeData, ScrollSource, IDisposable, IColor, CursorStyle, IOscLinkData } from 'common/Types'; import { createDecorator } from 'common/services/ServiceRegistry'; @@ -318,5 +318,5 @@ export interface IInternalDecoration extends IDecoration { readonly options: IDecorationOptions; readonly backgroundColorRGB: IColor | undefined; readonly foregroundColorRGB: IColor | undefined; - readonly onRenderEmitter: IEventEmitter; + readonly onRender: IEventWithEmitter; } diff --git a/src/common/services/UnicodeService.ts b/src/common/services/UnicodeService.ts index 239f4d6225..7306db93f0 100644 --- a/src/common/services/UnicodeService.ts +++ b/src/common/services/UnicodeService.ts @@ -3,7 +3,7 @@ * @license MIT */ import { IUnicodeService, IUnicodeVersionProvider } from 'common/services/Services'; -import { EventEmitter, IEvent } from 'common/EventEmitter'; +import { EventEmitter, IEvent, initEvent } from 'common/EventEmitter'; import { UnicodeV6 } from 'common/input/UnicodeV6'; @@ -14,8 +14,7 @@ export class UnicodeService implements IUnicodeService { private _active: string = ''; private _activeProvider: IUnicodeVersionProvider; - private readonly _onChange = new EventEmitter(); - public readonly onChange = this._onChange.event; + public readonly onChange = initEvent(); constructor() { const defaultProvider = new UnicodeV6(); @@ -38,7 +37,7 @@ export class UnicodeService implements IUnicodeService { } this._active = version; this._activeProvider = this._providers[version]; - this._onChange.fire(version); + this.onChange.fire(version); } public register(provider: IUnicodeVersionProvider): void { diff --git a/src/headless/Terminal.ts b/src/headless/Terminal.ts index 639988ebd8..45b8aa7494 100644 --- a/src/headless/Terminal.ts +++ b/src/headless/Terminal.ts @@ -24,7 +24,7 @@ import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine'; import { IBuffer } from 'common/buffer/Types'; import { CoreTerminal } from 'common/CoreTerminal'; -import { EventEmitter, forwardEvent, IEvent } from 'common/EventEmitter'; +import { EventEmitter, forwardEvent, IEvent, initEvent } from 'common/EventEmitter'; import { ITerminalOptions as IInitializedTerminalOptions } from 'common/services/Services'; import { IMarker, ITerminalOptions, ScrollSource } from 'common/Types'; @@ -32,16 +32,11 @@ export class Terminal extends CoreTerminal { // TODO: We should remove options once components adopt optionsService public get options(): Required { return this.optionsService.options; } - private readonly _onBell = new EventEmitter(); - public readonly onBell = this._onBell.event; - private readonly _onCursorMove = new EventEmitter(); - public readonly onCursorMove = this._onCursorMove.event; - private readonly _onTitleChange = new EventEmitter(); - public readonly onTitleChange = this._onTitleChange.event; - private readonly _onA11yCharEmitter = new EventEmitter(); - public readonly onA11yChar = this._onA11yCharEmitter.event; - private readonly _onA11yTabEmitter = new EventEmitter(); - public readonly onA11yTab = this._onA11yTabEmitter.event; + public readonly onBell = initEvent(); + public readonly onCursorMove = initEvent(); + public readonly onTitleChange = initEvent(); + public readonly onA11yChar = initEvent(); + public readonly onA11yTab = initEvent(); /** * Creates a new `Terminal` object. @@ -65,10 +60,10 @@ export class Terminal extends CoreTerminal { // Setup InputHandler listeners this.register(this._inputHandler.onRequestBell(() => this.bell())); this.register(this._inputHandler.onRequestReset(() => this.reset())); - this.register(forwardEvent(this._inputHandler.onCursorMove, this._onCursorMove)); - this.register(forwardEvent(this._inputHandler.onTitleChange, this._onTitleChange)); - this.register(forwardEvent(this._inputHandler.onA11yChar, this._onA11yCharEmitter)); - this.register(forwardEvent(this._inputHandler.onA11yTab, this._onA11yTabEmitter)); + this.register(forwardEvent(this._inputHandler.onCursorMove, this.onCursorMove)); + this.register(forwardEvent(this._inputHandler.onTitleChange, this.onTitleChange)); + this.register(forwardEvent(this._inputHandler.onA11yChar, this.onA11yChar)); + this.register(forwardEvent(this._inputHandler.onA11yTab, this.onA11yTab)); } public dispose(): void { @@ -111,7 +106,7 @@ export class Terminal extends CoreTerminal { } public bell(): void { - this._onBell.fire(); + this.onBell.fire(); } /**