diff --git a/src/vs/base/parts/ipc/common/ipc.ts b/src/vs/base/parts/ipc/common/ipc.ts index f909c554528..411bfe46cca 100644 --- a/src/vs/base/parts/ipc/common/ipc.ts +++ b/src/vs/base/parts/ipc/common/ipc.ts @@ -1002,6 +1002,12 @@ export interface IChannelSenderOptions extends IBaseChannelOptions { * to each method call to the target. */ context?: unknown; + + /** + * If provided, will not proxy any of the properties + * that are part of the Map but rather return that value. + */ + properties?: Map; } export function createChannelSender(channel: IChannel, options?: IChannelSenderOptions): T { @@ -1011,6 +1017,11 @@ export function createChannelSender(channel: IChannel, options?: IChannelSend get(_target: T, propKey: PropertyKey) { if (typeof propKey === 'string') { + // Check for predefined values + if (options?.properties?.has(propKey)) { + return options.properties.get(propKey); + } + // Event if (propertyIsEvent(propKey)) { return channel.listen(propKey); diff --git a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts index 7cd6ff02b6c..7820c103b27 100644 --- a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts +++ b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts @@ -91,7 +91,6 @@ const eventPrefix = 'monacoworkbench'; class MainProcessService implements IMainProcessService { constructor( - public readonly windowId: number, private server: Server, private mainRouter: StaticRouter ) { } @@ -126,7 +125,7 @@ async function main(server: Server, initData: ISharedProcessInitData, configurat disposables.add(logService); logService.info('main', JSON.stringify(configuration)); - const mainProcessService = new MainProcessService(configuration.windowId, server, mainRouter); + const mainProcessService = new MainProcessService(server, mainRouter); services.set(IMainProcessService, mainProcessService); // Files diff --git a/src/vs/platform/electron/common/electron.ts b/src/vs/platform/electron/common/electron.ts index c80cf992081..f25e2bb1a1b 100644 --- a/src/vs/platform/electron/common/electron.ts +++ b/src/vs/platform/electron/common/electron.ts @@ -16,6 +16,9 @@ export interface IElectronService { _serviceBrand: undefined; + // Properties + readonly windowId: number; + // Events readonly onWindowOpen: Event; diff --git a/src/vs/platform/electron/electron-main/electronMainService.ts b/src/vs/platform/electron/electron-main/electronMainService.ts index d95d1c3f39d..e0078274351 100644 --- a/src/vs/platform/electron/electron-main/electronMainService.ts +++ b/src/vs/platform/electron/electron-main/electronMainService.ts @@ -41,6 +41,12 @@ export class ElectronMainService implements IElectronMainService { ) { } + //#region Properties + + get windowId(): never { throw new Error('Not implemented in electron-main'); } + + //#endregion + //#region Events readonly onWindowOpen: Event = Event.filter(Event.fromNodeEventEmitter(app, 'browser-window-created', (_, window: BrowserWindow) => window.id), windowId => !!this.windowsMainService.getWindowById(windowId)); diff --git a/src/vs/platform/ipc/common/mainProcessService.ts b/src/vs/platform/ipc/common/mainProcessService.ts index 3992ed9150e..325eda580c4 100644 --- a/src/vs/platform/ipc/common/mainProcessService.ts +++ b/src/vs/platform/ipc/common/mainProcessService.ts @@ -12,8 +12,6 @@ export interface IMainProcessService { _serviceBrand: undefined; - readonly windowId: number; - getChannel(channelName: string): IChannel; registerChannel(channelName: string, channel: IServerChannel): void; diff --git a/src/vs/platform/ipc/electron-sandbox/mainProcessService.ts b/src/vs/platform/ipc/electron-sandbox/mainProcessService.ts index d496c839494..e8ceeb88525 100644 --- a/src/vs/platform/ipc/electron-sandbox/mainProcessService.ts +++ b/src/vs/platform/ipc/electron-sandbox/mainProcessService.ts @@ -15,7 +15,7 @@ export class MainProcessService extends Disposable implements IMainProcessServic private mainProcessConnection: Client; constructor( - public readonly windowId: number + windowId: number ) { super(); diff --git a/src/vs/workbench/contrib/splash/electron-browser/partsSplash.contribution.ts b/src/vs/workbench/contrib/splash/electron-browser/partsSplash.contribution.ts index b4c945f4714..0fb74c2e7cb 100644 --- a/src/vs/workbench/contrib/splash/electron-browser/partsSplash.contribution.ts +++ b/src/vs/workbench/contrib/splash/electron-browser/partsSplash.contribution.ts @@ -26,6 +26,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import * as perf from 'vs/base/common/performance'; import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-browser/environmentService'; import { assertIsDefined } from 'vs/base/common/types'; +import { IElectronService } from 'vs/platform/electron/common/electron'; class PartsSplash { @@ -45,6 +46,7 @@ class PartsSplash { @ILifecycleService lifecycleService: ILifecycleService, @IEditorGroupsService editorGroupsService: IEditorGroupsService, @IConfigurationService configService: IConfigurationService, + @IElectronService private readonly _electronService: IElectronService ) { lifecycleService.when(LifecyclePhase.Restored).then(_ => { this._removePartsSplash(); @@ -112,7 +114,7 @@ class PartsSplash { // the color needs to be in hex const backgroundColor = this._themeService.getColorTheme().getColor(editorBackground) || themes.WORKBENCH_BACKGROUND(this._themeService.getColorTheme()); const payload = JSON.stringify({ baseTheme, background: Color.Format.CSS.formatHex(backgroundColor) }); - ipcRenderer.send('vscode:changeColorTheme', this._envService.configuration.windowId, payload); + ipcRenderer.send('vscode:changeColorTheme', this._electronService.windowId, payload); } } diff --git a/src/vs/workbench/electron-browser/actions/windowActions.ts b/src/vs/workbench/electron-browser/actions/windowActions.ts index bbff3bb92e9..08ad2588398 100644 --- a/src/vs/workbench/electron-browser/actions/windowActions.ts +++ b/src/vs/workbench/electron-browser/actions/windowActions.ts @@ -20,8 +20,6 @@ import { ICommandHandler } from 'vs/platform/commands/common/commands'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IElectronService } from 'vs/platform/electron/common/electron'; -import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-browser/environmentService'; -import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { Codicon } from 'vs/base/common/codicons'; export class CloseCurrentWindowAction extends Action { @@ -169,7 +167,6 @@ export abstract class BaseSwitchWindow extends Action { constructor( id: string, label: string, - private readonly environmentService: INativeWorkbenchEnvironmentService, private readonly quickInputService: IQuickInputService, private readonly keybindingService: IKeybindingService, private readonly modelService: IModelService, @@ -182,7 +179,7 @@ export abstract class BaseSwitchWindow extends Action { protected abstract isQuickNavigate(): boolean; async run(): Promise { - const currentWindowId = this.environmentService.configuration.windowId; + const currentWindowId = this.electronService.windowId; const windows = await this.electronService.getWindows(); const placeHolder = nls.localize('switchWindowPlaceHolder', "Select a window to switch to"); @@ -225,14 +222,13 @@ export class SwitchWindow extends BaseSwitchWindow { constructor( id: string, label: string, - @IWorkbenchEnvironmentService environmentService: INativeWorkbenchEnvironmentService, @IQuickInputService quickInputService: IQuickInputService, @IKeybindingService keybindingService: IKeybindingService, @IModelService modelService: IModelService, @IModeService modeService: IModeService, @IElectronService electronService: IElectronService ) { - super(id, label, environmentService, quickInputService, keybindingService, modelService, modeService, electronService); + super(id, label, quickInputService, keybindingService, modelService, modeService, electronService); } protected isQuickNavigate(): boolean { @@ -248,14 +244,13 @@ export class QuickSwitchWindow extends BaseSwitchWindow { constructor( id: string, label: string, - @IWorkbenchEnvironmentService environmentService: INativeWorkbenchEnvironmentService, @IQuickInputService quickInputService: IQuickInputService, @IKeybindingService keybindingService: IKeybindingService, @IModelService modelService: IModelService, @IModeService modeService: IModeService, @IElectronService electronService: IElectronService ) { - super(id, label, environmentService, quickInputService, keybindingService, modelService, modeService, electronService); + super(id, label, quickInputService, keybindingService, modelService, modeService, electronService); } protected isQuickNavigate(): boolean { diff --git a/src/vs/workbench/electron-browser/desktop.main.ts b/src/vs/workbench/electron-browser/desktop.main.ts index cd46c8c8c2f..f4a86a58370 100644 --- a/src/vs/workbench/electron-browser/desktop.main.ts +++ b/src/vs/workbench/electron-browser/desktop.main.ts @@ -199,7 +199,7 @@ class DesktopMain extends Disposable { serviceCollection.set(IRemoteAgentService, remoteAgentService); // Electron - const electronService = new ElectronService(mainProcessService) as IElectronService; + const electronService = new ElectronService(this.configuration.windowId, mainProcessService) as IElectronService; serviceCollection.set(IElectronService, electronService); // Files diff --git a/src/vs/workbench/electron-browser/window.ts b/src/vs/workbench/electron-browser/window.ts index 971d117d924..104dadf9cbe 100644 --- a/src/vs/workbench/electron-browser/window.ts +++ b/src/vs/workbench/electron-browser/window.ts @@ -285,8 +285,8 @@ export class NativeWindow extends Disposable { // Detect minimize / maximize this._register(Event.any( - Event.map(Event.filter(this.electronService.onWindowMaximize, id => id === this.environmentService.configuration.windowId), () => true), - Event.map(Event.filter(this.electronService.onWindowUnmaximize, id => id === this.environmentService.configuration.windowId), () => false) + Event.map(Event.filter(this.electronService.onWindowMaximize, id => id === this.electronService.windowId), () => true), + Event.map(Event.filter(this.electronService.onWindowUnmaximize, id => id === this.electronService.windowId), () => false) )(e => this.onDidChangeMaximized(e))); this.onDidChangeMaximized(this.environmentService.configuration.maximized ?? false); @@ -400,7 +400,7 @@ export class NativeWindow extends Disposable { this.setupOpenHandlers(); // Emit event when vscode is ready - this.lifecycleService.when(LifecyclePhase.Ready).then(() => ipcRenderer.send('vscode:workbenchReady', this.environmentService.configuration.windowId)); + this.lifecycleService.when(LifecyclePhase.Ready).then(() => ipcRenderer.send('vscode:workbenchReady', this.electronService.windowId)); // Integrity warning this.integrityService.isPure().then(res => this.titleService.updateProperties({ isPure: res.isPure })); @@ -727,6 +727,7 @@ class NativeMenubarControl extends MenubarControl { @IAccessibilityService accessibilityService: IAccessibilityService, @IMenubarService private readonly menubarService: IMenubarService, @IHostService hostService: IHostService, + @IElectronService private readonly electronService: IElectronService ) { super( menuService, @@ -775,7 +776,7 @@ class NativeMenubarControl extends MenubarControl { // Send menus to main process to be rendered by Electron const menubarData = { menus: {}, keybindings: {} }; if (this.getMenubarMenus(menubarData)) { - this.menubarService.updateMenubar(this.environmentService.configuration.windowId, menubarData); + this.menubarService.updateMenubar(this.electronService.windowId, menubarData); } } diff --git a/src/vs/workbench/services/electron/electron-sandbox/electronService.ts b/src/vs/workbench/services/electron/electron-sandbox/electronService.ts index 033d02dcdde..1a3b40dff92 100644 --- a/src/vs/workbench/services/electron/electron-sandbox/electronService.ts +++ b/src/vs/workbench/services/electron/electron-sandbox/electronService.ts @@ -12,8 +12,17 @@ export class ElectronService { _serviceBrand: undefined; constructor( + readonly windowId: number, @IMainProcessService mainProcessService: IMainProcessService ) { - return createChannelSender(mainProcessService.getChannel('electron'), { context: mainProcessService.windowId }); + return createChannelSender(mainProcessService.getChannel('electron'), { + context: windowId, + properties: (() => { + const properties = new Map(); + properties.set('windowId', windowId); + + return properties; + })() + }); } } diff --git a/src/vs/workbench/services/host/electron-browser/desktopHostService.ts b/src/vs/workbench/services/host/electron-browser/desktopHostService.ts index d883e646a1a..5ef55e3b63f 100644 --- a/src/vs/workbench/services/host/electron-browser/desktopHostService.ts +++ b/src/vs/workbench/services/host/electron-browser/desktopHostService.ts @@ -27,8 +27,8 @@ export class DesktopHostService extends Disposable implements IHostService { get onDidChangeFocus(): Event { return this._onDidChangeFocus; } private _onDidChangeFocus: Event = Event.latch(Event.any( - Event.map(Event.filter(this.electronService.onWindowFocus, id => id === this.environmentService.configuration.windowId), () => this.hasFocus), - Event.map(Event.filter(this.electronService.onWindowBlur, id => id === this.environmentService.configuration.windowId), () => this.hasFocus) + Event.map(Event.filter(this.electronService.onWindowFocus, id => id === this.electronService.windowId), () => this.hasFocus), + Event.map(Event.filter(this.electronService.onWindowBlur, id => id === this.electronService.windowId), () => this.hasFocus) )); get hasFocus(): boolean { @@ -42,7 +42,7 @@ export class DesktopHostService extends Disposable implements IHostService { return false; } - return activeWindowId === this.environmentService.configuration.windowId; + return activeWindowId === this.electronService.windowId; } openWindow(options?: IOpenEmptyWindowOptions): Promise; diff --git a/src/vs/workbench/services/lifecycle/electron-browser/lifecycleService.ts b/src/vs/workbench/services/lifecycle/electron-sandbox/lifecycleService.ts similarity index 93% rename from src/vs/workbench/services/lifecycle/electron-browser/lifecycleService.ts rename to src/vs/workbench/services/lifecycle/electron-sandbox/lifecycleService.ts index b675425335d..9a7f621c073 100644 --- a/src/vs/workbench/services/lifecycle/electron-browser/lifecycleService.ts +++ b/src/vs/workbench/services/lifecycle/electron-sandbox/lifecycleService.ts @@ -14,8 +14,7 @@ import { onUnexpectedError } from 'vs/base/common/errors'; import { AbstractLifecycleService } from 'vs/platform/lifecycle/common/lifecycleService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import Severity from 'vs/base/common/severity'; -import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; -import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-browser/environmentService'; +import { IElectronService } from 'vs/platform/electron/common/electron'; export class NativeLifecycleService extends AbstractLifecycleService { @@ -27,7 +26,7 @@ export class NativeLifecycleService extends AbstractLifecycleService { constructor( @INotificationService private readonly notificationService: INotificationService, - @IWorkbenchEnvironmentService private readonly environmentService: INativeWorkbenchEnvironmentService, + @IElectronService private readonly electronService: IElectronService, @IStorageService readonly storageService: IStorageService, @ILogService readonly logService: ILogService ) { @@ -57,7 +56,7 @@ export class NativeLifecycleService extends AbstractLifecycleService { } private registerListeners(): void { - const windowId = this.environmentService.configuration.windowId; + const windowId = this.electronService.windowId; // Main side indicates that window is about to unload, check for vetos ipcRenderer.on('vscode:onBeforeUnload', (event: unknown, reply: { okChannel: string, cancelChannel: string, reason: ShutdownReason }) => { diff --git a/src/vs/workbench/services/output/electron-browser/outputChannelModelService.ts b/src/vs/workbench/services/output/electron-browser/outputChannelModelService.ts index c4322d81a9c..ae0c95b56ba 100644 --- a/src/vs/workbench/services/output/electron-browser/outputChannelModelService.ts +++ b/src/vs/workbench/services/output/electron-browser/outputChannelModelService.ts @@ -22,6 +22,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { Emitter, Event } from 'vs/base/common/event'; import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-browser/environmentService'; +import { IElectronService } from 'vs/platform/electron/common/electron'; class OutputChannelBackedByFile extends AbstractFileOutputChannelModel implements IOutputChannelModel { @@ -204,7 +205,8 @@ export class OutputChannelModelService extends AsbtractOutputChannelModelService constructor( @IInstantiationService instantiationService: IInstantiationService, @IWorkbenchEnvironmentService private readonly environmentService: INativeWorkbenchEnvironmentService, - @IFileService private readonly fileService: IFileService + @IFileService private readonly fileService: IFileService, + @IElectronService private readonly electronService: IElectronService ) { super(instantiationService); } @@ -217,7 +219,7 @@ export class OutputChannelModelService extends AsbtractOutputChannelModelService private _outputDir: Promise | null = null; private get outputDir(): Promise { if (!this._outputDir) { - const outputDir = URI.file(join(this.environmentService.logsPath, `output_${this.environmentService.configuration.windowId}_${toLocalISOString(new Date()).replace(/-|:|\.\d+Z$/g, '')}`)); + const outputDir = URI.file(join(this.environmentService.logsPath, `output_${this.electronService.windowId}_${toLocalISOString(new Date()).replace(/-|:|\.\d+Z$/g, '')}`)); this._outputDir = this.fileService.createFolder(outputDir).then(() => outputDir); } return this._outputDir; diff --git a/src/vs/workbench/services/sharedProcess/electron-browser/sharedProcessService.ts b/src/vs/workbench/services/sharedProcess/electron-browser/sharedProcessService.ts index 3e9c579408b..f956a917667 100644 --- a/src/vs/workbench/services/sharedProcess/electron-browser/sharedProcessService.ts +++ b/src/vs/workbench/services/sharedProcess/electron-browser/sharedProcessService.ts @@ -11,6 +11,7 @@ import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedPr import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-browser/environmentService'; +import { IElectronService } from 'vs/platform/electron/common/electron'; export class SharedProcessService implements ISharedProcessService { @@ -21,12 +22,13 @@ export class SharedProcessService implements ISharedProcessService { constructor( @IMainProcessService mainProcessService: IMainProcessService, + @IElectronService electronService: IElectronService, @IWorkbenchEnvironmentService environmentService: INativeWorkbenchEnvironmentService ) { this.sharedProcessMainChannel = mainProcessService.getChannel('sharedProcess'); this.withSharedProcessConnection = this.whenSharedProcessReady() - .then(() => connect(environmentService.sharedIPCHandle, `window:${environmentService.configuration.windowId}`)); + .then(() => connect(environmentService.sharedIPCHandle, `window:${electronService.windowId}`)); } whenSharedProcessReady(): Promise { diff --git a/src/vs/workbench/services/url/electron-sandbox/urlService.ts b/src/vs/workbench/services/url/electron-sandbox/urlService.ts index 0d1363f509e..c58ff6e89eb 100644 --- a/src/vs/workbench/services/url/electron-sandbox/urlService.ts +++ b/src/vs/workbench/services/url/electron-sandbox/urlService.ts @@ -24,7 +24,7 @@ export class RelayURLService extends NativeURLService implements IURLHandler, IO private urlService: IURLService; constructor( - @IMainProcessService private readonly mainProcessService: IMainProcessService, + @IMainProcessService mainProcessService: IMainProcessService, @IOpenerService openerService: IOpenerService, @IElectronService private electronService: IElectronService ) { @@ -41,9 +41,9 @@ export class RelayURLService extends NativeURLService implements IURLHandler, IO let query = uri.query; if (!query) { - query = `windowId=${encodeURIComponent(this.mainProcessService.windowId)}`; + query = `windowId=${encodeURIComponent(this.electronService.windowId)}`; } else { - query += `&windowId=${encodeURIComponent(this.mainProcessService.windowId)}`; + query += `&windowId=${encodeURIComponent(this.electronService.windowId)}`; } return uri.with({ query }); diff --git a/src/vs/workbench/services/workspaces/electron-sandbox/workspacesService.ts b/src/vs/workbench/services/workspaces/electron-sandbox/workspacesService.ts index 2e68d7b154b..f0e2aef5650 100644 --- a/src/vs/workbench/services/workspaces/electron-sandbox/workspacesService.ts +++ b/src/vs/workbench/services/workspaces/electron-sandbox/workspacesService.ts @@ -7,15 +7,17 @@ import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces'; import { IMainProcessService } from 'vs/platform/ipc/common/mainProcessService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { createChannelSender } from 'vs/base/parts/ipc/common/ipc'; +import { IElectronService } from 'vs/platform/electron/common/electron'; export class NativeWorkspacesService { _serviceBrand: undefined; constructor( - @IMainProcessService mainProcessService: IMainProcessService + @IMainProcessService mainProcessService: IMainProcessService, + @IElectronService electronService: IElectronService ) { - return createChannelSender(mainProcessService.getChannel('workspaces'), { context: mainProcessService.windowId }); + return createChannelSender(mainProcessService.getChannel('workspaces'), { context: electronService.windowId }); } } diff --git a/src/vs/workbench/test/electron-browser/workbenchTestServices.ts b/src/vs/workbench/test/electron-browser/workbenchTestServices.ts index 67c69cb92c6..b5f33a62fa6 100644 --- a/src/vs/workbench/test/electron-browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/electron-browser/workbenchTestServices.ts @@ -162,6 +162,8 @@ export class TestSharedProcessService implements ISharedProcessService { export class TestElectronService implements IElectronService { _serviceBrand: undefined; + readonly windowId = -1; + onWindowOpen: Event = Event.None; onWindowMaximize: Event = Event.None; onWindowUnmaximize: Event = Event.None; diff --git a/src/vs/workbench/workbench.desktop.main.ts b/src/vs/workbench/workbench.desktop.main.ts index 4348c650491..e6fc152ace3 100644 --- a/src/vs/workbench/workbench.desktop.main.ts +++ b/src/vs/workbench/workbench.desktop.main.ts @@ -56,7 +56,6 @@ import 'vs/workbench/services/authentication/electron-browser/authenticationToke import 'vs/workbench/services/authentication/browser/authenticationService'; import 'vs/workbench/services/host/electron-browser/desktopHostService'; import 'vs/workbench/services/request/electron-browser/requestService'; -import 'vs/workbench/services/lifecycle/electron-browser/lifecycleService'; import 'vs/workbench/services/sharedProcess/electron-browser/sharedProcessService'; import 'vs/workbench/services/localizations/electron-browser/localizationsService'; import 'vs/workbench/services/clipboard/electron-browser/clipboardService'; diff --git a/src/vs/workbench/workbench.sandbox.main.ts b/src/vs/workbench/workbench.sandbox.main.ts index f9886185048..30b737e8d2c 100644 --- a/src/vs/workbench/workbench.sandbox.main.ts +++ b/src/vs/workbench/workbench.sandbox.main.ts @@ -19,6 +19,7 @@ import 'vs/workbench/services/menubar/electron-sandbox/menubarService'; import 'vs/workbench/services/issue/electron-sandbox/issueService'; import 'vs/workbench/services/update/electron-sandbox/updateService'; import 'vs/workbench/services/url/electron-sandbox/urlService'; +import 'vs/workbench/services/lifecycle/electron-sandbox/lifecycleService'; //#endregion