From 010e5e1aba6264958618e16451d0c79b20e66d1e Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Fri, 24 May 2024 18:23:22 +0200 Subject: [PATCH] fix #194105 --- src/vs/platform/window/common/window.ts | 1 + .../electron-main/windowsMainService.ts | 4 +- .../browser/workbench.contribution.ts | 10 +-- src/vs/workbench/common/configuration.ts | 76 +++++++++++++++++++ .../browser/configurationService.ts | 6 ++ .../host/browser/browserHostService.ts | 10 ++- 6 files changed, 99 insertions(+), 8 deletions(-) diff --git a/src/vs/platform/window/common/window.ts b/src/vs/platform/window/common/window.ts index ae20d9d762085..16eef424015ad 100644 --- a/src/vs/platform/window/common/window.ts +++ b/src/vs/platform/window/common/window.ts @@ -158,6 +158,7 @@ export interface IWindowSettings { readonly enableMenuBarMnemonics: boolean; readonly closeWhenEmpty: boolean; readonly clickThroughInactive: boolean; + readonly newWindowProfile: string; readonly density: IDensitySettings; } diff --git a/src/vs/platform/windows/electron-main/windowsMainService.ts b/src/vs/platform/windows/electron-main/windowsMainService.ts index a4cb0ca698b19..8c9cb2b186853 100644 --- a/src/vs/platform/windows/electron-main/windowsMainService.ts +++ b/src/vs/platform/windows/electron-main/windowsMainService.ts @@ -1390,7 +1390,9 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic const windowConfig = this.configurationService.getValue('window'); const lastActiveWindow = this.getLastActiveWindow(); - const defaultProfile = lastActiveWindow?.profile ?? this.userDataProfilesMainService.defaultProfile; + const newWindowProfile = windowConfig?.newWindowProfile + ? this.userDataProfilesMainService.profiles.find(profile => profile.name === windowConfig.newWindowProfile) : undefined; + const defaultProfile = newWindowProfile ?? lastActiveWindow?.profile ?? this.userDataProfilesMainService.defaultProfile; let window: ICodeWindow | undefined; if (!options.forceNewWindow && !options.forceNewTabbedWindow) { diff --git a/src/vs/workbench/browser/workbench.contribution.ts b/src/vs/workbench/browser/workbench.contribution.ts index ce003932bf348..8494c963f3fa2 100644 --- a/src/vs/workbench/browser/workbench.contribution.ts +++ b/src/vs/workbench/browser/workbench.contribution.ts @@ -7,7 +7,7 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { localize } from 'vs/nls'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { isMacintosh, isWindows, isLinux, isWeb } from 'vs/base/common/platform'; -import { ConfigurationMigrationWorkbenchContribution, DynamicWorkbenchSecurityConfiguration, IConfigurationMigrationRegistry, workbenchConfigurationNodeBase, Extensions, ConfigurationKeyValuePairs, problemsConfigurationNodeBase } from 'vs/workbench/common/configuration'; +import { ConfigurationMigrationWorkbenchContribution, DynamicWorkbenchSecurityConfiguration, IConfigurationMigrationRegistry, workbenchConfigurationNodeBase, Extensions, ConfigurationKeyValuePairs, problemsConfigurationNodeBase, windowConfigurationNodeBase, DynamicWindowConfiguration } from 'vs/workbench/common/configuration'; import { isStandalone } from 'vs/base/browser/browser'; import { WorkbenchPhase, registerWorkbenchContribution2 } from 'vs/workbench/common/contributions'; import { ActivityBarPosition, EditorActionsLocation, EditorTabsMode, LayoutSettings } from 'vs/workbench/services/layout/browser/layoutService'; @@ -653,10 +653,7 @@ const registry = Registry.as(ConfigurationExtensions.Con ].join('\n- '); // intentionally concatenated to not produce a string that is too long for translations registry.registerConfiguration({ - 'id': 'window', - 'order': 8, - 'title': localize('windowConfigurationTitle', "Window"), - 'type': 'object', + ...windowConfigurationNodeBase, 'properties': { 'window.title': { 'type': 'string', @@ -762,6 +759,9 @@ const registry = Registry.as(ConfigurationExtensions.Con } }); + // Dynamic Window Configuration + registerWorkbenchContribution2(DynamicWindowConfiguration.ID, DynamicWindowConfiguration, WorkbenchPhase.Eventually); + // Problems registry.registerConfiguration({ ...problemsConfigurationNodeBase, diff --git a/src/vs/workbench/common/configuration.ts b/src/vs/workbench/common/configuration.ts index 4e15bd458bede..30ab0f27e4852 100644 --- a/src/vs/workbench/common/configuration.ts +++ b/src/vs/workbench/common/configuration.ts @@ -16,6 +16,7 @@ import { OperatingSystem, isWindows } from 'vs/base/common/platform'; import { URI } from 'vs/base/common/uri'; import { equals } from 'vs/base/common/objects'; import { DeferredPromise } from 'vs/base/common/async'; +import { IUserDataProfile, IUserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile'; export const applicationConfigurationNodeBase = Object.freeze({ 'id': 'application', @@ -46,6 +47,13 @@ export const problemsConfigurationNodeBase = Object.freeze({ 'order': 101 }); +export const windowConfigurationNodeBase = Object.freeze({ + 'id': 'window', + 'order': 8, + 'title': localize('windowConfigurationTitle', "Window"), + 'type': 'object', +}); + export const Extensions = { ConfigurationMigration: 'base.contributions.configuration.migration' }; @@ -225,3 +233,71 @@ export class DynamicWorkbenchSecurityConfiguration extends Disposable implements }); } } + +const CONFIG_NEW_WINDOW_PROFILE = 'window.newWindowProfile'; + +export class DynamicWindowConfiguration extends Disposable implements IWorkbenchContribution { + + static readonly ID = 'workbench.contrib.dynamicWindowConfiguration'; + + private configurationNode: IConfigurationNode | undefined; + private newWindowProfile: IUserDataProfile | undefined; + + constructor( + @IUserDataProfilesService private readonly userDataProfilesService: IUserDataProfilesService, + @IConfigurationService private readonly configurationService: IConfigurationService, + ) { + super(); + this.registerNewWindowProfileConfiguration(); + this._register(this.userDataProfilesService.onDidChangeProfiles((e) => this.registerNewWindowProfileConfiguration())); + + this.setNewWindowProfile(); + this.checkAndResetNewWindowProfileConfig(); + + this._register(configurationService.onDidChangeConfiguration(e => { + if (e.source !== ConfigurationTarget.DEFAULT && e.affectsConfiguration(CONFIG_NEW_WINDOW_PROFILE)) { + this.setNewWindowProfile(); + } + })); + this._register(this.userDataProfilesService.onDidChangeProfiles(() => this.checkAndResetNewWindowProfileConfig())); + } + + private registerNewWindowProfileConfiguration(): void { + const registry = Registry.as(ConfigurationExtensions.Configuration); + const configurationNode: IConfigurationNode = { + ...windowConfigurationNodeBase, + 'properties': { + [CONFIG_NEW_WINDOW_PROFILE]: { + 'type': ['string', 'null'], + 'default': null, + 'enum': [...this.userDataProfilesService.profiles.map(profile => profile.name), null], + 'description': localize('newWindowProfile', "Specifies the profile to use when opening a new window. If a profile name is provided, the new window will use that profile. If no profile name is provided, the new window will use the profile of the last window or the default profile if no previous window exists."), + 'scope': ConfigurationScope.APPLICATION, + } + } + }; + if (this.configurationNode) { + registry.updateConfigurations({ add: [configurationNode], remove: [this.configurationNode] }); + } else { + registry.registerConfiguration(configurationNode); + } + this.configurationNode = configurationNode; + } + + private setNewWindowProfile(): void { + const newWindowProfileName = this.configurationService.getValue(CONFIG_NEW_WINDOW_PROFILE); + this.newWindowProfile = newWindowProfileName ? this.userDataProfilesService.profiles.find(profile => profile.name === newWindowProfileName) : undefined; + } + + private checkAndResetNewWindowProfileConfig(): void { + const newWindowProfileName = this.configurationService.getValue(CONFIG_NEW_WINDOW_PROFILE); + if (!newWindowProfileName) { + return; + } + const profile = this.newWindowProfile ? this.userDataProfilesService.profiles.find(profile => profile.id === this.newWindowProfile!.id) : undefined; + if (newWindowProfileName === profile?.name) { + return; + } + this.configurationService.updateValue(CONFIG_NEW_WINDOW_PROFILE, profile?.name); + } +} diff --git a/src/vs/workbench/services/configuration/browser/configurationService.ts b/src/vs/workbench/services/configuration/browser/configurationService.ts index 974d5a93552bd..b44f1e122353e 100644 --- a/src/vs/workbench/services/configuration/browser/configurationService.ts +++ b/src/vs/workbench/services/configuration/browser/configurationService.ts @@ -1094,6 +1094,9 @@ export class WorkspaceService extends Disposable implements IWorkbenchConfigurat if (inspect.userLocalValue !== undefined) { definedTargets.push(ConfigurationTarget.USER_LOCAL); } + if (inspect.applicationValue !== undefined) { + definedTargets.push(ConfigurationTarget.APPLICATION); + } if (value === undefined) { // Remove the setting in all defined targets @@ -1115,6 +1118,9 @@ export class WorkspaceService extends Disposable implements IWorkbenchConfigurat } private toEditableConfigurationTarget(target: ConfigurationTarget, key: string): EditableConfigurationTarget | null { + if (target === ConfigurationTarget.APPLICATION) { + return EditableConfigurationTarget.USER_LOCAL; + } if (target === ConfigurationTarget.USER) { if (this.remoteUserConfiguration) { const scope = this.configurationRegistry.getConfigurationProperties()[key]?.scope; diff --git a/src/vs/workbench/services/host/browser/browserHostService.ts b/src/vs/workbench/services/host/browser/browserHostService.ts index 3ce96bba22a82..738e41bd672b9 100644 --- a/src/vs/workbench/services/host/browser/browserHostService.ts +++ b/src/vs/workbench/services/host/browser/browserHostService.ts @@ -40,6 +40,7 @@ import { IUserDataProfileService } from 'vs/workbench/services/userDataProfile/c import { coalesce } from 'vs/base/common/arrays'; import { mainWindow, isAuxiliaryWindow } from 'vs/base/browser/window'; import { isIOS, isMacintosh } from 'vs/base/common/platform'; +import { IUserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile'; enum HostShutdownReason { @@ -79,6 +80,7 @@ export class BrowserHostService extends Disposable implements IHostService { @IDialogService private readonly dialogService: IDialogService, @IWorkspaceContextService private readonly contextService: IWorkspaceContextService, @IUserDataProfileService private readonly userDataProfileService: IUserDataProfileService, + @IUserDataProfilesService private readonly userDataProfilesService: IUserDataProfilesService, ) { super(); @@ -409,8 +411,12 @@ export class BrowserHostService extends Disposable implements IHostService { } } - if (!this.userDataProfileService.currentProfile.isDefault) { - newPayload.push(['lastActiveProfile', this.userDataProfileService.currentProfile.id]); + const windowConfig = this.configurationService.getValue('window'); + const newWindowProfile = (windowConfig?.newWindowProfile + ? this.userDataProfilesService.profiles.find(profile => profile.name === windowConfig.newWindowProfile) + : undefined) ?? this.userDataProfileService.currentProfile; + if (!newWindowProfile.isDefault) { + newPayload.push(['lastActiveProfile', newWindowProfile.id]); } return newPayload.length ? newPayload : undefined;