@@ -18,27 +18,36 @@ import * as platform from 'vs/base/common/platform';
18
18
import { URI } from 'vs/base/common/uri' ;
19
19
import { hash } from 'vs/base/common/hash' ;
20
20
21
- type WindowGlobal = Window & typeof globalThis ;
21
+ export type CodeWindow = Window & typeof globalThis & {
22
+ readonly vscodeWindowId : number ;
23
+ } ;
22
24
23
- interface IWindow {
24
- readonly window : WindowGlobal ;
25
+ interface IRegisteredCodeWindow {
26
+ readonly window : CodeWindow ;
25
27
readonly disposables : DisposableStore ;
26
28
}
27
29
28
- export const { registerWindow, getWindows, getWindowsCount, onDidRegisterWindow, onWillUnregisterWindow, onDidUnregisterWindow } = ( function ( ) {
29
- const windows = new Map < WindowGlobal , IWindow > ( ) ;
30
- windows . set ( window , { window, disposables : new DisposableStore ( ) } ) ;
30
+ export const { registerWindow, getWindows, getWindowsCount, getWindowId, onDidRegisterWindow, onWillUnregisterWindow, onDidUnregisterWindow } = ( function ( ) {
31
+ const windows = new Map < number , IRegisteredCodeWindow > ( ) ;
32
+
33
+ const mainWindow = window as CodeWindow ;
34
+ if ( typeof mainWindow . vscodeWindowId !== 'number' ) {
35
+ Object . defineProperty ( window , 'vscodeWindowId' , {
36
+ get : ( ) => - 1
37
+ } ) ;
38
+ }
39
+ windows . set ( mainWindow . vscodeWindowId , { window : mainWindow , disposables : new DisposableStore ( ) } ) ;
31
40
32
- const onDidRegisterWindow = new event . Emitter < IWindow > ( ) ;
33
- const onDidUnregisterWindow = new event . Emitter < WindowGlobal > ( ) ;
34
- const onWillUnregisterWindow = new event . Emitter < WindowGlobal > ( ) ;
41
+ const onDidRegisterWindow = new event . Emitter < IRegisteredCodeWindow > ( ) ;
42
+ const onDidUnregisterWindow = new event . Emitter < CodeWindow > ( ) ;
43
+ const onWillUnregisterWindow = new event . Emitter < CodeWindow > ( ) ;
35
44
36
45
return {
37
46
onDidRegisterWindow : onDidRegisterWindow . event ,
38
47
onWillUnregisterWindow : onWillUnregisterWindow . event ,
39
48
onDidUnregisterWindow : onDidUnregisterWindow . event ,
40
- registerWindow ( window : WindowGlobal ) : IDisposable {
41
- if ( windows . has ( window ) ) {
49
+ registerWindow ( window : CodeWindow ) : IDisposable {
50
+ if ( windows . has ( window . vscodeWindowId ) ) {
42
51
return Disposable . None ;
43
52
}
44
53
@@ -48,10 +57,10 @@ export const { registerWindow, getWindows, getWindowsCount, onDidRegisterWindow,
48
57
window,
49
58
disposables : disposables . add ( new DisposableStore ( ) )
50
59
} ;
51
- windows . set ( window , registeredWindow ) ;
60
+ windows . set ( window . vscodeWindowId , registeredWindow ) ;
52
61
53
62
disposables . add ( toDisposable ( ( ) => {
54
- windows . delete ( window ) ;
63
+ windows . delete ( window . vscodeWindowId ) ;
55
64
onDidUnregisterWindow . fire ( window ) ;
56
65
} ) ) ;
57
66
@@ -63,11 +72,14 @@ export const { registerWindow, getWindows, getWindowsCount, onDidRegisterWindow,
63
72
64
73
return disposables ;
65
74
} ,
66
- getWindows ( ) : Iterable < IWindow > {
75
+ getWindows ( ) : Iterable < IRegisteredCodeWindow > {
67
76
return windows . values ( ) ;
68
77
} ,
69
78
getWindowsCount ( ) : number {
70
79
return windows . size ;
80
+ } ,
81
+ getWindowId ( targetWindow : Window ) : number {
82
+ return ( targetWindow as CodeWindow ) . vscodeWindowId ;
71
83
}
72
84
} ;
73
85
} ) ( ) ;
@@ -223,51 +235,65 @@ class AnimationFrameQueueItem implements IDisposable {
223
235
/**
224
236
* The runners scheduled at the next animation frame
225
237
*/
226
- let NEXT_QUEUE : AnimationFrameQueueItem [ ] = [ ] ;
238
+ const NEXT_QUEUE = new Map < number /* window ID */ , AnimationFrameQueueItem [ ] > ( ) ;
227
239
/**
228
240
* The runners scheduled at the current animation frame
229
241
*/
230
- let CURRENT_QUEUE : AnimationFrameQueueItem [ ] | null = null ;
242
+ const CURRENT_QUEUE = new Map < number /* window ID */ , AnimationFrameQueueItem [ ] > ( ) ;
231
243
/**
232
244
* A flag to keep track if the native requestAnimationFrame was already called
233
245
*/
234
- let animFrameRequested = false ;
246
+ const animFrameRequested = new Map < number /* window ID */ , boolean > ( ) ;
235
247
/**
236
248
* A flag to indicate if currently handling a native requestAnimationFrame callback
237
249
*/
238
- let inAnimationFrameRunner = false ;
250
+ const inAnimationFrameRunner = new Map < number /* window ID */ , boolean > ( ) ;
239
251
240
- const animationFrameRunner = ( ) => {
241
- animFrameRequested = false ;
252
+ const animationFrameRunner = ( targetWindowId : number ) => {
253
+ animFrameRequested . set ( targetWindowId , false ) ;
242
254
243
- CURRENT_QUEUE = NEXT_QUEUE ;
244
- NEXT_QUEUE = [ ] ;
255
+ const currentQueue = NEXT_QUEUE . get ( targetWindowId ) ?? [ ] ;
256
+ CURRENT_QUEUE . set ( targetWindowId , currentQueue ) ;
257
+ NEXT_QUEUE . set ( targetWindowId , [ ] ) ;
245
258
246
- inAnimationFrameRunner = true ;
247
- while ( CURRENT_QUEUE . length > 0 ) {
248
- CURRENT_QUEUE . sort ( AnimationFrameQueueItem . sort ) ;
249
- const top = CURRENT_QUEUE . shift ( ) ! ;
259
+ inAnimationFrameRunner . set ( targetWindowId , true ) ;
260
+ while ( currentQueue . length > 0 ) {
261
+ currentQueue . sort ( AnimationFrameQueueItem . sort ) ;
262
+ const top = currentQueue . shift ( ) ! ;
250
263
top . execute ( ) ;
251
264
}
252
- inAnimationFrameRunner = false ;
265
+ inAnimationFrameRunner . set ( targetWindowId , false ) ;
253
266
} ;
254
267
255
268
scheduleAtNextAnimationFrame = ( runner : ( ) => void , targetWindow : Window , priority : number = 0 ) => {
269
+ const targetWindowId = getWindowId ( targetWindow ) ;
256
270
const item = new AnimationFrameQueueItem ( runner , priority ) ;
257
- NEXT_QUEUE . push ( item ) ;
258
271
259
- if ( ! animFrameRequested ) {
260
- animFrameRequested = true ;
261
- targetWindow . requestAnimationFrame ( animationFrameRunner ) ;
272
+ let nextQueue = NEXT_QUEUE . get ( targetWindowId ) ;
273
+ if ( ! nextQueue ) {
274
+ nextQueue = [ ] ;
275
+ NEXT_QUEUE . set ( targetWindowId , nextQueue ) ;
276
+ }
277
+ nextQueue . push ( item ) ;
278
+
279
+ if ( ! animFrameRequested . get ( targetWindowId ) ) {
280
+ animFrameRequested . set ( targetWindowId , true ) ;
281
+ targetWindow . requestAnimationFrame ( ( ) => animationFrameRunner ( targetWindowId ) ) ;
262
282
}
263
283
264
284
return item ;
265
285
} ;
266
286
267
287
runAtThisOrScheduleAtNextAnimationFrame = ( runner : ( ) => void , targetWindow : Window , priority ?: number ) => {
268
- if ( inAnimationFrameRunner ) {
288
+ const targetWindowId = getWindowId ( targetWindow ) ;
289
+ if ( inAnimationFrameRunner . get ( targetWindowId ) ) {
269
290
const item = new AnimationFrameQueueItem ( runner , priority ) ;
270
- CURRENT_QUEUE ! . push ( item ) ;
291
+ let currentQueue = CURRENT_QUEUE . get ( targetWindowId ) ;
292
+ if ( ! currentQueue ) {
293
+ currentQueue = [ ] ;
294
+ CURRENT_QUEUE . set ( targetWindowId , currentQueue ) ;
295
+ }
296
+ currentQueue . push ( item ) ;
271
297
return item ;
272
298
} else {
273
299
return scheduleAtNextAnimationFrame ( runner , targetWindow , priority ) ;
@@ -775,25 +801,25 @@ export function getActiveDocument(): Document {
775
801
return documents . find ( document => document . hasFocus ( ) ) ?? document ;
776
802
}
777
803
778
- export function getActiveWindow ( ) : WindowGlobal {
804
+ export function getActiveWindow ( ) : CodeWindow {
779
805
const document = getActiveDocument ( ) ;
780
- return document . defaultView ?. window ?? window ;
806
+ return ( document . defaultView ?. window ?? window ) as CodeWindow ;
781
807
}
782
808
783
- export function getWindow ( element : Node | undefined | null ) : WindowGlobal ;
784
- export function getWindow ( event : UIEvent | undefined | null ) : WindowGlobal ;
785
- export function getWindow ( e : unknown ) : WindowGlobal {
809
+ export function getWindow ( element : Node | undefined | null ) : CodeWindow ;
810
+ export function getWindow ( event : UIEvent | undefined | null ) : CodeWindow ;
811
+ export function getWindow ( e : unknown ) : CodeWindow {
786
812
const candidateNode = e as Node | undefined | null ;
787
813
if ( candidateNode ?. ownerDocument ?. defaultView ) {
788
- return candidateNode . ownerDocument . defaultView . window ;
814
+ return candidateNode . ownerDocument . defaultView . window as CodeWindow ;
789
815
}
790
816
791
817
const candidateEvent = e as UIEvent | undefined | null ;
792
818
if ( candidateEvent ?. view ) {
793
- return candidateEvent . view . window ;
819
+ return candidateEvent . view . window as CodeWindow ;
794
820
}
795
821
796
- return window ;
822
+ return window as CodeWindow ;
797
823
}
798
824
799
825
export function focusWindow ( element : Node ) : void {
0 commit comments