diff --git a/src/vs/code/common/windows.ts b/src/vs/code/common/windows.ts index 43c5fba2864..9d1610531c7 100644 --- a/src/vs/code/common/windows.ts +++ b/src/vs/code/common/windows.ts @@ -7,27 +7,6 @@ import Event from 'vs/base/common/event'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { IWindowsService } from 'vs/platform/windows/common/windows'; -export enum OpenContext { - - // opening when running from the command line - CLI, - - // macOS only: opening from the dock (also when opening files to a running instance from desktop) - DOCK, - - // opening from the main application window - MENU, - - // opening from a file or folder dialog - DIALOG, - - // opening from the OS's UI - DESKTOP, - - // opening through the API - API -} - export interface IWindowEventService { _serviceBrand: any; diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 435423de2c2..bfa18af3509 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -7,12 +7,11 @@ import { app, ipcMain as ipc, BrowserWindow } from 'electron'; import * as platform from 'vs/base/common/platform'; -import { OpenContext } from 'vs/code/common/windows'; import { IWindowsMainService, WindowsManager } from 'vs/code/electron-main/windows'; -import { IWindowsService } from 'vs/platform/windows/common/windows'; +import { IWindowsService, OpenContext } from 'vs/platform/windows/common/windows'; import { WindowsChannel } from 'vs/platform/windows/common/windowsIpc'; import { WindowsService } from 'vs/platform/windows/electron-main/windowsService'; -import { ILifecycleService } from 'vs/code/electron-main/lifecycle'; +import { ILifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain'; import { VSCodeMenu } from 'vs/code/electron-main/menus'; import { getShellEnvironment } from 'vs/code/node/shellEnv'; import { IUpdateService } from 'vs/platform/update/common/update'; @@ -26,8 +25,8 @@ import { LaunchService, LaunchChannel, ILaunchService } from './launch'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; -import { ILogService } from 'vs/code/common/log'; -import { IStorageService } from 'vs/code/node/storage'; +import { ILogService } from 'vs/platform/log/common/log'; +import { IStorageService } from 'vs/platform/storage/node/storage'; import { IBackupMainService } from 'vs/platform/backup/common/backup'; import { BackupChannel } from 'vs/platform/backup/common/backupIpc'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; diff --git a/src/vs/code/electron-main/launch.ts b/src/vs/code/electron-main/launch.ts index c8a6347a9de..99103a7b5b4 100644 --- a/src/vs/code/electron-main/launch.ts +++ b/src/vs/code/electron-main/launch.ts @@ -5,17 +5,16 @@ 'use strict'; -import { OpenContext } from 'vs/code/common/windows'; import { IWindowsMainService } from 'vs/code/electron-main/windows'; -import { VSCodeWindow } from 'vs/code/electron-main/window'; import { TPromise } from 'vs/base/common/winjs.base'; import { IChannel } from 'vs/base/parts/ipc/common/ipc'; -import { ILogService } from 'vs/code/common/log'; +import { ILogService } from 'vs/platform/log/common/log'; import { IURLService } from 'vs/platform/url/common/url'; import { IProcessEnvironment } from 'vs/base/common/platform'; import { ParsedArgs } from 'vs/platform/environment/common/environment'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { once } from 'vs/base/common/event'; +import { ICodeWindow, OpenContext } from "vs/platform/windows/common/windows"; export const ID = 'launchService'; export const ILaunchService = createDecorator(ID); @@ -94,7 +93,7 @@ export class LaunchService implements ILaunchService { // Otherwise handle in windows service const context = !!userEnv['VSCODE_CLI'] ? OpenContext.CLI : OpenContext.DESKTOP; - let usedWindows: VSCodeWindow[]; + let usedWindows: ICodeWindow[]; if (!!args.extensionDevelopmentPath) { this.windowsService.openExtensionDevelopmentHostWindow({ context, cli: args, userEnv }); } else if (args._.length === 0 && (args['new-window'] || args['unity-launch'])) { diff --git a/src/vs/code/electron-main/main.ts b/src/vs/code/electron-main/main.ts index 41bb32a7c01..4b76c411f8f 100644 --- a/src/vs/code/electron-main/main.ts +++ b/src/vs/code/electron-main/main.ts @@ -11,7 +11,7 @@ import * as platform from 'vs/base/common/platform'; import { parseMainProcessArgv } from 'vs/platform/environment/node/argv'; import { mkdirp } from 'vs/base/node/pfs'; import { validatePaths } from 'vs/code/node/paths'; -import { LifecycleService, ILifecycleService } from 'vs/code/electron-main/lifecycle'; +import { LifecycleService, ILifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain'; import { Server, serve, connect } from 'vs/base/parts/ipc/node/ipc.net'; import { TPromise } from 'vs/base/common/winjs.base'; import { ILaunchChannel, LaunchChannelClient } from './launch'; @@ -19,8 +19,8 @@ import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiati import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; -import { ILogService, MainLogService } from 'vs/code/common/log'; -import { IStorageService, StorageService } from 'vs/code/node/storage'; +import { ILogService, MainLogService } from 'vs/platform/log/common/log'; +import { IStorageService, StorageService } from 'vs/platform/storage/node/storage'; import { IBackupMainService } from 'vs/platform/backup/common/backup'; import { BackupMainService } from 'vs/platform/backup/electron-main/backupMainService'; import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment'; diff --git a/src/vs/code/electron-main/menus.ts b/src/vs/code/electron-main/menus.ts index f267b326372..559b253ff55 100644 --- a/src/vs/code/electron-main/menus.ts +++ b/src/vs/code/electron-main/menus.ts @@ -10,11 +10,11 @@ import { isMacintosh, isLinux, isWindows, language } from 'vs/base/common/platfo import * as arrays from 'vs/base/common/arrays'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ipcMain as ipc, app, shell, dialog, Menu, MenuItem, BrowserWindow } from 'electron'; -import { OpenContext } from 'vs/code/common/windows'; +import { OpenContext } from "vs/platform/windows/common/windows"; import { IWindowsMainService } from 'vs/code/electron-main/windows'; import { VSCodeWindow } from 'vs/code/electron-main/window'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IStorageService } from 'vs/code/node/storage'; +import { IStorageService } from 'vs/platform/storage/node/storage'; import { IFilesConfiguration, AutoSaveConfiguration } from 'vs/platform/files/common/files'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IUpdateService, State as UpdateState } from 'vs/platform/update/common/update'; diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index 58f27e2a355..c4dfa4046ec 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -9,20 +9,21 @@ import * as path from 'path'; import * as objects from 'vs/base/common/objects'; import { stopProfiling } from 'vs/base/node/profiler'; import nls = require('vs/nls'); -import { IStorageService } from 'vs/code/node/storage'; +import { IStorageService } from 'vs/platform/storage/node/storage'; import { shell, screen, BrowserWindow, systemPreferences, app } from 'electron'; import { TPromise, TValueCallback } from 'vs/base/common/winjs.base'; import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment'; -import { ILogService } from 'vs/code/common/log'; +import { ILogService } from 'vs/platform/log/common/log'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IWorkbenchEditorConfiguration } from 'vs/workbench/common/editor'; import { parseArgs } from 'vs/platform/environment/node/argv'; import product from 'vs/platform/node/product'; import { getCommonHTTPHeaders } from 'vs/platform/environment/node/http'; -import { IWindowSettings, MenuBarVisibility } from 'vs/platform/windows/common/windows'; +import { IWindowSettings, MenuBarVisibility, ICodeWindow, ReadyState, IWindowCloseEvent } from 'vs/platform/windows/common/windows'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { KeyboardLayoutMonitor } from 'vs/code/node/keyboard'; import { IProcessEnvironment, isLinux, isMacintosh, isWindows } from "vs/base/common/platform"; +import CommonEvent, { Emitter } from "vs/base/common/event"; export interface IWindowState { width?: number; @@ -102,30 +103,7 @@ export interface IWindowConfiguration extends ParsedArgs { nodeCachedDataDir: string; } -export enum ReadyState { - - /** - * This window has not loaded any HTML yet - */ - NONE, - - /** - * This window is loading HTML - */ - LOADING, - - /** - * This window is navigating to another HTML - */ - NAVIGATING, - - /** - * This window is done loading HTML - */ - READY -} - -export class VSCodeWindow { +export class VSCodeWindow implements ICodeWindow { public static themeStorageKey = 'theme'; public static themeBackgroundStorageKey = 'themeBackground'; @@ -133,6 +111,7 @@ export class VSCodeWindow { private static MIN_WIDTH = 200; private static MIN_HEIGHT = 120; + private _onClose: Emitter; private options: IWindowCreationOptions; private hiddenTitleBarStyle: boolean; private showTimeoutHandle: any; @@ -167,6 +146,9 @@ export class VSCodeWindow { this.whenReadyCallbacks = []; this.toDispose = []; + this._onClose = new Emitter(); + this.toDispose.push(this._onClose); + // create browser window this.createBrowserWindow(config); @@ -181,6 +163,10 @@ export class VSCodeWindow { this.registerListeners(); } + public get onClose(): CommonEvent { + return this._onClose.event; + } + private createBrowserWindow(config: IWindowCreationOptions): void { // Load window state @@ -374,6 +360,11 @@ export class VSCodeWindow { private registerListeners(): void { + // Re-emit close event + this._win.on('close', e => { + this._onClose.fire(e); + }); + // Remember that we loaded this._win.webContents.on('did-finish-load', () => { this._readyState = ReadyState.LOADING; @@ -861,6 +852,12 @@ export class VSCodeWindow { } } + public close(): void { + if (this._win) { + this._win.close(); + } + } + public sendWhenReady(channel: string, ...args: any[]): void { this.ready().then(() => { this.send(channel, ...args); diff --git a/src/vs/code/electron-main/windows.ts b/src/vs/code/electron-main/windows.ts index 75b6792e95d..2fb4b771094 100644 --- a/src/vs/code/electron-main/windows.ts +++ b/src/vs/code/electron-main/windows.ts @@ -15,20 +15,19 @@ import { assign, mixin } from 'vs/base/common/objects'; import { IBackupMainService } from 'vs/platform/backup/common/backup'; import { trim } from 'vs/base/common/strings'; import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment'; -import { IStorageService } from 'vs/code/node/storage'; +import { IStorageService } from 'vs/platform/storage/node/storage'; import { IPath, VSCodeWindow, IWindowConfiguration, IWindowState as ISingleWindowState, defaultWindowState, WindowMode } from 'vs/code/electron-main/window'; import { ipcMain as ipc, app, screen, BrowserWindow, dialog } from 'electron'; import { IPathWithLineAndColumn, parseLineAndColumnAware } from 'vs/code/node/paths'; -import { ILifecycleService, UnloadReason } from 'vs/code/electron-main/lifecycle'; +import { ILifecycleService, UnloadReason } from 'vs/platform/lifecycle/electron-main/lifecycleMain'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { ILogService } from 'vs/code/common/log'; +import { ILogService } from 'vs/platform/log/common/log'; import { getPathLabel } from 'vs/base/common/labels'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { IWindowSettings } from 'vs/platform/windows/common/windows'; +import { IWindowSettings, OpenContext } from 'vs/platform/windows/common/windows'; import { getLastActiveWindow, findBestWindowOrFolder } from 'vs/code/node/windowsUtils'; import CommonEvent, { Emitter } from 'vs/base/common/event'; import product from 'vs/platform/node/product'; -import { OpenContext } from 'vs/code/common/windows'; import { ITelemetryService, ITelemetryData } from 'vs/platform/telemetry/common/telemetry'; import { isParent, isEqual, isEqualOrParent } from 'vs/platform/files/common/files'; import { KeyboardLayoutMonitor } from 'vs/code/node/keyboard'; @@ -253,7 +252,7 @@ export class WindowsManager implements IWindowsMainService { }); // Update our windows state before quitting and before closing windows - this.lifecycleService.onBeforeWindowClose(win => this.onBeforeWindowClose(win)); + this.lifecycleService.onBeforeWindowClose(win => this.onBeforeWindowClose(win as VSCodeWindow)); this.lifecycleService.onBeforeQuit(() => this.onBeforeQuit()); // Keyboard layout changes diff --git a/src/vs/code/node/windowsUtils.ts b/src/vs/code/node/windowsUtils.ts index a46c1d96168..2f8407e0a4e 100644 --- a/src/vs/code/node/windowsUtils.ts +++ b/src/vs/code/node/windowsUtils.ts @@ -9,7 +9,7 @@ import * as path from 'path'; import * as fs from 'fs'; import * as platform from 'vs/base/common/platform'; import * as paths from 'vs/base/common/paths'; -import { OpenContext } from 'vs/code/common/windows'; +import { OpenContext } from "vs/platform/windows/common/windows"; import { isEqualOrParent } from 'vs/platform/files/common/files'; /** diff --git a/src/vs/code/test/node/windowsUtils.test.ts b/src/vs/code/test/node/windowsUtils.test.ts index 42649abda76..e8472fd9ae9 100644 --- a/src/vs/code/test/node/windowsUtils.test.ts +++ b/src/vs/code/test/node/windowsUtils.test.ts @@ -7,7 +7,7 @@ import assert = require('assert'); import path = require('path'); import { findBestWindowOrFolder, ISimpleWindow, IBestWindowOrFolderOptions } from 'vs/code/node/windowsUtils'; -import { OpenContext } from 'vs/code/common/windows'; +import { OpenContext } from "vs/platform/windows/common/windows"; const fixturesFolder = require.toUrl('./fixtures'); diff --git a/src/vs/code/electron-main/lifecycle.ts b/src/vs/platform/lifecycle/electron-main/lifecycleMain.ts similarity index 85% rename from src/vs/code/electron-main/lifecycle.ts rename to src/vs/platform/lifecycle/electron-main/lifecycleMain.ts index fbeb9a85472..2dc0242f8cf 100644 --- a/src/vs/code/electron-main/lifecycle.ts +++ b/src/vs/platform/lifecycle/electron-main/lifecycleMain.ts @@ -7,12 +7,12 @@ import { ipcMain as ipc, app } from 'electron'; import { TPromise, TValueCallback } from 'vs/base/common/winjs.base'; -import { ReadyState, VSCodeWindow } from 'vs/code/electron-main/window'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { ILogService } from 'vs/code/common/log'; -import { IStorageService } from 'vs/code/node/storage'; +import { ILogService } from 'vs/platform/log/common/log'; +import { IStorageService } from 'vs/platform/storage/node/storage'; import Event, { Emitter } from 'vs/base/common/event'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; +import { ICodeWindow, ReadyState } from "vs/platform/windows/common/windows"; export const ILifecycleService = createDecorator('lifecycleService'); @@ -43,12 +43,12 @@ export interface ILifecycleService { * is called even when the window prevents the closing. We want an event that truly fires * before the window gets closed for real. */ - onBeforeWindowClose: Event; + onBeforeWindowClose: Event; ready(): void; - registerWindow(vscodeWindow: VSCodeWindow): void; + registerWindow(codeWindow: ICodeWindow): void; - unload(vscodeWindow: VSCodeWindow, reason: UnloadReason): TPromise; + unload(codeWindow: ICodeWindow, reason: UnloadReason): TPromise; relaunch(options?: { addArgs?: string[], removeArgs?: string[] }); @@ -74,8 +74,8 @@ export class LifecycleService implements ILifecycleService { private _onBeforeQuit = new Emitter(); onBeforeQuit: Event = this._onBeforeQuit.event; - private _onBeforeWindowClose = new Emitter(); - onBeforeWindowClose: Event = this._onBeforeWindowClose.event; + private _onBeforeWindowClose = new Emitter(); + onBeforeWindowClose: Event = this._onBeforeWindowClose.event; constructor( @IEnvironmentService private environmentService: IEnvironmentService, @@ -132,11 +132,11 @@ export class LifecycleService implements ILifecycleService { }); } - public registerWindow(vscodeWindow: VSCodeWindow): void { + public registerWindow(codeWindow: ICodeWindow): void { // Window Before Closing: Main -> Renderer - vscodeWindow.win.on('close', (e) => { - const windowId = vscodeWindow.id; + codeWindow.onClose(e => { + const windowId = codeWindow.id; this.logService.log('Lifecycle#window-before-close', windowId); // The window already acknowledged to be closed @@ -150,11 +150,11 @@ export class LifecycleService implements ILifecycleService { // Otherwise prevent unload and handle it from window e.preventDefault(); - this.unload(vscodeWindow, UnloadReason.CLOSE).done(veto => { + this.unload(codeWindow, UnloadReason.CLOSE).done(veto => { if (!veto) { this.windowToCloseRequest[windowId] = true; - this._onBeforeWindowClose.fire(vscodeWindow); - vscodeWindow.win.close(); + this._onBeforeWindowClose.fire(codeWindow); + codeWindow.close(); } else { this.quitRequested = false; delete this.windowToCloseRequest[windowId]; @@ -163,14 +163,14 @@ export class LifecycleService implements ILifecycleService { }); } - public unload(vscodeWindow: VSCodeWindow, reason: UnloadReason): TPromise { + public unload(codeWindow: ICodeWindow, reason: UnloadReason): TPromise { // Always allow to unload a window that is not yet ready - if (vscodeWindow.readyState !== ReadyState.READY) { + if (codeWindow.readyState !== ReadyState.READY) { return TPromise.as(false); } - this.logService.log('Lifecycle#unload()', vscodeWindow.id); + this.logService.log('Lifecycle#unload()', codeWindow.id); return new TPromise((c) => { const oneTimeEventToken = this.oneTimeListenerTokenGenerator++; @@ -193,7 +193,7 @@ export class LifecycleService implements ILifecycleService { c(true); // veto }); - vscodeWindow.send('vscode:beforeUnload', { okChannel, cancelChannel, reason: this.quitRequested ? UnloadReason.QUIT : reason }); + codeWindow.send('vscode:beforeUnload', { okChannel, cancelChannel, reason: this.quitRequested ? UnloadReason.QUIT : reason }); }); } diff --git a/src/vs/code/common/log.ts b/src/vs/platform/log/common/log.ts similarity index 100% rename from src/vs/code/common/log.ts rename to src/vs/platform/log/common/log.ts diff --git a/src/vs/code/node/storage.ts b/src/vs/platform/storage/node/storage.ts similarity index 100% rename from src/vs/code/node/storage.ts rename to src/vs/platform/storage/node/storage.ts diff --git a/src/vs/platform/update/electron-main/updateService.ts b/src/vs/platform/update/electron-main/updateService.ts index 4db56de6d64..9a106da3718 100644 --- a/src/vs/platform/update/electron-main/updateService.ts +++ b/src/vs/platform/update/electron-main/updateService.ts @@ -16,7 +16,7 @@ import { fromEventEmitter } from 'vs/base/node/event'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { Win32AutoUpdaterImpl } from './auto-updater.win32'; import { LinuxAutoUpdaterImpl } from './auto-updater.linux'; -import { ILifecycleService } from 'vs/code/electron-main/lifecycle'; +import { ILifecycleService } from 'vs/platform/lifecycle/electron-main/lifecycleMain'; import { IRequestService } from 'vs/platform/request/node/request'; import product from 'vs/platform/node/product'; import { TPromise } from 'vs/base/common/winjs.base'; diff --git a/src/vs/platform/windows/common/windows.ts b/src/vs/platform/windows/common/windows.ts index b85f0b15315..3ca41ea3f3b 100644 --- a/src/vs/platform/windows/common/windows.ts +++ b/src/vs/platform/windows/common/windows.ts @@ -108,3 +108,61 @@ export interface IWindowSettings { nativeTabs: boolean; enableMenuBarMnemonics: boolean; } + +export interface IWindowCloseEvent { + preventDefault: Function; +} + +export interface ICodeWindow { + id: number; + readyState: ReadyState; + + onClose: Event; + + close(): void; + send(channel: string, ...args: any[]): void; +} + +export enum ReadyState { + + /** + * This window has not loaded any HTML yet + */ + NONE, + + /** + * This window is loading HTML + */ + LOADING, + + /** + * This window is navigating to another HTML + */ + NAVIGATING, + + /** + * This window is done loading HTML + */ + READY +} + +export enum OpenContext { + + // opening when running from the command line + CLI, + + // macOS only: opening from the dock (also when opening files to a running instance from desktop) + DOCK, + + // opening from the main application window + MENU, + + // opening from a file or folder dialog + DIALOG, + + // opening from the OS's UI + DESKTOP, + + // opening through the API + API +} \ No newline at end of file diff --git a/src/vs/platform/windows/electron-main/windowsService.ts b/src/vs/platform/windows/electron-main/windowsService.ts index 9d147b623ca..28d29556f17 100644 --- a/src/vs/platform/windows/electron-main/windowsService.ts +++ b/src/vs/platform/windows/electron-main/windowsService.ts @@ -9,16 +9,15 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { assign } from 'vs/base/common/objects'; import URI from 'vs/base/common/uri'; -import { IWindowsService } from 'vs/platform/windows/common/windows'; +import { IWindowsService, OpenContext } from 'vs/platform/windows/common/windows'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { shell, crashReporter, app } from 'electron'; import Event, { chain } from 'vs/base/common/event'; import { fromEventEmitter } from 'vs/base/node/event'; import { IURLService } from 'vs/platform/url/common/url'; import { ITelemetryData } from 'vs/platform/telemetry/common/telemetry'; -import { OpenContext } from 'vs/code/common/windows'; // TODO@Joao: remove this dependency, move all implementation to this class import { IWindowsMainService } from 'vs/code/electron-main/windows'; -import { ILifecycleService } from "vs/code/electron-main/lifecycle"; +import { ILifecycleService } from "vs/platform/lifecycle/electron-main/lifecycleMain"; export interface ISharedProcess { whenReady(): TPromise;