Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/vs/platform/window/common/window.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ export interface IWindowSettings {
readonly enableMenuBarMnemonics: boolean;
readonly closeWhenEmpty: boolean;
readonly clickThroughInactive: boolean;
readonly newWindowProfile: string;
readonly density: IDensitySettings;
}

Expand Down
4 changes: 3 additions & 1 deletion src/vs/platform/windows/electron-main/windowsMainService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1390,7 +1390,9 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
const windowConfig = this.configurationService.getValue<IWindowSettings | undefined>('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) {
Expand Down
10 changes: 5 additions & 5 deletions src/vs/workbench/browser/workbench.contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -653,10 +653,7 @@ const registry = Registry.as<IConfigurationRegistry>(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',
Expand Down Expand Up @@ -762,6 +759,9 @@ const registry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Con
}
});

// Dynamic Window Configuration
registerWorkbenchContribution2(DynamicWindowConfiguration.ID, DynamicWindowConfiguration, WorkbenchPhase.Eventually);

// Problems
registry.registerConfiguration({
...problemsConfigurationNodeBase,
Expand Down
76 changes: 76 additions & 0 deletions src/vs/workbench/common/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<IConfigurationNode>({
'id': 'application',
Expand Down Expand Up @@ -46,6 +47,13 @@ export const problemsConfigurationNodeBase = Object.freeze<IConfigurationNode>({
'order': 101
});

export const windowConfigurationNodeBase = Object.freeze<IConfigurationNode>({
'id': 'window',
'order': 8,
'title': localize('windowConfigurationTitle', "Window"),
'type': 'object',
});

export const Extensions = {
ConfigurationMigration: 'base.contributions.configuration.migration'
};
Expand Down Expand Up @@ -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<IConfigurationRegistry>(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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
Expand Down
10 changes: 8 additions & 2 deletions src/vs/workbench/services/host/browser/browserHostService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -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<IWindowSettings | undefined>('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;
Expand Down