💄 main side

This commit is contained in:
Benjamin Pasero 2017-06-08 09:48:37 +02:00
parent 7ceab4ec6e
commit 4aa3f05d08
14 changed files with 94 additions and 93 deletions

View file

@ -12,6 +12,7 @@ export const ILogService = createDecorator<ILogService>('logService');
export interface ILogService {
_serviceBrand: any;
log(...args: any[]): void;
}
@ -22,7 +23,7 @@ export class MainLogService implements ILogService {
constructor( @IEnvironmentService private environmentService: IEnvironmentService) {
}
log(...args: any[]): void {
public log(...args: any[]): void {
if (this.environmentService.verbose) {
console.log(`\x1b[93m[main ${new Date().toLocaleTimeString()}]\x1b[0m`, ...args);
}

View file

@ -36,7 +36,6 @@ export interface IWindowEventService {
}
export class ActiveWindowManager implements IDisposable {
private disposables: IDisposable[] = [];
private _activeWindowId: number;
@ -49,11 +48,11 @@ export class ActiveWindowManager implements IDisposable {
this._activeWindowId = windowId;
}
get activeClientId(): string {
public get activeClientId(): string {
return `window:${this._activeWindowId}`;
}
dispose() {
public dispose() {
this.disposables = dispose(this.disposables);
}
}

View file

@ -14,7 +14,7 @@ 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 { VSCodeMenu } from 'vs/code/electron-main/menus';
import { getShellEnvironment } from 'vs/code/electron-main/shellEnv';
import { getShellEnvironment } from 'vs/code/node/shellEnv';
import { IUpdateService } from 'vs/platform/update/common/update';
import { UpdateChannel } from 'vs/platform/update/common/updateIpc';
import { UpdateService } from 'vs/platform/update/electron-main/updateService';
@ -26,8 +26,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/electron-main/log';
import { IStorageService } from 'vs/code/electron-main/storage';
import { ILogService } from 'vs/code/common/log';
import { IStorageService } from 'vs/code/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';
@ -146,8 +146,7 @@ export class VSCodeApplication {
// Spawn shared process
this.sharedProcess = new SharedProcess(this.environmentService, this.userEnv);
this.toDispose.push(this.sharedProcess);
this.sharedProcessClient = this.sharedProcess.whenReady()
.then(() => connect(this.environmentService.sharedIPCHandle, 'main'));
this.sharedProcessClient = this.sharedProcess.whenReady().then(() => connect(this.environmentService.sharedIPCHandle, 'main'));
// Services
const appInstantiationService = this.initServices();

View file

@ -10,7 +10,7 @@ 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/electron-main/log';
import { ILogService } from 'vs/code/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';
@ -41,7 +41,7 @@ export class LaunchChannel implements ILaunchChannel {
constructor(private service: ILaunchService) { }
call(command: string, arg: any): TPromise<any> {
public call(command: string, arg: any): TPromise<any> {
switch (command) {
case 'start':
const { args, userEnv } = arg as IStartArguments;
@ -50,6 +50,7 @@ export class LaunchChannel implements ILaunchChannel {
case 'get-main-process-id':
return this.service.getMainProcessId();
}
return undefined;
}
}
@ -60,11 +61,11 @@ export class LaunchChannelClient implements ILaunchService {
constructor(private channel: ILaunchChannel) { }
start(args: ParsedArgs, userEnv: IProcessEnvironment): TPromise<void> {
public start(args: ParsedArgs, userEnv: IProcessEnvironment): TPromise<void> {
return this.channel.call('start', { args, userEnv });
}
getMainProcessId(): TPromise<number> {
public getMainProcessId(): TPromise<number> {
return this.channel.call('get-main-process-id', null);
}
}
@ -79,19 +80,20 @@ export class LaunchService implements ILaunchService {
@IURLService private urlService: IURLService
) { }
start(args: ParsedArgs, userEnv: IProcessEnvironment): TPromise<void> {
public start(args: ParsedArgs, userEnv: IProcessEnvironment): TPromise<void> {
this.logService.log('Received data from other instance: ', args, userEnv);
// Check early for open-url which is handled in URL service
const openUrlArg = args['open-url'] || [];
const openUrl = typeof openUrlArg === 'string' ? [openUrlArg] : openUrlArg;
const context = !!userEnv['VSCODE_CLI'] ? OpenContext.CLI : OpenContext.DESKTOP;
if (openUrl.length > 0) {
openUrl.forEach(url => this.urlService.open(url));
return TPromise.as(null);
}
// Otherwise handle in windows service
const context = !!userEnv['VSCODE_CLI'] ? OpenContext.CLI : OpenContext.DESKTOP;
let usedWindows: VSCodeWindow[];
if (!!args.extensionDevelopmentPath) {
this.windowsService.openExtensionDevelopmentHostWindow({ context, cli: args, userEnv });
@ -129,8 +131,9 @@ export class LaunchService implements ILaunchService {
return TPromise.as(null);
}
getMainProcessId(): TPromise<number> {
public getMainProcessId(): TPromise<number> {
this.logService.log('Received request for process ID from other instance.');
return TPromise.as(process.pid);
}
}

View file

@ -9,8 +9,8 @@ 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/electron-main/log';
import { IStorageService } from 'vs/code/electron-main/storage';
import { ILogService } from 'vs/code/common/log';
import { IStorageService } from 'vs/code/node/storage';
import Event, { Emitter } from 'vs/base/common/event';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';

View file

@ -10,7 +10,7 @@ import { assign } from 'vs/base/common/objects';
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/electron-main/paths';
import { validatePaths } from 'vs/code/node/paths';
import { LifecycleService, ILifecycleService } from 'vs/code/electron-main/lifecycle';
import { Server, serve, connect } from 'vs/base/parts/ipc/node/ipc.net';
import { TPromise } from 'vs/base/common/winjs.base';
@ -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/electron-main/log';
import { IStorageService, StorageService } from 'vs/code/electron-main/storage';
import { ILogService, MainLogService } from 'vs/code/common/log';
import { IStorageService, StorageService } from 'vs/code/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';

View file

@ -14,7 +14,7 @@ import { OpenContext } from 'vs/code/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/electron-main/storage';
import { IStorageService } from 'vs/code/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';

View file

@ -14,6 +14,8 @@ import { PromiseSource } from 'vs/base/common/async';
export class SharedProcess {
private spawnPromiseSource: PromiseSource<void>;
private window: Electron.BrowserWindow;
private disposables: IDisposable[] = [];
@ -41,6 +43,7 @@ export class SharedProcess {
this.disposables.push(toDisposable(() => this.window.removeListener('close', onClose)));
this.disposables.push(toDisposable(() => {
// Electron seems to crash on Windows without this setTimeout :|
setTimeout(() => {
try {
@ -65,8 +68,6 @@ export class SharedProcess {
});
}
private spawnPromiseSource: PromiseSource<void>;
constructor(
private environmentService: IEnvironmentService,
private userEnv: IProcessEnvironment
@ -74,15 +75,15 @@ export class SharedProcess {
this.spawnPromiseSource = new PromiseSource<void>();
}
spawn(): void {
public spawn(): void {
this.spawnPromiseSource.complete();
}
whenReady(): TPromise<void> {
public whenReady(): TPromise<void> {
return this.spawnPromiseSource.value.then(() => this._whenReady);
}
toggle(): void {
public toggle(): void {
if (this.window.isVisible()) {
this.hide();
} else {
@ -90,17 +91,17 @@ export class SharedProcess {
}
}
show(): void {
public show(): void {
this.window.show();
this.window.webContents.openDevTools();
}
hide(): void {
public hide(): void {
this.window.webContents.closeDevTools();
this.window.hide();
}
dispose(): void {
public dispose(): void {
this.disposables = dispose(this.disposables);
}
}

View file

@ -9,11 +9,11 @@ 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/electron-main/storage';
import { IStorageService } from 'vs/code/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/electron-main/log';
import { ILogService } from 'vs/code/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';
@ -78,9 +78,6 @@ export interface IWindowConfiguration extends ParsedArgs {
userEnv: IProcessEnvironment;
/**
* The physical keyboard is of ISO type (on OSX).
*/
isISOKeyboard?: boolean;
zoomLevel?: number;
@ -128,12 +125,6 @@ export enum ReadyState {
READY
}
interface IConfiguration {
window: {
menuBarVisibility: MenuBarVisibility;
};
}
export class VSCodeWindow {
public static themeStorageKey = 'theme';
@ -153,7 +144,6 @@ export class VSCodeWindow {
private _isExtensionTestHost: boolean;
private windowState: IWindowState;
private currentMenuBarVisibility: MenuBarVisibility;
private currentWindowMode: WindowMode;
private toDispose: IDisposable[];
private representedFilename: string;
@ -177,11 +167,27 @@ export class VSCodeWindow {
this.whenReadyCallbacks = [];
this.toDispose = [];
// create browser window
this.createBrowserWindow(config);
// respect configured menu bar visibility
this.onConfigurationUpdated();
// TODO@joao: hook this up to some initialization routine this causes a race between setting the headers and doing
// a request that needs them. chances are low
this.setCommonHTTPHeaders();
// Eventing
this.registerListeners();
}
private createBrowserWindow(config: IWindowCreationOptions): void {
// Load window state
this.restoreWindowState(config.state);
this.windowState = this.restoreWindowState(config.state);
// in case we are maximized or fullscreen, only show later after the call to maximize/fullscreen (see below)
const isFullscreenOrMaximized = (this.currentWindowMode === WindowMode.Maximized || this.currentWindowMode === WindowMode.Fullscreen);
const isFullscreenOrMaximized = (this.windowState.mode === WindowMode.Maximized || this.windowState.mode === WindowMode.Fullscreen);
const options: Electron.BrowserWindowOptions = {
width: this.windowState.width,
@ -248,7 +254,7 @@ export class VSCodeWindow {
if (isFullscreenOrMaximized) {
this._win.maximize();
if (this.currentWindowMode === WindowMode.Fullscreen) {
if (this.windowState.mode === WindowMode.Fullscreen) {
this._win.setFullScreen(true);
}
@ -258,16 +264,6 @@ export class VSCodeWindow {
}
this._lastFocusTime = Date.now(); // since we show directly, we need to set the last focus time too
// respect configured menu bar visibility
this.onConfigurationUpdated();
// TODO@joao: hook this up to some initialization routine this causes a race between setting the headers and doing
// a request that needs them. chances are low
this.setCommonHTTPHeaders();
// Eventing
this.registerListeners();
}
private setCommonHTTPHeaders(): void {
@ -376,20 +372,6 @@ export class VSCodeWindow {
return this._readyState;
}
private registerNavigationListenerOn(command: 'swipe' | 'app-command', back: 'left' | 'browser-backward', forward: 'right' | 'browser-forward', acrossEditors: boolean) {
this._win.on(command, (e, cmd) => {
if (this.readyState !== ReadyState.READY) {
return; // window must be ready
}
if (cmd === back) {
this.send('vscode:runAction', acrossEditors ? 'workbench.action.openPreviousRecentlyUsedEditor' : 'workbench.action.navigateBack');
} else if (cmd === forward) {
this.send('vscode:runAction', acrossEditors ? 'workbench.action.openNextRecentlyUsedEditor' : 'workbench.action.navigateForward');
}
});
}
private registerListeners(): void {
// Remember that we loaded
@ -405,7 +387,7 @@ export class VSCodeWindow {
// To prevent flashing, we set the window visible after the page has finished to load but before VSCode is loaded
if (!this._win.isVisible()) {
if (this.currentWindowMode === WindowMode.Maximized) {
if (this.windowState.mode === WindowMode.Maximized) {
this._win.maximize();
}
@ -487,6 +469,20 @@ export class VSCodeWindow {
}
};
private registerNavigationListenerOn(command: 'swipe' | 'app-command', back: 'left' | 'browser-backward', forward: 'right' | 'browser-forward', acrossEditors: boolean) {
this._win.on(command, (e, cmd) => {
if (this.readyState !== ReadyState.READY) {
return; // window must be ready
}
if (cmd === back) {
this.send('vscode:runAction', acrossEditors ? 'workbench.action.openPreviousRecentlyUsedEditor' : 'workbench.action.navigateBack');
} else if (cmd === forward) {
this.send('vscode:runAction', acrossEditors ? 'workbench.action.openNextRecentlyUsedEditor' : 'workbench.action.navigateForward');
}
});
}
public load(config: IWindowConfiguration): void {
// If this is the first time the window is loaded, we associate the paths
@ -527,8 +523,7 @@ export class VSCodeWindow {
// (--prof-startup) save profile to disk
const { profileStartup } = this.environmentService;
if (profileStartup) {
stopProfiling(profileStartup.dir, profileStartup.prefix)
.done(undefined, err => console.error(err));
stopProfiling(profileStartup.dir, profileStartup.prefix).done(undefined, err => console.error(err));
}
}
@ -556,7 +551,6 @@ export class VSCodeWindow {
}
private getUrl(windowConfiguration: IWindowConfiguration): string {
let url = require.toUrl('vs/workbench/electron-browser/bootstrap/index.html');
// Set zoomlevel
const windowConfig = this.configurationService.getConfiguration<IWindowSettings>('window');
@ -593,16 +587,16 @@ export class VSCodeWindow {
}
}
url += '?config=' + encodeURIComponent(JSON.stringify(config));
return url;
return `${require.toUrl('vs/workbench/electron-browser/bootstrap/index.html')}?config=${encodeURIComponent(JSON.stringify(config))}`;
}
private getBaseTheme(): string {
if (isWindows && systemPreferences.isInvertedColorScheme()) {
return 'hc-black';
}
const theme = this.storageService.getItem<string>(VSCodeWindow.themeStorageKey, 'vs-dark');
return theme.split(' ')[0];
}
@ -611,9 +605,10 @@ export class VSCodeWindow {
return '#000000';
}
let background = this.storageService.getItem<string>(VSCodeWindow.themeBackgroundStorageKey, null);
const background = this.storageService.getItem<string>(VSCodeWindow.themeBackgroundStorageKey, null);
if (!background) {
let baseTheme = this.getBaseTheme();
const baseTheme = this.getBaseTheme();
return baseTheme === 'hc-black' ? '#000000' : (baseTheme === 'vs' ? '#FFFFFF' : (isMacintosh ? '#171717' : '#1E1E1E')); // https://github.com/electron/electron/issues/5150
}
@ -668,7 +663,7 @@ export class VSCodeWindow {
return state;
}
private restoreWindowState(state?: IWindowState): void {
private restoreWindowState(state?: IWindowState): IWindowState {
if (state) {
try {
state = this.validateWindowState(state);
@ -681,8 +676,7 @@ export class VSCodeWindow {
state = defaultWindowState();
}
this.windowState = state;
this.currentWindowMode = this.windowState.mode;
return state;
}
private validateWindowState(state: IWindowState): IWindowState {

View file

@ -15,13 +15,13 @@ 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/electron-main/storage';
import { IStorageService } from 'vs/code/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/electron-main/paths';
import { IPathWithLineAndColumn, parseLineAndColumnAware } from 'vs/code/node/paths';
import { ILifecycleService, UnloadReason } from 'vs/code/electron-main/lifecycle';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ILogService } from 'vs/code/electron-main/log';
import { ILogService } from 'vs/code/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';

View file

@ -11,7 +11,6 @@ import { generateUuid } from 'vs/base/common/uuid';
import { TPromise } from 'vs/base/common/winjs.base';
import { isWindows } from 'vs/base/common/platform';
function getUnixShellEnvironment(): TPromise<typeof process.env> {
const promise = new TPromise((c, e) => {
const runAsNode = process.env['ELECTRON_RUN_AS_NODE'];
@ -88,5 +87,6 @@ export function getShellEnvironment(): TPromise<typeof process.env> {
_shellEnv = getUnixShellEnvironment();
}
}
return _shellEnv;
}

View file

@ -30,7 +30,7 @@ export class StorageService implements IStorageService {
this.dbPath = path.join(environmentService.userDataPath, 'storage.json');
}
getItem<T>(key: string, defaultValue?: T): T {
public getItem<T>(key: string, defaultValue?: T): T {
if (!this.database) {
this.database = this.load();
}
@ -43,7 +43,7 @@ export class StorageService implements IStorageService {
return this.database[key];
}
setItem(key: string, data: any): void {
public setItem(key: string, data: any): void {
if (!this.database) {
this.database = this.load();
}
@ -59,7 +59,7 @@ export class StorageService implements IStorageService {
this.save();
}
removeItem(key: string): void {
public removeItem(key: string): void {
if (!this.database) {
this.database = this.load();
}

View file

@ -43,6 +43,7 @@ export function findBestWindowOrFolder<SimpleWindow extends ISimpleWindow>({ win
} else if (bestFolder) {
return bestFolder;
}
return !newWindow ? getLastActiveWindow(windows) : null;
}
@ -51,6 +52,7 @@ function findBestWindow<WINDOW extends ISimpleWindow>(windows: WINDOW[], filePat
if (containers.length) {
return containers.sort((a, b) => -(a.openedWorkspacePath.length - b.openedWorkspacePath.length))[0];
}
return null;
}
@ -60,6 +62,7 @@ function findBestFolder(filePath: string, userHome?: string, vscodeFolder?: stri
if (!platform.isLinux) {
homeFolder = homeFolder && homeFolder.toLowerCase();
}
let previous = null;
try {
while (folder !== previous) {
@ -72,22 +75,23 @@ function findBestFolder(filePath: string, userHome?: string, vscodeFolder?: stri
} catch (err) {
// assume impossible to access
}
return null;
}
function isProjectFolder(folder: string, normalizedUserHome?: string, vscodeFolder = '.vscode') {
try {
if ((platform.isLinux ? folder : folder.toLowerCase()) === normalizedUserHome) {
// ~/.vscode/extensions is used for extensions
return fs.statSync(path.join(folder, vscodeFolder, 'settings.json')).isFile();
} else {
return fs.statSync(path.join(folder, vscodeFolder)).isDirectory();
return fs.statSync(path.join(folder, vscodeFolder, 'settings.json')).isFile(); // ~/.vscode/extensions is used for extensions
}
return fs.statSync(path.join(folder, vscodeFolder)).isDirectory();
} catch (err) {
if (!(err && err.code === 'ENOENT')) {
throw err;
}
}
return false;
}