diff --git a/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindow.ts b/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindow.ts index 28cb3aafdd0..1b1271068a4 100644 --- a/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindow.ts +++ b/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindow.ts @@ -30,11 +30,7 @@ export class AuxiliaryWindow extends BaseWindow implements IAuxiliaryWindow { private _win: BrowserWindow | null = null; get win() { if (!this._win) { - const window = BrowserWindow.fromWebContents(this.contents); - if (window) { - this._win = window; - this.registerWindowListeners(window); - } + this.tryClaimWindow(); } return this._win; @@ -62,6 +58,30 @@ export class AuxiliaryWindow extends BaseWindow implements IAuxiliaryWindow { if (this.environmentMainService.args['open-devtools'] === true) { this.contents.openDevTools({ mode: 'bottom' }); } + + // Try to claim now + this.tryClaimWindow(); + } + + tryClaimWindow(): void { + if (this._win) { + return; // already claimed + } + + if (this._store.isDisposed || this.contents.isDestroyed()) { + return; // already disposed + } + + const window = BrowserWindow.fromWebContents(this.contents); + if (window) { + this._win = window; + + // Disable Menu + window.setMenu(null); + + // Listeners + this.registerWindowListeners(window); + } } private registerWindowListeners(window: BrowserWindow): void { diff --git a/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindows.ts b/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindows.ts index 8effe598041..70783086269 100644 --- a/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindows.ts +++ b/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindows.ts @@ -20,4 +20,6 @@ export interface IAuxiliaryWindowsMainService { getFocusedWindow(): IAuxiliaryWindow | undefined; getLastActiveWindow(): IAuxiliaryWindow | undefined; + + getWindows(): readonly IAuxiliaryWindow[]; } diff --git a/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindowsMainService.ts b/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindowsMainService.ts index a85937cf5da..01718d334cc 100644 --- a/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindowsMainService.ts +++ b/src/vs/platform/auxiliaryWindow/electron-main/auxiliaryWindowsMainService.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { BrowserWindow, BrowserWindowConstructorOptions, WebContents } from 'electron'; +import { BrowserWindow, BrowserWindowConstructorOptions, WebContents, app } from 'electron'; import { Event } from 'vs/base/common/event'; import { FileAccess } from 'vs/base/common/network'; import { AuxiliaryWindow, IAuxiliaryWindow } from 'vs/platform/auxiliaryWindow/electron-main/auxiliaryWindow'; @@ -15,11 +15,29 @@ export class AuxiliaryWindowsMainService implements IAuxiliaryWindowsMainService declare readonly _serviceBrand: undefined; - private readonly windows = new Map(); + private readonly windows = new Map(); constructor( @IInstantiationService private readonly instantiationService: IInstantiationService - ) { } + ) { + this.registerListeners(); + } + + private registerListeners(): void { + + // We have to ensure that an auxiliary window gets to know its + // parent `BrowserWindow` so that it can apply listeners to it + // Unfortunately we cannot rely on static `BrowserWindow` methods + // because we might call the methods too early before the window + // is created. + + app.on('browser-window-created', (_event, browserWindow) => { + const auxiliaryWindow = this.getWindowById(browserWindow.id); + if (auxiliaryWindow) { + auxiliaryWindow.tryClaimWindow(); + } + }); + } createWindow(): BrowserWindowConstructorOptions { return this.instantiationService.invokeFunction(defaultBrowserWindowOptions, undefined, { @@ -36,7 +54,7 @@ export class AuxiliaryWindowsMainService implements IAuxiliaryWindowsMainService Event.once(auxiliaryWindow.onDidClose)(() => this.windows.delete(auxiliaryWindow.id)); } - getWindowById(windowId: number): IAuxiliaryWindow | undefined { + getWindowById(windowId: number): AuxiliaryWindow | undefined { return this.windows.get(windowId); } @@ -52,4 +70,8 @@ export class AuxiliaryWindowsMainService implements IAuxiliaryWindowsMainService getLastActiveWindow(): IAuxiliaryWindow | undefined { return getLastFocused(Array.from(this.windows.values())); } + + getWindows(): readonly IAuxiliaryWindow[] { + return Array.from(this.windows.values()); + } } diff --git a/src/vs/platform/menubar/electron-main/menubar.ts b/src/vs/platform/menubar/electron-main/menubar.ts index e928d0bb273..0ef12205389 100644 --- a/src/vs/platform/menubar/electron-main/menubar.ts +++ b/src/vs/platform/menubar/electron-main/menubar.ts @@ -11,6 +11,7 @@ import { mnemonicMenuLabel } from 'vs/base/common/labels'; import { isMacintosh, language } from 'vs/base/common/platform'; import { URI } from 'vs/base/common/uri'; import * as nls from 'vs/nls'; +import { IAuxiliaryWindowsMainService } from 'vs/platform/auxiliaryWindow/electron-main/auxiliaryWindows'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IEnvironmentMainService } from 'vs/platform/environment/electron-main/environmentMainService'; import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; @@ -74,7 +75,8 @@ export class Menubar { @ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService, @ILogService private readonly logService: ILogService, @INativeHostMainService private readonly nativeHostMainService: INativeHostMainService, - @IProductService private readonly productService: IProductService + @IProductService private readonly productService: IProductService, + @IAuxiliaryWindowsMainService private readonly auxiliaryWindowsMainService: IAuxiliaryWindowsMainService ) { this.menuUpdater = new RunOnceScheduler(() => this.doUpdateMenu(), 0); @@ -255,7 +257,7 @@ export class Menubar { // If we don't have a menu yet, set it to null to avoid the electron menu. // This should only happen on the first launch ever if (Object.keys(this.menubarMenus).length === 0) { - Menu.setApplicationMenu(isMacintosh ? new Menu() : null); + this.doSetApplicationMenu(isMacintosh ? new Menu() : null); return; } @@ -358,15 +360,28 @@ export class Menubar { } if (menubar.items && menubar.items.length > 0) { - Menu.setApplicationMenu(menubar); + this.doSetApplicationMenu(menubar); } else { - Menu.setApplicationMenu(null); + this.doSetApplicationMenu(null); } // Dispose of older menus after some time this.menuGC.schedule(); } + private doSetApplicationMenu(menu: (Menu) | (null)): void { + + // Setting the application menu sets it to all opened windows, + // but we currently do not support a menu in auxiliary windows, + // so we need to unset it there. + + Menu.setApplicationMenu(menu); + + for (const window of this.auxiliaryWindowsMainService.getWindows()) { + window.win?.setMenu(null); + } + } + private setMacApplicationMenu(macApplicationMenu: Menu): void { const about = this.createMenuItem(nls.localize('mAbout', "About {0}", this.productService.nameLong), 'workbench.action.showAboutDialog'); const checkForUpdates = this.getUpdateMenuItems();