Skip to content

Commit dd06f3c

Browse files
author
Benjamin Pasero
committed
💄
1 parent 82ebb10 commit dd06f3c

4 files changed

Lines changed: 144 additions & 140 deletions

File tree

src/vs/code/electron-main/windows.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import { ILifecycleService, UnloadReason } from 'vs/platform/lifecycle/electron-
2121
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
2222
import { ILogService } from 'vs/platform/log/common/log';
2323
import { IWindowSettings, OpenContext, IPath, IWindowConfiguration } from 'vs/platform/windows/common/windows';
24-
import { getLastActiveWindow, findBestWindowOrFolder } from 'vs/code/node/windowsUtils';
24+
import { getLastActiveWindow, findBestWindowOrFolderForFile } from 'vs/code/node/windowsFinder';
2525
import CommonEvent, { Emitter } from 'vs/base/common/event';
2626
import product from 'vs/platform/node/product';
2727
import { ITelemetryService, ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
@@ -345,7 +345,7 @@ export class WindowsManager implements IWindowsMainService {
345345

346346
// Open Files in last instance if any and flag tells us so
347347
const fileToCheck = filesToOpen[0] || filesToCreate[0] || filesToDiff[0];
348-
const windowOrFolder = findBestWindowOrFolder({
348+
const bestWindowOrFolder = findBestWindowOrFolderForFile({
349349
windows: WindowsManager.WINDOWS,
350350
newWindow: openFilesInNewWindow,
351351
reuseWindow: openConfig.forceReuseWindow,
@@ -354,23 +354,24 @@ export class WindowsManager implements IWindowsMainService {
354354
userHome: this.environmentService.userHome
355355
});
356356

357-
if (windowOrFolder instanceof CodeWindow) {
358-
windowOrFolder.focus();
357+
// We found a suitable window to open the files within
358+
if (bestWindowOrFolder instanceof CodeWindow) {
359+
bestWindowOrFolder.focus();
359360
const files = { filesToOpen, filesToCreate, filesToDiff }; // copy to object because they get reset shortly after
360-
windowOrFolder.ready().then(readyWindow => {
361+
bestWindowOrFolder.ready().then(readyWindow => {
361362
readyWindow.send('vscode:openFiles', files);
362363
});
363364

364-
usedWindows.push(windowOrFolder);
365+
usedWindows.push(bestWindowOrFolder);
365366
}
366367

367-
// Otherwise open instance with files
368+
// Otherwise open a new window with the best folder to use for the file
368369
else {
369370
const browserWindow = this.openInBrowserWindow({
370371
userEnv: openConfig.userEnv,
371372
cli: openConfig.cli,
372373
initialStartup: openConfig.initialStartup,
373-
workspacePath: windowOrFolder,
374+
workspacePath: bestWindowOrFolder,
374375
filesToOpen,
375376
filesToCreate,
376377
filesToDiff,

src/vs/code/node/windowsFinder.ts

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
'use strict';
7+
8+
import * as path from 'path';
9+
import * as fs from 'fs';
10+
import * as platform from 'vs/base/common/platform';
11+
import * as paths from 'vs/base/common/paths';
12+
import { OpenContext } from 'vs/platform/windows/common/windows';
13+
14+
/**
15+
* Exported subset of CodeWindow for testing.
16+
*/
17+
export interface ISimpleWindow {
18+
openedWorkspacePath: string;
19+
lastFocusTime: number;
20+
}
21+
22+
/**
23+
* Exported for testing.
24+
*/
25+
export interface IBestWindowOrFolderOptions<W extends ISimpleWindow> {
26+
windows: W[];
27+
newWindow: boolean;
28+
reuseWindow: boolean;
29+
context: OpenContext;
30+
filePath?: string;
31+
userHome?: string;
32+
codeSettingsFolder?: string;
33+
}
34+
35+
export function findBestWindowOrFolderForFile<W extends ISimpleWindow>({ windows, newWindow, reuseWindow, context, filePath, userHome, codeSettingsFolder }: IBestWindowOrFolderOptions<W>): W | string {
36+
if (!newWindow && filePath && (context === OpenContext.DESKTOP || context === OpenContext.CLI || context === OpenContext.DOCK)) {
37+
const windowOnFilePath = findWindowOnFilePath(windows, filePath);
38+
const folderWithCodeSettings = !reuseWindow && findFolderWithCodeSettings(filePath, userHome, codeSettingsFolder);
39+
40+
// Return if we found a window that has the parent of the file path opened
41+
if (windowOnFilePath && !(folderWithCodeSettings && folderWithCodeSettings.length > windowOnFilePath.openedWorkspacePath.length)) {
42+
return windowOnFilePath;
43+
}
44+
45+
// Return if we found a parent folder with a code settings folder inside
46+
if (folderWithCodeSettings) {
47+
return folderWithCodeSettings;
48+
}
49+
}
50+
51+
return !newWindow ? getLastActiveWindow(windows) : null;
52+
}
53+
54+
function findWindowOnFilePath<W extends ISimpleWindow>(windows: W[], filePath: string): W {
55+
56+
// From all windows that have the parent of the file opened, return the window
57+
// that has the most specific folder opened ( = longest path wins)
58+
const windowsOnFilePath = windows.filter(window => typeof window.openedWorkspacePath === 'string' && paths.isEqualOrParent(filePath, window.openedWorkspacePath, !platform.isLinux /* ignorecase */));
59+
if (windowsOnFilePath.length) {
60+
return windowsOnFilePath.sort((a, b) => -(a.openedWorkspacePath.length - b.openedWorkspacePath.length))[0];
61+
}
62+
63+
return null;
64+
}
65+
66+
function findFolderWithCodeSettings(filePath: string, userHome?: string, codeSettingsFolder?: string): string {
67+
let folder = path.dirname(paths.normalize(filePath, true));
68+
let homeFolder = userHome && paths.normalize(userHome, true);
69+
if (!platform.isLinux) {
70+
homeFolder = homeFolder && homeFolder.toLowerCase();
71+
}
72+
73+
let previous = null;
74+
while (folder !== previous) {
75+
if (hasCodeSettings(folder, homeFolder, codeSettingsFolder)) {
76+
return folder;
77+
}
78+
79+
previous = folder;
80+
folder = path.dirname(folder);
81+
}
82+
83+
return null;
84+
}
85+
86+
function hasCodeSettings(folder: string, normalizedUserHome?: string, codeSettingsFolder = '.vscode') {
87+
try {
88+
if ((platform.isLinux ? folder : folder.toLowerCase()) === normalizedUserHome) {
89+
return fs.statSync(path.join(folder, codeSettingsFolder, 'settings.json')).isFile(); // ~/.vscode/extensions is used for extensions
90+
}
91+
92+
return fs.statSync(path.join(folder, codeSettingsFolder)).isDirectory();
93+
} catch (err) {
94+
// assume impossible to access
95+
}
96+
97+
return false;
98+
}
99+
100+
export function getLastActiveWindow<W extends ISimpleWindow>(windows: W[]): W {
101+
if (windows.length) {
102+
const lastFocussedDate = Math.max.apply(Math, windows.map(w => w.lastFocusTime));
103+
const res = windows.filter(w => w.lastFocusTime === lastFocussedDate);
104+
if (res && res.length) {
105+
return res[0];
106+
}
107+
}
108+
109+
return null;
110+
}

src/vs/code/node/windowsUtils.ts

Lines changed: 0 additions & 107 deletions
This file was deleted.

0 commit comments

Comments
 (0)