Skip to content

Commit 25fb4bc

Browse files
author
Benjamin Pasero
committed
debt - move enterWorkspace into workspace service
1 parent 65c65e2 commit 25fb4bc

24 files changed

Lines changed: 420 additions & 329 deletions

File tree

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -384,8 +384,7 @@ export class CodeApplication extends Disposable {
384384
}
385385

386386
// Setup Auth Handler
387-
const authHandler = appInstantiationService.createInstance(ProxyAuthHandler);
388-
this._register(authHandler);
387+
this._register(new ProxyAuthHandler());
389388

390389
// Open Windows
391390
const windows = appInstantiationService.invokeFunction(accessor => this.openFirstWindow(accessor, electronIpcServer, sharedProcessClient));

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

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { localize } from 'vs/nls';
7-
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
8-
import { IWindowsMainService } from 'vs/platform/windows/electron-main/windows';
7+
import { Disposable } from 'vs/base/common/lifecycle';
98
import { Event } from 'vs/base/common/event';
109
import { BrowserWindow, app, AuthInfo, WebContents, Event as ElectronEvent } from 'electron';
1110

@@ -22,18 +21,21 @@ type Credentials = {
2221
password: string;
2322
};
2423

25-
export class ProxyAuthHandler {
24+
export class ProxyAuthHandler extends Disposable {
2625

2726
_serviceBrand: undefined;
2827

2928
private retryCount = 0;
30-
private disposables: IDisposable[] = [];
3129

32-
constructor(
33-
@IWindowsMainService private readonly windowsMainService: IWindowsMainService
34-
) {
30+
constructor() {
31+
super();
32+
33+
this.registerListeners();
34+
}
35+
36+
private registerListeners(): void {
3537
const onLogin = Event.fromNodeEventEmitter<LoginEvent>(app, 'login', (event, webContents, req, authInfo, cb) => ({ event, webContents, req, authInfo, cb }));
36-
onLogin(this.onLogin, this, this.disposables);
38+
this._register(onLogin(this.onLogin, this));
3739
}
3840

3941
private onLogin({ event, authInfo, cb }: LoginEvent): void {
@@ -61,10 +63,9 @@ export class ProxyAuthHandler {
6163
}
6264
};
6365

64-
const focusedWindow = this.windowsMainService.getFocusedWindow();
65-
66+
const focusedWindow = BrowserWindow.getFocusedWindow();
6667
if (focusedWindow) {
67-
opts.parent = focusedWindow.win;
68+
opts.parent = focusedWindow;
6869
opts.modal = true;
6970
}
7071

@@ -89,8 +90,4 @@ export class ProxyAuthHandler {
8990
win.close();
9091
});
9192
}
92-
93-
dispose(): void {
94-
this.disposables = dispose(this.disposables);
95-
}
9693
}

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

Lines changed: 29 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,20 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
2020
import { ILogService } from 'vs/platform/log/common/log';
2121
import { IWindowSettings, OpenContext, IPath, IWindowConfiguration, IPathsToWaitFor, isFileToOpen, isWorkspaceToOpen, isFolderToOpen, IWindowOpenable, IOpenEmptyWindowOptions, IAddFoldersRequest } from 'vs/platform/windows/common/windows';
2222
import { INativeOpenDialogOptions } from 'vs/platform/dialogs/node/dialogs';
23-
import { getLastActiveWindow, findBestWindowOrFolderForFile, findWindowOnWorkspace, findWindowOnExtensionDevelopmentPath, findWindowOnWorkspaceOrFolderUri } from 'vs/code/node/windowsFinder';
23+
import { getLastActiveWindow, findBestWindowOrFolderForFile, findWindowOnWorkspace, findWindowOnExtensionDevelopmentPath, findWindowOnWorkspaceOrFolderUri } from 'vs/platform/windows/node/window';
2424
import { Event as CommonEvent, Emitter } from 'vs/base/common/event';
2525
import product from 'vs/platform/product/common/product';
2626
import { ITelemetryService, ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
2727
import { IWindowsMainService, IOpenConfiguration, IWindowsCountChangedEvent, ICodeWindow, IWindowState as ISingleWindowState, WindowMode } from 'vs/platform/windows/electron-main/windows';
2828
import { IWorkspacesHistoryMainService } from 'vs/platform/workspaces/electron-main/workspacesHistoryMainService';
2929
import { IProcessEnvironment, isMacintosh, isWindows } from 'vs/base/common/platform';
30-
import { IWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, hasWorkspaceFileExtension, IEnterWorkspaceResult, IRecent } from 'vs/platform/workspaces/common/workspaces';
30+
import { IWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, hasWorkspaceFileExtension, IRecent } from 'vs/platform/workspaces/common/workspaces';
3131
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
3232
import { mnemonicButtonLabel } from 'vs/base/common/labels';
3333
import { Schemas } from 'vs/base/common/network';
3434
import { URI } from 'vs/base/common/uri';
3535
import { dirExists } from 'vs/base/node/pfs';
36-
import { getComparisonKey, isEqual, normalizePath, basename as resourcesBasename, originalFSPath, hasTrailingPathSeparator, removeTrailingPathSeparator } from 'vs/base/common/resources';
36+
import { getComparisonKey, isEqual, normalizePath, originalFSPath, hasTrailingPathSeparator, removeTrailingPathSeparator } from 'vs/base/common/resources';
3737
import { getRemoteAuthority } from 'vs/platform/remote/common/remoteHosts';
3838
import { restoreWindowsState, WindowsStateStorageData, getWindowsStateStoreData } from 'vs/code/electron-main/windowsStateStorage';
3939
import { getWorkspaceIdentifier, IWorkspacesMainService } from 'vs/platform/workspaces/electron-main/workspacesMainService';
@@ -167,8 +167,6 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
167167
private readonly windowsState: IWindowsState;
168168
private lastClosedWindowState?: IWindowState;
169169

170-
private readonly workspacesManager: WorkspacesManager;
171-
172170
private readonly _onWindowReady = this._register(new Emitter<ICodeWindow>());
173171
readonly onWindowReady: CommonEvent<ICodeWindow> = this._onWindowReady.event;
174172

@@ -203,8 +201,6 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
203201
this.windowsState.openedWindows = [];
204202
}
205203

