From 18c10b15735223fea244c23a8c0993d28752ebc0 Mon Sep 17 00:00:00 2001 From: nrayburn Date: Wed, 5 Feb 2020 17:33:33 -0600 Subject: [PATCH 1/2] Replace timeout interval with MutationObserver for monaco editor AutoLayout --- .../browser/config/elementSizeObserver.ts | 30 ++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/vs/editor/browser/config/elementSizeObserver.ts b/src/vs/editor/browser/config/elementSizeObserver.ts index 16eea46d1f303..f2477802e9434 100644 --- a/src/vs/editor/browser/config/elementSizeObserver.ts +++ b/src/vs/editor/browser/config/elementSizeObserver.ts @@ -9,18 +9,18 @@ import { IDimension } from 'vs/editor/common/editorCommon'; export class ElementSizeObserver extends Disposable { private readonly referenceDomElement: HTMLElement | null; - private measureReferenceDomElementToken: any; private readonly changeCallback: () => void; private width: number; private height: number; + private resizeObserver: any; constructor(referenceDomElement: HTMLElement | null, dimension: IDimension | undefined, changeCallback: () => void) { super(); this.referenceDomElement = referenceDomElement; this.changeCallback = changeCallback; - this.measureReferenceDomElementToken = -1; this.width = -1; this.height = -1; + this.resizeObserver = null; this.measureReferenceDomElement(false, dimension); } @@ -38,15 +38,23 @@ export class ElementSizeObserver extends Disposable { } public startObserving(): void { - if (this.measureReferenceDomElementToken === -1) { - this.measureReferenceDomElementToken = setInterval(() => this.measureReferenceDomElement(true), 100); + if (this.resizeObserver === null) { + this.resizeObserver = new MutationObserver(this.mutationObserve.bind(this)); + this.resizeObserver.observe(this.referenceDomElement, { + attributes: true, + childList: true, + characterData: true, + subtree: true + }); + window.addEventListener('resize', this.windowObserve.bind(this)); } } public stopObserving(): void { - if (this.measureReferenceDomElementToken !== -1) { - clearInterval(this.measureReferenceDomElementToken); - this.measureReferenceDomElementToken = -1; + if (this.resizeObserver !== null) { + this.resizeObserver.disconnect(); + this.resizeObserver = null; + window.removeEventListener('resize', this.windowObserve.bind(this)); } } @@ -54,6 +62,14 @@ export class ElementSizeObserver extends Disposable { this.measureReferenceDomElement(true, dimension); } + private mutationObserve(mutations: MutationRecord[], observer: MutationObserver): void { + this.measureReferenceDomElement(true); + } + + private windowObserve(): void { + this.measureReferenceDomElement(true); + } + private measureReferenceDomElement(callChangeCallback: boolean, dimension?: IDimension): void { let observedWidth = 0; let observedHeight = 0; From 1bce32d6038a4edcc19556a017a4ffc6fca8dade Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Thu, 6 Feb 2020 23:01:43 +0100 Subject: [PATCH 2/2] Improve types & avoid callbacks when rendering the editor --- .../browser/config/elementSizeObserver.ts | 37 +++++++++++-------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/src/vs/editor/browser/config/elementSizeObserver.ts b/src/vs/editor/browser/config/elementSizeObserver.ts index f2477802e9434..b78ede941f478 100644 --- a/src/vs/editor/browser/config/elementSizeObserver.ts +++ b/src/vs/editor/browser/config/elementSizeObserver.ts @@ -3,8 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Disposable } from 'vs/base/common/lifecycle'; +import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { IDimension } from 'vs/editor/common/editorCommon'; +import * as dom from 'vs/base/browser/dom'; export class ElementSizeObserver extends Disposable { @@ -12,7 +13,8 @@ export class ElementSizeObserver extends Disposable { private readonly changeCallback: () => void; private width: number; private height: number; - private resizeObserver: any; + private mutationObserver: MutationObserver | null; + private windowSizeListener: IDisposable | null; constructor(referenceDomElement: HTMLElement | null, dimension: IDimension | undefined, changeCallback: () => void) { super(); @@ -20,7 +22,8 @@ export class ElementSizeObserver extends Disposable { this.changeCallback = changeCallback; this.width = -1; this.height = -1; - this.resizeObserver = null; + this.mutationObserver = null; + this.windowSizeListener = null; this.measureReferenceDomElement(false, dimension); } @@ -38,23 +41,25 @@ export class ElementSizeObserver extends Disposable { } public startObserving(): void { - if (this.resizeObserver === null) { - this.resizeObserver = new MutationObserver(this.mutationObserve.bind(this)); - this.resizeObserver.observe(this.referenceDomElement, { + if (!this.mutationObserver && this.referenceDomElement) { + this.mutationObserver = new MutationObserver(() => this._onDidMutate()); + this.mutationObserver.observe(this.referenceDomElement, { attributes: true, - childList: true, - characterData: true, - subtree: true }); - window.addEventListener('resize', this.windowObserve.bind(this)); + } + if (!this.windowSizeListener) { + this.windowSizeListener = dom.addDisposableListener(window, 'resize', () => this._onDidResizeWindow()); } } public stopObserving(): void { - if (this.resizeObserver !== null) { - this.resizeObserver.disconnect(); - this.resizeObserver = null; - window.removeEventListener('resize', this.windowObserve.bind(this)); + if (this.mutationObserver) { + this.mutationObserver.disconnect(); + this.mutationObserver = null; + } + if (this.windowSizeListener) { + this.windowSizeListener.dispose(); + this.windowSizeListener = null; } } @@ -62,11 +67,11 @@ export class ElementSizeObserver extends Disposable { this.measureReferenceDomElement(true, dimension); } - private mutationObserve(mutations: MutationRecord[], observer: MutationObserver): void { + private _onDidMutate(): void { this.measureReferenceDomElement(true); } - private windowObserve(): void { + private _onDidResizeWindow(): void { this.measureReferenceDomElement(true); }