Skip to content

Commit 1a3461f

Browse files
authored
aux window - require a target window for requestAnimationFrame (#197126)
1 parent c43d9c4 commit 1a3461f

File tree

34 files changed

+119
-107
lines changed

34 files changed

+119
-107
lines changed

src/vs/base/browser/dom.ts

+21-22
Original file line numberDiff line numberDiff line change
@@ -176,14 +176,14 @@ export function addDisposableGenericMouseUpListener(node: EventTarget, handler:
176176
* If currently in an animation frame, `runner` will be executed immediately.
177177
* @return token that can be used to cancel the scheduled runner (only if `runner` was not executed immediately).
178178
*/
179-
export let runAtThisOrScheduleAtNextAnimationFrame: (runner: () => void, priority?: number) => IDisposable;
179+
export let runAtThisOrScheduleAtNextAnimationFrame: (runner: () => void, targetWindow: Window, priority?: number) => IDisposable;
180180
/**
181181
* Schedule a callback to be run at the next animation frame.
182182
* This allows multiple parties to register callbacks that should run at the next animation frame.
183183
* If currently in an animation frame, `runner` will be executed at the next animation frame.
184184
* @return token that can be used to cancel the scheduled runner.
185185
*/
186-
export let scheduleAtNextAnimationFrame: (runner: () => void, priority?: number) => IDisposable;
186+
export let scheduleAtNextAnimationFrame: (runner: () => void, targetWindow: Window, priority?: number) => IDisposable;
187187

188188
class AnimationFrameQueueItem implements IDisposable {
189189

@@ -252,35 +252,35 @@ class AnimationFrameQueueItem implements IDisposable {
252252
inAnimationFrameRunner = false;
253253
};
254254

255-
scheduleAtNextAnimationFrame = (runner: () => void, priority: number = 0) => {
255+
scheduleAtNextAnimationFrame = (runner: () => void, targetWindow: Window, priority: number = 0) => {
256256
const item = new AnimationFrameQueueItem(runner, priority);
257257
NEXT_QUEUE.push(item);
258258

259259
if (!animFrameRequested) {
260260
animFrameRequested = true;
261-
requestAnimationFrame(animationFrameRunner);
261+
targetWindow.requestAnimationFrame(animationFrameRunner);
262262
}
263263

264264
return item;
265265
};
266266

267-
runAtThisOrScheduleAtNextAnimationFrame = (runner: () => void, priority?: number) => {
267+
runAtThisOrScheduleAtNextAnimationFrame = (runner: () => void, targetWindow: Window, priority?: number) => {
268268
if (inAnimationFrameRunner) {
269269
const item = new AnimationFrameQueueItem(runner, priority);
270270
CURRENT_QUEUE!.push(item);
271271
return item;
272272
} else {
273-
return scheduleAtNextAnimationFrame(runner, priority);
273+
return scheduleAtNextAnimationFrame(runner, targetWindow, priority);
274274
}
275275
};
276276
})();
277277

278-
export function measure(callback: () => void): IDisposable {
279-
return scheduleAtNextAnimationFrame(callback, 10000 /* must be early */);
278+
export function measure(callback: () => void, targetWindow: Window): IDisposable {
279+
return scheduleAtNextAnimationFrame(callback, targetWindow, 10000 /* must be early */);
280280
}
281281

282-
export function modify(callback: () => void): IDisposable {
283-
return scheduleAtNextAnimationFrame(callback, -10000 /* must be late */);
282+
export function modify(callback: () => void, targetWindow: Window): IDisposable {
283+
return scheduleAtNextAnimationFrame(callback, targetWindow, -10000 /* must be late */);
284284
}
285285

286286
/**
@@ -780,16 +780,15 @@ export function getActiveWindow(): WindowGlobal {
780780
return document.defaultView?.window ?? window;
781781
}
782782

783-
export function getWindow(element: Node): WindowGlobal;
784-
export function getWindow(event: UIEvent): WindowGlobal;
785-
export function getWindow(obj: unknown): WindowGlobal;
783+
export function getWindow(element: Node | undefined | null): WindowGlobal;
784+
export function getWindow(event: UIEvent | undefined | null): WindowGlobal;
786785
export function getWindow(e: unknown): WindowGlobal {
787-
const candidateNode = e as Node | undefined;
786+
const candidateNode = e as Node | undefined | null;
788787
if (candidateNode?.ownerDocument?.defaultView) {
789788
return candidateNode.ownerDocument.defaultView.window;
790789
}
791790

792-
const candidateEvent = e as UIEvent | undefined;
791+
const candidateEvent = e as UIEvent | undefined | null;
793792
if (candidateEvent?.view) {
794793
return candidateEvent.view.window;
795794
}
@@ -996,22 +995,22 @@ function isCSSStyleRule(rule: CSSRule): rule is CSSStyleRule {
996995

997996
export function isMouseEvent(e: unknown): e is MouseEvent {
998997
// eslint-disable-next-line no-restricted-syntax
999-
return e instanceof MouseEvent || e instanceof getWindow(e).MouseEvent;
998+
return e instanceof MouseEvent || e instanceof getWindow(e as UIEvent).MouseEvent;
1000999
}
10011000

10021001
export function isKeyboardEvent(e: unknown): e is KeyboardEvent {
10031002
// eslint-disable-next-line no-restricted-syntax
1004-
return e instanceof KeyboardEvent || e instanceof getWindow(e).KeyboardEvent;
1003+
return e instanceof KeyboardEvent || e instanceof getWindow(e as UIEvent).KeyboardEvent;
10051004
}
10061005

10071006
export function isPointerEvent(e: unknown): e is PointerEvent {
10081007
// eslint-disable-next-line no-restricted-syntax
1009-
return e instanceof PointerEvent || e instanceof getWindow(e).PointerEvent;
1008+
return e instanceof PointerEvent || e instanceof getWindow(e as UIEvent).PointerEvent;
10101009
}
10111010

10121011
export function isDragEvent(e: unknown): e is DragEvent {
10131012
// eslint-disable-next-line no-restricted-syntax
1014-
return e instanceof DragEvent || e instanceof getWindow(e).DragEvent;
1013+
return e instanceof DragEvent || e instanceof getWindow(e as UIEvent).DragEvent;
10151014
}
10161015

10171016
export const EventType = {
@@ -1463,13 +1462,13 @@ export function windowOpenWithSuccess(url: string, noOpener = true): boolean {
14631462
return false;
14641463
}
14651464

1466-
export function animate(fn: () => void): IDisposable {
1465+
export function animate(fn: () => void, targetWindow: Window): IDisposable {
14671466
const step = () => {
14681467
fn();
1469-
stepDisposable = scheduleAtNextAnimationFrame(step);
1468+
stepDisposable = scheduleAtNextAnimationFrame(step, targetWindow);
14701469
};
14711470

1472-
let stepDisposable = scheduleAtNextAnimationFrame(step);
1471+
let stepDisposable = scheduleAtNextAnimationFrame(step, targetWindow);
14731472
return toDisposable(() => stepDisposable.dispose());
14741473
}
14751474

src/vs/base/browser/touch.ts

+12-12
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ export class Gesture extends Disposable {
9393

9494
this._register(EventUtils.runAndSubscribe(DomUtils.onDidRegisterWindow, ({ window, disposables }) => {
9595
disposables.add(DomUtils.addDisposableListener(window.document, 'touchstart', (e: TouchEvent) => this.onTouchStart(e), { passive: false }));
96-
disposables.add(DomUtils.addDisposableListener(window.document, 'touchend', (e: TouchEvent) => this.onTouchEnd(e)));
96+
disposables.add(DomUtils.addDisposableListener(window.document, 'touchend', (e: TouchEvent) => this.onTouchEnd(window, e)));
9797
disposables.add(DomUtils.addDisposableListener(window.document, 'touchmove', (e: TouchEvent) => this.onTouchMove(e), { passive: false }));
9898
}, { window, disposables: this._store }));
9999
}
@@ -173,7 +173,7 @@ export class Gesture extends Disposable {
173173
}
174174
}
175175

176-
private onTouchEnd(e: TouchEvent): void {
176+
private onTouchEnd(targetWindow: Window, e: TouchEvent): void {
177177
const timestamp = Date.now(); // use Date.now() because on FF e.timeStamp is not epoch based.
178178

179179
const activeTouchCount = Object.keys(this.activeTouches).length;
@@ -218,13 +218,13 @@ export class Gesture extends Disposable {
218218

219219
// We need to get all the dispatch targets on the start of the inertia event
220220
const dispatchTo = [...this.targets].filter(t => data.initialTarget instanceof Node && t.contains(data.initialTarget));
221-
this.inertia(dispatchTo, timestamp, // time now
222-
Math.abs(deltaX) / deltaT, // speed
223-
deltaX > 0 ? 1 : -1, // x direction
224-
finalX, // x now
225-
Math.abs(deltaY) / deltaT, // y speed
226-
deltaY > 0 ? 1 : -1, // y direction
227-
finalY // y now
221+
this.inertia(targetWindow, dispatchTo, timestamp, // time now
222+
Math.abs(deltaX) / deltaT, // speed
223+
deltaX > 0 ? 1 : -1, // x direction
224+
finalX, // x now
225+
Math.abs(deltaY) / deltaT, // y speed
226+
deltaY > 0 ? 1 : -1, // y direction
227+
finalY // y now
228228
);
229229
}
230230

@@ -282,7 +282,7 @@ export class Gesture extends Disposable {
282282
}
283283
}
284284

285-
private inertia(dispatchTo: readonly EventTarget[], t1: number, vX: number, dirX: number, x: number, vY: number, dirY: number, y: number): void {
285+
private inertia(targetWindow: Window, dispatchTo: readonly EventTarget[], t1: number, vX: number, dirX: number, x: number, vY: number, dirY: number, y: number): void {
286286
this.handle = DomUtils.scheduleAtNextAnimationFrame(() => {
287287
const now = Date.now();
288288

@@ -311,9 +311,9 @@ export class Gesture extends Disposable {
311311
dispatchTo.forEach(d => d.dispatchEvent(evt));
312312

313313
if (!stopped) {
314-
this.inertia(dispatchTo, now, vX, dirX, x + delta_pos_x, vY, dirY, y + delta_pos_y);
314+
this.inertia(targetWindow, dispatchTo, now, vX, dirX, x + delta_pos_x, vY, dirY, y + delta_pos_y);
315315
}
316-
});
316+
}, targetWindow);
317317
}
318318

319319
private onTouchMove(e: TouchEvent): void {

src/vs/base/browser/ui/breadcrumbs/breadcrumbsWidget.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ export class BreadcrumbsWidget {
128128
this._domNode.style.width = `${dim.width}px`;
129129
this._domNode.style.height = `${dim.height}px`;
130130
disposables.add(this._updateScrollbar());
131-
}));
131+
}, dom.getWindow(this._domNode)));
132132
return disposables;
133133
}
134134

@@ -138,8 +138,8 @@ export class BreadcrumbsWidget {
138138
this._scrollable.setRevealOnScroll(false);
139139
this._scrollable.scanDomNode();
140140
this._scrollable.setRevealOnScroll(true);
141-
});
142-
});
141+
}, dom.getWindow(this._domNode));
142+
}, dom.getWindow(this._domNode));
143143
}
144144

145145
private _style(styleElement: HTMLStyleElement, style: IBreadcrumbsWidgetStyles): void {

src/vs/base/browser/ui/list/listView.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { DataTransfers, IDragAndDropData } from 'vs/base/browser/dnd';
7-
import { $, addDisposableListener, animate, Dimension, getContentHeight, getContentWidth, getTopLeftOffset, scheduleAtNextAnimationFrame } from 'vs/base/browser/dom';
7+
import { $, addDisposableListener, animate, Dimension, getContentHeight, getContentWidth, getTopLeftOffset, getWindow, scheduleAtNextAnimationFrame } from 'vs/base/browser/dom';
88
import { DomEmitter } from 'vs/base/browser/event';
99
import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
1010
import { EventType as TouchEventType, Gesture, GestureEvent } from 'vs/base/browser/touch';
@@ -407,7 +407,7 @@ export class ListView<T> implements IListView<T> {
407407
this.scrollable = this.disposables.add(new Scrollable({
408408
forceIntegerValues: true,
409409
smoothScrollDuration: (options.smoothScrolling ?? false) ? 125 : 0,
410-
scheduleAtNextAnimationFrame: cb => scheduleAtNextAnimationFrame(cb)
410+
scheduleAtNextAnimationFrame: cb => scheduleAtNextAnimationFrame(cb, getWindow(this.domNode))
411411
}));
412412
this.scrollableElement = this.disposables.add(new SmoothScrollableElement(this.rowsContainer, {
413413
alwaysConsumeMouseWheel: options.alwaysConsumeMouseWheel ?? DefaultOptions.alwaysConsumeMouseWheel,
@@ -684,7 +684,7 @@ export class ListView<T> implements IListView<T> {
684684
this.scrollableElement.setScrollDimensions({ scrollHeight: this.scrollHeight });
685685
this.updateScrollWidth();
686686
this.scrollableElementUpdateDisposable = null;
687-
});
687+
}, getWindow(this.domNode));
688688
}
689689
}
690690

@@ -1291,7 +1291,7 @@ export class ListView<T> implements IListView<T> {
12911291
private setupDragAndDropScrollTopAnimation(event: DragEvent): void {
12921292
if (!this.dragOverAnimationDisposable) {
12931293
const viewTop = getTopLeftOffset(this.domNode).top;
1294-
this.dragOverAnimationDisposable = animate(this.animateDragAndDropScrollTop.bind(this, viewTop));
1294+
this.dragOverAnimationDisposable = animate(this.animateDragAndDropScrollTop.bind(this, viewTop), getWindow(this.domNode));
12951295
}
12961296

12971297
this.dragOverAnimationStopDisposable.dispose();

src/vs/base/browser/ui/menu/menubar.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,7 @@ export class MenuBar extends Disposable {
630630
this.overflowLayoutScheduled = DOM.scheduleAtNextAnimationFrame(() => {
631631
this.updateOverflowAction();
632632
this.overflowLayoutScheduled = undefined;
633-
});
633+
}, DOM.getWindow(this.container));
634634
}
635635

636636
this.setUnfocusedState();

src/vs/base/browser/ui/scrollbar/scrollableElement.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,7 @@ export class ScrollableElement extends AbstractScrollableElement {
576576
const scrollable = new Scrollable({
577577
forceIntegerValues: true,
578578
smoothScrollDuration: 0,
579-
scheduleAtNextAnimationFrame: (callback) => dom.scheduleAtNextAnimationFrame(callback)
579+
scheduleAtNextAnimationFrame: (callback) => dom.scheduleAtNextAnimationFrame(callback, dom.getWindow(element))
580580
});
581581
super(element, options, scrollable);
582582
this._register(scrollable);
@@ -621,7 +621,7 @@ export class DomScrollableElement extends AbstractScrollableElement {
621621
const scrollable = new Scrollable({
622622
forceIntegerValues: false, // See https://github.com/microsoft/vscode/issues/139877
623623
smoothScrollDuration: 0,
624-
scheduleAtNextAnimationFrame: (callback) => dom.scheduleAtNextAnimationFrame(callback)
624+
scheduleAtNextAnimationFrame: (callback) => dom.scheduleAtNextAnimationFrame(callback, dom.getWindow(element))
625625
});
626626
super(element, options, scrollable);
627627
this._register(scrollable);

src/vs/base/browser/ui/splitview/splitview.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { $, addDisposableListener, append, scheduleAtNextAnimationFrame } from 'vs/base/browser/dom';
6+
import { $, addDisposableListener, append, getWindow, scheduleAtNextAnimationFrame } from 'vs/base/browser/dom';
77
import { DomEmitter } from 'vs/base/browser/event';
88
import { ISashEvent as IBaseSashEvent, Orientation, Sash, SashState } from 'vs/base/browser/ui/sash/sash';
99
import { SmoothScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
@@ -584,7 +584,7 @@ export class SplitView<TLayoutContext = undefined, TView extends IView<TLayoutCo
584584
this.scrollable = this._register(new Scrollable({
585585
forceIntegerValues: true,
586586
smoothScrollDuration: 125,
587-
scheduleAtNextAnimationFrame
587+
scheduleAtNextAnimationFrame: callback => scheduleAtNextAnimationFrame(callback, getWindow(this.el)),
588588
}));
589589
this.scrollableElement = this._register(new SmoothScrollableElement(this.viewContainer, {
590590
vertical: this.orientation === Orientation.VERTICAL ? (options.scrollbarVisibility ?? ScrollbarVisibility.Auto) : ScrollbarVisibility.Hidden,

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import { Disposable } from 'vs/base/common/lifecycle';
77
import { IDimension } from 'vs/editor/common/core/dimension';
88
import { Emitter, Event } from 'vs/base/common/event';
9+
import { getWindow, scheduleAtNextAnimationFrame } from 'vs/base/browser/dom';
910

1011
export class ElementSizeObserver extends Disposable {
1112

@@ -65,10 +66,10 @@ export class ElementSizeObserver extends Disposable {
6566
alreadyObservedThisAnimationFrame = true;
6667
observeNow();
6768
} finally {
68-
requestAnimationFrame(() => {
69+
scheduleAtNextAnimationFrame(() => {
6970
alreadyObservedThisAnimationFrame = false;
7071
update();
71-
});
72+
}, getWindow(this._referenceDomElement));
7273
}
7374
}
7475
};

src/vs/editor/browser/controller/mouseHandler.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -682,7 +682,7 @@ class TopBottomDragScrollingOperation extends Disposable {
682682
this._position = position;
683683
this._mouseEvent = mouseEvent;
684684
this._lastTime = Date.now();
685-
this._animationFrameDisposable = dom.scheduleAtNextAnimationFrame(() => this._execute());
685+
this._animationFrameDisposable = dom.scheduleAtNextAnimationFrame(() => this._execute(), dom.getWindow(mouseEvent.browserEvent));
686686
}
687687

688688
public override dispose(): void {
@@ -752,7 +752,7 @@ class TopBottomDragScrollingOperation extends Disposable {
752752
}
753753

754754
this._dispatchMouse(mouseTarget, true, NavigationCommandRevealType.None);
755-
this._animationFrameDisposable = dom.scheduleAtNextAnimationFrame(() => this._execute());
755+
this._animationFrameDisposable = dom.scheduleAtNextAnimationFrame(() => this._execute(), dom.getWindow(mouseTarget.element));
756756
}
757757
}
758758

src/vs/editor/browser/view.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ export class View extends ViewEventHandler {
432432

433433
private _scheduleRender(): void {
434434
if (this._renderAnimationFrame === null) {
435-
this._renderAnimationFrame = dom.runAtThisOrScheduleAtNextAnimationFrame(this._onRenderScheduled.bind(this), 100);
435+
this._renderAnimationFrame = dom.runAtThisOrScheduleAtNextAnimationFrame(this._onRenderScheduled.bind(this), dom.getWindow(this.domNode.domNode), 100);
436436
}
437437
}
438438

src/vs/editor/browser/viewParts/viewCursors/viewCursor.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ export class ViewCursor {
146146
return null;
147147
}
148148

149-
const window = dom.getWindow(this._domNode);
149+
const window = dom.getWindow(this._domNode.domNode);
150150
let width: number;
151151
if (this._cursorStyle === TextEditorCursorStyle.Line) {
152152
width = dom.computeScreenAwareSize(window, this._lineCursorWidth > 0 ? this._lineCursorWidth : 2);

src/vs/editor/browser/widget/codeEditorWidget.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1648,7 +1648,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
16481648
model,
16491649
DOMLineBreaksComputerFactory.create(),
16501650
MonospaceLineBreaksComputerFactory.create(this._configuration.options),
1651-
(callback) => dom.scheduleAtNextAnimationFrame(callback),
1651+
(callback) => dom.scheduleAtNextAnimationFrame(callback, dom.getWindow(this._domElement)),
16521652
this.languageConfigurationService,
16531653
this._themeService,
16541654
attachedView,

src/vs/editor/browser/widget/diffEditor/diffEditorWidget.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* Copyright (c) Microsoft Corporation. All rights reserved.
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
5-
import { $, h } from 'vs/base/browser/dom';
5+
import { $, getWindow, h } from 'vs/base/browser/dom';
66
import { IBoundarySashes } from 'vs/base/browser/ui/sash/sash';
77
import { findLast } from 'vs/base/common/arraysFind';
88
import { onUnexpectedError } from 'vs/base/common/errors';
@@ -178,6 +178,7 @@ export class DiffEditorWidget extends DelegatingEditor implements IDiffEditor {
178178
/** @description ViewZoneManager */
179179
store.add(this._instantiationService.createInstance(
180180
readHotReloadableExport(ViewZoneManager, reader),
181+
getWindow(this._domElement),
181182
this._editors,
182183
this._diffModel,
183184
this._options,

src/vs/editor/browser/widget/diffEditor/lineAlignment.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,15 @@ export class ViewZoneManager extends Disposable {
4242
private readonly _originalTopPadding = observableValue(this, 0);
4343
private readonly _originalScrollTop: IObservable<number>;
4444
private readonly _originalScrollOffset = observableValue<number, boolean>(this, 0);
45-
private readonly _originalScrollOffsetAnimated = animatedObservable(this._originalScrollOffset, this._store);
45+
private readonly _originalScrollOffsetAnimated = animatedObservable(this._targetWindow, this._originalScrollOffset, this._store);
4646

4747
private readonly _modifiedTopPadding = observableValue(this, 0);
4848
private readonly _modifiedScrollTop: IObservable<number>;
4949
private readonly _modifiedScrollOffset = observableValue<number, boolean>(this, 0);
50-
private readonly _modifiedScrollOffsetAnimated = animatedObservable(this._modifiedScrollOffset, this._store);
50+
private readonly _modifiedScrollOffsetAnimated = animatedObservable(this._targetWindow, this._modifiedScrollOffset, this._store);
5151

5252
constructor(
53+
private readonly _targetWindow: Window,
5354
private readonly _editors: DiffEditorEditors,
5455
private readonly _diffModel: IObservable<DiffEditorViewModel | undefined>,
5556
private readonly _options: DiffEditorOptions,

0 commit comments

Comments
 (0)