Skip to content

Commit 35cbc3f

Browse files
authored
Merge pull request microsoft#93630 from nrayburn-tech/resizeobserver
Use ResizeObserver for monaco editor automaticLayout
2 parents dcdb4b7 + dbc1450 commit 35cbc3f

1 file changed

Lines changed: 53 additions & 28 deletions

File tree

src/vs/editor/browser/config/elementSizeObserver.ts

Lines changed: 53 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,52 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
6+
import { Disposable } from 'vs/base/common/lifecycle';
77
import { IDimension } from 'vs/editor/common/editorCommon';
8-
import * as dom from 'vs/base/browser/dom';
8+
9+
interface ResizeObserver {
10+
observe(target: Element): void;
11+
unobserve(target: Element): void;
12+
disconnect(): void;
13+
}
14+
15+
interface ResizeObserverSize {
16+
inlineSize: number;
17+
blockSize: number;
18+
}
19+
20+
interface ResizeObserverEntry {
21+
readonly target: Element;
22+
readonly contentRect: DOMRectReadOnly;
23+
readonly borderBoxSize: ResizeObserverSize;
24+
readonly contentBoxSize: ResizeObserverSize;
25+
}
26+
27+
type ResizeObserverCallback = (entries: ReadonlyArray<ResizeObserverEntry>, observer: ResizeObserver) => void;
28+
29+
declare const ResizeObserver: {
30+
prototype: ResizeObserver;
31+
new(callback: ResizeObserverCallback): ResizeObserver;
32+
};
33+
934

1035
export class ElementSizeObserver extends Disposable {
1136

1237
private readonly referenceDomElement: HTMLElement | null;
1338
private readonly changeCallback: () => void;
1439
private width: number;
1540
private height: number;
16-
private mutationObserver: MutationObserver | null;
17-
private windowSizeListener: IDisposable | null;
41+
private resizeObserver: ResizeObserver | null;
42+
private measureReferenceDomElementToken: number;
1843

1944
constructor(referenceDomElement: HTMLElement | null, dimension: IDimension | undefined, changeCallback: () => void) {
2045
super();
2146
this.referenceDomElement = referenceDomElement;
2247
this.changeCallback = changeCallback;
2348
this.width = -1;
2449
this.height = -1;
25-
this.mutationObserver = null;
26-
this.windowSizeListener = null;
50+
this.resizeObserver = null;
51+
this.measureReferenceDomElementToken = -1;
2752
this.measureReferenceDomElement(false, dimension);
2853
}
2954

@@ -41,40 +66,40 @@ export class ElementSizeObserver extends Disposable {
4166
}
4267

4368
public startObserving(): void {
44-
if (!this.mutationObserver && this.referenceDomElement) {
45-
this.mutationObserver = new MutationObserver(() => this._onDidMutate());
46-
this.mutationObserver.observe(this.referenceDomElement, {
47-
attributes: true,
48-
});
49-
}
50-
if (!this.windowSizeListener) {
51-
this.windowSizeListener = dom.addDisposableListener(window, 'resize', () => this._onDidResizeWindow());
69+
if (typeof ResizeObserver !== 'undefined') {
70+
if (!this.resizeObserver && this.referenceDomElement) {
71+
this.resizeObserver = new ResizeObserver((entries) => {
72+
if (entries && entries[0] && entries[0].contentRect) {
73+
this.observe({ width: entries[0].contentRect.width, height: entries[0].contentRect.height });
74+
} else {
75+
this.observe();
76+
}
77+
});
78+
this.resizeObserver.observe(this.referenceDomElement);
79+
}
80+
} else {
81+
if (this.measureReferenceDomElementToken === -1) {
82+
// setInterval type defaults to NodeJS.Timeout instead of number, so specify it as a number
83+
this.measureReferenceDomElementToken = <number><any>setInterval(() => this.observe(), 100);
84+
}
5285
}
5386
}
5487

5588
public stopObserving(): void {
56-
if (this.mutationObserver) {
57-
this.mutationObserver.disconnect();
58-
this.mutationObserver = null;
89+
if (this.resizeObserver) {
90+
this.resizeObserver.disconnect();
91+
this.resizeObserver = null;
5992
}
60-
if (this.windowSizeListener) {
61-
this.windowSizeListener.dispose();
62-
this.windowSizeListener = null;
93+
if (this.measureReferenceDomElementToken !== -1) {
94+
clearInterval(this.measureReferenceDomElementToken);
95+
this.measureReferenceDomElementToken = -1;
6396
}
6497
}
6598

6699
public observe(dimension?: IDimension): void {
67100
this.measureReferenceDomElement(true, dimension);
68101
}
69102

70-
private _onDidMutate(): void {
71-
this.measureReferenceDomElement(true);
72-
}
73-
74-
private _onDidResizeWindow(): void {
75-
this.measureReferenceDomElement(true);
76-
}
77-
78103
private measureReferenceDomElement(callChangeCallback: boolean, dimension?: IDimension): void {
79104
let observedWidth = 0;
80105
let observedHeight = 0;

0 commit comments

Comments
 (0)