From cb9c48673f166ae72f55cf19d6f77da518244180 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 9 Nov 2023 09:09:02 +0100 Subject: [PATCH] aux window - reduce deprecated `$window` usages (#197800) * aux window - reduce deprecated $window usages * aux window - reduce deprecated $window usages * aux window - reduce deprecated $window usages * aux window - reduce deprecated $window usages --- .../code-no-global-document-listener.ts | 30 +++++++++++++++++++ .eslintrc.json | 5 ++++ src/vs/base/browser/dom.ts | 20 ++++++------- .../editor/browser/controller/mouseTarget.ts | 14 ++++----- .../browser/controller/textAreaInput.ts | 6 ++-- .../contrib/codelens/browser/codeLensCache.ts | 4 +-- .../browser/parts/globalCompositeBar.ts | 5 ++-- src/vs/workbench/browser/web.main.ts | 2 +- src/vs/workbench/browser/window.ts | 4 +-- .../contrib/chat/browser/chatListRenderer.ts | 3 +- .../electron-sandbox/inputClipboardActions.ts | 4 +-- .../electron-sandbox/selectionClipboard.ts | 30 +++++++++++-------- .../extensionProfileService.ts | 4 +-- .../contrib/files/browser/fileImportExport.ts | 8 ++--- .../browser/languageStatus.contribution.ts | 10 +++---- .../contrib/clipboard/notebookClipboard.ts | 3 +- .../preferences/browser/settingsEditor2.ts | 5 ++-- .../contrib/remote/browser/remote.ts | 4 +-- .../links/browser/terminalLink.ts | 6 ++-- .../themes/browser/themes.contribution.ts | 6 ++-- .../url/browser/trustedDomainsValidator.ts | 10 +++---- .../webview/browser/webview.contribution.ts | 4 +-- .../browser/gettingStarted.ts | 7 ++--- .../browser/configurationService.ts | 4 +-- .../dialogs/browser/fileDialogService.ts | 25 +++++++++------- .../dialogs/browser/simpleFileDialog.ts | 6 ++-- .../builtinExtensionsScannerService.ts | 4 +-- .../extensions/browser/extensionUrlHandler.ts | 4 +-- .../browser/webWorkerExtensionHost.ts | 8 ++--- .../nativeExtensionService.ts | 4 +-- .../services/hover/browser/hoverService.ts | 9 +++--- .../services/hover/browser/hoverWidget.ts | 24 +++++++-------- .../themes/browser/fileIconThemeData.ts | 4 +-- .../browser/domActivityTracker.ts | 17 ++++++----- 34 files changed, 173 insertions(+), 130 deletions(-) create mode 100644 .eslintplugin/code-no-global-document-listener.ts diff --git a/.eslintplugin/code-no-global-document-listener.ts b/.eslintplugin/code-no-global-document-listener.ts new file mode 100644 index 00000000000..6b3e83fe1f5 --- /dev/null +++ b/.eslintplugin/code-no-global-document-listener.ts @@ -0,0 +1,30 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as eslint from 'eslint'; + +export = new class NoGlobalDocumentListener implements eslint.Rule.RuleModule { + + create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { + return { + CallExpression(node: any) { + if ( + ( + node.callee.name === 'addDisposableListener' || + node.callee.property?.name === 'addDisposableListener' + ) && + node.arguments.length > 0 && + node.arguments[0].type === 'Identifier' && + node.arguments[0].name === 'document' + ) { + context.report({ + node, + message: 'Use .document to support multi-window scenarios. Resolve targetWindow with DOM.getWindow(element) or DOM.getActiveWindow() or use the predefined mainWindow constant.', + }); + } + }, + } + } +}; diff --git a/.eslintrc.json b/.eslintrc.json index 585ad5be737..68ec2cf473f 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -261,6 +261,7 @@ "src/**/{browser,electron-sandbox}/*.ts" ], "rules": { + "local/code-no-global-document-listener": "warn", "no-restricted-syntax": [ "warn", { @@ -283,6 +284,10 @@ "selector": "MemberExpression[object.name='document'][property.name='activeElement']", "message": "Use .document.activeElement to support multi-window scenarios. Resolve targetWindow with DOM.getWindow(element) or DOM.getActiveWindow() or use the predefined mainWindow constant." }, + { + "selector": "MemberExpression[object.name='document'][property.name='contains']", + "message": "Use .document.contains to support multi-window scenarios. Resolve targetWindow with DOM.getWindow(element) or DOM.getActiveWindow() or use the predefined mainWindow constant." + }, { "selector": "MemberExpression[object.name='document'][property.name='styleSheets']", "message": "Use .document.styleSheets to support multi-window scenarios. Resolve targetWindow with DOM.getWindow(element) or DOM.getActiveWindow() or use the predefined mainWindow constant." diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts index 6f5b645357c..b82c6e95660 100644 --- a/src/vs/base/browser/dom.ts +++ b/src/vs/base/browser/dom.ts @@ -17,7 +17,7 @@ import { FileAccess, RemoteAuthorities, Schemas } from 'vs/base/common/network'; import * as platform from 'vs/base/common/platform'; import { URI } from 'vs/base/common/uri'; import { hash } from 'vs/base/common/hash'; -import { CodeWindow, mainWindow, $window } from 'vs/base/browser/window'; +import { CodeWindow, mainWindow } from 'vs/base/browser/window'; interface IRegisteredCodeWindow { readonly window: CodeWindow; @@ -1490,7 +1490,7 @@ export function windowOpenNoOpener(url: string): void { // See https://developer.mozilla.org/en-US/docs/Web/API/Window/open#noopener // However, this also doesn't allow us to realize if the browser blocked // the creation of the window. - $window.open(url, '_blank', 'noopener'); + mainWindow.open(url, '_blank', 'noopener'); } /** @@ -1506,9 +1506,9 @@ export function windowOpenNoOpener(url: string): void { */ const popupWidth = 780, popupHeight = 640; export function windowOpenPopup(url: string): void { - const left = Math.floor($window.screenLeft + $window.innerWidth / 2 - popupWidth / 2); - const top = Math.floor($window.screenTop + $window.innerHeight / 2 - popupHeight / 2); - $window.open( + const left = Math.floor(mainWindow.screenLeft + mainWindow.innerWidth / 2 - popupWidth / 2); + const top = Math.floor(mainWindow.screenTop + mainWindow.innerHeight / 2 - popupHeight / 2); + mainWindow.open( url, '_blank', `width=${popupWidth},height=${popupHeight},top=${top},left=${left}` @@ -1531,7 +1531,7 @@ export function windowOpenPopup(url: string): void { * @returns boolean indicating if the {@link window.open} call succeeded */ export function windowOpenWithSuccess(url: string, noOpener = true): boolean { - const newTab = $window.open(); + const newTab = mainWindow.open(); if (newTab) { if (noOpener) { // see `windowOpenNoOpener` for details on why this is important @@ -1667,10 +1667,10 @@ export interface IDetectedFullscreen { guess: boolean; } -export function detectFullscreen(): IDetectedFullscreen | null { +export function detectFullscreen(targetWindow: Window): IDetectedFullscreen | null { // Browser fullscreen: use DOM APIs to detect - if ($window.document.fullscreenElement || ($window.document).webkitFullscreenElement || ($window.document).webkitIsFullScreen) { + if (targetWindow.document.fullscreenElement || (targetWindow.document).webkitFullscreenElement || (targetWindow.document).webkitIsFullScreen) { return { mode: DetectedFullscreenMode.DOCUMENT, guess: false }; } @@ -1679,7 +1679,7 @@ export function detectFullscreen(): IDetectedFullscreen | null { // height and comparing that to window height, we can guess // it though. - if ($window.innerHeight === $window.screen.height) { + if (targetWindow.innerHeight === targetWindow.screen.height) { // if the height of the window matches the screen height, we can // safely assume that the browser is fullscreen because no browser // chrome is taking height away (e.g. like toolbars). @@ -1688,7 +1688,7 @@ export function detectFullscreen(): IDetectedFullscreen | null { if (platform.isMacintosh || platform.isLinux) { // macOS and Linux do not properly report `innerHeight`, only Windows does - if ($window.outerHeight === $window.screen.height && $window.outerWidth === $window.screen.width) { + if (targetWindow.outerHeight === targetWindow.screen.height && targetWindow.outerWidth === targetWindow.screen.width) { // if the height of the browser matches the screen height, we can // only guess that we are in fullscreen. It is also possible that // the user has turned off taskbars in the OS and the browser is diff --git a/src/vs/editor/browser/controller/mouseTarget.ts b/src/vs/editor/browser/controller/mouseTarget.ts index 9f09b02f397..991199472b3 100644 --- a/src/vs/editor/browser/controller/mouseTarget.ts +++ b/src/vs/editor/browser/controller/mouseTarget.ts @@ -20,7 +20,6 @@ import * as dom from 'vs/base/browser/dom'; import { AtomicTabMoveOperations, Direction } from 'vs/editor/common/cursor/cursorAtomicMoveOperations'; import { PositionAffinity } from 'vs/editor/common/model'; import { InjectedText } from 'vs/editor/common/modelLineProjectionData'; -import { $window } from 'vs/base/browser/window'; const enum HitTestResultType { Unknown, @@ -1047,12 +1046,13 @@ function shadowCaretRangeFromPoint(shadowRoot: ShadowRoot, x: number, y: number) const rect = el.getBoundingClientRect(); // And its font (the computed shorthand font property might be empty, see #3217) - const fontStyle = $window.getComputedStyle(el, null).getPropertyValue('font-style'); - const fontVariant = $window.getComputedStyle(el, null).getPropertyValue('font-variant'); - const fontWeight = $window.getComputedStyle(el, null).getPropertyValue('font-weight'); - const fontSize = $window.getComputedStyle(el, null).getPropertyValue('font-size'); - const lineHeight = $window.getComputedStyle(el, null).getPropertyValue('line-height'); - const fontFamily = $window.getComputedStyle(el, null).getPropertyValue('font-family'); + const elWindow = dom.getWindow(el); + const fontStyle = elWindow.getComputedStyle(el, null).getPropertyValue('font-style'); + const fontVariant = elWindow.getComputedStyle(el, null).getPropertyValue('font-variant'); + const fontWeight = elWindow.getComputedStyle(el, null).getPropertyValue('font-weight'); + const fontSize = elWindow.getComputedStyle(el, null).getPropertyValue('font-size'); + const lineHeight = elWindow.getComputedStyle(el, null).getPropertyValue('line-height'); + const fontFamily = elWindow.getComputedStyle(el, null).getPropertyValue('font-family'); const font = `${fontStyle} ${fontVariant} ${fontWeight} ${fontSize}/${lineHeight} ${fontFamily}`; // And also its txt content diff --git a/src/vs/editor/browser/controller/textAreaInput.ts b/src/vs/editor/browser/controller/textAreaInput.ts index cc8c58ebbd4..d0a06a18c51 100644 --- a/src/vs/editor/browser/controller/textAreaInput.ts +++ b/src/vs/editor/browser/controller/textAreaInput.ts @@ -8,7 +8,6 @@ import * as dom from 'vs/base/browser/dom'; import { DomEmitter } from 'vs/base/browser/event'; import { IKeyboardEvent, StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { inputLatency } from 'vs/base/browser/performance'; -import { $window } from 'vs/base/browser/window'; import { RunOnceScheduler } from 'vs/base/common/async'; import { Emitter, Event } from 'vs/base/common/event'; import { KeyCode } from 'vs/base/common/keyCodes'; @@ -784,6 +783,7 @@ export class TextAreaWrapper extends Disposable implements ICompleteTextAreaWrap } else { activeElement = textArea.ownerDocument.activeElement; } + const activeWindow = dom.getWindow(activeElement); const currentIsFocused = (activeElement === textArea); const currentSelectionStart = textArea.selectionStart; @@ -792,7 +792,7 @@ export class TextAreaWrapper extends Disposable implements ICompleteTextAreaWrap if (currentIsFocused && currentSelectionStart === selectionStart && currentSelectionEnd === selectionEnd) { // No change // Firefox iframe bug https://github.com/microsoft/monaco-editor/issues/643#issuecomment-367871377 - if (browser.isFirefox && $window.parent !== $window) { + if (browser.isFirefox && activeWindow.parent !== activeWindow) { textArea.focus(); } return; @@ -804,7 +804,7 @@ export class TextAreaWrapper extends Disposable implements ICompleteTextAreaWrap // No need to focus, only need to change the selection range this.setIgnoreSelectionChangeTime('setSelectionRange'); textArea.setSelectionRange(selectionStart, selectionEnd); - if (browser.isFirefox && $window.parent !== $window) { + if (browser.isFirefox && activeWindow.parent !== activeWindow) { textArea.focus(); } return; diff --git a/src/vs/editor/contrib/codelens/browser/codeLensCache.ts b/src/vs/editor/contrib/codelens/browser/codeLensCache.ts index 1984f38f898..67fa3b8009c 100644 --- a/src/vs/editor/contrib/codelens/browser/codeLensCache.ts +++ b/src/vs/editor/contrib/codelens/browser/codeLensCache.ts @@ -12,7 +12,7 @@ import { CodeLensModel } from 'vs/editor/contrib/codelens/browser/codelens'; import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IStorageService, StorageScope, StorageTarget, WillSaveStateReason } from 'vs/platform/storage/common/storage'; -import { $window } from 'vs/base/browser/window'; +import { mainWindow } from 'vs/base/browser/window'; import { runWhenWindowIdle } from 'vs/base/browser/dom'; export const ICodeLensCache = createDecorator('ICodeLensCache'); @@ -53,7 +53,7 @@ export class CodeLensCache implements ICodeLensCache { // remove old data const oldkey = 'codelens/cache'; - runWhenWindowIdle($window, () => storageService.remove(oldkey, StorageScope.WORKSPACE)); + runWhenWindowIdle(mainWindow, () => storageService.remove(oldkey, StorageScope.WORKSPACE)); // restore lens data on start const key = 'codelens/cache2'; diff --git a/src/vs/workbench/browser/parts/globalCompositeBar.ts b/src/vs/workbench/browser/parts/globalCompositeBar.ts index 231b23648a6..604f48f90b6 100644 --- a/src/vs/workbench/browser/parts/globalCompositeBar.ts +++ b/src/vs/workbench/browser/parts/globalCompositeBar.ts @@ -18,7 +18,7 @@ import { ThemeIcon } from 'vs/base/common/themables'; import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; import { Action, IAction, Separator, SubmenuAction, toAction } from 'vs/base/common/actions'; import { IMenu, IMenuService, MenuId } from 'vs/platform/actions/common/actions'; -import { addDisposableListener, EventType, append, clearNode, hide, show, EventHelper, $, runWhenWindowIdle } from 'vs/base/browser/dom'; +import { addDisposableListener, EventType, append, clearNode, hide, show, EventHelper, $, runWhenWindowIdle, getWindow } from 'vs/base/browser/dom'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; import { EventType as TouchEventType, GestureEvent } from 'vs/base/browser/touch'; @@ -42,7 +42,6 @@ import { DEFAULT_ICON } from 'vs/workbench/services/userDataProfile/common/userD import { isString } from 'vs/base/common/types'; import { KeyCode } from 'vs/base/common/keyCodes'; import { ACTIVITY_BAR_BADGE_BACKGROUND, ACTIVITY_BAR_BADGE_FOREGROUND } from 'vs/workbench/common/theme'; -import { $window } from 'vs/base/browser/window'; export class GlobalCompositeBar extends Disposable { @@ -354,7 +353,7 @@ export class AccountsActivityActionViewItem extends AbstractGlobalActivityAction if (this._store.isDisposed) { return; } - const disposable = this._register(runWhenWindowIdle($window, async () => { + const disposable = this._register(runWhenWindowIdle(getWindow(this.element), async () => { await this.doInitialize(); disposable.dispose(); })); diff --git a/src/vs/workbench/browser/web.main.ts b/src/vs/workbench/browser/web.main.ts index 10b6141ce9c..c0243a0785c 100644 --- a/src/vs/workbench/browser/web.main.ts +++ b/src/vs/workbench/browser/web.main.ts @@ -114,7 +114,7 @@ export class BrowserMain extends Disposable { private init(): void { // Browser config - setFullscreen(!!detectFullscreen()); + setFullscreen(!!detectFullscreen(mainWindow)); } async open(): Promise { diff --git a/src/vs/workbench/browser/window.ts b/src/vs/workbench/browser/window.ts index 0293a819b2f..47d532a7251 100644 --- a/src/vs/workbench/browser/window.ts +++ b/src/vs/workbench/browser/window.ts @@ -75,12 +75,12 @@ export class BrowserWindow extends Disposable { // Fullscreen (Browser) for (const event of [EventType.FULLSCREEN_CHANGE, EventType.WK_FULLSCREEN_CHANGE]) { - this._register(addDisposableListener(document, event, () => setFullscreen(!!detectFullscreen()))); + this._register(addDisposableListener(mainWindow.document, event, () => setFullscreen(!!detectFullscreen(mainWindow)))); } // Fullscreen (Native) this._register(addDisposableThrottledListener(viewport, EventType.RESIZE, () => { - setFullscreen(!!detectFullscreen()); + setFullscreen(!!detectFullscreen(mainWindow)); }, undefined, isMacintosh ? 2000 /* adjust for macOS animation */ : 800 /* can be throttled */)); } diff --git a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts index 8524d2263fd..7ca9fde120a 100644 --- a/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts +++ b/src/vs/workbench/contrib/chat/browser/chatListRenderer.ts @@ -14,7 +14,6 @@ import { ITreeCompressionDelegate } from 'vs/base/browser/ui/tree/asyncDataTree' import { ICompressedTreeNode } from 'vs/base/browser/ui/tree/compressedObjectTreeModel'; import { ICompressibleTreeRenderer } from 'vs/base/browser/ui/tree/objectTree'; import { IAsyncDataSource, ITreeNode, ITreeRenderer } from 'vs/base/browser/ui/tree/tree'; -import { $window } from 'vs/base/browser/window'; import { IAction } from 'vs/base/common/actions'; import { distinct } from 'vs/base/common/arrays'; import { disposableTimeout } from 'vs/base/common/async'; @@ -312,7 +311,7 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer { - $window.document.execCommand(command); + getActiveWindow().document.execCommand(command); }; } } diff --git a/src/vs/workbench/contrib/codeEditor/electron-sandbox/selectionClipboard.ts b/src/vs/workbench/contrib/codeEditor/electron-sandbox/selectionClipboard.ts index ba50a21294c..025c038bfe4 100644 --- a/src/vs/workbench/contrib/codeEditor/electron-sandbox/selectionClipboard.ts +++ b/src/vs/workbench/contrib/codeEditor/electron-sandbox/selectionClipboard.ts @@ -21,7 +21,9 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { Extensions as WorkbenchExtensions, IWorkbenchContribution, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; -import { $window } from 'vs/base/browser/window'; +import { mainWindow } from 'vs/base/browser/window'; +import { Event } from 'vs/base/common/event'; +import { addDisposableListener, onDidRegisterWindow } from 'vs/base/browser/dom'; export class SelectionClipboard extends Disposable implements IEditorContribution { private static readonly SELECTION_LENGTH_LIMIT = 65536; @@ -90,22 +92,26 @@ export class SelectionClipboard extends Disposable implements IEditorContributio } } -class SelectionClipboardPastePreventer implements IWorkbenchContribution { +class SelectionClipboardPastePreventer extends Disposable implements IWorkbenchContribution { constructor( @IConfigurationService configurationService: IConfigurationService ) { + super(); + if (platform.isLinux) { - $window.document.addEventListener('mouseup', (e) => { - if (e.button === 1) { - // middle button - const config = configurationService.getValue<{ selectionClipboard: boolean }>('editor'); - if (!config.selectionClipboard) { - // selection clipboard is disabled - // try to stop the upcoming paste - e.preventDefault(); + this._register(Event.runAndSubscribe(onDidRegisterWindow, ({ window, disposables }) => { + disposables.add(addDisposableListener(window.document, 'mouseup', e => { + if (e.button === 1) { + // middle button + const config = configurationService.getValue<{ selectionClipboard: boolean }>('editor'); + if (!config.selectionClipboard) { + // selection clipboard is disabled + // try to stop the upcoming paste + e.preventDefault(); + } } - } - }); + })); + }, { window: mainWindow, disposables: this._store })); } } } diff --git a/src/vs/workbench/contrib/extensions/electron-sandbox/extensionProfileService.ts b/src/vs/workbench/contrib/extensions/electron-sandbox/extensionProfileService.ts index 6a3b99cd942..bd147b70b7e 100644 --- a/src/vs/workbench/contrib/extensions/electron-sandbox/extensionProfileService.ts +++ b/src/vs/workbench/contrib/extensions/electron-sandbox/extensionProfileService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { disposableWindowInterval } from 'vs/base/browser/dom'; -import { $window } from 'vs/base/browser/window'; +import { mainWindow } from 'vs/base/browser/window'; import { onUnexpectedError } from 'vs/base/common/errors'; import { Emitter, Event } from 'vs/base/common/event'; import { Disposable, MutableDisposable } from 'vs/base/common/lifecycle'; @@ -94,7 +94,7 @@ export class ExtensionHostProfileService extends Disposable implements IExtensio }; const timeStarted = Date.now(); - const handle = disposableWindowInterval($window, () => { + const handle = disposableWindowInterval(mainWindow, () => { this.profilingStatusBarIndicator?.update({ ...indicator, text: nls.localize('profilingExtensionHostTime', "Profiling Extension Host ({0} sec)", Math.round((new Date().getTime() - timeStarted) / 1000)), }); }, 1000); this.profilingStatusBarIndicatorLabelUpdater.value = handle; diff --git a/src/vs/workbench/contrib/files/browser/fileImportExport.ts b/src/vs/workbench/contrib/files/browser/fileImportExport.ts index efb8b50534c..86f4f228580 100644 --- a/src/vs/workbench/contrib/files/browser/fileImportExport.ts +++ b/src/vs/workbench/contrib/files/browser/fileImportExport.ts @@ -23,7 +23,7 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace import { extractEditorsAndFilesDropData } from 'vs/platform/dnd/browser/dnd'; import { IWorkspaceEditingService } from 'vs/workbench/services/workspaces/common/workspaceEditing'; import { isWeb } from 'vs/base/common/platform'; -import { isDragEvent, triggerDownload } from 'vs/base/browser/dom'; +import { getActiveWindow, isDragEvent, triggerDownload } from 'vs/base/browser/dom'; import { ILogService } from 'vs/platform/log/common/log'; import { FileAccess, Schemas } from 'vs/base/common/network'; import { mnemonicButtonLabel } from 'vs/base/common/labels'; @@ -36,7 +36,6 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { WebFileSystemAccess } from 'vs/platform/files/browser/webFileSystemAccess'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; -import { $window } from 'vs/base/browser/window'; //#region Browser File Upload (drag and drop, input element) @@ -655,9 +654,10 @@ export class FileDownload { const preferFileSystemAccessWebApis = stat.isDirectory || stat.size > maxBlobDownloadSize; // Folder: use FS APIs to download files and folders if available and preferred - if (preferFileSystemAccessWebApis && WebFileSystemAccess.supported($window)) { + const activeWindow = getActiveWindow(); + if (preferFileSystemAccessWebApis && WebFileSystemAccess.supported(activeWindow)) { try { - const parentFolder: FileSystemDirectoryHandle = await $window.showDirectoryPicker(); + const parentFolder: FileSystemDirectoryHandle = await activeWindow.showDirectoryPicker(); const operation: IDownloadOperation = { startTime: Date.now(), progressScheduler: new RunOnceWorker(steps => { progress.report(steps[steps.length - 1]); }, 1000), diff --git a/src/vs/workbench/contrib/languageStatus/browser/languageStatus.contribution.ts b/src/vs/workbench/contrib/languageStatus/browser/languageStatus.contribution.ts index 1160e6249a8..d0f622842b7 100644 --- a/src/vs/workbench/contrib/languageStatus/browser/languageStatus.contribution.ts +++ b/src/vs/workbench/contrib/languageStatus/browser/languageStatus.contribution.ts @@ -31,7 +31,7 @@ import { Action2, registerAction2 } from 'vs/platform/actions/common/actions'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { Categories } from 'vs/platform/action/common/actionCommonCategories'; import { IAccessibilityInformation } from 'vs/platform/accessibility/common/accessibility'; -import { $window } from 'vs/base/browser/window'; +import { mainWindow } from 'vs/base/browser/window'; class LanguageStatusViewModel { @@ -203,8 +203,8 @@ class EditorStatusContribution implements IWorkbenchContribution { // animate the status bar icon whenever language status changes, repeat animation // when severity is warning or error, don't show animation when showing progress/busy const userHasInteractedWithStatus = this._interactionCounter.value >= 3; - const node = $window.document.querySelector('.monaco-workbench .statusbar DIV#status\\.languageStatus A>SPAN.codicon'); - const container = $window.document.querySelector('.monaco-workbench .statusbar DIV#status\\.languageStatus'); + const node = mainWindow.document.querySelector('.monaco-workbench .statusbar DIV#status\\.languageStatus A>SPAN.codicon'); + const container = mainWindow.document.querySelector('.monaco-workbench .statusbar DIV#status\\.languageStatus'); if (node instanceof HTMLElement && container) { const _wiggle = 'wiggle'; const _flash = 'flash'; @@ -224,10 +224,10 @@ class EditorStatusContribution implements IWorkbenchContribution { // track when the hover shows (this is automagic and DOM mutation spying is needed...) // use that as signal that the user has interacted/learned language status items work if (!userHasInteractedWithStatus) { - const hoverTarget = $window.document.querySelector('.monaco-workbench .context-view'); + const hoverTarget = mainWindow.document.querySelector('.monaco-workbench .context-view'); if (hoverTarget instanceof HTMLElement) { const observer = new MutationObserver(() => { - if (document.contains(element)) { + if (mainWindow.document.contains(element)) { this._interactionCounter.increment(); observer.disconnect(); } diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/clipboard/notebookClipboard.ts b/src/vs/workbench/contrib/notebook/browser/contrib/clipboard/notebookClipboard.ts index d112e828555..a80df1911de 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/clipboard/notebookClipboard.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/clipboard/notebookClipboard.ts @@ -31,7 +31,6 @@ import { ILogService } from 'vs/platform/log/common/log'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { showWindowLogActionId } from 'vs/workbench/services/log/common/logConstants'; import { getActiveElement, getWindow } from 'vs/base/browser/dom'; -import { $window } from 'vs/base/browser/window'; let _logging: boolean = false; function toggleLogging() { @@ -162,7 +161,7 @@ export function runCopyCells(accessor: ServicesAccessor, editor: INotebookEditor } if (editor.hasOutputTextSelection()) { - $window.document.execCommand('copy'); + getWindow(editor.getDomNode()).document.execCommand('copy'); return true; } diff --git a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts index 8f4062d9f25..274de133d37 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts @@ -65,7 +65,6 @@ import { defaultButtonStyles } from 'vs/platform/theme/browser/defaultStyles'; import { IProductService } from 'vs/platform/product/common/productService'; import { registerNavigableContainer } from 'vs/workbench/browser/actions/widgetNavigationCommands'; import { IEditorProgressService } from 'vs/platform/progress/common/progress'; -import { $window } from 'vs/base/browser/window'; export const enum SettingsFocusContext { @@ -1412,7 +1411,7 @@ export class SettingsEditor2 extends EditorPane { // If the context view is focused, delay rendering settings if (this.contextViewFocused()) { - const element = $window.document.querySelector('.context-view'); + const element = DOM.getWindow(this.settingsTree.getHTMLElement()).document.querySelector('.context-view'); if (element) { this.scheduleRefresh(element as HTMLElement, key); } @@ -1869,7 +1868,7 @@ class SyncControls extends Disposable { })); const updateLastSyncedTimer = this._register(new DOM.WindowIntervalTimer()); - updateLastSyncedTimer.cancelAndSet(() => this.updateLastSyncedTime(), 60 * 1000, $window); + updateLastSyncedTimer.cancelAndSet(() => this.updateLastSyncedTime(), 60 * 1000, DOM.getWindow(container)); this.update(); this._register(this.userDataSyncService.onDidChangeStatus(() => { diff --git a/src/vs/workbench/contrib/remote/browser/remote.ts b/src/vs/workbench/contrib/remote/browser/remote.ts index 4c428f50575..ffa5cdd0204 100644 --- a/src/vs/workbench/contrib/remote/browser/remote.ts +++ b/src/vs/workbench/contrib/remote/browser/remote.ts @@ -53,7 +53,7 @@ import { getRemoteName } from 'vs/platform/remote/common/remoteHosts'; import { getVirtualWorkspaceLocation } from 'vs/platform/workspace/common/virtualWorkspace'; import { IWalkthroughsService } from 'vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedService'; import { Schemas } from 'vs/base/common/network'; -import { $window } from 'vs/base/browser/window'; +import { mainWindow } from 'vs/base/browser/window'; interface IViewModel { onDidChangeHelpInformation: Event; @@ -752,7 +752,7 @@ class ReconnectionTimer implements IDisposable { constructor(parent: VisibleProgress, completionTime: number) { this._parent = parent; this._completionTime = completionTime; - this._renderInterval = dom.disposableWindowInterval($window, () => this._render(), 1000); + this._renderInterval = dom.disposableWindowInterval(mainWindow, () => this._render(), 1000); this._render(); } diff --git a/src/vs/workbench/contrib/terminalContrib/links/browser/terminalLink.ts b/src/vs/workbench/contrib/terminalContrib/links/browser/terminalLink.ts index 3ed2f05ef08..a06be140f57 100644 --- a/src/vs/workbench/contrib/terminalContrib/links/browser/terminalLink.ts +++ b/src/vs/workbench/contrib/terminalContrib/links/browser/terminalLink.ts @@ -64,12 +64,12 @@ export class TerminalLink extends DisposableStore implements ILink { hover(event: MouseEvent, text: string): void { // Listen for modifier before handing it off to the hover to handle so it gets disposed correctly this._hoverListeners = new DisposableStore(); - this._hoverListeners.add(dom.addDisposableListener(document, 'keydown', e => { + this._hoverListeners.add(dom.addDisposableListener($window.document, 'keydown', e => { if (!e.repeat && this._isModifierDown(e)) { this._enableDecorations(); } })); - this._hoverListeners.add(dom.addDisposableListener(document, 'keyup', e => { + this._hoverListeners.add(dom.addDisposableListener($window.document, 'keyup', e => { if (!e.repeat && !this._isModifierDown(e)) { this._disableDecorations(); } @@ -102,7 +102,7 @@ export class TerminalLink extends DisposableStore implements ILink { } const origin = { x: event.pageX, y: event.pageY }; - this._hoverListeners.add(dom.addDisposableListener(document, dom.EventType.MOUSE_MOVE, e => { + this._hoverListeners.add(dom.addDisposableListener($window.document, dom.EventType.MOUSE_MOVE, e => { // Update decorations if (this._isModifierDown(e)) { this._enableDecorations(); diff --git a/src/vs/workbench/contrib/themes/browser/themes.contribution.ts b/src/vs/workbench/contrib/themes/browser/themes.contribution.ts index aef2eca7dc7..9f8044bbb1b 100644 --- a/src/vs/workbench/contrib/themes/browser/themes.contribution.ts +++ b/src/vs/workbench/contrib/themes/browser/themes.contribution.ts @@ -44,7 +44,7 @@ import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storag import { isWeb } from 'vs/base/common/platform'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IHostService } from 'vs/workbench/services/host/browser/host'; -import { $window } from 'vs/base/browser/window'; +import { getActiveWindow } from 'vs/base/browser/dom'; export const manageExtensionIcon = registerIcon('theme-selection-manage-extension', Codicon.gear, localize('manageExtensionIcon', 'Icon for the \'Manage\' action in the theme selection quick pick.')); @@ -307,7 +307,7 @@ class InstalledThemesPicker { if (selectThemeTimeout) { clearTimeout(selectThemeTimeout); } - selectThemeTimeout = $window.setTimeout(() => { + selectThemeTimeout = getActiveWindow().setTimeout(() => { selectThemeTimeout = undefined; const newTheme = (theme ?? currentTheme) as IWorkbenchTheme; this.setTheme(newTheme, applyTheme ? 'auto' : 'preview').then(undefined, @@ -702,7 +702,7 @@ registerAction2(class extends Action2 { if (selectThemeTimeout) { clearTimeout(selectThemeTimeout); } - selectThemeTimeout = $window.setTimeout(() => { + selectThemeTimeout = getActiveWindow().setTimeout(() => { selectThemeTimeout = undefined; const newTheme = (theme ?? currentTheme) as IWorkbenchTheme; themeService.setColorTheme(newTheme as IWorkbenchColorTheme, applyTheme ? 'auto' : 'preview').then(undefined, diff --git a/src/vs/workbench/contrib/url/browser/trustedDomainsValidator.ts b/src/vs/workbench/contrib/url/browser/trustedDomainsValidator.ts index f0cab6c4094..20cb4e67a50 100644 --- a/src/vs/workbench/contrib/url/browser/trustedDomainsValidator.ts +++ b/src/vs/workbench/contrib/url/browser/trustedDomainsValidator.ts @@ -23,7 +23,7 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace import { testUrlMatchesGlob } from 'vs/workbench/contrib/url/common/urlGlob'; import { IWorkspaceTrustManagementService } from 'vs/platform/workspace/common/workspaceTrust'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { $window } from 'vs/base/browser/window'; +import { mainWindow } from 'vs/base/browser/window'; import { WindowIdleValue } from 'vs/base/browser/dom'; export class OpenerValidatorContributions implements IWorkbenchContribution { @@ -48,19 +48,19 @@ export class OpenerValidatorContributions implements IWorkbenchContribution { ) { this._openerService.registerValidator({ shouldOpen: (uri, options) => this.validateLink(uri, options) }); - this._readAuthenticationTrustedDomainsResult = new WindowIdleValue($window, () => + this._readAuthenticationTrustedDomainsResult = new WindowIdleValue(mainWindow, () => this._instantiationService.invokeFunction(readAuthenticationTrustedDomains)); this._authenticationService.onDidRegisterAuthenticationProvider(() => { this._readAuthenticationTrustedDomainsResult?.dispose(); - this._readAuthenticationTrustedDomainsResult = new WindowIdleValue($window, () => + this._readAuthenticationTrustedDomainsResult = new WindowIdleValue(mainWindow, () => this._instantiationService.invokeFunction(readAuthenticationTrustedDomains)); }); - this._readWorkspaceTrustedDomainsResult = new WindowIdleValue($window, () => + this._readWorkspaceTrustedDomainsResult = new WindowIdleValue(mainWindow, () => this._instantiationService.invokeFunction(readWorkspaceTrustedDomains)); this._workspaceContextService.onDidChangeWorkspaceFolders(() => { this._readWorkspaceTrustedDomainsResult?.dispose(); - this._readWorkspaceTrustedDomainsResult = new WindowIdleValue($window, () => + this._readWorkspaceTrustedDomainsResult = new WindowIdleValue(mainWindow, () => this._instantiationService.invokeFunction(readWorkspaceTrustedDomains)); }); } diff --git a/src/vs/workbench/contrib/webview/browser/webview.contribution.ts b/src/vs/workbench/contrib/webview/browser/webview.contribution.ts index 95db9a4365a..6fde8271d07 100644 --- a/src/vs/workbench/contrib/webview/browser/webview.contribution.ts +++ b/src/vs/workbench/contrib/webview/browser/webview.contribution.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { $window } from 'vs/base/browser/window'; +import { getActiveElement } from 'vs/base/browser/dom'; import { MultiCommand, RedoCommand, SelectAllCommand, UndoCommand } from 'vs/editor/browser/editorExtensions'; import { CopyAction, CutAction, PasteAction } from 'vs/editor/contrib/clipboard/browser/clipboard'; import * as nls from 'vs/nls'; @@ -27,7 +27,7 @@ function overrideCommandForWebview(command: MultiCommand | undefined, f: (webvie // When focused in a custom menu try to fallback to the active webview // This is needed for context menu actions and the menubar - if ($window.document.activeElement?.classList.contains('action-menu-item')) { + if (getActiveElement()?.classList.contains('action-menu-item')) { const editorService = accessor.get(IEditorService); if (editorService.activeEditor instanceof WebviewInput) { f(editorService.activeEditor.webview); diff --git a/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.ts b/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.ts index db958f14be6..5fd3578b39f 100644 --- a/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.ts +++ b/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.ts @@ -10,7 +10,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { IEditorSerializer, IEditorOpenContext } from 'vs/workbench/common/editor'; import { DisposableStore, toDisposable } from 'vs/base/common/lifecycle'; import { assertIsDefined } from 'vs/base/common/types'; -import { $, addDisposableListener, append, clearNode, Dimension, reset } from 'vs/base/browser/dom'; +import { $, addDisposableListener, append, clearNode, Dimension, getWindow, reset } from 'vs/base/browser/dom'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { IProductService } from 'vs/platform/product/common/productService'; import { hiddenEntriesConfigurationKey, IResolvedWalkthrough, IResolvedWalkthroughStep, IWalkthroughsService } from 'vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedService'; @@ -74,7 +74,6 @@ import { IFeaturedExtension } from 'vs/base/common/product'; import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; import { onUnexpectedError } from 'vs/base/common/errors'; -import { $window } from 'vs/base/browser/window'; const SLIDE_TRANSITION_TIME_MS = 250; const configurationKey = 'workbench.startupEditor'; @@ -286,7 +285,7 @@ export class GettingStartedPage extends EditorPane { ourStep.done = step.done; if (category.id === this.currentWalkthrough?.id) { - const badgeelements = assertIsDefined($window.document.querySelectorAll(`[data-done-step-id="${step.id}"]`)); + const badgeelements = assertIsDefined(getWindow(this.container).document.querySelectorAll(`[data-done-step-id="${step.id}"]`)); badgeelements.forEach(badgeelement => { if (step.done) { badgeelement.parentElement?.setAttribute('aria-checked', 'true'); @@ -1176,7 +1175,7 @@ export class GettingStartedPage extends EditorPane { } private updateCategoryProgress() { - $window.document.querySelectorAll('.category-progress').forEach(element => { + getWindow(this.container).document.querySelectorAll('.category-progress').forEach(element => { const categoryID = element.getAttribute('x-data-category-id'); const category = this.gettingStartedCategories.find(category => category.id === categoryID); if (!category) { throw Error('Could not find category with ID ' + categoryID); } diff --git a/src/vs/workbench/services/configuration/browser/configurationService.ts b/src/vs/workbench/services/configuration/browser/configurationService.ts index ba5fbd5e83c..4b2d169a83b 100644 --- a/src/vs/workbench/services/configuration/browser/configurationService.ts +++ b/src/vs/workbench/services/configuration/browser/configurationService.ts @@ -45,7 +45,7 @@ import { IUserDataProfile, IUserDataProfilesService } from 'vs/platform/userData import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing'; import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService'; import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuration'; -import { $window } from 'vs/base/browser/window'; +import { mainWindow } from 'vs/base/browser/window'; import { runWhenWindowIdle } from 'vs/base/browser/dom'; function getLocalUserConfigurationScopes(userDataProfile: IUserDataProfile, hasRemote: boolean): ConfigurationScope[] | undefined { @@ -578,7 +578,7 @@ export class WorkspaceService extends Disposable implements IWorkbenchConfigurat if (!this.localUserConfiguration.hasTasksLoaded) { // Reload local user configuration again to load user tasks - this._register(runWhenWindowIdle($window, () => this.reloadLocalUserConfiguration(false, this._configuration.localUserConfiguration))); + this._register(runWhenWindowIdle(mainWindow, () => this.reloadLocalUserConfiguration(false, this._configuration.localUserConfiguration))); } } diff --git a/src/vs/workbench/services/dialogs/browser/fileDialogService.ts b/src/vs/workbench/services/dialogs/browser/fileDialogService.ts index 6c1a5f23341..aa590e8a240 100644 --- a/src/vs/workbench/services/dialogs/browser/fileDialogService.ts +++ b/src/vs/workbench/services/dialogs/browser/fileDialogService.ts @@ -13,13 +13,12 @@ import { HTMLFileSystemProvider } from 'vs/platform/files/browser/htmlFileSystem import { localize } from 'vs/nls'; import { getMediaOrTextMime } from 'vs/base/common/mime'; import { basename } from 'vs/base/common/resources'; -import { triggerDownload, triggerUpload } from 'vs/base/browser/dom'; +import { getActiveWindow, triggerDownload, triggerUpload } from 'vs/base/browser/dom'; import Severity from 'vs/base/common/severity'; import { VSBuffer } from 'vs/base/common/buffer'; import { extractFileListData } from 'vs/platform/dnd/browser/dnd'; import { Iterable } from 'vs/base/common/iterator'; import { WebFileSystemAccess } from 'vs/platform/files/browser/webFileSystemAccess'; -import { $window } from 'vs/base/browser/window'; export class FileDialogService extends AbstractFileDialogService implements IFileDialogService { @@ -58,13 +57,14 @@ export class FileDialogService extends AbstractFileDialogService implements IFil return super.pickFileAndOpenSimplified(schema, options, false); } - if (!WebFileSystemAccess.supported($window)) { + const activeWindow = getActiveWindow(); + if (!WebFileSystemAccess.supported(activeWindow)) { return this.showUnsupportedBrowserWarning('open'); } let fileHandle: FileSystemHandle | undefined = undefined; try { - ([fileHandle] = await $window.showOpenFilePicker({ multiple: false })); + ([fileHandle] = await activeWindow.showOpenFilePicker({ multiple: false })); } catch (error) { return; // `showOpenFilePicker` will throw an error when the user cancels } @@ -117,7 +117,8 @@ export class FileDialogService extends AbstractFileDialogService implements IFil return super.pickFileToSaveSimplified(schema, options); } - if (!WebFileSystemAccess.supported($window)) { + const activeWindow = getActiveWindow(); + if (!WebFileSystemAccess.supported(activeWindow)) { return this.showUnsupportedBrowserWarning('save'); } @@ -125,7 +126,7 @@ export class FileDialogService extends AbstractFileDialogService implements IFil const startIn = Iterable.first(this.fileSystemProvider.directories); try { - fileHandle = await $window.showSaveFilePicker({ types: this.getFilePickerTypes(options.filters), ...{ suggestedName: basename(defaultUri), startIn } }); + fileHandle = await activeWindow.showSaveFilePicker({ types: this.getFilePickerTypes(options.filters), ...{ suggestedName: basename(defaultUri), startIn } }); } catch (error) { return; // `showSaveFilePicker` will throw an error when the user cancels } @@ -158,7 +159,8 @@ export class FileDialogService extends AbstractFileDialogService implements IFil return super.showSaveDialogSimplified(schema, options); } - if (!WebFileSystemAccess.supported($window)) { + const activeWindow = getActiveWindow(); + if (!WebFileSystemAccess.supported(activeWindow)) { return this.showUnsupportedBrowserWarning('save'); } @@ -166,7 +168,7 @@ export class FileDialogService extends AbstractFileDialogService implements IFil const startIn = Iterable.first(this.fileSystemProvider.directories); try { - fileHandle = await $window.showSaveFilePicker({ types: this.getFilePickerTypes(options.filters), ...options.defaultUri ? { suggestedName: basename(options.defaultUri) } : undefined, ...{ startIn } }); + fileHandle = await activeWindow.showSaveFilePicker({ types: this.getFilePickerTypes(options.filters), ...options.defaultUri ? { suggestedName: basename(options.defaultUri) } : undefined, ...{ startIn } }); } catch (error) { return undefined; // `showSaveFilePicker` will throw an error when the user cancels } @@ -185,7 +187,8 @@ export class FileDialogService extends AbstractFileDialogService implements IFil return super.showOpenDialogSimplified(schema, options); } - if (!WebFileSystemAccess.supported($window)) { + const activeWindow = getActiveWindow(); + if (!WebFileSystemAccess.supported(activeWindow)) { return this.showUnsupportedBrowserWarning('open'); } @@ -194,12 +197,12 @@ export class FileDialogService extends AbstractFileDialogService implements IFil try { if (options.canSelectFiles) { - const handle = await $window.showOpenFilePicker({ multiple: false, types: this.getFilePickerTypes(options.filters), ...{ startIn } }); + const handle = await activeWindow.showOpenFilePicker({ multiple: false, types: this.getFilePickerTypes(options.filters), ...{ startIn } }); if (handle.length === 1 && WebFileSystemAccess.isFileSystemFileHandle(handle[0])) { uri = await this.fileSystemProvider.registerFileHandle(handle[0]); } } else { - const handle = await $window.showDirectoryPicker({ ...{ startIn } }); + const handle = await activeWindow.showDirectoryPicker({ ...{ startIn } }); uri = await this.fileSystemProvider.registerDirectoryHandle(handle); } } catch (error) { diff --git a/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts b/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts index 4d2bccd614b..ff5e421b8ab 100644 --- a/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts +++ b/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts @@ -35,7 +35,7 @@ import { normalizeDriveLetter } from 'vs/base/common/labels'; import { SaveReason } from 'vs/workbench/common/editor'; import { IPathService } from 'vs/workbench/services/path/common/pathService'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; -import { $window } from 'vs/base/browser/window'; +import { getActiveDocument } from 'vs/base/browser/dom'; export namespace OpenLocalFileCommand { export const ID = 'workbench.action.files.openLocalFile'; @@ -680,7 +680,7 @@ export class SimpleFileDialog implements ISimpleFileDialog { this.activeItem = quickPickItem; if (force) { // clear any selected text - $window.document.execCommand('insertText', false, ''); + getActiveDocument().execCommand('insertText', false, ''); } return false; } else if (!force && (itemBasename.length >= startingBasename.length) && equalsIgnoreCase(itemBasename.substr(0, startingBasename.length), startingBasename)) { @@ -716,7 +716,7 @@ export class SimpleFileDialog implements ISimpleFileDialog { private insertText(wholeValue: string, insertText: string) { if (this.filePickBox.inputHasFocus()) { - $window.document.execCommand('insertText', false, insertText); + getActiveDocument().execCommand('insertText', false, insertText); if (this.filePickBox.value !== wholeValue) { this.filePickBox.value = wholeValue; this.handleValueChange(wholeValue); diff --git a/src/vs/workbench/services/extensionManagement/browser/builtinExtensionsScannerService.ts b/src/vs/workbench/services/extensionManagement/browser/builtinExtensionsScannerService.ts index 5807556d7de..1666e9af34b 100644 --- a/src/vs/workbench/services/extensionManagement/browser/builtinExtensionsScannerService.ts +++ b/src/vs/workbench/services/extensionManagement/browser/builtinExtensionsScannerService.ts @@ -15,7 +15,7 @@ import { IExtensionResourceLoaderService } from 'vs/platform/extensionResourceLo import { IProductService } from 'vs/platform/product/common/productService'; import { ITranslations, localizeManifest } from 'vs/platform/extensionManagement/common/extensionNls'; import { ILogService } from 'vs/platform/log/common/log'; -import { $window } from 'vs/base/browser/window'; +import { mainWindow } from 'vs/base/browser/window'; interface IBundledExtension { extensionPath: string; @@ -56,7 +56,7 @@ export class BuiltinExtensionsScannerService implements IBuiltinExtensionsScanne bundledExtensions = [/*BUILD->INSERT_BUILTIN_EXTENSIONS*/]; } else { // Find builtin extensions by checking for DOM - const builtinExtensionsElement = $window.document.getElementById('vscode-workbench-builtin-extensions'); + const builtinExtensionsElement = mainWindow.document.getElementById('vscode-workbench-builtin-extensions'); const builtinExtensionsElementAttribute = builtinExtensionsElement ? builtinExtensionsElement.getAttribute('data-settings') : undefined; if (builtinExtensionsElementAttribute) { try { diff --git a/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts b/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts index 2fc861ad7a4..e3c810e97a2 100644 --- a/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts +++ b/src/vs/workbench/services/extensions/browser/extensionUrlHandler.ts @@ -30,7 +30,7 @@ import { CancellationToken } from 'vs/base/common/cancellation'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IProductService } from 'vs/platform/product/common/productService'; import { disposableWindowInterval } from 'vs/base/browser/dom'; -import { $window } from 'vs/base/browser/window'; +import { mainWindow } from 'vs/base/browser/window'; const FIVE_MINUTES = 5 * 60 * 1000; const THIRTY_SECONDS = 30 * 1000; @@ -126,7 +126,7 @@ class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler { ) { this.userTrustedExtensionsStorage = new UserTrustedExtensionIdStorage(storageService); - const interval = disposableWindowInterval($window, () => this.garbageCollect(), THIRTY_SECONDS); + const interval = disposableWindowInterval(mainWindow, () => this.garbageCollect(), THIRTY_SECONDS); const urlToHandleValue = this.storageService.get(URL_TO_HANDLE, StorageScope.WORKSPACE); if (urlToHandleValue) { this.storageService.remove(URL_TO_HANDLE, StorageScope.WORKSPACE); diff --git a/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts b/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts index 74aec081fa4..5e0a56eb94d 100644 --- a/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts +++ b/src/vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts @@ -5,7 +5,7 @@ import * as dom from 'vs/base/browser/dom'; import { parentOriginHash } from 'vs/base/browser/iframe'; -import { $window } from 'vs/base/browser/window'; +import { mainWindow } from 'vs/base/browser/window'; import { Barrier } from 'vs/base/common/async'; import { VSBuffer } from 'vs/base/common/buffer'; import { canceled, onUnexpectedError } from 'vs/base/common/errors'; @@ -98,7 +98,7 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost stableOriginUUID = generateUuid(); this._storageService.store(key, stableOriginUUID, StorageScope.WORKSPACE, StorageTarget.MACHINE); } - const hash = await parentOriginHash($window.origin, stableOriginUUID); + const hash = await parentOriginHash(mainWindow.origin, stableOriginUUID); const baseUrl = ( webEndpointUrlTemplate .replace('{{uuid}}', `v--${hash}`) // using `v--` as a marker to require `parentOrigin`/`salt` verification @@ -107,7 +107,7 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost ); const res = new URL(`${baseUrl}/out/${iframeModulePath}${suffix}`); - res.searchParams.set('parentOrigin', $window.origin); + res.searchParams.set('parentOrigin', mainWindow.origin); res.searchParams.set('salt', stableOriginUUID); return res.toString(); } @@ -166,7 +166,7 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost console.warn(`The Web Worker Extension Host did not start in 60s, that might be a problem.`); }, 60000); - this._register(dom.addDisposableListener($window, 'message', (event) => { + this._register(dom.addDisposableListener(mainWindow, 'message', (event) => { if (event.source !== iframe.contentWindow) { return; } diff --git a/src/vs/workbench/services/extensions/electron-sandbox/nativeExtensionService.ts b/src/vs/workbench/services/extensions/electron-sandbox/nativeExtensionService.ts index 9c35f632f23..123f189265e 100644 --- a/src/vs/workbench/services/extensions/electron-sandbox/nativeExtensionService.ts +++ b/src/vs/workbench/services/extensions/electron-sandbox/nativeExtensionService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { runWhenWindowIdle } from 'vs/base/browser/dom'; -import { $window } from 'vs/base/browser/window'; +import { mainWindow } from 'vs/base/browser/window'; import { CancellationToken } from 'vs/base/common/cancellation'; import { Schemas } from 'vs/base/common/network'; import * as performance from 'vs/base/common/performance'; @@ -135,7 +135,7 @@ export class NativeExtensionService extends AbstractExtensionService implements // see https://github.com/microsoft/vscode/issues/41322 lifecycleService.when(LifecyclePhase.Ready).then(() => { // reschedule to ensure this runs after restoring viewlets, panels, and editors - runWhenWindowIdle($window, () => { + runWhenWindowIdle(mainWindow, () => { this._initialize(); }, 50 /*max delay*/); }); diff --git a/src/vs/workbench/services/hover/browser/hoverService.ts b/src/vs/workbench/services/hover/browser/hoverService.ts index f82473e813d..22d44da9eee 100644 --- a/src/vs/workbench/services/hover/browser/hoverService.ts +++ b/src/vs/workbench/services/hover/browser/hoverService.ts @@ -13,7 +13,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { HoverWidget } from 'vs/workbench/services/hover/browser/hoverWidget'; import { IContextViewProvider, IDelegate } from 'vs/base/browser/ui/contextview/contextview'; import { DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; -import { addDisposableListener, EventType, getActiveElement, isAncestorOfActiveElement, isAncestor } from 'vs/base/browser/dom'; +import { addDisposableListener, EventType, getActiveElement, isAncestorOfActiveElement, isAncestor, getWindow } from 'vs/base/browser/dom'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { ResultKind } from 'vs/platform/keybinding/common/keybindingResolver'; @@ -91,7 +91,7 @@ export class HoverService implements IHoverService { ); hover.onRequestLayout(() => provider.layout()); if (options.persistence?.sticky) { - hoverDisposables.add(addDisposableListener(document, EventType.MOUSE_DOWN, e => { + hoverDisposables.add(addDisposableListener(getWindow(options.container).document, EventType.MOUSE_DOWN, e => { if (!isAncestor(e.target as HTMLElement, hover.domNode)) { this.doHideHover(); } @@ -106,10 +106,11 @@ export class HoverService implements IHoverService { } const focusedElement = getActiveElement(); if (focusedElement) { + const focusedElementDocument = getWindow(focusedElement).document; hoverDisposables.add(addDisposableListener(focusedElement, EventType.KEY_DOWN, e => this._keyDown(e, hover, !!options.persistence?.hideOnKeyDown))); - hoverDisposables.add(addDisposableListener(document, EventType.KEY_DOWN, e => this._keyDown(e, hover, !!options.persistence?.hideOnKeyDown))); + hoverDisposables.add(addDisposableListener(focusedElementDocument, EventType.KEY_DOWN, e => this._keyDown(e, hover, !!options.persistence?.hideOnKeyDown))); hoverDisposables.add(addDisposableListener(focusedElement, EventType.KEY_UP, e => this._keyUp(e, hover))); - hoverDisposables.add(addDisposableListener(document, EventType.KEY_UP, e => this._keyUp(e, hover))); + hoverDisposables.add(addDisposableListener(focusedElementDocument, EventType.KEY_UP, e => this._keyUp(e, hover))); } } diff --git a/src/vs/workbench/services/hover/browser/hoverWidget.ts b/src/vs/workbench/services/hover/browser/hoverWidget.ts index 9cb6db70e2a..44270eb41da 100644 --- a/src/vs/workbench/services/hover/browser/hoverWidget.ts +++ b/src/vs/workbench/services/hover/browser/hoverWidget.ts @@ -22,7 +22,7 @@ import { localize } from 'vs/nls'; import { isMacintosh } from 'vs/base/common/platform'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { status } from 'vs/base/browser/ui/aria/aria'; -import { $window, mainWindow } from 'vs/base/browser/window'; +import { mainWindow } from 'vs/base/browser/window'; const $ = dom.$; type TargetRect = { @@ -643,30 +643,30 @@ class CompositeMouseTracker extends Widget { private _elements: HTMLElement[] ) { super(); - this._elements.forEach(n => this.onmouseover(n, () => this._onTargetMouseOver())); - this._elements.forEach(n => this.onmouseleave(n, () => this._onTargetMouseLeave())); + this._elements.forEach(n => this.onmouseover(n, () => this._onTargetMouseOver(n))); + this._elements.forEach(n => this.onmouseleave(n, () => this._onTargetMouseLeave(n))); } - private _onTargetMouseOver(): void { + private _onTargetMouseOver(target: HTMLElement): void { this._isMouseIn = true; - this._clearEvaluateMouseStateTimeout(); + this._clearEvaluateMouseStateTimeout(target); } - private _onTargetMouseLeave(): void { + private _onTargetMouseLeave(target: HTMLElement): void { this._isMouseIn = false; - this._evaluateMouseState(); + this._evaluateMouseState(target); } - private _evaluateMouseState(): void { - this._clearEvaluateMouseStateTimeout(); + private _evaluateMouseState(target: HTMLElement): void { + this._clearEvaluateMouseStateTimeout(target); // Evaluate whether the mouse is still outside asynchronously such that other mouse targets // have the opportunity to first their mouse in event. - this._mouseTimeout = $window.setTimeout(() => this._fireIfMouseOutside(), 0); + this._mouseTimeout = dom.getWindow(target).setTimeout(() => this._fireIfMouseOutside(), 0); } - private _clearEvaluateMouseStateTimeout(): void { + private _clearEvaluateMouseStateTimeout(target: HTMLElement): void { if (this._mouseTimeout) { - $window.clearTimeout(this._mouseTimeout); + dom.getWindow(target).clearTimeout(this._mouseTimeout); this._mouseTimeout = undefined; } } diff --git a/src/vs/workbench/services/themes/browser/fileIconThemeData.ts b/src/vs/workbench/services/themes/browser/fileIconThemeData.ts index 228ff00394c..ec8f4a607cd 100644 --- a/src/vs/workbench/services/themes/browser/fileIconThemeData.ts +++ b/src/vs/workbench/services/themes/browser/fileIconThemeData.ts @@ -14,7 +14,7 @@ import { asCSSUrl } from 'vs/base/browser/dom'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { IExtensionResourceLoaderService } from 'vs/platform/extensionResourceLoader/common/extensionResourceLoader'; import { ILanguageService } from 'vs/editor/common/languages/language'; -import { $window } from 'vs/base/browser/window'; +import { mainWindow } from 'vs/base/browser/window'; export class FileIconThemeData implements IWorkbenchFileIconTheme { @@ -466,5 +466,5 @@ function handleParentFolder(key: string, selectors: string[]): string { function escapeCSS(str: string) { str = str.replace(/[\11\12\14\15\40]/g, '/'); // HTML class names can not contain certain whitespace characters, use / instead, which doesn't exist in file names. - return $window.CSS.escape(str); + return mainWindow.CSS.escape(str); } diff --git a/src/vs/workbench/services/userActivity/browser/domActivityTracker.ts b/src/vs/workbench/services/userActivity/browser/domActivityTracker.ts index 4c3b83485d1..087b4cb9e98 100644 --- a/src/vs/workbench/services/userActivity/browser/domActivityTracker.ts +++ b/src/vs/workbench/services/userActivity/browser/domActivityTracker.ts @@ -4,7 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import * as dom from 'vs/base/browser/dom'; -import { $window } from 'vs/base/browser/window'; +import { mainWindow } from 'vs/base/browser/window'; +import { Event } from 'vs/base/common/event'; import { Disposable, MutableDisposable } from 'vs/base/common/lifecycle'; import { IUserActivityService } from 'vs/workbench/services/userActivity/common/userActivityService'; @@ -44,20 +45,22 @@ export class DomActivityTracker extends Disposable { } }; - const onActivity = () => { + const onActivity = (targetWindow: Window & typeof globalThis) => { // if was inactive, they've now returned if (intervalsWithoutActivity === MIN_INTERVALS_WITHOUT_ACTIVITY) { activeMutex.value = userActivityService.markActive(); - intervalTimer.cancelAndSet(onInterval, CHECK_INTERVAL, $window); + intervalTimer.cancelAndSet(onInterval, CHECK_INTERVAL, targetWindow); } intervalsWithoutActivity = 0; }; - this._register(dom.addDisposableListener(document, 'touchstart', onActivity, eventListenerOptions)); - this._register(dom.addDisposableListener(document, 'mousedown', onActivity, eventListenerOptions)); - this._register(dom.addDisposableListener(document, 'keydown', onActivity, eventListenerOptions)); + this._register(Event.runAndSubscribe(dom.onDidRegisterWindow, ({ window, disposables }) => { + disposables.add(dom.addDisposableListener(window.document, 'touchstart', () => onActivity(window), eventListenerOptions)); + disposables.add(dom.addDisposableListener(window.document, 'mousedown', () => onActivity(window), eventListenerOptions)); + disposables.add(dom.addDisposableListener(window.document, 'keydown', () => onActivity(window), eventListenerOptions)); + }, { window: mainWindow, disposables: this._store })); - onActivity(); + onActivity(mainWindow); } }