diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts
index 62b509ccda2..ff113c9baa9 100644
--- a/src/vs/base/browser/dom.ts
+++ b/src/vs/base/browser/dom.ts
@@ -921,26 +921,6 @@ export function getActiveWindow(): CodeWindow {
return (document.defaultView?.window ?? mainWindow) as CodeWindow;
}
-export function focusWindow(element: Node, options?: { force: boolean }): void {
- const window = getWindow(element);
-
- // Force: always focus the element window
- if (options?.force) {
- window.focus();
- }
-
- // Not forced: only focus the element window if another
- // window in the same workspace group has focus (when auxiliary
- // windows are opened).
- // This prevents stealing focus from another workspace window.
- else {
- const activeWindow = getActiveWindow();
- if (activeWindow.document.hasFocus() && activeWindow !== window) {
- window.focus();
- }
- }
-}
-
const globalStylesheets = new Map>();
export function isGlobalStylesheet(node: Node): boolean {
diff --git a/src/vs/workbench/browser/composite.ts b/src/vs/workbench/browser/composite.ts
index 59eba8e11ff..424fcfa19e5 100644
--- a/src/vs/workbench/browser/composite.ts
+++ b/src/vs/workbench/browser/composite.ts
@@ -10,7 +10,7 @@ import { IComposite, ICompositeControl } from 'vs/workbench/common/composite';
import { Event, Emitter } from 'vs/base/common/event';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IConstructorSignature, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
-import { trackFocus, Dimension, IDomPosition, focusWindow } from 'vs/base/browser/dom';
+import { trackFocus, Dimension, IDomPosition } from 'vs/base/browser/dom';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { Disposable } from 'vs/base/common/lifecycle';
import { assertIsDefined } from 'vs/base/common/types';
@@ -149,13 +149,7 @@ export abstract class Composite extends Component implements IComposite {
* Called when this composite should receive keyboard focus.
*/
focus(): void {
- const container = this.getContainer();
- if (container) {
- // Make sure to focus the window of the container
- // because it is possible that the composite is
- // opened in a auxiliary window that is not focused.
- focusWindow(container);
- }
+ // Subclasses can implement
}
/**
diff --git a/src/vs/workbench/browser/layout.ts b/src/vs/workbench/browser/layout.ts
index 797a1713dd8..b71d9dd9477 100644
--- a/src/vs/workbench/browser/layout.ts
+++ b/src/vs/workbench/browser/layout.ts
@@ -5,7 +5,7 @@
import { Disposable, DisposableMap, DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { Event, Emitter } from 'vs/base/common/event';
-import { EventType, addDisposableListener, getClientArea, position, size, IDimension, isAncestorUsingFlowTo, computeScreenAwareSize, getActiveDocument, getWindows, getActiveWindow, focusWindow, isActiveDocument, getWindow, getWindowId, getActiveElement } from 'vs/base/browser/dom';
+import { EventType, addDisposableListener, getClientArea, position, size, IDimension, isAncestorUsingFlowTo, computeScreenAwareSize, getActiveDocument, getWindows, getActiveWindow, isActiveDocument, getWindow, getWindowId, getActiveElement } from 'vs/base/browser/dom';
import { onDidChangeFullscreen, isFullscreen, isWCOEnabled } from 'vs/base/browser/browser';
import { IWorkingCopyBackupService } from 'vs/workbench/services/workingCopy/common/workingCopyBackup';
import { isWindows, isLinux, isMacintosh, isWeb, isIOS } from 'vs/base/common/platform';
@@ -1124,9 +1124,6 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
focusPart(part: SINGLE_WINDOW_PARTS): void;
focusPart(part: Parts, targetWindow: Window = mainWindow): void {
const container = this.getContainer(targetWindow, part) ?? this.mainContainer;
- if (container) {
- focusWindow(container);
- }
switch (part) {
case Parts.EDITOR_PART:
diff --git a/src/vs/workbench/browser/parts/editor/editorGroupView.ts b/src/vs/workbench/browser/parts/editor/editorGroupView.ts
index faddd4e7b06..69bfb90f5d4 100644
--- a/src/vs/workbench/browser/parts/editor/editorGroupView.ts
+++ b/src/vs/workbench/browser/parts/editor/editorGroupView.ts
@@ -11,7 +11,7 @@ import { EditorInput } from 'vs/workbench/common/editor/editorInput';
import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput';
import { Emitter, Relay } from 'vs/base/common/event';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
-import { Dimension, trackFocus, addDisposableListener, EventType, EventHelper, findParentWithClass, isAncestor, IDomNodePagePosition, isMouseEvent, isActiveElement, focusWindow, getWindow, getActiveElement } from 'vs/base/browser/dom';
+import { Dimension, trackFocus, addDisposableListener, EventType, EventHelper, findParentWithClass, isAncestor, IDomNodePagePosition, isMouseEvent, isActiveElement, getWindow, getActiveElement } from 'vs/base/browser/dom';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar';
@@ -976,9 +976,6 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
focus(): void {
- // Ensure window focus
- focusWindow(this.element);
-
// Pass focus to editor panes
if (this.activeEditorPane) {
this.activeEditorPane.focus();
diff --git a/src/vs/workbench/browser/parts/views/viewPane.ts b/src/vs/workbench/browser/parts/views/viewPane.ts
index 84e11baf381..6ef0b18cdb1 100644
--- a/src/vs/workbench/browser/parts/views/viewPane.ts
+++ b/src/vs/workbench/browser/parts/views/viewPane.ts
@@ -8,7 +8,7 @@ import * as nls from 'vs/nls';
import { Event, Emitter } from 'vs/base/common/event';
import { asCssVariable, foreground } from 'vs/platform/theme/common/colorRegistry';
import { PANEL_BACKGROUND, SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
-import { after, append, $, trackFocus, EventType, addDisposableListener, createCSSRule, asCSSUrl, Dimension, reset, asCssValueWithDefault, focusWindow } from 'vs/base/browser/dom';
+import { after, append, $, trackFocus, EventType, addDisposableListener, createCSSRule, asCSSUrl, Dimension, reset, asCssValueWithDefault } from 'vs/base/browser/dom';
import { DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
import { Action, IAction, IActionRunner } from 'vs/base/common/actions';
import { ActionsOrientation, IActionViewItem, prepareActions } from 'vs/base/browser/ui/actionbar/actionbar';
@@ -630,8 +630,6 @@ export abstract class ViewPane extends Pane implements IView {
}
focus(): void {
- focusWindow(this.element);
-
if (this.viewWelcomeController.enabled) {
this.viewWelcomeController.focus();
} else if (this.element) {
diff --git a/src/vs/workbench/browser/window.ts b/src/vs/workbench/browser/window.ts
index 69a5fe4dee2..9f98ac1c680 100644
--- a/src/vs/workbench/browser/window.ts
+++ b/src/vs/workbench/browser/window.ts
@@ -4,14 +4,14 @@
*--------------------------------------------------------------------------------------------*/
import { isSafari, setFullscreen } from 'vs/base/browser/browser';
-import { addDisposableListener, EventHelper, EventType, focusWindow, getWindowById, getWindows, getWindowsCount, windowOpenNoOpener, windowOpenPopup, windowOpenWithSuccess } from 'vs/base/browser/dom';
+import { addDisposableListener, EventHelper, EventType, getActiveWindow, getWindow, getWindowById, getWindows, getWindowsCount, windowOpenNoOpener, windowOpenPopup, windowOpenWithSuccess } from 'vs/base/browser/dom';
import { DomEmitter } from 'vs/base/browser/event';
import { HidDeviceData, requestHidDevice, requestSerialPort, requestUsbDevice, SerialPortData, UsbDeviceData } from 'vs/base/browser/deviceAccess';
import { timeout } from 'vs/base/common/async';
import { Event } from 'vs/base/common/event';
import { Disposable, IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
import { matchesScheme, Schemas } from 'vs/base/common/network';
-import { isIOS, isMacintosh } from 'vs/base/common/platform';
+import { isIOS, isMacintosh, isNative } from 'vs/base/common/platform';
import Severity from 'vs/base/common/severity';
import { URI } from 'vs/base/common/uri';
import { localize } from 'vs/nls';
@@ -30,6 +30,7 @@ import { registerWindowDriver } from 'vs/workbench/services/driver/browser/drive
import { CodeWindow, isAuxiliaryWindow, mainWindow } from 'vs/base/browser/window';
import { createSingleCallFunction } from 'vs/base/common/functional';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
+import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
export abstract class BaseWindow extends Disposable {
@@ -39,11 +40,16 @@ export abstract class BaseWindow extends Disposable {
constructor(
targetWindow: CodeWindow,
dom = { getWindowsCount, getWindows }, /* for testing */
- @IHostService protected readonly hostService: IHostService
+ @IHostService protected readonly hostService: IHostService,
+ @IWorkbenchEnvironmentService protected readonly environmentService: IWorkbenchEnvironmentService
) {
super();
+ if (isNative) {
+ this.enableNativeWindowFocus(targetWindow);
+ }
this.enableWindowFocusOnElementFocus(targetWindow);
+
this.enableMultiWindowAwareTimeout(targetWindow, dom);
this.registerFullScreenListeners(targetWindow.vscodeWindowId);
@@ -51,13 +57,40 @@ export abstract class BaseWindow extends Disposable {
//#region focus handling in multi-window applications
+ protected enableNativeWindowFocus(targetWindow: CodeWindow): void {
+ const originalWindowFocus = targetWindow.focus.bind(targetWindow);
+
+ const that = this;
+ targetWindow.focus = function () {
+ originalWindowFocus();
+
+ if (
+ !that.environmentService.extensionTestsLocationURI && // never steal focus when running tests
+ !targetWindow.document.hasFocus() // skip when already having focus
+ ) {
+ // Enable `window.focus()` to work in Electron by
+ // asking the main process to focus the window.
+ // https://github.com/electron/electron/issues/25578
+ that.hostService.focus(targetWindow);
+ }
+ };
+ }
+
protected enableWindowFocusOnElementFocus(targetWindow: CodeWindow): void {
const originalFocus = HTMLElement.prototype.focus;
targetWindow.HTMLElement.prototype.focus = function (this: HTMLElement, options?: FocusOptions | undefined): void {
- // Ensure elements window is focused
- focusWindow(this);
+ // If the active focused window is not the same as the
+ // window of the element to focus, make sure to focus
+ // that window first before focusing the element.
+ const activeWindow = getActiveWindow();
+ if (activeWindow.document.hasFocus()) {
+ const elementWindow = getWindow(this);
+ if (activeWindow !== elementWindow) {
+ elementWindow.focus();
+ }
+ }
// Pass to original focus() method
originalFocus.apply(this, [options]);
@@ -178,12 +211,12 @@ export class BrowserWindow extends BaseWindow {
@IDialogService private readonly dialogService: IDialogService,
@ILabelService private readonly labelService: ILabelService,
@IProductService private readonly productService: IProductService,
- @IBrowserWorkbenchEnvironmentService private readonly environmentService: IBrowserWorkbenchEnvironmentService,
+ @IBrowserWorkbenchEnvironmentService private readonly browserEnvironmentService: IBrowserWorkbenchEnvironmentService,
@IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IHostService hostService: IHostService
) {
- super(mainWindow, undefined, hostService);
+ super(mainWindow, undefined, hostService, browserEnvironmentService);
this.registerListeners();
this.create();
@@ -280,8 +313,8 @@ export class BrowserWindow extends BaseWindow {
this.openerService.setDefaultExternalOpener({
openExternal: async (href: string) => {
let isAllowedOpener = false;
- if (this.environmentService.options?.openerAllowedExternalUrlPrefixes) {
- for (const trustedPopupPrefix of this.environmentService.options.openerAllowedExternalUrlPrefixes) {
+ if (this.browserEnvironmentService.options?.openerAllowedExternalUrlPrefixes) {
+ for (const trustedPopupPrefix of this.browserEnvironmentService.options.openerAllowedExternalUrlPrefixes) {
if (href.startsWith(trustedPopupPrefix)) {
isAllowedOpener = true;
break;
diff --git a/src/vs/workbench/electron-sandbox/window.ts b/src/vs/workbench/electron-sandbox/window.ts
index f207e15834f..eb2159272be 100644
--- a/src/vs/workbench/electron-sandbox/window.ts
+++ b/src/vs/workbench/electron-sandbox/window.ts
@@ -8,7 +8,7 @@ import { localize } from 'vs/nls';
import { URI } from 'vs/base/common/uri';
import { onUnexpectedError } from 'vs/base/common/errors';
import { equals } from 'vs/base/common/objects';
-import { EventType, EventHelper, addDisposableListener, ModifierKeyEmitter, getActiveElement, hasWindow, getWindow, getWindowById, getWindowId, getWindows } from 'vs/base/browser/dom';
+import { EventType, EventHelper, addDisposableListener, ModifierKeyEmitter, getActiveElement, hasWindow, getWindow, getWindowById, getWindows } from 'vs/base/browser/dom';
import { Action, Separator, WorkbenchActionExecutedClassification, WorkbenchActionExecutedEvent } from 'vs/base/common/actions';
import { IFileService } from 'vs/platform/files/common/files';
import { EditorResourceAccessor, IUntitledTextResourceEditorInput, SideBySideEditor, pathsToEditors, IResourceDiffEditorInput, IUntypedEditorInput, IEditorPane, isResourceEditorInput, IResourceMergeEditorInput } from 'vs/workbench/common/editor';
@@ -107,7 +107,7 @@ export class NativeWindow extends BaseWindow {
@IMenuService private readonly menuService: IMenuService,
@ILifecycleService private readonly lifecycleService: ILifecycleService,
@IIntegrityService private readonly integrityService: IIntegrityService,
- @INativeWorkbenchEnvironmentService private readonly environmentService: INativeWorkbenchEnvironmentService,
+ @INativeWorkbenchEnvironmentService private readonly nativeEnvironmentService: INativeWorkbenchEnvironmentService,
@IAccessibilityService private readonly accessibilityService: IAccessibilityService,
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
@IOpenerService private readonly openerService: IOpenerService,
@@ -131,7 +131,7 @@ export class NativeWindow extends BaseWindow {
@IUtilityProcessWorkerWorkbenchService private readonly utilityProcessWorkerWorkbenchService: IUtilityProcessWorkerWorkbenchService,
@IHostService hostService: IHostService
) {
- super(mainWindow, undefined, hostService);
+ super(mainWindow, undefined, hostService, nativeEnvironmentService);
this.mainPartEditorService = editorService.createScoped('main', this._store);
@@ -353,7 +353,7 @@ export class NativeWindow extends BaseWindow {
this._register(Event.debounce(this.editorService.onDidVisibleEditorsChange, () => undefined, 0, undefined, undefined, undefined, this._store)(() => this.maybeCloseWindow()));
// Listen to editor closing (if we run with --wait)
- const filesToWait = this.environmentService.filesToWait;
+ const filesToWait = this.nativeEnvironmentService.filesToWait;
if (filesToWait) {
this.trackClosedWaitFiles(filesToWait.waitMarkerFileUri, coalesce(filesToWait.paths.map(path => path.fileUri)));
}
@@ -412,7 +412,7 @@ export class NativeWindow extends BaseWindow {
Event.map(Event.filter(this.nativeHostService.onDidMaximizeWindow, windowId => !!hasWindow(windowId)), windowId => ({ maximized: true, windowId })),
Event.map(Event.filter(this.nativeHostService.onDidUnmaximizeWindow, windowId => !!hasWindow(windowId)), windowId => ({ maximized: false, windowId }))
)(e => this.layoutService.updateWindowMaximizedState(getWindowById(e.windowId)!.window, e.maximized)));
- this.layoutService.updateWindowMaximizedState(mainWindow, this.environmentService.window.maximized ?? false);
+ this.layoutService.updateWindowMaximizedState(mainWindow, this.nativeEnvironmentService.window.maximized ?? false);
// Detect panel position to determine minimum width
this._register(this.layoutService.onDidChangePanelPosition(pos => this.onDidChangePanelPosition(positionFromString(pos))));
@@ -582,7 +582,7 @@ export class NativeWindow extends BaseWindow {
}
private maybeCloseWindow(): void {
- const closeWhenEmpty = this.configurationService.getValue('window.closeWhenEmpty') || this.environmentService.args.wait;
+ const closeWhenEmpty = this.configurationService.getValue('window.closeWhenEmpty') || this.nativeEnvironmentService.args.wait;
if (!closeWhenEmpty) {
return; // return early if configured to not close when empty
}
@@ -671,29 +671,6 @@ export class NativeWindow extends BaseWindow {
if (this.environmentService.enableSmokeTestDriver) {
this.setupDriver();
}
-
- // Patch methods that we need to work properly
- this.patchMethods();
- }
-
- private patchMethods(): void {
-
- // Enable `window.focus()` to work in Electron by
- // asking the main process to focus the window.
- // https://github.com/electron/electron/issues/25578
- const that = this;
- const originalWindowFocus = mainWindow.focus.bind(mainWindow);
- mainWindow.focus = function () {
- if (that.environmentService.extensionTestsLocationURI) {
- return; // no focus when we are running tests from CLI
- }
-
- originalWindowFocus();
-
- if (!mainWindow.document.hasFocus()) {
- that.nativeHostService.focusWindow({ targetWindowId: getWindowId(mainWindow) });
- }
- };
}
private async handleWarnings(): Promise {
@@ -731,11 +708,11 @@ export class NativeWindow extends BaseWindow {
let installLocationUri: URI;
if (isMacintosh) {
// appRoot = /Applications/Visual Studio Code - Insiders.app/Contents/Resources/app
- installLocationUri = dirname(dirname(dirname(URI.file(this.environmentService.appRoot))));
+ installLocationUri = dirname(dirname(dirname(URI.file(this.nativeEnvironmentService.appRoot))));
} else {
// appRoot = C:\Users\\AppData\Local\Programs\Microsoft VS Code Insiders\resources\app
// appRoot = /usr/share/code-insiders/resources/app
- installLocationUri = dirname(dirname(URI.file(this.environmentService.appRoot)));
+ installLocationUri = dirname(dirname(URI.file(this.nativeEnvironmentService.appRoot)));
}
for (const folder of this.contextService.getWorkspace().folders) {
@@ -753,7 +730,7 @@ export class NativeWindow extends BaseWindow {
// macOS 10.13 and 10.14 warning
if (isMacintosh) {
- const majorVersion = this.environmentService.os.release.split('.')[0];
+ const majorVersion = this.nativeEnvironmentService.os.release.split('.')[0];
const eolReleases = new Map([
['17', 'macOS High Sierra'],
['18', 'macOS Mojave'],
diff --git a/src/vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService.ts b/src/vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService.ts
index ce6f32b0914..6864585e014 100644
--- a/src/vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService.ts
+++ b/src/vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService.ts
@@ -22,6 +22,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { Barrier } from 'vs/base/common/async';
import { IHostService } from 'vs/workbench/services/host/browser/host';
+import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
export const IAuxiliaryWindowService = createDecorator('auxiliaryWindowService');
@@ -84,9 +85,10 @@ export class AuxiliaryWindow extends BaseWindow implements IAuxiliaryWindow {
readonly container: HTMLElement,
stylesHaveLoaded: Barrier,
@IConfigurationService private readonly configurationService: IConfigurationService,
- @IHostService hostService: IHostService
+ @IHostService hostService: IHostService,
+ @IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService
) {
- super(window, undefined, hostService);
+ super(window, undefined, hostService, environmentService);
this.whenStylesHaveLoaded = stylesHaveLoaded.wait().then(() => { });
this.registerListeners();
@@ -182,7 +184,8 @@ export class BrowserAuxiliaryWindowService extends Disposable implements IAuxili
@IDialogService private readonly dialogService: IDialogService,
@IConfigurationService protected readonly configurationService: IConfigurationService,
@ITelemetryService private readonly telemetryService: ITelemetryService,
- @IHostService protected readonly hostService: IHostService
+ @IHostService protected readonly hostService: IHostService,
+ @IWorkbenchEnvironmentService protected readonly environmentService: IWorkbenchEnvironmentService
) {
super();
}
@@ -237,7 +240,7 @@ export class BrowserAuxiliaryWindowService extends Disposable implements IAuxili
}
protected createAuxiliaryWindow(targetWindow: CodeWindow, container: HTMLElement, stylesLoaded: Barrier): AuxiliaryWindow {
- return new AuxiliaryWindow(targetWindow, container, stylesLoaded, this.configurationService, this.hostService);
+ return new AuxiliaryWindow(targetWindow, container, stylesLoaded, this.configurationService, this.hostService, this.environmentService);
}
private async openWindow(options?: IAuxiliaryWindowOpenOptions): Promise {
@@ -293,24 +296,20 @@ export class BrowserAuxiliaryWindowService extends Disposable implements IAuxili
}
protected createContainer(auxiliaryWindow: CodeWindow, disposables: DisposableStore, options?: IAuxiliaryWindowOpenOptions): { stylesLoaded: Barrier; container: HTMLElement } {
- this.patchMethods(auxiliaryWindow);
+ auxiliaryWindow.document.createElement = function () {
+ // Disallow `createElement` because it would create
+ // HTML Elements in the "wrong" context and break
+ // code that does "instanceof HTMLElement" etc.
+ throw new Error('Not allowed to create elements in child window JavaScript context. Always use the main window so that "xyz instanceof HTMLElement" continues to work.');
+ };
this.applyMeta(auxiliaryWindow);
const { stylesLoaded } = this.applyCSS(auxiliaryWindow, disposables);
const container = this.applyHTML(auxiliaryWindow, disposables);
+
return { stylesLoaded, container };
}
- protected patchMethods(auxiliaryWindow: CodeWindow): void {
-
- // Disallow `createElement` because it would create
- // HTML Elements in the "wrong" context and break
- // code that does "instanceof HTMLElement" etc.
- auxiliaryWindow.document.createElement = function () {
- throw new Error('Not allowed to create elements in child window JavaScript context. Always use the main window so that "xyz instanceof HTMLElement" continues to work.');
- };
- }
-
private applyMeta(auxiliaryWindow: CodeWindow): void {
for (const metaTag of ['meta[charset="utf-8"]', 'meta[http-equiv="Content-Security-Policy"]', 'meta[name="viewport"]', 'meta[name="theme-color"]']) {
const metaElement = mainWindow.document.querySelector(metaTag);
diff --git a/src/vs/workbench/services/auxiliaryWindow/electron-sandbox/auxiliaryWindowService.ts b/src/vs/workbench/services/auxiliaryWindow/electron-sandbox/auxiliaryWindowService.ts
index d07c6d8addf..4a687027faf 100644
--- a/src/vs/workbench/services/auxiliaryWindow/electron-sandbox/auxiliaryWindowService.ts
+++ b/src/vs/workbench/services/auxiliaryWindow/electron-sandbox/auxiliaryWindowService.ts
@@ -17,11 +17,11 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import { ShutdownReason } from 'vs/workbench/services/lifecycle/common/lifecycle';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { Barrier } from 'vs/base/common/async';
-import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { applyZoom } from 'vs/platform/window/electron-sandbox/window';
import { getZoomLevel } from 'vs/base/browser/browser';
import { getActiveWindow } from 'vs/base/browser/dom';
+import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
type NativeCodeWindow = CodeWindow & {
readonly vscode: ISandboxGlobals;
@@ -38,9 +38,10 @@ export class NativeAuxiliaryWindow extends AuxiliaryWindow {
@IConfigurationService configurationService: IConfigurationService,
@INativeHostService private readonly nativeHostService: INativeHostService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
- @IHostService hostService: IHostService
+ @IHostService hostService: IHostService,
+ @IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService
) {
- super(window, container, stylesHaveLoaded, configurationService, hostService);
+ super(window, container, stylesHaveLoaded, configurationService, hostService, environmentService);
}
protected override async confirmBeforeClose(e: BeforeUnloadEvent): Promise {
@@ -68,10 +69,10 @@ export class NativeAuxiliaryWindowService extends BrowserAuxiliaryWindowService
@IDialogService dialogService: IDialogService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@ITelemetryService telemetryService: ITelemetryService,
- @IEnvironmentService private readonly environmentService: IEnvironmentService,
- @IHostService hostService: IHostService
+ @IHostService hostService: IHostService,
+ @IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService
) {
- super(layoutService, dialogService, configurationService, telemetryService, hostService);
+ super(layoutService, dialogService, configurationService, telemetryService, hostService, environmentService);
}
protected override async resolveWindowId(auxiliaryWindow: NativeCodeWindow): Promise {
@@ -97,29 +98,8 @@ export class NativeAuxiliaryWindowService extends BrowserAuxiliaryWindowService
return super.createContainer(auxiliaryWindow, disposables);
}
- protected override patchMethods(auxiliaryWindow: NativeCodeWindow): void {
- super.patchMethods(auxiliaryWindow);
-
- // Enable `window.focus()` to work in Electron by
- // asking the main process to focus the window.
- // https://github.com/electron/electron/issues/25578
- const that = this;
- const originalWindowFocus = auxiliaryWindow.focus.bind(auxiliaryWindow);
- auxiliaryWindow.focus = function () {
- if (that.environmentService.extensionTestsLocationURI) {
- return; // no focus when we are running tests from CLI
- }
-
- originalWindowFocus();
-
- if (!auxiliaryWindow.document.hasFocus()) {
- that.nativeHostService.focusWindow({ targetWindowId: auxiliaryWindow.vscodeWindowId });
- }
- };
- }
-
protected override createAuxiliaryWindow(targetWindow: CodeWindow, container: HTMLElement, stylesHaveLoaded: Barrier,): AuxiliaryWindow {
- return new NativeAuxiliaryWindow(targetWindow, container, stylesHaveLoaded, this.configurationService, this.nativeHostService, this.instantiationService, this.hostService);
+ return new NativeAuxiliaryWindow(targetWindow, container, stylesHaveLoaded, this.configurationService, this.nativeHostService, this.instantiationService, this.hostService, this.environmentService);
}
}
diff --git a/src/vs/workbench/test/browser/window.test.ts b/src/vs/workbench/test/browser/window.test.ts
index 6d9b702cea6..4a395ee47b3 100644
--- a/src/vs/workbench/test/browser/window.test.ts
+++ b/src/vs/workbench/test/browser/window.test.ts
@@ -10,7 +10,7 @@ import { DisposableStore } from 'vs/base/common/lifecycle';
import { runWithFakedTimers } from 'vs/base/test/common/timeTravelScheduler';
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
import { BaseWindow } from 'vs/workbench/browser/window';
-import { TestHostService } from 'vs/workbench/test/browser/workbenchTestServices';
+import { TestEnvironmentService, TestHostService } from 'vs/workbench/test/browser/workbenchTestServices';
suite('Window', () => {
@@ -19,9 +19,10 @@ suite('Window', () => {
class TestWindow extends BaseWindow {
constructor(window: CodeWindow, dom: { getWindowsCount: () => number; getWindows: () => Iterable }) {
- super(window, dom, new TestHostService());
+ super(window, dom, new TestHostService(), TestEnvironmentService);
}
+ protected override enableNativeWindowFocus(): void { }
protected override enableWindowFocusOnElementFocus(): void { }
}