Move to dom.ts addDisposableListener

This commit is contained in:
Daniel Imms
2024-07-14 16:07:39 -07:00
parent a7952ff36c
commit 866bc9eb90
8 changed files with 36 additions and 112 deletions
+3 -3
View File
@@ -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;
+2 -1
View File
@@ -29,7 +29,8 @@
"downlevelIteration": true,
"experimentalDecorators": true,
"types": [
"../../../node_modules/@types/mocha"
"../../../node_modules/@types/mocha",
"../../../src/vs/typings/thenable"
]
},
"include": [
+2 -2
View File
@@ -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();
+20 -20
View File
@@ -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;
-40
View File
@@ -1,40 +0,0 @@
/**
* Copyright (c) 2020 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { assert } from 'chai';
import { addDisposableDomListener } from './Lifecycle';
import jsdom = require('jsdom');
describe('addDisposableDomListener', () => {
const dom = new jsdom.JSDOM();
const document = dom.window.document;
function createEvent(type: string): Event {
const event = document.createEvent('Event');
event.initEvent(type);
return event;
}
it('dispose', () => {
let calledTimes = 0;
const div = document.createElement('div');
const disposable = addDisposableDomListener(div, 'test', () => { calledTimes++; });
assert.equal(calledTimes, 0);
div.dispatchEvent(createEvent('test'));
assert.equal(calledTimes, 1);
disposable.dispose();
div.dispatchEvent(createEvent('test'));
assert.equal(calledTimes, 1);
disposable.dispose(); // double disposing
div.dispatchEvent(createEvent('test'));
assert.equal(calledTimes, 1);
});
});
-33
View File
@@ -1,33 +0,0 @@
/**
* Copyright (c) 2018 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { IDisposable } from 'common/Types';
/**
* Adds a disposable listener to a node in the DOM, returning the disposable.
* @param node The node to add a listener to.
* @param type The event type.
* @param handler The handler for the listener.
* @param options The boolean or options object to pass on to the event
* listener.
*/
export function addDisposableDomListener(
node: Element | Window | Document,
type: string,
handler: (e: any) => void,
options?: boolean | AddEventListenerOptions
): IDisposable {
node.addEventListener(type, handler, options);
let disposed = false;
return {
dispose: () => {
if (disposed) {
return;
}
disposed = true;
node.removeEventListener(type, handler, options);
}
};
}
+5 -5
View File
@@ -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 {
+4 -8
View File
@@ -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 {