in patched-vscode/src/vs/platform/windows/electron-main/windowsMainService.ts [284:435]
async open(openConfig: IOpenConfiguration): Promise<ICodeWindow[]> {
this.logService.trace('windowsManager#open');
if (openConfig.addMode && (openConfig.initialStartup || !this.getLastActiveWindow())) {
openConfig.addMode = false; // Make sure addMode is only enabled if we have an active window
}
const foldersToAdd: ISingleFolderWorkspacePathToOpen[] = [];
const foldersToOpen: ISingleFolderWorkspacePathToOpen[] = [];
const workspacesToOpen: IWorkspacePathToOpen[] = [];
const untitledWorkspacesToRestore: IWorkspacePathToOpen[] = [];
const emptyWindowsWithBackupsToRestore: IEmptyWindowBackupInfo[] = [];
let filesToOpen: IFilesToOpen | undefined;
let emptyToOpen = 0;
// Identify things to open from open config
const pathsToOpen = await this.getPathsToOpen(openConfig);
this.logService.trace('windowsManager#open pathsToOpen', pathsToOpen);
for (const path of pathsToOpen) {
if (isSingleFolderWorkspacePathToOpen(path)) {
if (openConfig.addMode) {
// When run with --add, take the folders that are to be opened as
// folders that should be added to the currently active window.
foldersToAdd.push(path);
} else {
foldersToOpen.push(path);
}
} else if (isWorkspacePathToOpen(path)) {
workspacesToOpen.push(path);
} else if (path.fileUri) {
if (!filesToOpen) {
filesToOpen = { filesToOpenOrCreate: [], filesToDiff: [], filesToMerge: [], remoteAuthority: path.remoteAuthority };
}
filesToOpen.filesToOpenOrCreate.push(path);
} else if (path.backupPath) {
emptyWindowsWithBackupsToRestore.push({ backupFolder: basename(path.backupPath), remoteAuthority: path.remoteAuthority });
} else {
emptyToOpen++;
}
}
// When run with --diff, take the first 2 files to open as files to diff
if (openConfig.diffMode && filesToOpen && filesToOpen.filesToOpenOrCreate.length >= 2) {
filesToOpen.filesToDiff = filesToOpen.filesToOpenOrCreate.slice(0, 2);
filesToOpen.filesToOpenOrCreate = [];
}
// When run with --merge, take the first 4 files to open as files to merge
if (openConfig.mergeMode && filesToOpen && filesToOpen.filesToOpenOrCreate.length === 4) {
filesToOpen.filesToMerge = filesToOpen.filesToOpenOrCreate.slice(0, 4);
filesToOpen.filesToOpenOrCreate = [];
filesToOpen.filesToDiff = [];
}
// When run with --wait, make sure we keep the paths to wait for
if (filesToOpen && openConfig.waitMarkerFileURI) {
filesToOpen.filesToWait = { paths: coalesce([...filesToOpen.filesToDiff, filesToOpen.filesToMerge[3] /* [3] is the resulting merge file */, ...filesToOpen.filesToOpenOrCreate]), waitMarkerFileUri: openConfig.waitMarkerFileURI };
}
// These are windows to restore because of hot-exit or from previous session (only performed once on startup!)
if (openConfig.initialStartup) {
// Untitled workspaces are always restored
untitledWorkspacesToRestore.push(...this.workspacesManagementMainService.getUntitledWorkspaces());
workspacesToOpen.push(...untitledWorkspacesToRestore);
// Empty windows with backups are always restored
emptyWindowsWithBackupsToRestore.push(...this.backupMainService.getEmptyWindowBackups());
} else {
emptyWindowsWithBackupsToRestore.length = 0;
}
// Open based on config
const { windows: usedWindows, filesOpenedInWindow } = await this.doOpen(openConfig, workspacesToOpen, foldersToOpen, emptyWindowsWithBackupsToRestore, emptyToOpen, filesToOpen, foldersToAdd);
this.logService.trace(`windowsManager#open used window count ${usedWindows.length} (workspacesToOpen: ${workspacesToOpen.length}, foldersToOpen: ${foldersToOpen.length}, emptyToRestore: ${emptyWindowsWithBackupsToRestore.length}, emptyToOpen: ${emptyToOpen})`);
// Make sure to pass focus to the most relevant of the windows if we open multiple
if (usedWindows.length > 1) {
// 1.) focus window we opened files in always with highest priority
if (filesOpenedInWindow) {
filesOpenedInWindow.focus();
}
// Otherwise, find a good window based on open params
else {
const focusLastActive = this.windowsStateHandler.state.lastActiveWindow && !openConfig.forceEmpty && !openConfig.cli._.length && !openConfig.cli['file-uri'] && !openConfig.cli['folder-uri'] && !(openConfig.urisToOpen && openConfig.urisToOpen.length);
let focusLastOpened = true;
let focusLastWindow = true;
// 2.) focus last active window if we are not instructed to open any paths
if (focusLastActive) {
const lastActiveWindow = usedWindows.filter(window => this.windowsStateHandler.state.lastActiveWindow && window.backupPath === this.windowsStateHandler.state.lastActiveWindow.backupPath);
if (lastActiveWindow.length) {
lastActiveWindow[0].focus();
focusLastOpened = false;
focusLastWindow = false;
}
}
// 3.) if instructed to open paths, focus last window which is not restored
if (focusLastOpened) {
for (let i = usedWindows.length - 1; i >= 0; i--) {
const usedWindow = usedWindows[i];
if (
(usedWindow.openedWorkspace && untitledWorkspacesToRestore.some(workspace => usedWindow.openedWorkspace && workspace.workspace.id === usedWindow.openedWorkspace.id)) || // skip over restored workspace
(usedWindow.backupPath && emptyWindowsWithBackupsToRestore.some(empty => usedWindow.backupPath && empty.backupFolder === basename(usedWindow.backupPath))) // skip over restored empty window
) {
continue;
}
usedWindow.focus();
focusLastWindow = false;
break;
}
}
// 4.) finally, always ensure to have at least last used window focused
if (focusLastWindow) {
usedWindows[usedWindows.length - 1].focus();
}
}
}
// Remember in recent document list (unless this opens for extension development)
// Also do not add paths when files are opened for diffing or merging, only if opened individually
const isDiff = filesToOpen && filesToOpen.filesToDiff.length > 0;
const isMerge = filesToOpen && filesToOpen.filesToMerge.length > 0;
if (!usedWindows.some(window => window.isExtensionDevelopmentHost) && !isDiff && !isMerge && !openConfig.noRecentEntry) {
const recents: IRecent[] = [];
for (const pathToOpen of pathsToOpen) {
if (isWorkspacePathToOpen(pathToOpen) && !pathToOpen.transient /* never add transient workspaces to history */) {
recents.push({ label: pathToOpen.label, workspace: pathToOpen.workspace, remoteAuthority: pathToOpen.remoteAuthority });
} else if (isSingleFolderWorkspacePathToOpen(pathToOpen)) {
recents.push({ label: pathToOpen.label, folderUri: pathToOpen.workspace.uri, remoteAuthority: pathToOpen.remoteAuthority });
} else if (pathToOpen.fileUri) {
recents.push({ label: pathToOpen.label, fileUri: pathToOpen.fileUri, remoteAuthority: pathToOpen.remoteAuthority });
}
}
this.workspacesHistoryMainService.addRecentlyOpened(recents);
}
// Handle --wait
this.handleWaitMarkerFile(openConfig, usedWindows);
return usedWindows;
}