diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js
index ff35e0a5a6f..9fa7fc9f28f 100644
--- a/build/gulpfile.vscode.js
+++ b/build/gulpfile.vscode.js
@@ -87,6 +87,7 @@ const vscodeResources = [
'out-build/vs/workbench/services/files/**/*.md',
'out-build/vs/code/electron-browser/sharedProcess/sharedProcess.js',
'out-build/vs/code/electron-browser/issue/issueReporter.js',
+ 'out-build/vs/code/electron-browser/processExplorer/processExplorer.js',
'!**/test/**'
];
diff --git a/src/vs/code/buildfile.js b/src/vs/code/buildfile.js
index 0293acbb5be..2ff372605b7 100644
--- a/src/vs/code/buildfile.js
+++ b/src/vs/code/buildfile.js
@@ -12,7 +12,7 @@ function createModuleDescription(name, exclude) {
excludes = excludes.concat(exclude);
}
result.exclude= excludes;
-
+
return result;
}
@@ -21,7 +21,8 @@ exports.collectModules= function() {
createModuleDescription('vs/code/electron-main/main', []),
createModuleDescription('vs/code/node/cli', []),
createModuleDescription('vs/code/node/cliProcessMain', ['vs/code/node/cli']),
+ createModuleDescription('vs/code/electron-browser/issue/issueReporterMain', []),
createModuleDescription('vs/code/electron-browser/sharedProcess/sharedProcessMain', []),
- createModuleDescription('vs/code/electron-browser/issue/issueReporterMain', [])
+ createModuleDescription('vs/code/electron-browser/processExplorer/processExplorerMain', [])
];
-};
\ No newline at end of file
+};
diff --git a/src/vs/code/electron-browser/processExplorer/media/processExplorer.css b/src/vs/code/electron-browser/processExplorer/media/processExplorer.css
new file mode 100644
index 00000000000..6f38b441592
--- /dev/null
+++ b/src/vs/code/electron-browser/processExplorer/media/processExplorer.css
@@ -0,0 +1,63 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+html,
+body {
+ margin: 0;
+ padding: 0;
+ height: 100%;
+ width: 100%;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ user-select: none;
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", "HelveticaNeue-Light", "Ubuntu", "Droid Sans", sans-serif;
+ font-size: 13px;
+ color: #cccccc;
+}
+
+.cpu {
+ width: 45px;
+}
+
+.pid {
+ width: 50px
+}
+
+.memory {
+ width: 90px;
+}
+
+.process-item {
+ line-height: 22px;
+}
+
+table {
+ border-collapse: collapse;
+ width: 100%;
+ table-layout: fixed;
+}
+th {
+ vertical-align: bottom;
+ border-bottom: 1px solid #cccccc;
+ padding: .5rem;
+ border-top: 1px solid #cccccc;
+ text-align: center;
+}
+td {
+ padding: .25rem;
+ vertical-align: top;
+}
+
+.centered {
+ text-align: center;
+}
+
+.data {
+ white-space: pre;
+}
+
+tbody > tr:hover {
+ background-color: #2A2D2E;
+}
diff --git a/src/vs/code/electron-browser/processExplorer/processExplorer.html b/src/vs/code/electron-browser/processExplorer/processExplorer.html
new file mode 100644
index 00000000000..4d6930d9987
--- /dev/null
+++ b/src/vs/code/electron-browser/processExplorer/processExplorer.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/vs/code/electron-browser/processExplorer/processExplorer.js b/src/vs/code/electron-browser/processExplorer/processExplorer.js
new file mode 100644
index 00000000000..1fdb4bb8296
--- /dev/null
+++ b/src/vs/code/electron-browser/processExplorer/processExplorer.js
@@ -0,0 +1,175 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+'use strict';
+
+const path = require('path');
+const fs = require('fs');
+const remote = require('electron').remote;
+
+function assign(destination, source) {
+ return Object.keys(source)
+ .reduce(function (r, key) { r[key] = source[key]; return r; }, destination);
+}
+
+function parseURLQueryArgs() {
+ const search = window.location.search || '';
+
+ return search.split(/[?&]/)
+ .filter(function (param) { return !!param; })
+ .map(function (param) { return param.split('='); })
+ .filter(function (param) { return param.length === 2; })
+ .reduce(function (r, param) { r[param[0]] = decodeURIComponent(param[1]); return r; }, {});
+}
+
+function uriFromPath(_path) {
+ var pathName = path.resolve(_path).replace(/\\/g, '/');
+ if (pathName.length > 0 && pathName.charAt(0) !== '/') {
+ pathName = '/' + pathName;
+ }
+
+ return encodeURI('file://' + pathName);
+}
+
+function readFile(file) {
+ return new Promise(function(resolve, reject) {
+ fs.readFile(file, 'utf8', function(err, data) {
+ if (err) {
+ reject(err);
+ return;
+ }
+ resolve(data);
+ });
+ });
+}
+
+function main() {
+ const args = parseURLQueryArgs();
+ const configuration = JSON.parse(args['config'] || '{}') || {};
+
+ assign(process.env, configuration.userEnv);
+
+ //#region Add support for using node_modules.asar
+ (function () {
+ const path = require('path');
+ const Module = require('module');
+ let NODE_MODULES_PATH = path.join(configuration.appRoot, 'node_modules');
+ if (/[a-z]\:/.test(NODE_MODULES_PATH)) {
+ // Make drive letter uppercase
+ NODE_MODULES_PATH = NODE_MODULES_PATH.charAt(0).toUpperCase() + NODE_MODULES_PATH.substr(1);
+ }
+ const NODE_MODULES_ASAR_PATH = NODE_MODULES_PATH + '.asar';
+
+ const originalResolveLookupPaths = Module._resolveLookupPaths;
+ Module._resolveLookupPaths = function (request, parent, newReturn) {
+ const result = originalResolveLookupPaths(request, parent, newReturn);
+
+ const paths = newReturn ? result : result[1];
+ for (let i = 0, len = paths.length; i < len; i++) {
+ if (paths[i] === NODE_MODULES_PATH) {
+ paths.splice(i, 0, NODE_MODULES_ASAR_PATH);
+ break;
+ }
+ }
+
+ return result;
+ };
+ })();
+ //#endregion
+
+ // Get the nls configuration into the process.env as early as possible.
+ var nlsConfig = { availableLanguages: {} };
+ const config = process.env['VSCODE_NLS_CONFIG'];
+ if (config) {
+ process.env['VSCODE_NLS_CONFIG'] = config;
+ try {
+ nlsConfig = JSON.parse(config);
+ } catch (e) { /*noop*/ }
+ }
+
+ if (nlsConfig._resolvedLanguagePackCoreLocation) {
+ let bundles = Object.create(null);
+ nlsConfig.loadBundle = function(bundle, language, cb) {
+ let result = bundles[bundle];
+ if (result) {
+ cb(undefined, result);
+ return;
+ }
+ let bundleFile = path.join(nlsConfig._resolvedLanguagePackCoreLocation, bundle.replace(/\//g, '!') + '.nls.json');
+ readFile(bundleFile).then(function (content) {
+ let json = JSON.parse(content);
+ bundles[bundle] = json;
+ cb(undefined, json);
+ })
+ .catch(cb);
+ };
+ }
+
+ var locale = nlsConfig.availableLanguages['*'] || 'en';
+ if (locale === 'zh-tw') {
+ locale = 'zh-Hant';
+ } else if (locale === 'zh-cn') {
+ locale = 'zh-Hans';
+ }
+
+ window.document.documentElement.setAttribute('lang', locale);
+
+ const extractKey = function (e) {
+ return [
+ e.ctrlKey ? 'ctrl-' : '',
+ e.metaKey ? 'meta-' : '',
+ e.altKey ? 'alt-' : '',
+ e.shiftKey ? 'shift-' : '',
+ e.keyCode
+ ].join('');
+ };
+
+ const TOGGLE_DEV_TOOLS_KB = (process.platform === 'darwin' ? 'meta-alt-73' : 'ctrl-shift-73'); // mac: Cmd-Alt-I, rest: Ctrl-Shift-I
+ const RELOAD_KB = (process.platform === 'darwin' ? 'meta-82' : 'ctrl-82'); // mac: Cmd-R, rest: Ctrl-R
+
+ window.addEventListener('keydown', function (e) {
+ const key = extractKey(e);
+ if (key === TOGGLE_DEV_TOOLS_KB) {
+ remote.getCurrentWebContents().toggleDevTools();
+ } else if (key === RELOAD_KB) {
+ remote.getCurrentWindow().reload();
+ }
+ });
+
+ // Load the loader
+ const loaderFilename = configuration.appRoot + '/out/vs/loader.js';
+ const loaderSource = fs.readFileSync(loaderFilename);
+ require('vm').runInThisContext(loaderSource, { filename: loaderFilename });
+ var define = global.define;
+ global.define = undefined;
+
+ window.nodeRequire = require.__$__nodeRequire;
+
+ define('fs', ['original-fs'], function (originalFS) { return originalFS; }); // replace the patched electron fs with the original node fs for all AMD code
+
+ window.MonacoEnvironment = {};
+ const rootUrl = uriFromPath(configuration.appRoot) + '/out';
+
+ require.config({
+ baseUrl: rootUrl,
+ 'vs/nls': nlsConfig,
+ nodeCachedDataDir: configuration.nodeCachedDataDir,
+ nodeModules: [/*BUILD->INSERT_NODE_MODULES*/]
+ });
+
+ if (nlsConfig.pseudo) {
+ require(['vs/nls'], function (nlsPlugin) {
+ nlsPlugin.setPseudoTranslation(nlsConfig.pseudo);
+ });
+ }
+
+ require([
+ 'vs/code/electron-browser/processExplorer/processExplorerMain'
+ ], function (processExplorer) {
+ processExplorer.startup(configuration.data);
+ });
+}
+
+main();
diff --git a/src/vs/code/electron-browser/processExplorer/processExplorerMain.ts b/src/vs/code/electron-browser/processExplorer/processExplorerMain.ts
new file mode 100644
index 00000000000..1fb3ca60b3b
--- /dev/null
+++ b/src/vs/code/electron-browser/processExplorer/processExplorerMain.ts
@@ -0,0 +1,184 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+'use strict';
+
+import 'vs/css!./media/processExplorer';
+import { listProcesses, ProcessItem } from 'vs/base/node/ps';
+import { remote, webFrame } from 'electron';
+import { repeat } from 'vs/base/common/strings';
+import { totalmem } from 'os';
+import product from 'vs/platform/node/product';
+import { localize } from 'vs/nls';
+import { ProcessExplorerData, ProcessExplorerStyles } from '../../../platform/issue/common/issue';
+import * as browser from 'vs/base/browser/browser';
+import * as platform from 'vs/base/common/platform';
+
+let processList: any[];
+
+function getProcessList(rootProcess: ProcessItem) {
+ const processes: any[] = [];
+
+ if (rootProcess) {
+ getProcessItem(processes, rootProcess, 0);
+ }
+
+ return processes;
+}
+
+function getProcessItem(processes: any[], item: ProcessItem, indent: number): void {
+ const isRoot = (indent === 0);
+
+ const MB = 1024 * 1024;
+
+ // Format name with indent
+ const name = isRoot ? `${product.applicationName} main` : item.name;
+ const formattedName = isRoot ? name : `${repeat(' ', indent)} ${name}`;
+ const memory = process.platform === 'win32' ? item.mem : (totalmem() * (item.mem / 100));
+ processes.push({
+ cpu: Number(item.load.toFixed(0)),
+ memory: Number((memory / MB).toFixed(0)),
+ pid: Number((item.pid).toFixed(0)),
+ name,
+ formattedName,
+ cmd: item.cmd
+ });
+
+ // Recurse into children if any
+ if (Array.isArray(item.children)) {
+ item.children.forEach(child => getProcessItem(processes, child, indent + 1));
+ }
+}
+
+function getProcessIdWithHighestProperty(processList, propertyName: string) {
+ let max = 0;
+ let maxProcessId;
+ processList.forEach(process => {
+ if (process[propertyName] > max) {
+ max = process[propertyName];
+ maxProcessId = process.pid;
+ }
+ });
+
+ return maxProcessId;
+}
+
+function updateProcessInfo(processList): void {
+ const target = document.getElementById('process-list');
+ const highestCPUProcess = getProcessIdWithHighestProperty(processList, 'cpu');
+ const highestMemoryProcess = getProcessIdWithHighestProperty(processList, 'memory');
+
+ let tableHtml = `
+
+ | ${localize('cpu', "CPU %")} |
+ ${localize('memory', "Memory (MB)")} |
+ ${localize('pid', "pid")} |
+ ${localize('name', "Name")} |
+
`;
+
+ processList.forEach(p => {
+ const cpuClass = p.pid === highestCPUProcess ? 'highest' : '';
+ const memoryClass = p.pid === highestMemoryProcess ? 'highest' : '';
+
+ tableHtml += `
+
+ | ${p.cpu} |
+ ${p.memory} |
+ ${p.pid} |
+ ${p.formattedName} |
+
`;
+ });
+
+ target.innerHTML = ``;
+}
+
+function applyStyles(styles: ProcessExplorerStyles): void {
+ const styleTag = document.createElement('style');
+ const content: string[] = [];
+
+ if (styles.hoverBackground) {
+ content.push(`tbody > tr:hover { background-color: ${styles.hoverBackground}; }`);
+ }
+
+ if (styles.hoverForeground) {
+ content.push(`tbody > tr:hover{ color: ${styles.hoverForeground}; }`);
+ }
+
+ if (styles.highlightForeground) {
+ content.push(`.highest { color: ${styles.highlightForeground}; }`);
+ }
+
+ styleTag.innerHTML = content.join('\n');
+ document.head.appendChild(styleTag);
+ document.body.style.color = styles.color;
+}
+
+function applyZoom(zoomLevel: number): void {
+ webFrame.setZoomLevel(zoomLevel);
+ browser.setZoomFactor(webFrame.getZoomFactor());
+ // See https://github.com/Microsoft/vscode/issues/26151
+ // Cannot be trusted because the webFrame might take some time
+ // until it really applies the new zoom level
+ browser.setZoomLevel(webFrame.getZoomLevel(), /*isTrusted*/false);
+}
+
+function showContextMenu(e) {
+ e.preventDefault();
+
+ const pid = parseInt(e.currentTarget.id);
+ if (pid && typeof pid === 'number') {
+ const menu = new remote.Menu();
+ menu.append(new remote.MenuItem({
+ label: localize('killProcess', "Kill Process"),
+ click() {
+ process.kill(pid, 'SIGTERM');
+ }
+ })
+ );
+
+ menu.append(new remote.MenuItem({
+ label: localize('forceKillProcess', "Force Kill Process"),
+ click() {
+ process.kill(pid, 'SIGKILL');
+ }
+ })
+ );
+
+ menu.popup(remote.getCurrentWindow());
+ }
+}
+
+export function startup(data: ProcessExplorerData): void {
+ applyStyles(data.styles);
+ applyZoom(data.zoomLevel);
+
+ setInterval(() => listProcesses(remote.process.pid).then(processes => {
+ processList = getProcessList(processes);
+ updateProcessInfo(processList);
+
+ const tableRows = document.getElementsByTagName('tr');
+ for (let i = 0; i < tableRows.length; i++) {
+ const tableRow = tableRows[i];
+ tableRow.addEventListener('click', (e) => {
+ showContextMenu(e);
+ });
+ }
+ }), 1200);
+
+
+ document.onkeydown = (e: KeyboardEvent) => {
+ const cmdOrCtrlKey = platform.isMacintosh ? e.metaKey : e.ctrlKey;
+
+ // Cmd/Ctrl + zooms in
+ if (cmdOrCtrlKey && e.keyCode === 187) {
+ applyZoom(webFrame.getZoomLevel() + 1);
+ }
+
+ // Cmd/Ctrl - zooms out
+ if (cmdOrCtrlKey && e.keyCode === 189) {
+ applyZoom(webFrame.getZoomLevel() - 1);
+ }
+ };
+}
\ No newline at end of file
diff --git a/src/vs/code/electron-main/menus.ts b/src/vs/code/electron-main/menus.ts
index 46d965ac212..dad88c4fc00 100644
--- a/src/vs/code/electron-main/menus.ts
+++ b/src/vs/code/electron-main/menus.ts
@@ -942,6 +942,8 @@ export class CodeMenu {
}
}, false));
+ const openProcessExplorer = new MenuItem({ label: this.mnemonicLabel(nls.localize({ key: 'miOpenProcessExplorerer', comment: ['&& denotes a mnemonic'] }, "Open &&Process Explorer")), click: () => this.runActionInRenderer('workbench.action.openProcessExplorer') });
+
let reportIssuesItem: Electron.MenuItem = null;
if (product.reportIssueUrl) {
const label = nls.localize({ key: 'miReportIssue', comment: ['&& denotes a mnemonic', 'Translate this to "Report Issue in English" in all languages please!'] }, "Report &&Issue");
@@ -990,7 +992,8 @@ export class CodeMenu {
}) : null,
(product.licenseUrl || product.privacyStatementUrl) ? __separator__() : null,
toggleDevToolsItem,
- isWindows && product.quality !== 'stable' ? showAccessibilityOptions : null
+ openProcessExplorer,
+ isWindows && product.quality !== 'stable' ? showAccessibilityOptions : null,
]).forEach(item => helpMenu.append(item));
if (!isMacintosh) {
@@ -1029,7 +1032,7 @@ export class CodeMenu {
}
private openAccessibilityOptions(): void {
- let win = new BrowserWindow({
+ const win = new BrowserWindow({
alwaysOnTop: true,
skipTaskbar: true,
resizable: false,
diff --git a/src/vs/platform/issue/common/issue.ts b/src/vs/platform/issue/common/issue.ts
index 8955b50b076..228bcdfefb1 100644
--- a/src/vs/platform/issue/common/issue.ts
+++ b/src/vs/platform/issue/common/issue.ts
@@ -11,6 +11,15 @@ import { ILocalExtension } from 'vs/platform/extensionManagement/common/extensio
export const IIssueService = createDecorator('issueService');
+export interface WindowStyles {
+ backgroundColor: string;
+ color: string;
+}
+export interface WindowData {
+ styles: WindowStyles;
+ zoomLevel: number;
+}
+
export enum IssueType {
Bug,
PerformanceIssue,
@@ -18,9 +27,7 @@ export enum IssueType {
SettingsSearchIssue
}
-export interface IssueReporterStyles {
- backgroundColor: string;
- color: string;
+export interface IssueReporterStyles extends WindowStyles {
textLinkColor: string;
inputBackground: string;
inputForeground: string;
@@ -35,9 +42,8 @@ export interface IssueReporterStyles {
sliderActiveColor: string;
}
-export interface IssueReporterData {
+export interface IssueReporterData extends WindowData {
styles: IssueReporterStyles;
- zoomLevel: number;
enabledExtensions: ILocalExtension[];
issueType?: IssueType;
}
@@ -58,7 +64,18 @@ export interface ISettingsSearchIssueReporterData extends IssueReporterData {
export interface IssueReporterFeatures {
}
+export interface ProcessExplorerStyles extends WindowStyles {
+ hoverBackground: string;
+ hoverForeground: string;
+ highlightForeground: string;
+}
+
+export interface ProcessExplorerData extends WindowData {
+ styles: ProcessExplorerStyles;
+}
+
export interface IIssueService {
_serviceBrand: any;
openReporter(data: IssueReporterData): TPromise;
+ openProcessExplorer(data: ProcessExplorerData): TPromise;
}
diff --git a/src/vs/platform/issue/common/issueIpc.ts b/src/vs/platform/issue/common/issueIpc.ts
index 99d73534b5e..d804c6579fe 100644
--- a/src/vs/platform/issue/common/issueIpc.ts
+++ b/src/vs/platform/issue/common/issueIpc.ts
@@ -7,7 +7,7 @@
import { TPromise } from 'vs/base/common/winjs.base';
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
-import { IIssueService, IssueReporterData } from './issue';
+import { IIssueService, IssueReporterData, ProcessExplorerData } from './issue';
export interface IIssueChannel extends IChannel {
call(command: 'openIssueReporter', arg: IssueReporterData): TPromise;
@@ -23,6 +23,8 @@ export class IssueChannel implements IIssueChannel {
switch (command) {
case 'openIssueReporter':
return this.service.openReporter(arg);
+ case 'openProcessExplorer':
+ return this.service.openProcessExplorer(arg);
}
return undefined;
}
@@ -37,4 +39,8 @@ export class IssueChannelClient implements IIssueService {
openReporter(data: IssueReporterData): TPromise {
return this.channel.call('openIssueReporter', data);
}
+
+ openProcessExplorer(data: ProcessExplorerData): TPromise {
+ return this.channel.call('openProcessExplorer', data);
+ }
}
\ No newline at end of file
diff --git a/src/vs/platform/issue/electron-main/issueService.ts b/src/vs/platform/issue/electron-main/issueService.ts
index 7232efc90fb..1d589bf8f16 100644
--- a/src/vs/platform/issue/electron-main/issueService.ts
+++ b/src/vs/platform/issue/electron-main/issueService.ts
@@ -9,7 +9,7 @@ import { TPromise, Promise } from 'vs/base/common/winjs.base';
import { localize } from 'vs/nls';
import * as objects from 'vs/base/common/objects';
import { parseArgs } from 'vs/platform/environment/node/argv';
-import { IIssueService, IssueReporterData, IssueReporterFeatures } from 'vs/platform/issue/common/issue';
+import { IIssueService, IssueReporterData, IssueReporterFeatures, ProcessExplorerData } from 'vs/platform/issue/common/issue';
import { BrowserWindow, ipcMain, screen } from 'electron';
import { ILaunchService } from 'vs/code/electron-main/launch';
import { getPerformanceInfo, PerformanceInfo, getSystemInfo, SystemInfo } from 'vs/code/electron-main/diagnostics';
@@ -22,7 +22,8 @@ const DEFAULT_BACKGROUND_COLOR = '#1E1E1E';
export class IssueService implements IIssueService {
_serviceBrand: any;
_issueWindow: BrowserWindow;
- _parentWindow: BrowserWindow;
+ _issueParentWindow: BrowserWindow;
+ _processExplorerWindow: BrowserWindow;
constructor(
private machineId: string,
@@ -46,11 +47,11 @@ export class IssueService implements IIssueService {
});
ipcMain.on('workbenchCommand', (event, arg) => {
- this._parentWindow.webContents.send('vscode:runAction', { id: arg, from: 'issueReporter' });
+ this._issueParentWindow.webContents.send('vscode:runAction', { id: arg, from: 'issueReporter' });
});
- this._parentWindow = BrowserWindow.getFocusedWindow();
- const position = this.getWindowPosition();
+ this._issueParentWindow = BrowserWindow.getFocusedWindow();
+ const position = this.getWindowPosition(this._issueParentWindow, 800, 900);
this._issueWindow = new BrowserWindow({
width: position.width,
height: position.height,
@@ -73,7 +74,54 @@ export class IssueService implements IIssueService {
return TPromise.as(null);
}
- private getWindowPosition() {
+ openProcessExplorer(data: ProcessExplorerData): TPromise {
+ // Create as singleton
+ if (!this._processExplorerWindow) {
+ const position = this.getWindowPosition(BrowserWindow.getFocusedWindow(), 800, 300);
+ this._processExplorerWindow = new BrowserWindow({
+ skipTaskbar: true,
+ resizable: true,
+ width: position.width,
+ height: position.height,
+ minWidth: 300,
+ minHeight: 200,
+ x: position.x,
+ y: position.y,
+ backgroundColor: data.styles.backgroundColor,
+ title: localize('processExplorer', "Process Explorer")
+ });
+
+ this._processExplorerWindow.setMenuBarVisibility(false);
+
+ const windowConfiguration = {
+ appRoot: this.environmentService.appRoot,
+ nodeCachedDataDir: this.environmentService.nodeCachedDataDir,
+ windowId: this._processExplorerWindow.id,
+ userEnv: this.userEnv,
+ machineId: this.machineId,
+ data
+ };
+
+ const environment = parseArgs(process.argv);
+ const config = objects.assign(environment, windowConfiguration);
+ for (let key in config) {
+ if (config[key] === void 0 || config[key] === null || config[key] === '') {
+ delete config[key]; // only send over properties that have a true value
+ }
+ }
+
+ this._processExplorerWindow.loadURL(`${require.toUrl('vs/code/electron-browser/processExplorer/processExplorer.html')}?config=${encodeURIComponent(JSON.stringify(config))}`);
+
+ this._processExplorerWindow.on('close', () => this._processExplorerWindow = void 0);
+ }
+
+ // Focus
+ this._processExplorerWindow.focus();
+
+ return TPromise.as(null);
+ }
+
+ private getWindowPosition(parentWindow: BrowserWindow, defaultWidth: number, defaultHeight: number) {
// We want the new window to open on the same display that the parent is in
let displayToUse: Electron.Display;
const displays = screen.getAllDisplays();
@@ -93,8 +141,8 @@ export class IssueService implements IIssueService {
}
// if we have a last active window, use that display for the new window
- if (!displayToUse && this._parentWindow) {
- displayToUse = screen.getDisplayMatching(this._parentWindow.getBounds());
+ if (!displayToUse && parentWindow) {
+ displayToUse = screen.getDisplayMatching(parentWindow.getBounds());
}
// fallback to primary display or first display
@@ -104,8 +152,8 @@ export class IssueService implements IIssueService {
}
let state = {
- width: 800,
- height: 900,
+ width: defaultWidth,
+ height: defaultHeight,
x: undefined,
y: undefined
};
diff --git a/src/vs/workbench/electron-browser/actions.ts b/src/vs/workbench/electron-browser/actions.ts
index 3e0b42414db..7abd5ddb6b1 100644
--- a/src/vs/workbench/electron-browser/actions.ts
+++ b/src/vs/workbench/electron-browser/actions.ts
@@ -871,6 +871,24 @@ export class OpenIssueReporterAction extends Action {
}
}
+export class OpenProcessExplorer extends Action {
+ public static readonly ID = 'workbench.action.openProcessExplorer';
+ public static readonly LABEL = nls.localize('openProcessExplorer', "Open Process Explorer");
+
+ constructor(
+ id: string,
+ label: string,
+ @IWorkbenchIssueService private issueService: IWorkbenchIssueService
+ ) {
+ super(id, label);
+ }
+
+ public run(): TPromise {
+ return this.issueService.openProcessExplorer()
+ .then(() => true);
+ }
+}
+
export class ReportPerformanceIssueUsingReporterAction extends Action {
public static readonly ID = 'workbench.action.reportPerformanceIssueUsingReporter';
public static readonly LABEL = nls.localize('reportPerformanceIssue', "Report Performance Issue");
diff --git a/src/vs/workbench/electron-browser/main.contribution.ts b/src/vs/workbench/electron-browser/main.contribution.ts
index c57c28d3c1b..26d69e90739 100644
--- a/src/vs/workbench/electron-browser/main.contribution.ts
+++ b/src/vs/workbench/electron-browser/main.contribution.ts
@@ -14,7 +14,7 @@ import { IConfigurationRegistry, Extensions as ConfigurationExtensions, Configur
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions';
import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes';
import { isWindows, isLinux, isMacintosh } from 'vs/base/common/platform';
-import { KeybindingsReferenceAction, OpenDocumentationUrlAction, OpenIntroductoryVideosUrlAction, OpenTipsAndTricksUrlAction, OpenIssueReporterAction, ReportPerformanceIssueUsingReporterAction, ZoomResetAction, ZoomOutAction, ZoomInAction, ToggleFullScreenAction, ToggleMenuBarAction, CloseWorkspaceAction, CloseCurrentWindowAction, SwitchWindow, NewWindowAction, NavigateUpAction, NavigateDownAction, NavigateLeftAction, NavigateRightAction, IncreaseViewSizeAction, DecreaseViewSizeAction, ShowStartupPerformance, ToggleSharedProcessAction, QuickSwitchWindow, QuickOpenRecentAction, inRecentFilesPickerContextKey, ShowAboutDialogAction, InspectContextKeysAction } from 'vs/workbench/electron-browser/actions';
+import { KeybindingsReferenceAction, OpenDocumentationUrlAction, OpenIntroductoryVideosUrlAction, OpenTipsAndTricksUrlAction, OpenIssueReporterAction, ReportPerformanceIssueUsingReporterAction, ZoomResetAction, ZoomOutAction, ZoomInAction, ToggleFullScreenAction, ToggleMenuBarAction, CloseWorkspaceAction, CloseCurrentWindowAction, SwitchWindow, NewWindowAction, NavigateUpAction, NavigateDownAction, NavigateLeftAction, NavigateRightAction, IncreaseViewSizeAction, DecreaseViewSizeAction, ShowStartupPerformance, ToggleSharedProcessAction, QuickSwitchWindow, QuickOpenRecentAction, inRecentFilesPickerContextKey, ShowAboutDialogAction, InspectContextKeysAction, OpenProcessExplorer } from 'vs/workbench/electron-browser/actions';
import { registerCommands } from 'vs/workbench/electron-browser/commands';
import { AddRootFolderAction, GlobalRemoveRootFolderAction, OpenWorkspaceAction, SaveWorkspaceAsAction, OpenWorkspaceConfigFileAction, OpenFolderAsWorkspaceInNewWindowAction, OpenFileFolderAction, OpenFileAction, OpenFolderAction } from 'vs/workbench/browser/actions/workspaceActions';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
@@ -111,6 +111,7 @@ const developerCategory = nls.localize('developer', "Developer");
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(ShowStartupPerformance, ShowStartupPerformance.ID, ShowStartupPerformance.LABEL), 'Developer: Startup Performance', developerCategory);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleSharedProcessAction, ToggleSharedProcessAction.ID, ToggleSharedProcessAction.LABEL), 'Developer: Toggle Shared Process', developerCategory);
workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(InspectContextKeysAction, InspectContextKeysAction.ID, InspectContextKeysAction.LABEL), 'Developer: Inspect Context Keys', developerCategory);
+workbenchActionsRegistry.registerWorkbenchAction(new SyncActionDescriptor(OpenProcessExplorer, OpenProcessExplorer.ID, OpenProcessExplorer.LABEL), 'Developer: Open Process Explorer', developerCategory);
const recentFilesPickerContext = ContextKeyExpr.and(inQuickOpenContext, ContextKeyExpr.has(inRecentFilesPickerContextKey));
diff --git a/src/vs/workbench/services/issue/common/issue.ts b/src/vs/workbench/services/issue/common/issue.ts
index b998241ce1c..e97d68ea091 100644
--- a/src/vs/workbench/services/issue/common/issue.ts
+++ b/src/vs/workbench/services/issue/common/issue.ts
@@ -14,4 +14,5 @@ export const IWorkbenchIssueService = createDecorator('w
export interface IWorkbenchIssueService {
_serviceBrand: any;
openReporter(dataOverrides?: Partial): TPromise;
+ openProcessExplorer(): TPromise;
}
diff --git a/src/vs/workbench/services/issue/electron-browser/workbenchIssueService.ts b/src/vs/workbench/services/issue/electron-browser/workbenchIssueService.ts
index 7e78f2904a5..80d5a39cad2 100644
--- a/src/vs/workbench/services/issue/electron-browser/workbenchIssueService.ts
+++ b/src/vs/workbench/services/issue/electron-browser/workbenchIssueService.ts
@@ -8,7 +8,7 @@
import { IssueReporterStyles, IIssueService, IssueReporterData } from 'vs/platform/issue/common/issue';
import { TPromise } from 'vs/base/common/winjs.base';
import { ITheme, IThemeService } from 'vs/platform/theme/common/themeService';
-import { textLinkForeground, inputBackground, inputBorder, inputForeground, buttonBackground, buttonHoverBackground, buttonForeground, inputValidationErrorBorder, foreground, inputActiveOptionBorder, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground } from 'vs/platform/theme/common/colorRegistry';
+import { textLinkForeground, inputBackground, inputBorder, inputForeground, buttonBackground, buttonHoverBackground, buttonForeground, inputValidationErrorBorder, foreground, inputActiveOptionBorder, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground, editorBackground, editorForeground, listHoverBackground, listHoverForeground, listHighlightForeground } from 'vs/platform/theme/common/colorRegistry';
import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
import { IExtensionManagementService, IExtensionEnablementService, LocalExtensionType } from 'vs/platform/extensionManagement/common/extensionManagement';
import { webFrame } from 'electron';
@@ -41,6 +41,21 @@ export class WorkbenchIssueService implements IWorkbenchIssueService {
return this.issueService.openReporter(issueReporterData);
});
}
+
+ openProcessExplorer(): TPromise {
+ const theme = this.themeService.getTheme();
+ const data = {
+ zoomLevel: webFrame.getZoomLevel(),
+ styles: {
+ backgroundColor: theme.getColor(editorBackground) && theme.getColor(editorBackground).toString(),
+ color: theme.getColor(editorForeground).toString(),
+ hoverBackground: theme.getColor(listHoverBackground) && theme.getColor(listHoverBackground).toString(),
+ hoverForeground: theme.getColor(listHoverForeground) && theme.getColor(listHoverForeground).toString(),
+ highlightForeground: theme.getColor(listHighlightForeground) && theme.getColor(listHighlightForeground).toString()
+ }
+ };
+ return this.issueService.openProcessExplorer(data);
+ }
}
export function getIssueReporterStyles(theme: ITheme): IssueReporterStyles {
diff --git a/tslint.json b/tslint.json
index 31396c2aa56..9a59614556e 100644
--- a/tslint.json
+++ b/tslint.json
@@ -409,6 +409,18 @@
"*" // node modules
]
},
+ {
+ "target": "**/vs/code/electron-browser/**",
+ "restrictions": [
+ "vs/nls",
+ "vs/css!./**/*",
+ "vs/nls",
+ "**/vs/base/**",
+ "**/vs/platform/**",
+ "**/vs/code/**",
+ "*" // node modules
+ ]
+ },
{
"target": "**/vs/code/**",
"restrictions": [