206-
this.workspacesManager = new WorkspacesManager(workspacesMainService, backupMainService, this, dialogMainService);
207-
208204
this.lifecycleMainService.when(LifecycleMainPhase.Ready).then(() => this.registerListeners());
209205
this.lifecycleMainService.when(LifecycleMainPhase.AfterWindowOpen).then(() => this.installWindowsMutex());
210206
}
@@ -259,6 +255,11 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
259255
this.lastClosedWindowState = undefined;
260256
}
261257
});
258+
259+
// Signal a window is ready after having entered a workspace
260+
this._register(this.workspacesMainService.onWorkspaceEntered(event => {
261+
this._onWindowReady.fire(event.window);
262+
}));
262263
}
263264

264265
// Note that onBeforeShutdown() and onBeforeWindowClose() are fired in different order depending on the OS:
@@ -857,7 +858,8 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
857858
path.label = pathToOpen.label;
858859
pathsToOpen.push(path);
859860
} else {
860-
const uri = resourceFromURIToOpen(pathToOpen);
861+
const uri = this.resourceFromURIToOpen(pathToOpen);
862+
861863
// Warn about the invalid URI or path
862864
let message, detail;
863865
if (uri.scheme === Schemas.file) {
@@ -1020,7 +1022,7 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
10201022
return undefined;
10211023
}
10221024

1023-
let uri = resourceFromURIToOpen(toOpen);
1025+
let uri = this.resourceFromURIToOpen(toOpen);
10241026
if (uri.scheme === Schemas.file) {
10251027
return this.parsePath(uri.fsPath, options, isFileToOpen(toOpen));
10261028
}
@@ -1069,6 +1071,18 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
10691071
};
10701072
}
10711073

1074+
private resourceFromURIToOpen(openable: IWindowOpenable): URI {
1075+
if (isWorkspaceToOpen(openable)) {
1076+
return openable.workspaceUri;
1077+
}
1078+
1079+
if (isFolderToOpen(openable)) {
1080+
return openable.folderUri;
1081+
}
1082+
1083+
return openable.fileUri;
1084+
}
1085+
10721086
private parsePath(anyPath: string, options: IPathParseOptions, forceOpenWorkspaceAsFile?: boolean): IPathToOpen | undefined {
10731087
if (!anyPath) {
10741088
return undefined;
@@ -1183,7 +1197,7 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
11831197
return { openFolderInNewWindow: !!openFolderInNewWindow, openFilesInNewWindow };
11841198
}
11851199

1186-
openExtensionDevelopmentHostWindow(extensionDevelopmentPath: string[], openConfig: IOpenConfiguration): void {
1200+
openExtensionDevelopmentHostWindow(extensionDevelopmentPath: string[], openConfig: IOpenConfiguration): ICodeWindow[] {
11871201

11881202
// Reload an existing extension development host window on the same path
11891203
// We currently do not allow more than one extension development window
@@ -1193,7 +1207,7 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
11931207
this.reload(existingWindow, openConfig.cli);
11941208
existingWindow.focus(); // make sure it gets focus and is restored
11951209

1196-
return;
1210+
return [existingWindow];
11971211
}
11981212
let folderUris = openConfig.cli['folder-uri'] || [];
11991213
let fileUris = openConfig.cli['file-uri'] || [];
@@ -1284,7 +1298,8 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
12841298
noRecentEntry: true,
12851299
waitMarkerFileURI: openConfig.waitMarkerFileURI
12861300
};
1287-
this.open(openArgs);
1301+
1302+
return this.open(openArgs);
12881303
}
12891304

