diff --git a/src/vs/code/electron-main/windows.ts b/src/vs/code/electron-main/windows.ts index 754a63af36dfe6481ca4abf941c25a54f0807803..743776829a765daff227700fa60410bf863c2d34 100644 --- a/src/vs/code/electron-main/windows.ts +++ b/src/vs/code/electron-main/windows.ts @@ -14,7 +14,7 @@ import { IBackupMainService } from 'vs/platform/backup/common/backup'; import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment'; import { IStorageService } from 'vs/platform/storage/node/storage'; import { CodeWindow, IWindowState as ISingleWindowState, defaultWindowState, WindowMode } from 'vs/code/electron-main/window'; -import { ipcMain as ipc, app, screen, BrowserWindow, dialog } from 'electron'; +import { ipcMain as ipc, screen, BrowserWindow, dialog } from 'electron'; import { IPathWithLineAndColumn, parseLineAndColumnAware } from 'vs/code/node/paths'; import { ILifecycleService, UnloadReason } from 'vs/platform/lifecycle/electron-main/lifecycleMain'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -231,15 +231,15 @@ export class WindowsManager implements IWindowsMainService { let foldersToRestore = (openConfig.initialStartup && !openConfig.cli.extensionDevelopmentPath) ? this.backupService.getWorkspaceBackupPaths() : []; let filesToOpen: IPath[] = []; let filesToDiff: IPath[] = []; + let filesToCreate = pathsToOpen.filter(iPath => !!iPath.filePath && iPath.createFilePath); let emptyToOpen = pathsToOpen.filter(iPath => !iPath.workspacePath && !iPath.filePath); let emptyToRestore = (openConfig.initialStartup && !openConfig.cli.extensionDevelopmentPath) ? this.backupService.getEmptyWorkspaceBackupPaths() : []; - let filesToCreate = pathsToOpen.filter(iPath => !!iPath.filePath && iPath.createFilePath); // Diff mode needs special care - const candidates = pathsToOpen.filter(iPath => !!iPath.filePath && !iPath.createFilePath); + const filesToOpenCandidates = pathsToOpen.filter(iPath => !!iPath.filePath && !iPath.createFilePath); if (openConfig.diffMode) { - if (candidates.length === 2) { - filesToDiff = candidates; + if (filesToOpenCandidates.length === 2) { + filesToDiff = filesToOpenCandidates; } else { emptyToOpen = [Object.create(null)]; // improper use of diffMode, open empty } @@ -248,34 +248,16 @@ export class WindowsManager implements IWindowsMainService { foldersToRestore = []; // diff is always in empty workspace filesToCreate = []; // diff ignores other files that do not exist } else { - filesToOpen = candidates; + filesToOpen = filesToOpenCandidates; } - // let the user settings override how folders are open in a new window or same window unless we are forced - const windowConfig = this.configurationService.getConfiguration('window'); - let openFolderInNewWindow = (openConfig.preferNewWindow || openConfig.forceNewWindow) && !openConfig.forceReuseWindow; - if (!openConfig.forceNewWindow && !openConfig.forceReuseWindow && windowConfig && (windowConfig.openFoldersInNewWindow === 'on' || windowConfig.openFoldersInNewWindow === 'off')) { - openFolderInNewWindow = (windowConfig.openFoldersInNewWindow === 'on'); - } + // Settings can decide if files/folders open in new window or not + let { openFolderInNewWindow, openFilesInNewWindow } = this.shouldOpenNewWindow(openConfig); // Handle files to open/diff or to create when we dont open a folder and we do not restore any folder/untitled from hot-exit const usedWindows: CodeWindow[] = []; if (!foldersToOpen.length && !foldersToRestore.length && !emptyToRestore.length && (filesToOpen.length > 0 || filesToCreate.length > 0 || filesToDiff.length > 0)) { - // let the user settings override how files are open in a new window or same window unless we are forced (not for extension development though) - let openFilesInNewWindow: boolean; - if (openConfig.forceNewWindow || openConfig.forceReuseWindow) { - openFilesInNewWindow = openConfig.forceNewWindow && !openConfig.forceReuseWindow; - } else { - if (openConfig.context === OpenContext.DOCK) { - openFilesInNewWindow = true; // only on macOS do we allow to open files in a new window if this is triggered via DOCK context - } - - if (!openConfig.cli.extensionDevelopmentPath && windowConfig && (windowConfig.openFilesInNewWindow === 'on' || windowConfig.openFilesInNewWindow === 'off')) { - openFilesInNewWindow = (windowConfig.openFilesInNewWindow === 'on'); - } - } - // Open Files in last instance if any and flag tells us so const fileToCheck = filesToOpen[0] || filesToCreate[0] || filesToDiff[0]; const windowOrFolder = findBestWindowOrFolder({ @@ -286,6 +268,7 @@ export class WindowsManager implements IWindowsMainService { filePath: fileToCheck && fileToCheck.filePath, userHome: this.environmentService.userHome }); + if (windowOrFolder instanceof CodeWindow) { windowOrFolder.focus(); const files = { filesToOpen, filesToCreate, filesToDiff }; // copy to object because they get reset shortly after @@ -328,6 +311,7 @@ export class WindowsManager implements IWindowsMainService { if (windowsOnWorkspacePath.length > 0) { const browserWindow = windowsOnWorkspacePath[0]; browserWindow.focus(); // just focus one of them + const files = { filesToOpen, filesToCreate, filesToDiff }; // copy to object because they get reset shortly after browserWindow.ready().then(readyWindow => { readyWindow.send('vscode:openFiles', files); @@ -418,7 +402,6 @@ export class WindowsManager implements IWindowsMainService { pathsToOpen.forEach(iPath => { if (iPath.filePath || iPath.workspacePath) { - app.addRecentDocument(iPath.filePath || iPath.workspacePath); recentPaths.push({ path: iPath.filePath || iPath.workspacePath, isFile: !!iPath.filePath }); } }); @@ -576,6 +559,32 @@ export class WindowsManager implements IWindowsMainService { return null; } + private shouldOpenNewWindow(openConfig: IOpenConfiguration): { openFolderInNewWindow: boolean; openFilesInNewWindow: boolean; } { + + // let the user settings override how folders are open in a new window or same window unless we are forced + const windowConfig = this.configurationService.getConfiguration('window'); + let openFolderInNewWindow = (openConfig.preferNewWindow || openConfig.forceNewWindow) && !openConfig.forceReuseWindow; + if (!openConfig.forceNewWindow && !openConfig.forceReuseWindow && windowConfig && (windowConfig.openFoldersInNewWindow === 'on' || windowConfig.openFoldersInNewWindow === 'off')) { + openFolderInNewWindow = (windowConfig.openFoldersInNewWindow === 'on'); + } + + // let the user settings override how files are open in a new window or same window unless we are forced (not for extension development though) + let openFilesInNewWindow: boolean; + if (openConfig.forceNewWindow || openConfig.forceReuseWindow) { + openFilesInNewWindow = openConfig.forceNewWindow && !openConfig.forceReuseWindow; + } else { + if (openConfig.context === OpenContext.DOCK) { + openFilesInNewWindow = true; // only on macOS do we allow to open files in a new window if this is triggered via DOCK context + } + + if (!openConfig.cli.extensionDevelopmentPath && windowConfig && (windowConfig.openFilesInNewWindow === 'on' || windowConfig.openFilesInNewWindow === 'off')) { + openFilesInNewWindow = (windowConfig.openFilesInNewWindow === 'on'); + } + } + + return { openFolderInNewWindow, openFilesInNewWindow }; + } + public openExtensionDevelopmentHostWindow(openConfig: IOpenConfiguration): void { // Reload an existing extension development host window on the same path diff --git a/src/vs/platform/history/electron-main/historyMainService.ts b/src/vs/platform/history/electron-main/historyMainService.ts index 31ce2c45c7965b8642cf87854c4f36f14f059450..568b27917e7f598f8c6acb14b83d7412a4518f15 100644 --- a/src/vs/platform/history/electron-main/historyMainService.ts +++ b/src/vs/platform/history/electron-main/historyMainService.ts @@ -6,7 +6,6 @@ 'use strict'; import * as path from 'path'; -import * as platform from 'vs/base/common/platform'; import * as nls from 'vs/nls'; import * as arrays from 'vs/base/common/arrays'; import { trim } from 'vs/base/common/strings'; @@ -17,6 +16,7 @@ import { getPathLabel } from 'vs/base/common/labels'; import { IPath } from 'vs/platform/windows/common/windows'; import CommonEvent, { Emitter } from 'vs/base/common/event'; import { createDecorator } from "vs/platform/instantiation/common/instantiation"; +import { isWindows, isMacintosh, isLinux } from "vs/base/common/platform"; export const IHistoryMainService = createDecorator('historyMainService'); @@ -69,15 +69,20 @@ export class HistoryMainService implements IHistoryMainService { if (isFile) { mru.files.unshift(path); - mru.files = arrays.distinct(mru.files, (f) => platform.isLinux ? f : f.toLowerCase()); + mru.files = arrays.distinct(mru.files, (f) => isLinux ? f : f.toLowerCase()); } else { mru.folders.unshift(path); - mru.folders = arrays.distinct(mru.folders, (f) => platform.isLinux ? f : f.toLowerCase()); + mru.folders = arrays.distinct(mru.folders, (f) => isLinux ? f : f.toLowerCase()); } // Make sure its bounded mru.folders = mru.folders.slice(0, HistoryMainService.MAX_TOTAL_RECENT_ENTRIES); mru.files = mru.files.slice(0, HistoryMainService.MAX_TOTAL_RECENT_ENTRIES); + + // Add to recent documents (Windows/macOS only) + if (isMacintosh || isWindows) { + app.addRecentDocument(path); + } }); this.storageService.setItem(HistoryMainService.recentPathsListStorageKey, mru); @@ -157,7 +162,7 @@ export class HistoryMainService implements IHistoryMainService { } public updateWindowsJumpList(): void { - if (!platform.isWindows) { + if (!isWindows) { return; // only on windows }