From 866bc9eb90530436c4c4aeae57a9881753f35bf9 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Sun, 14 Jul 2024 16:07:39 -0700 Subject: [PATCH] Move to dom.ts addDisposableListener --- addons/addon-webgl/src/WebglRenderer.ts | 6 ++-- addons/addon-webgl/src/tsconfig.json | 3 +- src/browser/AccessibilityManager.ts | 4 +-- src/browser/CoreBrowserTerminal.ts | 40 +++++++++++----------- src/browser/Lifecycle.test.ts | 40 ---------------------- src/browser/Lifecycle.ts | 33 ------------------ src/browser/Linkifier.ts | 10 +++--- src/browser/services/CoreBrowserService.ts | 12 +++---- 8 files changed, 36 insertions(+), 112 deletions(-) delete mode 100644 src/browser/Lifecycle.test.ts delete mode 100644 src/browser/Lifecycle.ts diff --git a/addons/addon-webgl/src/WebglRenderer.ts b/addons/addon-webgl/src/WebglRenderer.ts index 4e7bb803..663cf70a 100644 --- a/addons/addon-webgl/src/WebglRenderer.ts +++ b/addons/addon-webgl/src/WebglRenderer.ts @@ -3,7 +3,6 @@ * @license MIT */ -import { addDisposableDomListener } from 'browser/Lifecycle'; import { ITerminal } from 'browser/Types'; import { CellColorResolver } from 'browser/renderer/shared/CellColorResolver'; import { acquireTextureAtlas, removeTerminalFromCache } from 'browser/renderer/shared/CharAtlasCache'; @@ -26,6 +25,7 @@ import { IWebGL2RenderingContext } from './Types'; import { LinkRenderLayer } from './renderLayer/LinkRenderLayer'; import { IRenderLayer } from './renderLayer/Types'; import { Emitter, Event } from 'vs/base/common/event'; +import { addDisposableListener } from 'vs/base/browser/dom'; export class WebglRenderer extends Disposable implements IRenderer { private _renderLayers: IRenderLayer[]; @@ -102,7 +102,7 @@ export class WebglRenderer extends Disposable implements IRenderer { throw new Error('WebGL2 not supported ' + this._gl); } - this.register(addDisposableDomListener(this._canvas, 'webglcontextlost', (e) => { + this.register(addDisposableListener(this._canvas, 'webglcontextlost', (e) => { console.log('webglcontextlost event received'); // Prevent the default behavior in order to enable WebGL context restoration. e.preventDefault(); @@ -114,7 +114,7 @@ export class WebglRenderer extends Disposable implements IRenderer { this._onContextLoss.fire(e); }, 3000 /* ms */); })); - this.register(addDisposableDomListener(this._canvas, 'webglcontextrestored', (e) => { + this.register(addDisposableListener(this._canvas, 'webglcontextrestored', (e) => { console.warn('webglcontextrestored event received'); clearTimeout(this._contextRestorationTimeout); this._contextRestorationTimeout = undefined; diff --git a/addons/addon-webgl/src/tsconfig.json b/addons/addon-webgl/src/tsconfig.json index 55d754d7..6f1fefe8 100644 --- a/addons/addon-webgl/src/tsconfig.json +++ b/addons/addon-webgl/src/tsconfig.json @@ -29,7 +29,8 @@ "downlevelIteration": true, "experimentalDecorators": true, "types": [ - "../../../node_modules/@types/mocha" + "../../../node_modules/@types/mocha", + "../../../src/vs/typings/thenable" ] }, "include": [ diff --git a/src/browser/AccessibilityManager.ts b/src/browser/AccessibilityManager.ts index 174ccc44..120bc4d4 100644 --- a/src/browser/AccessibilityManager.ts +++ b/src/browser/AccessibilityManager.ts @@ -10,7 +10,7 @@ import { Disposable, toDisposable } from 'common/Lifecycle'; import { ICoreBrowserService, IRenderService } from 'browser/services/Services'; import { IBuffer } from 'common/buffer/Types'; import { IInstantiationService } from 'common/services/Services'; -import { addDisposableDomListener } from 'browser/Lifecycle'; +import { addDisposableListener } from 'vs/base/browser/dom'; const MAX_ROWS_TO_READ = 20; @@ -115,7 +115,7 @@ export class AccessibilityManager extends Disposable { this.register(this._terminal.onKey(e => this._handleKey(e.key))); this.register(this._terminal.onBlur(() => this._clearLiveRegion())); this.register(this._renderService.onDimensionsChange(() => this._refreshRowsDimensions())); - this.register(addDisposableDomListener(doc, 'selectionchange', () => this._handleSelectionChange())); + this.register(addDisposableListener(doc, 'selectionchange', () => this._handleSelectionChange())); this.register(this._coreBrowserService.onDprChange(() => this._refreshRowsDimensions())); this._refreshRowsDimensions(); diff --git a/src/browser/CoreBrowserTerminal.ts b/src/browser/CoreBrowserTerminal.ts index 235cb79f..0263fbfe 100644 --- a/src/browser/CoreBrowserTerminal.ts +++ b/src/browser/CoreBrowserTerminal.ts @@ -23,7 +23,6 @@ import { IDecoration, IDecorationOptions, IDisposable, ILinkProvider, IMarker } from '@xterm/xterm'; import { copyHandler, handlePasteEvent, moveTextAreaUnderMouseCursor, paste, rightClickHandler } from 'browser/Clipboard'; -import { addDisposableDomListener } from 'browser/Lifecycle'; import * as Strings from 'browser/LocalizableStrings'; import { OscLinkProvider } from 'browser/OscLinkProvider'; import { CharacterJoinerHandler, CustomKeyEventHandler, CustomWheelEventHandler, IBrowser, IBufferRange, ICompositionHelper, ILinkifier2, ITerminal } from 'browser/Types'; @@ -58,6 +57,7 @@ import { WindowsOptionsReportType } from '../common/InputHandler'; import { AccessibilityManager } from './AccessibilityManager'; import { Linkifier } from './Linkifier'; import { Emitter, Event } from 'vs/base/common/event'; +import { addDisposableListener } from 'vs/base/browser/dom'; export class CoreBrowserTerminal extends CoreTerminal implements ITerminal { public textarea: HTMLTextAreaElement | undefined; @@ -330,7 +330,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal { this._bindKeys(); // Bind clipboard functionality - this.register(addDisposableDomListener(this.element!, 'copy', (event: ClipboardEvent) => { + this.register(addDisposableListener(this.element!, 'copy', (event: ClipboardEvent) => { // If mouse events are active it means the selection manager is disabled and // copy should be handled by the host program. if (!this.hasSelection()) { @@ -339,19 +339,19 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal { copyHandler(event, this._selectionService!); })); const pasteHandlerWrapper = (event: ClipboardEvent): void => handlePasteEvent(event, this.textarea!, this.coreService, this.optionsService); - this.register(addDisposableDomListener(this.textarea!, 'paste', pasteHandlerWrapper)); - this.register(addDisposableDomListener(this.element!, 'paste', pasteHandlerWrapper)); + this.register(addDisposableListener(this.textarea!, 'paste', pasteHandlerWrapper)); + this.register(addDisposableListener(this.element!, 'paste', pasteHandlerWrapper)); // Handle right click context menus if (Browser.isFirefox) { // Firefox doesn't appear to fire the contextmenu event on right click - this.register(addDisposableDomListener(this.element!, 'mousedown', (event: MouseEvent) => { + this.register(addDisposableListener(this.element!, 'mousedown', (event: MouseEvent) => { if (event.button === 2) { rightClickHandler(event, this.textarea!, this.screenElement!, this._selectionService!, this.options.rightClickSelectsWord); } })); } else { - this.register(addDisposableDomListener(this.element!, 'contextmenu', (event: MouseEvent) => { + this.register(addDisposableListener(this.element!, 'contextmenu', (event: MouseEvent) => { rightClickHandler(event, this.textarea!, this.screenElement!, this._selectionService!, this.options.rightClickSelectsWord); })); } @@ -362,7 +362,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal { if (Browser.isLinux) { // Use auxclick event over mousedown the latter doesn't seem to work. Note // that the regular click event doesn't fire for the middle mouse button. - this.register(addDisposableDomListener(this.element!, 'auxclick', (event: MouseEvent) => { + this.register(addDisposableListener(this.element!, 'auxclick', (event: MouseEvent) => { if (event.button === 1) { moveTextAreaUnderMouseCursor(event, this.textarea!, this.screenElement!); } @@ -374,13 +374,13 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal { * Apply key handling to the terminal */ private _bindKeys(): void { - this.register(addDisposableDomListener(this.textarea!, 'keyup', (ev: KeyboardEvent) => this._keyUp(ev), true)); - this.register(addDisposableDomListener(this.textarea!, 'keydown', (ev: KeyboardEvent) => this._keyDown(ev), true)); - this.register(addDisposableDomListener(this.textarea!, 'keypress', (ev: KeyboardEvent) => this._keyPress(ev), true)); - this.register(addDisposableDomListener(this.textarea!, 'compositionstart', () => this._compositionHelper!.compositionstart())); - this.register(addDisposableDomListener(this.textarea!, 'compositionupdate', (e: CompositionEvent) => this._compositionHelper!.compositionupdate(e))); - this.register(addDisposableDomListener(this.textarea!, 'compositionend', () => this._compositionHelper!.compositionend())); - this.register(addDisposableDomListener(this.textarea!, 'input', (ev: InputEvent) => this._inputEvent(ev), true)); + this.register(addDisposableListener(this.textarea!, 'keyup', (ev: KeyboardEvent) => this._keyUp(ev), true)); + this.register(addDisposableListener(this.textarea!, 'keydown', (ev: KeyboardEvent) => this._keyDown(ev), true)); + this.register(addDisposableListener(this.textarea!, 'keypress', (ev: KeyboardEvent) => this._keyPress(ev), true)); + this.register(addDisposableListener(this.textarea!, 'compositionstart', () => this._compositionHelper!.compositionstart())); + this.register(addDisposableListener(this.textarea!, 'compositionupdate', (e: CompositionEvent) => this._compositionHelper!.compositionupdate(e))); + this.register(addDisposableListener(this.textarea!, 'compositionend', () => this._compositionHelper!.compositionend())); + this.register(addDisposableListener(this.textarea!, 'input', (ev: InputEvent) => this._inputEvent(ev), true)); this.register(this.onRender(() => this._compositionHelper!.updateCompositionElements())); } @@ -428,7 +428,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal { this.screenElement = this._document.createElement('div'); this.screenElement.classList.add('xterm-screen'); - this.register(addDisposableDomListener(this.screenElement, 'mousemove', (ev: MouseEvent) => this.updateCursorStyle(ev))); + this.register(addDisposableListener(this.screenElement, 'mousemove', (ev: MouseEvent) => this.updateCursorStyle(ev))); // Create the container that will hold helpers like the textarea for // capturing DOM Events. Then produce the helpers. this._helperContainer = this._document.createElement('div'); @@ -459,8 +459,8 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal { )); this._instantiationService.setService(ICoreBrowserService, this._coreBrowserService); - this.register(addDisposableDomListener(this.textarea, 'focus', (ev: FocusEvent) => this._handleTextAreaFocus(ev))); - this.register(addDisposableDomListener(this.textarea, 'blur', () => this._handleTextAreaBlur())); + this.register(addDisposableListener(this.textarea, 'focus', (ev: FocusEvent) => this._handleTextAreaFocus(ev))); + this.register(addDisposableListener(this.textarea, 'blur', () => this._handleTextAreaBlur())); this._helperContainer.appendChild(this.textarea); this._charSizeService = this._instantiationService.createInstance(CharSizeService, this._document, this._helperContainer); @@ -532,7 +532,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal { this.register(this._onScroll.event(() => this._selectionService!.refresh())); this.register(this._instantiationService.createInstance(BufferDecorationRenderer, this.screenElement)); - this.register(addDisposableDomListener(this.element, 'mousedown', (e: MouseEvent) => this._selectionService!.handleMouseDown(e))); + this.register(addDisposableListener(this.element, 'mousedown', (e: MouseEvent) => this._selectionService!.handleMouseDown(e))); // apply mouse event classes set by escape codes before terminal was attached if (this.coreMouseService.areMouseEventsActive) { @@ -759,7 +759,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal { /** * "Always on" event listeners. */ - this.register(addDisposableDomListener(el, 'mousedown', (ev: MouseEvent) => { + this.register(addDisposableListener(el, 'mousedown', (ev: MouseEvent) => { ev.preventDefault(); this.focus(); @@ -786,7 +786,7 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal { return this.cancel(ev); })); - this.register(addDisposableDomListener(el, 'wheel', (ev: WheelEvent) => { + this.register(addDisposableListener(el, 'wheel', (ev: WheelEvent) => { // do nothing, if app side handles wheel itself if (requestedEvents.wheel) return; diff --git a/src/browser/Lifecycle.test.ts b/src/browser/Lifecycle.test.ts deleted file mode 100644 index 638f5dad..00000000 --- a/src/browser/Lifecycle.test.ts +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Copyright (c) 2020 The xterm.js authors. All rights reserved. - * @license MIT - */ - -import { assert } from 'chai'; -import { addDisposableDomListener } from './Lifecycle'; -import jsdom = require('jsdom'); - -describe('addDisposableDomListener', () => { - const dom = new jsdom.JSDOM(); - const document = dom.window.document; - - function createEvent(type: string): Event { - const event = document.createEvent('Event'); - event.initEvent(type); - return event; - } - - it('dispose', () => { - let calledTimes = 0; - const div = document.createElement('div'); - const disposable = addDisposableDomListener(div, 'test', () => { calledTimes++; }); - - assert.equal(calledTimes, 0); - - div.dispatchEvent(createEvent('test')); - assert.equal(calledTimes, 1); - - disposable.dispose(); - - div.dispatchEvent(createEvent('test')); - assert.equal(calledTimes, 1); - - disposable.dispose(); // double disposing - - div.dispatchEvent(createEvent('test')); - assert.equal(calledTimes, 1); - }); -}); diff --git a/src/browser/Lifecycle.ts b/src/browser/Lifecycle.ts deleted file mode 100644 index 8e0272b2..00000000 --- a/src/browser/Lifecycle.ts +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright (c) 2018 The xterm.js authors. All rights reserved. - * @license MIT - */ - -import { IDisposable } from 'common/Types'; - -/** - * Adds a disposable listener to a node in the DOM, returning the disposable. - * @param node The node to add a listener to. - * @param type The event type. - * @param handler The handler for the listener. - * @param options The boolean or options object to pass on to the event - * listener. - */ -export function addDisposableDomListener( - node: Element | Window | Document, - type: string, - handler: (e: any) => void, - options?: boolean | AddEventListenerOptions -): IDisposable { - node.addEventListener(type, handler, options); - let disposed = false; - return { - dispose: () => { - if (disposed) { - return; - } - disposed = true; - node.removeEventListener(type, handler, options); - } - }; -} diff --git a/src/browser/Linkifier.ts b/src/browser/Linkifier.ts index d01f0ebe..da6f26f2 100644 --- a/src/browser/Linkifier.ts +++ b/src/browser/Linkifier.ts @@ -3,13 +3,13 @@ * @license MIT */ -import { addDisposableDomListener } from 'browser/Lifecycle'; import { IBufferCellPosition, ILink, ILinkDecorations, ILinkWithState, ILinkifier2, ILinkifierEvent } from 'browser/Types'; import { Disposable, disposeArray, getDisposeArrayDisposable, toDisposable } from 'common/Lifecycle'; import { IDisposable } from 'common/Types'; import { IBufferService } from 'common/services/Services'; import { ILinkProviderService, IMouseService, IRenderService } from './services/Services'; import { Emitter } from 'vs/base/common/event'; +import { addDisposableListener } from 'vs/base/browser/dom'; export class Linkifier extends Disposable implements ILinkifier2 { public get currentLink(): ILinkWithState | undefined { return this._currentLink; } @@ -47,13 +47,13 @@ export class Linkifier extends Disposable implements ILinkifier2 { this._clearCurrentLink(); this._wasResized = true; })); - this.register(addDisposableDomListener(this._element, 'mouseleave', () => { + this.register(addDisposableListener(this._element, 'mouseleave', () => { this._isMouseOut = true; this._clearCurrentLink(); })); - this.register(addDisposableDomListener(this._element, 'mousemove', this._handleMouseMove.bind(this))); - this.register(addDisposableDomListener(this._element, 'mousedown', this._handleMouseDown.bind(this))); - this.register(addDisposableDomListener(this._element, 'mouseup', this._handleMouseUp.bind(this))); + this.register(addDisposableListener(this._element, 'mousemove', this._handleMouseMove.bind(this))); + this.register(addDisposableListener(this._element, 'mousedown', this._handleMouseDown.bind(this))); + this.register(addDisposableListener(this._element, 'mouseup', this._handleMouseUp.bind(this))); } private _handleMouseMove(event: MouseEvent): void { diff --git a/src/browser/services/CoreBrowserService.ts b/src/browser/services/CoreBrowserService.ts index 268afb77..ca21005d 100644 --- a/src/browser/services/CoreBrowserService.ts +++ b/src/browser/services/CoreBrowserService.ts @@ -5,8 +5,8 @@ import { Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle'; import { ICoreBrowserService } from './Services'; -import { addDisposableDomListener } from 'browser/Lifecycle'; import { Emitter, Event } from 'vs/base/common/event'; +import { addDisposableListener } from 'vs/base/browser/dom'; export class CoreBrowserService extends Disposable implements ICoreBrowserService { public serviceBrand: undefined; @@ -31,12 +31,8 @@ export class CoreBrowserService extends Disposable implements ICoreBrowserServic this.register(this.onWindowChange(w => this._screenDprMonitor.setWindow(w))); this.register(Event.forward(this._screenDprMonitor.onDprChange, this._onDprChange)); - this.register( - addDisposableDomListener(this._textarea, 'focus', () => (this._isFocused = true)) - ); - this.register( - addDisposableDomListener(this._textarea, 'blur', () => (this._isFocused = false)) - ); + this.register(addDisposableListener(this._textarea, 'focus', () => this._isFocused = true)); + this.register(addDisposableListener(this._textarea, 'blur', () => this._isFocused = false)); } public get window(): Window & typeof globalThis { @@ -106,7 +102,7 @@ class ScreenDprMonitor extends Disposable { } private _setWindowResizeListener(): void { - this._windowResizeListener.value = addDisposableDomListener(this._parentWindow, 'resize', () => this._setDprAndFireIfDiffers()); + this._windowResizeListener.value = addDisposableListener(this._parentWindow, 'resize', () => this._setDprAndFireIfDiffers()); } private _setDprAndFireIfDiffers(): void {