12901305
private openInBrowserWindow(options: IOpenBrowserWindowOptions): ICodeWindow {
@@ -1578,23 +1593,6 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
15781593
});
15791594
}
15801595

1581-
async enterWorkspace(win: ICodeWindow, path: URI): Promise<IEnterWorkspaceResult | undefined> {
1582-
const result = await this.workspacesManager.enterWorkspace(win, path);
1583-
1584-
return result ? this.doEnterWorkspace(win, result) : undefined;
1585-
}
1586-
1587-
private doEnterWorkspace(win: ICodeWindow, result: IEnterWorkspaceResult): IEnterWorkspaceResult {
1588-
1589-
// Mark as recently opened
1590-
this.workspacesHistoryMainService.addRecentlyOpened([{ workspace: result.workspace }]);
1591-
1592-
// Trigger Eevent to indicate load of workspace into window
1593-
this._onWindowReady.fire(win);
1594-
1595-
return result;
1596-
}
1597-
15981596
focusLastActive(cli: ParsedArgs, context: OpenContext): ICodeWindow {
15991597
const lastActive = this.getLastActiveWindow();
16001598
if (lastActive) {
@@ -1611,7 +1609,7 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
16111609
return getLastActiveWindow(WindowsManager.WINDOWS);
16121610
}
16131611

1614-
getLastActiveWindowForAuthority(remoteAuthority: string | undefined): ICodeWindow | undefined {
1612+
private getLastActiveWindowForAuthority(remoteAuthority: string | undefined): ICodeWindow | undefined {
16151613
return getLastActiveWindow(WindowsManager.WINDOWS.filter(window => window.remoteAuthority === remoteAuthority));
16161614
}
16171615

@@ -1628,10 +1626,6 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
16281626
return this.open({ context, cli, forceEmpty: true, forceNewWindow, forceReuseWindow });
16291627
}
16301628

1631-
openNewTabbedWindow(context: OpenContext): ICodeWindow[] {
1632-
return this.open({ context, cli: this.environmentService.args, forceNewTabbedWindow: true, forceEmpty: true });
1633-
}
1634-
16351629
waitForWindowCloseOrLoad(windowId: number): Promise<void> {
16361630
return new Promise<void>(resolve => {
16371631
function handler(id: number) {
@@ -1666,7 +1660,7 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
16661660
}
16671661
}
16681662

1669-
getFocusedWindow(): ICodeWindow | undefined {
1663+
private getFocusedWindow(): ICodeWindow | undefined {
16701664
const win = BrowserWindow.getFocusedWindow();
16711665
if (win) {
16721666
return this.getWindowById(win.id);
@@ -1860,88 +1854,3 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
18601854
}
18611855
}
18621856
}
1863-
1864-
class WorkspacesManager {
1865-
1866-
constructor(
1867-
private readonly workspacesMainService: IWorkspacesMainService,
1868-
private readonly backupMainService: IBackupMainService,
1869-
private readonly windowsMainService: IWindowsMainService,
1870-
private readonly dialogMainService: IDialogMainService
1871-
) { }
1872-
1873-
async enterWorkspace(window: ICodeWindow, path: URI): Promise<IEnterWorkspaceResult | null> {
1874-
if (!window || !window.win || !window.isReady) {
1875-
return null; // return early if the window is not ready or disposed
1876-
}
1877-
1878-
const isValid = await this.isValidTargetWorkspacePath(window, path);
1879-
if (!isValid) {
1880-
return null; // return early if the workspace is not valid
1881-
}
1882-
1883-
return this.doOpenWorkspace(window, getWorkspaceIdentifier(path));
1884-
}
1885-
1886-
private async isValidTargetWorkspacePath(window: ICodeWindow, path?: URI): Promise<boolean> {
1887-
if (!path) {
1888-
return true;
1889-
}
1890-
1891-
if (window.openedWorkspace && isEqual(window.openedWorkspace.configPath, path)) {
1892-
return false; // window is already opened on a workspace with that path
1893-
}
1894-
1895-
// Prevent overwriting a workspace that is currently opened in another window
1896-
if (findWindowOnWorkspace(this.windowsMainService.getWindows(), getWorkspaceIdentifier(path))) {
1897-
const options: MessageBoxOptions = {
1898-
title: product.nameLong,
1899-
type: 'info',
1900-
buttons: [localize('ok', "OK")],
1901-
message: localize('workspaceOpenedMessage', "Unable to save workspace '{0}'", resourcesBasename(path)),
1902-
detail: localize('workspaceOpenedDetail', "The workspace is already opened in another window. Please close that window first and then try again."),
1903-
noLink: true
1904-
};
1905-
1906-
await this.dialogMainService.showMessageBox(options, withNullAsUndefined(BrowserWindow.getFocusedWindow()));
1907-
1908-
return false;
1909-
}
1910-
1911-
return true; // OK
1912-
}
1913-
1914-
private doOpenWorkspace(window: ICodeWindow, workspace: IWorkspaceIdentifier): IEnterWorkspaceResult {
1915-
window.focus();
1916-
1917-
// Register window for backups and migrate current backups over
1918-
let backupPath: string | undefined;
1919-
if (!window.config.extensionDevelopmentPath) {
1920-
backupPath = this.backupMainService.registerWorkspaceBackupSync({ workspace, remoteAuthority: window.remoteAuthority }, window.config.backupPath);
1921-
}
1922-
1923-
// if the window was opened on an untitled workspace, delete it.
1924-
if (window.openedWorkspace && this.workspacesMainService.isUntitledWorkspace(window.openedWorkspace)) {
1925-
this.workspacesMainService.deleteUntitledWorkspaceSync(window.openedWorkspace);
1926-
}
1927-
1928-
// Update window configuration properly based on transition to workspace
1929-
window.config.folderUri = undefined;
1930-
window.config.workspace = workspace;
1931-
window.config.backupPath = backupPath;
1932-
1933-
return { workspace, backupPath };
1934-
}
1935-
}
1936-
1937-
function resourceFromURIToOpen(openable: IWindowOpenable): URI {
1938-
if (isWorkspaceToOpen(openable)) {
1939-
return openable.workspaceUri;
1940-
}
1941-
1942-
if (isFolderToOpen(openable)) {
1943-
return openable.folderUri;
1944-
}
1945-
1946-
return openable.fileUri;
1947-
}

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,15 @@ export function restoreWindowsState(data: WindowsStateStorageData | undefined):
3535
if (windowsState.lastActiveWindow) {
3636
result.lastActiveWindow = restoreWindowState(windowsState.lastActiveWindow);
3737
}
38+
3839
if (windowsState.lastPluginDevelopmentHostWindow) {
3940
result.lastPluginDevelopmentHostWindow = restoreWindowState(windowsState.lastPluginDevelopmentHostWindow);
4041
}
42+
4143
if (Array.isArray(windowsState.openedWindows)) {
4244
result.openedWindows = windowsState.openedWindows.map(windowState => restoreWindowState(windowState));
4345
}
46+
4447
return result;
4548
}
4649

@@ -49,21 +52,25 @@ function restoreWindowState(windowState: ISerializedWindowState): IWindowState {
4952
if (windowState.backupPath) {
5053
result.backupPath = windowState.backupPath;
5154
}
55+
5256
if (windowState.remoteAuthority) {
5357
result.remoteAuthority = windowState.remoteAuthority;
5458
}
59+
5560
if (windowState.folder) {
5661
result.folderUri = URI.parse(windowState.folder);
5762
} else if (windowState.folderUri) {
5863
result.folderUri = URI.revive(windowState.folderUri);
5964
} else if (windowState.folderPath) {
6065
result.folderUri = URI.file(windowState.folderPath);
6166
}
67+
6268
if (windowState.workspaceIdentifier) {
6369
result.workspace = { id: windowState.workspaceIdentifier.id, configPath: URI.parse(windowState.workspaceIdentifier.configURIPath) };
6470
} else if (windowState.workspace) {
6571
result.workspace = { id: windowState.workspace.id, configPath: URI.file(windowState.workspace.configPath) };
6672
}
73+
6774
return result;
6875
}
6976

@@ -83,4 +90,4 @@ function serializeWindowState(windowState: IWindowState): ISerializedWindowState
8390
remoteAuthority: windowState.remoteAuthority,
8491
uiState: windowState.uiState
8592
};
86-
}
93+
}

0 commit comments

Comments
 (0)