mirror of
https://github.com/Microsoft/vscode
synced 2024-08-27 21:09:43 +00:00
parent
ab5e5d0028
commit
609c4ba1e7
|
@ -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/**'
|
||||
];
|
||||
|
||||
|
|
|
@ -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', [])
|
||||
];
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
<!-- Copyright (C) Microsoft Corporation. All rights reserved. -->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' https: data:; media-src 'none'; child-src 'self'; object-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; connect-src 'self' https:; font-src 'self' https:;">
|
||||
</head>
|
||||
|
||||
<body aria-label="">
|
||||
<div id="process-list"></div>
|
||||
</body>
|
||||
|
||||
<!-- Startup via processExplorer.js -->
|
||||
<script src="processExplorer.js"></script>
|
||||
|
||||
</html>
|
175
src/vs/code/electron-browser/processExplorer/processExplorer.js
Normal file
175
src/vs/code/electron-browser/processExplorer/processExplorer.js
Normal file
|
@ -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();
|
|
@ -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 = `
|
||||
<tr>
|
||||
<th class="cpu">${localize('cpu', "CPU %")}</th>
|
||||
<th class="memory">${localize('memory', "Memory (MB)")}</th>
|
||||
<th class="pid">${localize('pid', "pid")}</th>
|
||||
<th>${localize('name', "Name")}</th>
|
||||
</tr>`;
|
||||
|
||||
processList.forEach(p => {
|
||||
const cpuClass = p.pid === highestCPUProcess ? 'highest' : '';
|
||||
const memoryClass = p.pid === highestMemoryProcess ? 'highest' : '';
|
||||
|
||||
tableHtml += `
|
||||
<tr id=${p.pid}>
|
||||
<td class="centered ${cpuClass}">${p.cpu}</td>
|
||||
<td class="centered ${memoryClass}">${p.memory}</td>
|
||||
<td class="centered">${p.pid}</td>
|
||||
<td title="${p.name}" class="data">${p.formattedName}</td>
|
||||
</tr>`;
|
||||
});
|
||||
|
||||
target.innerHTML = `<table>${tableHtml}</table>`;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -11,6 +11,15 @@ import { ILocalExtension } from 'vs/platform/extensionManagement/common/extensio
|
|||
|
||||
export const IIssueService = createDecorator<IIssueService>('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<void>;
|
||||
openProcessExplorer(data: ProcessExplorerData): TPromise<void>;
|
||||
}
|
||||
|
|
|
@ -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<void>;
|
||||
|
@ -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<void> {
|
||||
return this.channel.call('openIssueReporter', data);
|
||||
}
|
||||
|
||||
openProcessExplorer(data: ProcessExplorerData): TPromise<void> {
|
||||
return this.channel.call('openProcessExplorer', data);
|
||||
}
|
||||
}
|
|
@ -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<void> {
|
||||
// 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
|
||||
};
|
||||
|
|
|
@ -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<boolean> {
|
||||
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");
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -14,4 +14,5 @@ export const IWorkbenchIssueService = createDecorator<IWorkbenchIssueService>('w
|
|||
export interface IWorkbenchIssueService {
|
||||
_serviceBrand: any;
|
||||
openReporter(dataOverrides?: Partial<IssueReporterData>): TPromise<void>;
|
||||
openProcessExplorer(): TPromise<void>;
|
||||
}
|
||||
|
|
|
@ -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<void> {
|
||||
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 {
|
||||
|
|
12
tslint.json
12
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": [
|
||||
|
|
Loading…
Reference in a new issue