From 4d97729010538e9de4e1a1ee0655495f18aa0697 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Thu, 6 Oct 2022 09:48:54 -0700 Subject: [PATCH] Revert "Merge pull request #4166 from Tyriar/event_with_emitter" This reverts commit d22f7c9edd46f5ae0bed05489c915bbde4b35759, reversing changes made to 1f8e6f095266a5236899a1ebe151983ad527b9da. --- addons/xterm-addon-canvas/src/CanvasAddon.ts | 7 +- .../xterm-addon-canvas/src/CanvasRenderer.ts | 36 +++--- addons/xterm-addon-search/src/SearchAddon.ts | 11 +- addons/xterm-addon-webgl/src/WebglAddon.ts | 14 ++- addons/xterm-addon-webgl/src/WebglRenderer.ts | 25 +++-- src/browser/Linkifier2.ts | 10 +- src/browser/Terminal.ts | 55 ++++++---- src/browser/TestUtils.test.ts | 20 ++-- .../decorations/BufferDecorationRenderer.ts | 4 +- src/browser/renderer/dom/DomRenderer.ts | 4 +- src/browser/services/CharSizeService.ts | 7 +- src/browser/services/RenderService.ts | 20 ++-- src/browser/services/SelectionService.ts | 28 +++-- src/common/CircularList.ts | 25 +++-- src/common/CoreTerminal.ts | 27 +++-- src/common/EventEmitter.ts | 34 +----- src/common/InputHandler.ts | 103 ++++++++++-------- src/common/TestUtils.test.ts | 22 ++-- src/common/Types.d.ts | 11 +- src/common/buffer/Buffer.test.ts | 6 +- src/common/buffer/Buffer.ts | 4 +- src/common/buffer/BufferReflow.ts | 2 +- src/common/buffer/BufferSet.ts | 11 +- src/common/buffer/Marker.ts | 7 +- src/common/input/WriteBuffer.ts | 7 +- src/common/public/BufferNamespaceApi.ts | 7 +- src/common/services/BufferService.ts | 14 ++- src/common/services/CoreMouseService.ts | 7 +- src/common/services/CoreService.ts | 17 +-- src/common/services/DecorationService.ts | 22 ++-- src/common/services/OptionsService.ts | 7 +- src/common/services/Services.ts | 4 +- src/common/services/UnicodeService.ts | 7 +- src/headless/Terminal.ts | 27 +++-- 34 files changed, 329 insertions(+), 283 deletions(-) diff --git a/addons/xterm-addon-canvas/src/CanvasAddon.ts b/addons/xterm-addon-canvas/src/CanvasAddon.ts index 1f214767..36fa453d 100644 --- a/addons/xterm-addon-canvas/src/CanvasAddon.ts +++ b/addons/xterm-addon-canvas/src/CanvasAddon.ts @@ -8,13 +8,14 @@ import { IColorSet } from 'browser/Types'; import { CanvasRenderer } from './CanvasRenderer'; import { IBufferService, ICoreService, IDecorationService, IOptionsService } from 'common/services/Services'; import { ITerminalAddon, Terminal } from 'xterm'; -import { forwardEvent, initEvent } from 'common/EventEmitter'; +import { EventEmitter, forwardEvent } from 'common/EventEmitter'; export class CanvasAddon implements ITerminalAddon { private _terminal?: Terminal; private _renderer?: CanvasRenderer; - public readonly onChangeTextureAtlas = initEvent(); + private readonly _onChangeTextureAtlas = new EventEmitter(); + public readonly onChangeTextureAtlas = this._onChangeTextureAtlas.event; public activate(terminal: Terminal): void { if (!terminal.element) { @@ -33,7 +34,7 @@ export class CanvasAddon implements ITerminalAddon { const screenElement: HTMLElement = (terminal as any)._core.screenElement; const linkifier = (terminal as any)._core.linkifier2; this._renderer = new CanvasRenderer(terminal, colors, screenElement, linkifier, bufferService, charSizeService, optionsService, characterJoinerService, coreService, coreBrowserService, decorationService); - forwardEvent(this._renderer.onChangeTextureAtlas, this.onChangeTextureAtlas); + forwardEvent(this._renderer.onChangeTextureAtlas, this._onChangeTextureAtlas); renderService.setRenderer(this._renderer); renderService.onResize(bufferService.cols, bufferService.rows); } diff --git a/addons/xterm-addon-canvas/src/CanvasRenderer.ts b/addons/xterm-addon-canvas/src/CanvasRenderer.ts index b7abab76..34e75c01 100644 --- a/addons/xterm-addon-canvas/src/CanvasRenderer.ts +++ b/addons/xterm-addon-canvas/src/CanvasRenderer.ts @@ -3,20 +3,20 @@ * @license MIT */ -import { TextRenderLayer } from './TextRenderLayer'; -import { SelectionRenderLayer } from './SelectionRenderLayer'; -import { CursorRenderLayer } from './CursorRenderLayer'; -import { IRenderer, IRenderDimensions, IRequestRedrawEvent } from 'browser/renderer/shared/Types'; -import { IRenderLayer } from './Types'; -import { LinkRenderLayer } from './LinkRenderLayer'; -import { Disposable } from 'common/Lifecycle'; -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 { observeDevicePixelDimensions } from 'browser/renderer/shared/DevicePixelObserver'; +import { IRenderDimensions, IRenderer, IRequestRedrawEvent } from 'browser/renderer/shared/Types'; +import { ICharacterJoinerService, ICharSizeService, ICoreBrowserService } from 'browser/services/Services'; +import { IColorSet, ILinkifier2 } from 'browser/Types'; +import { EventEmitter } from 'common/EventEmitter'; +import { Disposable } from 'common/Lifecycle'; +import { IBufferService, ICoreService, IDecorationService, IOptionsService } from 'common/services/Services'; import { Terminal } from 'xterm'; -import { initEvent, EventEmitter, IEvent } from 'common/EventEmitter'; +import { removeTerminalFromCache } from './atlas/CharAtlasCache'; +import { CursorRenderLayer } from './CursorRenderLayer'; +import { LinkRenderLayer } from './LinkRenderLayer'; +import { SelectionRenderLayer } from './SelectionRenderLayer'; +import { TextRenderLayer } from './TextRenderLayer'; +import { IRenderLayer } from './Types'; export class CanvasRenderer extends Disposable implements IRenderer { private _renderLayers: IRenderLayer[]; @@ -24,8 +24,10 @@ export class CanvasRenderer extends Disposable implements IRenderer { public dimensions: IRenderDimensions; - public readonly onRequestRedraw = initEvent(); - public readonly onChangeTextureAtlas = initEvent(); + private readonly _onRequestRedraw = new EventEmitter(); + public readonly onRequestRedraw = this._onRequestRedraw.event; + private readonly _onChangeTextureAtlas = new EventEmitter(); + public readonly onChangeTextureAtlas = this._onChangeTextureAtlas.event; constructor( private readonly _terminal: Terminal, @@ -46,7 +48,7 @@ export class CanvasRenderer extends Disposable implements IRenderer { new TextRenderLayer(this._terminal, this._screenElement, 0, this._colors, allowTransparency, this._bufferService, this._optionsService, characterJoinerService, decorationService, this._coreBrowserService), new SelectionRenderLayer(this._terminal, this._screenElement, 1, this._colors, this._bufferService, this._coreBrowserService, decorationService, this._optionsService), new LinkRenderLayer(this._terminal, this._screenElement, 2, this._colors, linkifier2, this._bufferService, this._optionsService, decorationService, this._coreBrowserService), - new CursorRenderLayer(this._terminal, this._screenElement, 3, this._colors, this.onRequestRedraw, this._bufferService, this._optionsService, coreService, this._coreBrowserService, decorationService) + new CursorRenderLayer(this._terminal, this._screenElement, 3, this._colors, this._onRequestRedraw, this._bufferService, this._optionsService, coreService, this._coreBrowserService, decorationService) ]; this.dimensions = { scaledCharWidth: 0, @@ -130,7 +132,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 }); } } @@ -203,6 +205,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 d14e1fe7..689899ef 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 { initEvent } from 'common/EventEmitter'; +import { EventEmitter } from 'common/EventEmitter'; export interface ISearchOptions { regex?: boolean; @@ -72,7 +72,8 @@ export class SearchAddon implements ITerminalAddon { private _resultIndex: number | undefined; - public readonly onDidChangeResults = initEvent<{ resultIndex: number, resultCount: number } | undefined>(); + private readonly _onDidChangeResults = new EventEmitter<{ resultIndex: number, resultCount: number } | undefined>(); + public readonly onDidChangeResults = this._onDidChangeResults.event; public activate(terminal: Terminal): void { this._terminal = terminal; @@ -88,7 +89,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); } } @@ -324,9 +325,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 b26c565c..45858e8c 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, initEvent } from 'common/EventEmitter'; +import { EventEmitter, forwardEvent } from 'common/EventEmitter'; import { isSafari } from 'common/Platform'; import { ICoreService, IDecorationService } from 'common/services/Services'; @@ -15,12 +15,14 @@ export class WebglAddon implements ITerminalAddon { private _terminal?: Terminal; private _renderer?: WebglRenderer; - public readonly onChangeTextureAtlas = initEvent(); - public readonly onContextLoss = initEvent(); + private readonly _onChangeTextureAtlas = new EventEmitter(); + public readonly onChangeTextureAtlas = this._onChangeTextureAtlas.event; + private readonly _onContextLoss = new EventEmitter(); + public readonly onContextLoss = this._onContextLoss.event; constructor( private _preserveDrawingBuffer?: boolean - ) { } + ) {} public activate(terminal: Terminal): void { if (!terminal.element) { @@ -37,8 +39,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 c7511946..b22f3d5e 100644 --- a/addons/xterm-addon-webgl/src/WebglRenderer.ts +++ b/addons/xterm-addon-webgl/src/WebglRenderer.ts @@ -13,7 +13,7 @@ import { IColorSet, ITerminal } from 'browser/Types'; import { AttributeData } from 'common/buffer/AttributeData'; import { CellData } from 'common/buffer/CellData'; import { Content, NULL_CELL_CHAR, NULL_CELL_CODE } from 'common/buffer/Constants'; -import { initEvent } from 'common/EventEmitter'; +import { EventEmitter } from 'common/EventEmitter'; import { Disposable } from 'common/Lifecycle'; import { ICoreService, IDecorationService } from 'common/services/Services'; import { CharData, IBufferLine, ICellData } from 'common/Types'; @@ -46,9 +46,12 @@ export class WebglRenderer extends Disposable implements IRenderer { private _isAttached: boolean; private _contextRestorationTimeout: number | undefined; - public readonly onChangeTextureAtlas = initEvent(); - public readonly onRequestRedraw = initEvent(); - public readonly onContextLoss = initEvent(); + 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; constructor( private _terminal: Terminal, @@ -67,7 +70,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, @@ -107,7 +110,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) => { @@ -273,7 +276,7 @@ export class WebglRenderer extends Disposable implements IRenderer { const atlas = acquireTextureAtlas(this._terminal, this._colors, this.dimensions.scaledCellWidth, this.dimensions.scaledCellHeight, this.dimensions.scaledCharWidth, this.dimensions.scaledCharHeight, this._coreBrowserService.dpr); if (this._charAtlas !== atlas) { - this.onChangeTextureAtlas.fire(atlas.cacheCanvas); + this._onChangeTextureAtlas.fire(atlas.cacheCanvas); } this._charAtlas = atlas; this._charAtlas.warmUp(); @@ -412,9 +415,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._cellColorResolver.result.bg && - this._model.cells[i + RENDER_MODEL_FG_OFFSET] === this._cellColorResolver.result.fg && - this._model.cells[i + RENDER_MODEL_EXT_OFFSET] === this._cellColorResolver.result.ext) { + this._model.cells[i + RENDER_MODEL_BG_OFFSET] === this._cellColorResolver.result.bg && + this._model.cells[i + RENDER_MODEL_FG_OFFSET] === this._cellColorResolver.result.fg && + this._model.cells[i + RENDER_MODEL_EXT_OFFSET] === this._cellColorResolver.result.ext) { continue; } @@ -519,7 +522,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 844b64f8..cf5b9dd2 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, initEvent } from 'common/EventEmitter'; +import { EventEmitter, IEvent } from 'common/EventEmitter'; import { Disposable, getDisposeArrayDisposable, disposeArray } from 'common/Lifecycle'; import { addDisposableDomListener } from 'browser/Lifecycle'; @@ -26,8 +26,10 @@ export class Linkifier2 extends Disposable implements ILinkifier2 { private _activeProviderReplies: Map | undefined; private _activeLine: number = -1; - public readonly onShowLinkUnderline = this.register(initEvent()); - public readonly onHideLinkUnderline = this.register(initEvent()); + 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; constructor( @IBufferService private readonly _bufferService: IBufferService @@ -341,7 +343,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 bc8b19cf..be1f6777 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, initEvent } from 'common/EventEmitter'; +import { EventEmitter, IEvent, forwardEvent } from 'common/EventEmitter'; import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine'; import { ColorManager } from 'browser/ColorManager'; import { RenderService } from 'browser/services/RenderService'; @@ -122,16 +122,27 @@ export class Terminal extends CoreTerminal implements ITerminal { private _colorManager: ColorManager | undefined; private _theme: ITheme | undefined; - 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(); + 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; /** * Creates a new `Terminal` object. @@ -158,16 +169,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.onA11yChar)); - this.register(forwardEvent(this._inputHandler.onA11yTab, this.onA11yTab)); + 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)); // Setup listeners this.register(this._bufferService.onResize(e => this._afterResize(e.cols, e.rows))); @@ -315,7 +326,7 @@ export class Terminal extends CoreTerminal implements ITerminal { this.updateCursorStyle(ev); this.element!.classList.add('focus'); this._showCursor(); - this.onFocus.fire(); + this._onFocus.fire(); } /** @@ -338,7 +349,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 { @@ -501,7 +512,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'); @@ -541,7 +552,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 @@ -1090,7 +1101,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); @@ -1173,7 +1184,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 18c51864..1717c204 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, initEvent } from 'common/EventEmitter'; +import { IEvent, EventEmitter } from 'common/EventEmitter'; import { ICharacterJoinerService, ICharSizeService, ICoreBrowserService, IMouseService, IRenderService, ISelectionService } from 'browser/services/Services'; import { IRenderDimensions, IRenderer, IRequestRedrawEvent } from 'browser/renderer/shared/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 = initEvent(); + public onCharSizeChange: IEvent = new EventEmitter().event; 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 = 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 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 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 = initEvent(); - public onRequestRedraw = initEvent(); - public onRequestScrollLines = initEvent(); - public onSelectionChange = initEvent(); + public onLinuxMouseSelection = new EventEmitter().event; + public onRequestRedraw = new EventEmitter().event; + public onRequestScrollLines = new EventEmitter().event; + public onSelectionChange = new EventEmitter().event; public disable(): void { throw new Error('Method not implemented.'); } diff --git a/src/browser/decorations/BufferDecorationRenderer.ts b/src/browser/decorations/BufferDecorationRenderer.ts index 23ba174f..7fcc5ea9 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.onRender.fire(decoration.element); + decoration.onRenderEmitter.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.onRender.fire(element); + decoration.onRenderEmitter.fire(element); } } diff --git a/src/browser/renderer/dom/DomRenderer.ts b/src/browser/renderer/dom/DomRenderer.ts index 1a1f1013..6a70ccec 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, initEvent } from 'common/EventEmitter'; +import { EventEmitter, IEvent } 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 = initEvent(); + public readonly onRequestRedraw = new EventEmitter().event; constructor( private _colors: IColorSet, diff --git a/src/browser/services/CharSizeService.ts b/src/browser/services/CharSizeService.ts index 583006d6..7062deec 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, initEvent } from 'common/EventEmitter'; +import { IEvent, EventEmitter } from 'common/EventEmitter'; import { ICharSizeService } from 'browser/services/Services'; export class CharSizeService implements ICharSizeService { @@ -16,7 +16,8 @@ export class CharSizeService implements ICharSizeService { public get hasValidSize(): boolean { return this.width > 0 && this.height > 0; } - public readonly onCharSizeChange = initEvent(); + private readonly _onCharSizeChange = new EventEmitter(); + public readonly onCharSizeChange = this._onCharSizeChange.event; constructor( document: Document, @@ -31,7 +32,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 73850bdb..c81357cd 100644 --- a/src/browser/services/RenderService.ts +++ b/src/browser/services/RenderService.ts @@ -5,7 +5,7 @@ import { IRenderer, IRenderDimensions } from 'browser/renderer/shared/Types'; import { RenderDebouncer } from 'browser/RenderDebouncer'; -import { EventEmitter, IEvent, initEvent } from 'common/EventEmitter'; +import { EventEmitter, IEvent } from 'common/EventEmitter'; import { Disposable } from 'common/Lifecycle'; import { ScreenDprMonitor } from 'browser/ScreenDprMonitor'; import { addDisposableDomListener } from 'browser/Lifecycle'; @@ -39,10 +39,14 @@ export class RenderService extends Disposable implements IRenderService { columnSelectMode: false }; - 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 }>(); + 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 get dimensions(): IRenderDimensions { return this._renderer.dimensions; } @@ -131,9 +135,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; } @@ -153,7 +157,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 5da197b1..3780c7ee 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, initEvent } from 'common/EventEmitter'; +import { EventEmitter, IEvent } 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,10 +111,14 @@ export class SelectionService extends Disposable implements ISelectionService { private _oldSelectionStart: [number, number] | undefined = undefined; private _oldSelectionEnd: [number, number] | undefined = undefined; - public readonly onLinuxMouseSelection = this.register(initEvent()); - public readonly onRequestRedraw = this.register(initEvent()); - public readonly onSelectionChange = this.register(initEvent()); - public readonly onRequestScrollLines = this.register(initEvent()); + 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; constructor( private readonly _element: HTMLElement, @@ -256,7 +260,7 @@ export class SelectionService extends Disposable implements ISelectionService { this._model.clearSelection(); this._removeMouseDownListeners(); this.refresh(); - this.onSelectionChange.fire(); + this._onSelectionChange.fire(); } /** @@ -275,7 +279,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); } } } @@ -286,7 +290,7 @@ export class SelectionService extends Disposable implements ISelectionService { */ private _refresh(): void { this._refreshAnimationFrame = undefined; - this.onRequestRedraw.fire({ + this._onRedrawRequest.fire({ start: this._model.finalSelectionStart, end: this._model.finalSelectionEnd, columnSelectMode: this._activeSelectionMode === SelectionMode.COLUMN @@ -354,7 +358,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 { @@ -364,7 +368,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(); } /** @@ -661,7 +665,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 @@ -739,7 +743,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 53743449..599db1ab 100644 --- a/src/common/CircularList.ts +++ b/src/common/CircularList.ts @@ -4,7 +4,7 @@ */ import { ICircularList } from 'common/Types'; -import { initEvent } from 'common/EventEmitter'; +import { EventEmitter, IEvent } from 'common/EventEmitter'; export interface IInsertEvent { index: number; @@ -25,9 +25,12 @@ export class CircularList implements ICircularList { private _startIndex: number; private _length: number; - public readonly onDelete = initEvent(); - public readonly onInsert = initEvent(); - public readonly onTrim = initEvent(); + 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; constructor( private _maxLength: number @@ -104,7 +107,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.onTrim.fire(1); + this.onTrimEmitter.fire(1); } else { this._length++; } @@ -120,7 +123,7 @@ export class CircularList implements ICircularList { throw new Error('Can only recycle when the buffer is full'); } this._startIndex = ++this._startIndex % this._maxLength; - this.onTrim.fire(1); + this.onTrimEmitter.fire(1); return this._array[this._getCyclicIndex(this._length - 1)]!; } @@ -155,7 +158,7 @@ export class CircularList implements ICircularList { this._array[this._getCyclicIndex(i)] = this._array[this._getCyclicIndex(i + deleteCount)]; } this._length -= deleteCount; - this.onDelete.fire({ index: start, amount: deleteCount }); + this.onDeleteEmitter.fire({ index: start, amount: deleteCount }); } // Add items @@ -166,7 +169,7 @@ export class CircularList implements ICircularList { this._array[this._getCyclicIndex(start + i)] = items[i]; } if (items.length) { - this.onInsert.fire({ index: start, amount: items.length }); + this.onInsertEmitter.fire({ index: start, amount: items.length }); } // Adjust length as needed @@ -174,7 +177,7 @@ export class CircularList implements ICircularList { const countToTrim = (this._length + items.length) - this._maxLength; this._startIndex += countToTrim; this._length = this._maxLength; - this.onTrim.fire(countToTrim); + this.onTrimEmitter.fire(countToTrim); } else { this._length += items.length; } @@ -190,7 +193,7 @@ export class CircularList implements ICircularList { } this._startIndex += count; this._length -= count; - this.onTrim.fire(count); + this.onTrimEmitter.fire(count); } public shiftElements(start: number, count: number, offset: number): void { @@ -214,7 +217,7 @@ export class CircularList implements ICircularList { while (this._length > this._maxLength) { this._length--; this._startIndex++; - this.onTrim.fire(1); + this.onTrimEmitter.fire(1); } } } else { diff --git a/src/common/CoreTerminal.ts b/src/common/CoreTerminal.ts index dd6953bb..2ad6f735 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, initEvent } from 'common/EventEmitter'; +import { EventEmitter, IEvent, forwardEvent } from 'common/EventEmitter'; import { CoreMouseService } from 'common/services/CoreMouseService'; import { UnicodeService } from 'common/services/UnicodeService'; import { CharsetService } from 'common/services/CharsetService'; @@ -59,11 +59,16 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal { private _writeBuffer: WriteBuffer; private _windowsMode: IDisposable | undefined; - public readonly onBinary = initEvent(); - public readonly onData = initEvent(); - public readonly onLineFeed = initEvent(); - public readonly onResize = initEvent<{ cols: number, rows: number }>(); - public readonly onWriteParsed = initEvent(); + 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; /** * Internally we track the source of the scroll but this is meaningless outside the library so @@ -117,13 +122,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 => { @@ -137,7 +142,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 29e931d2..4684809f 100644 --- a/src/common/EventEmitter.ts +++ b/src/common/EventEmitter.ts @@ -14,15 +14,13 @@ 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 readonly _listeners: IListener[] = []; + private _listeners: IListener[] = []; private _event?: IEvent; private _disposed: boolean = false; @@ -66,34 +64,6 @@ 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 d4711c1f..7f0879ef 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, initEvent } from 'common/EventEmitter'; +import { EventEmitter, IEvent } 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,20 +132,33 @@ export class InputHandler extends Disposable implements IInputHandler { private _activeBuffer: IBuffer; - public readonly onRequestBell = initEvent(); - public readonly onRequestRefreshRows = initEvent(); - public readonly onRequestReset = initEvent(); - public readonly onRequestSendFocus = initEvent(); - public readonly onRequestSyncScrollBar = initEvent(); - public readonly onRequestWindowsOptionsReport = initEvent(); + 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; - 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 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; private _parseStack: IParseStack = { paused: false, @@ -479,11 +492,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 { @@ -522,7 +535,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); @@ -674,7 +687,7 @@ export class InputHandler extends Disposable implements IInputHandler { * and `ITerminalOptions.bellSound`. */ public bell(): boolean { - this.onRequestBell.fire(); + this._onRequestBell.fire(); return true; } @@ -706,7 +719,7 @@ export class InputHandler extends Disposable implements IInputHandler { } this._dirtyRowTracker.markDirty(this._activeBuffer.y); - this.onLineFeed.fire(); + this._onLineFeed.fire(); return true; } @@ -795,7 +808,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; } @@ -1205,7 +1218,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; } @@ -1836,7 +1849,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: @@ -1855,7 +1868,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. @@ -1877,7 +1890,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)'); @@ -1904,8 +1917,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; @@ -2074,7 +2087,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: @@ -2093,7 +2106,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 @@ -2132,8 +2145,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; @@ -2632,7 +2645,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(); @@ -2752,11 +2765,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) { @@ -2846,7 +2859,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; } @@ -2888,7 +2901,7 @@ export class InputHandler extends Disposable implements IInputHandler { } } if (event.length) { - this.onColor.fire(event); + this._onColor.fire(event); } return true; } @@ -2962,11 +2975,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 }]); } } } @@ -3027,7 +3040,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 = []; @@ -3041,7 +3054,7 @@ export class InputHandler extends Disposable implements IInputHandler { } } if (event.length) { - this.onColor.fire(event); + this._onColor.fire(event); } return true; } @@ -3052,7 +3065,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; } @@ -3062,7 +3075,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; } @@ -3072,7 +3085,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; } @@ -3099,7 +3112,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; } @@ -3111,7 +3124,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; } @@ -3225,7 +3238,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 2ac70a5e..e302d3e4 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, initEvent } from 'common/EventEmitter'; +import { IEvent, EventEmitter } from 'common/EventEmitter'; import { clone } from 'common/Clone'; import { DEFAULT_OPTIONS } from 'common/services/OptionsService'; import { IBufferSet, IBuffer } from 'common/buffer/Types'; @@ -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 }> = initEvent<{ cols: number, rows: number }>(); - public onScroll: IEvent = initEvent(); + public onResize: IEvent<{ cols: number, rows: number }> = new EventEmitter<{ cols: number, rows: number }>().event; + public onScroll: IEvent = new EventEmitter().event; 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 = initEvent(); + public onProtocolChange: IEvent = new EventEmitter().event; 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 = initEvent(); - public onUserInput: IEvent = initEvent(); - public onBinary: IEvent = initEvent(); + public onData: IEvent = new EventEmitter().event; + public onUserInput: IEvent = new EventEmitter().event; + public onBinary: IEvent = new EventEmitter().event; 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 = initEvent(); + public onOptionChange: IEvent = new EventEmitter().event; 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 = initEvent(); + public onChange: IEvent = new EventEmitter().event; 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 = initEvent(); - public onDecorationRemoved = initEvent(); + public onDecorationRegistered = new EventEmitter().event; + public onDecorationRemoved = new EventEmitter().event; 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 6e6e93e7..d44bb197 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, IEventWithEmitter } from 'common/EventEmitter'; +import { IEvent, IEventEmitter } 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,9 +71,12 @@ export interface ICircularList { maxLength: number; isFull: boolean; - onDelete: IEventWithEmitter; - onInsert: IEventWithEmitter; - onTrim: IEventWithEmitter; + onDeleteEmitter: IEventEmitter; + onDelete: IEvent; + onInsertEmitter: IEventEmitter; + onInsert: IEvent; + onTrimEmitter: IEventEmitter; + onTrim: IEvent; 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 03297ba6..e5ea7f5e 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.onTrim.fire(1); + buffer.lines.onTrimEmitter.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.onTrim.fire(1); + buffer.lines.onTrimEmitter.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.onTrim.fire(1); + buffer.lines.onTrimEmitter.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 ec3b9fcd..c8b0d1b2 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.onInsert.fire(insertEvents[i]); + this.lines.onInsertEmitter.fire(insertEvents[i]); insertCountEmitted += insertEvents[i].amount; } const amountToTrim = Math.max(0, originalLinesLength + countToInsert - this.lines.maxLength); if (amountToTrim > 0) { - this.lines.onTrim.fire(amountToTrim); + this.lines.onTrimEmitter.fire(amountToTrim); } } } diff --git a/src/common/buffer/BufferReflow.ts b/src/common/buffer/BufferReflow.ts index e496cbbb..ece9a96e 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.onDelete.fire({ + lines.onDeleteEmitter.fire({ index: i - countRemovedSoFar, amount: countToRemove }); diff --git a/src/common/buffer/BufferSet.ts b/src/common/buffer/BufferSet.ts index 1fa6fc27..46fcb097 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, initEvent } from 'common/EventEmitter'; +import { EventEmitter, IEvent } from 'common/EventEmitter'; import { IOptionsService, IBufferService } from 'common/services/Services'; import { Disposable } from 'common/Lifecycle'; @@ -19,7 +19,8 @@ export class BufferSet extends Disposable implements IBufferSet { private _alt!: Buffer; private _activeBuffer!: Buffer; - public readonly onBufferActivate = this.register(initEvent<{activeBuffer: IBuffer, inactiveBuffer: IBuffer}>()); + private readonly _onBufferActivate = this.register(new EventEmitter<{activeBuffer: IBuffer, inactiveBuffer: IBuffer}>()); + public readonly onBufferActivate = this._onBufferActivate.event; /** * Create a new BufferSet for the given terminal. @@ -41,7 +42,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 }); @@ -85,7 +86,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 }); @@ -104,7 +105,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 958bd9ed..56d64a72 100644 --- a/src/common/buffer/Marker.ts +++ b/src/common/buffer/Marker.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { initEvent } from 'common/EventEmitter'; +import { EventEmitter, IEvent } from 'common/EventEmitter'; import { Disposable } from 'common/Lifecycle'; import { IMarker } from 'common/Types'; @@ -15,7 +15,8 @@ export class Marker extends Disposable implements IMarker { public get id(): number { return this._id; } - public readonly onDispose = initEvent(); + private readonly _onDispose = new EventEmitter(); + public readonly onDispose = this._onDispose.event; constructor( public line: number @@ -30,7 +31,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 4a9c8555..cb40ffa1 100644 --- a/src/common/input/WriteBuffer.ts +++ b/src/common/input/WriteBuffer.ts @@ -4,7 +4,7 @@ * @license MIT */ -import { initEvent, EventEmitter, IEvent } from 'common/EventEmitter'; +import { EventEmitter, IEvent } from 'common/EventEmitter'; declare const setTimeout: (handler: () => void, timeout?: number) => void; @@ -42,7 +42,8 @@ export class WriteBuffer { private _syncCalls = 0; private _didUserInput = false; - public readonly onWriteParsed = initEvent(); + private readonly _onWriteParsed = new EventEmitter(); + public readonly onWriteParsed = this._onWriteParsed.event; constructor(private _action: (data: string | Uint8Array, promiseResult?: boolean) => void | Promise) { } @@ -236,6 +237,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 a00962ac..033f5955 100644 --- a/src/common/public/BufferNamespaceApi.ts +++ b/src/common/public/BufferNamespaceApi.ts @@ -5,19 +5,20 @@ import { IBuffer as IBufferApi, IBufferNamespace as IBufferNamespaceApi } from 'xterm'; import { BufferApiView } from 'common/public/BufferApiView'; -import { IEvent, EventEmitter, initEvent } from 'common/EventEmitter'; +import { IEvent, EventEmitter } from 'common/EventEmitter'; import { ICoreTerminal } from 'common/Types'; export class BufferNamespaceApi implements IBufferNamespaceApi { private _normal: BufferApiView; private _alternate: BufferApiView; - public readonly onBufferChange = initEvent(); + private readonly _onBufferChange = new EventEmitter(); + public readonly onBufferChange = this._onBufferChange.event; 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 3614fcfa..1bc93041 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, initEvent } from 'common/EventEmitter'; +import { EventEmitter, IEventEmitter, IEvent } from 'common/EventEmitter'; import { Disposable } from 'common/Lifecycle'; import { IAttributeData, IBufferLine, ScrollSource } from 'common/Types'; @@ -22,8 +22,10 @@ export class BufferService extends Disposable implements IBufferService { /** Whether the user is scrolling (locks the scroll position) */ public isUserScrolling: boolean = false; - public readonly onResize = initEvent<{ cols: number, rows: number }>(); - public readonly onScroll = initEvent(); + 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 get buffer(): IBuffer { return this.buffers.active; } @@ -47,7 +49,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 { @@ -116,7 +118,7 @@ export class BufferService extends Disposable implements IBufferService { buffer.ydisp = buffer.ybase; } - this.onScroll.fire(buffer.ydisp); + this._onScroll.fire(buffer.ydisp); } /** @@ -146,7 +148,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 a5f1528a..8c2a24de 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, initEvent } from 'common/EventEmitter'; +import { EventEmitter, IEvent } from 'common/EventEmitter'; import { ICoreMouseProtocol, ICoreMouseEvent, CoreMouseEncoding, CoreMouseEventType, CoreMouseButton, CoreMouseAction } from 'common/Types'; /** @@ -172,7 +172,8 @@ export class CoreMouseService implements ICoreMouseService { private _activeEncoding: string = ''; private _lastEvent: ICoreMouseEvent | null = null; - public readonly onProtocolChange = initEvent(); + private readonly _onProtocolChange = new EventEmitter(); + public readonly onProtocolChange = this._onProtocolChange.event; constructor( @IBufferService private readonly _bufferService: IBufferService, @@ -206,7 +207,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 35c75919..9282197b 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, initEvent } from 'common/EventEmitter'; +import { EventEmitter, IEvent } from 'common/EventEmitter'; import { IDecPrivateModes, IModes } from 'common/Types'; import { clone } from 'common/Clone'; import { Disposable } from 'common/Lifecycle'; @@ -34,9 +34,12 @@ export class CoreService extends Disposable implements ICoreService { // Circular dependency, this must be unset or memory will leak after Terminal.dispose private _scrollToBottom: (() => void) | undefined; - public readonly onData = this.register(initEvent()); - public readonly onUserInput = this.register(initEvent()); - public readonly onBinary = this.register(initEvent()); + 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; constructor( // TODO: Move this into a service @@ -71,12 +74,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 { @@ -84,6 +87,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 5efeb77d..522b04de 100644 --- a/src/common/services/DecorationService.ts +++ b/src/common/services/DecorationService.ts @@ -4,7 +4,7 @@ */ import { css } from 'common/Color'; -import { EventEmitter, initEvent } from 'common/EventEmitter'; +import { EventEmitter } from 'common/EventEmitter'; import { Disposable } from 'common/Lifecycle'; import { IDecorationService, IInternalDecoration } from 'common/services/Services'; import { SortedList } from 'common/SortedList'; @@ -25,8 +25,10 @@ export class DecorationService extends Disposable implements IDecorationService */ private readonly _decorations: SortedList = new SortedList(e => e?.marker.line); - public readonly onDecorationRegistered = this.register(initEvent()); - public readonly onDecorationRemoved = this.register(initEvent()); + 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 get decorations(): IterableIterator { return this._decorations.values(); } @@ -40,13 +42,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; } @@ -82,7 +84,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(); } @@ -93,8 +95,10 @@ class Decoration extends Disposable implements IInternalDecoration { public element: HTMLElement | undefined; public isDisposed: boolean = false; - public readonly onRender = this.register(initEvent()); - public readonly onDispose = this.register(initEvent()); + 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; private _cachedBg: IColor | undefined | null = null; public get backgroundColorRGB(): IColor | undefined { @@ -135,7 +139,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 16beddba..33aa3ee2 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,7 +57,8 @@ export class OptionsService implements IOptionsService { public readonly rawOptions: Required; public options: Required; - public readonly onOptionChange = initEvent(); + private readonly _onOptionChange = new EventEmitter(); + public readonly onOptionChange = this._onOptionChange.event; constructor(options: Partial) { // set the default value of each option @@ -96,7 +97,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 c47b1c2a..e2b517cd 100644 --- a/src/common/services/Services.ts +++ b/src/common/services/Services.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { IEvent, IEventEmitter, IEventWithEmitter } from 'common/EventEmitter'; +import { IEvent, IEventEmitter } 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 onRender: IEventWithEmitter; + readonly onRenderEmitter: IEventEmitter; } diff --git a/src/common/services/UnicodeService.ts b/src/common/services/UnicodeService.ts index 7306db93..239f4d62 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, initEvent } from 'common/EventEmitter'; +import { EventEmitter, IEvent } from 'common/EventEmitter'; import { UnicodeV6 } from 'common/input/UnicodeV6'; @@ -14,7 +14,8 @@ export class UnicodeService implements IUnicodeService { private _active: string = ''; private _activeProvider: IUnicodeVersionProvider; - public readonly onChange = initEvent(); + private readonly _onChange = new EventEmitter(); + public readonly onChange = this._onChange.event; constructor() { const defaultProvider = new UnicodeV6(); @@ -37,7 +38,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 45b8aa74..639988eb 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, initEvent } from 'common/EventEmitter'; +import { EventEmitter, forwardEvent, IEvent } from 'common/EventEmitter'; import { ITerminalOptions as IInitializedTerminalOptions } from 'common/services/Services'; import { IMarker, ITerminalOptions, ScrollSource } from 'common/Types'; @@ -32,11 +32,16 @@ export class Terminal extends CoreTerminal { // TODO: We should remove options once components adopt optionsService public get options(): Required { return this.optionsService.options; } - public readonly onBell = initEvent(); - public readonly onCursorMove = initEvent(); - public readonly onTitleChange = initEvent(); - public readonly onA11yChar = initEvent(); - public readonly onA11yTab = initEvent(); + 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; /** * Creates a new `Terminal` object. @@ -60,10 +65,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.onA11yChar)); - this.register(forwardEvent(this._inputHandler.onA11yTab, this.onA11yTab)); + 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)); } public dispose(): void { @@ -106,7 +111,7 @@ export class Terminal extends CoreTerminal { } public bell(): void { - this.onBell.fire(); + this._onBell.fire(); } /**