diff --git a/src/typings/electron.d.ts b/src/typings/electron.d.ts index 56c03cf5e2d..a13e294afe5 100644 --- a/src/typings/electron.d.ts +++ b/src/typings/electron.d.ts @@ -104,7 +104,7 @@ declare namespace Electron { const powerMonitor: PowerMonitor; const powerSaveBlocker: PowerSaveBlocker; const protocol: Protocol; - const remote: Remote; + // const remote: Remote; ### VSCODE CHANGE (we do not want to use remote) const screen: Screen; type session = Session; const session: typeof Session; @@ -2962,7 +2962,7 @@ declare namespace Electron { * event.returnValue. Note: Sending a synchronous message will block the whole * renderer process, unless you know what you are doing you should never use it. */ - sendSync(channel: string, ...args: any[]): any; + // sendSync(channel: string, ...args: any[]): any; ### VSCODE CHANGE (we do not want to use sendSync) /** * Sends a message to a window with windowid via channel. */ diff --git a/src/vs/base/browser/contextmenu.ts b/src/vs/base/browser/contextmenu.ts index c303d45eeb3..5dd631aa97f 100644 --- a/src/vs/base/browser/contextmenu.ts +++ b/src/vs/base/browser/contextmenu.ts @@ -10,7 +10,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { ResolvedKeybinding } from 'vs/base/common/keyCodes'; import { SubmenuAction } from 'vs/base/browser/ui/menu/menu'; -export interface IEvent { +export interface IContextMenuEvent { shiftKey?: boolean; ctrlKey?: boolean; altKey?: boolean; @@ -27,7 +27,7 @@ export interface IContextMenuDelegate { getAnchor(): HTMLElement | { x: number; y: number; }; getActions(): TPromise<(IAction | ContextSubMenu)[]>; getActionItem?(action: IAction): IActionItem; - getActionsContext?(event?: IEvent): any; + getActionsContext?(event?: IContextMenuEvent): any; getKeyBinding?(action: IAction): ResolvedKeybinding; getMenuClassName?(): string; onHide?(didCancel: boolean): void; diff --git a/src/vs/base/parts/contextmenu/common/contextmenu.ts b/src/vs/base/parts/contextmenu/common/contextmenu.ts new file mode 100644 index 00000000000..6998c66916f --- /dev/null +++ b/src/vs/base/parts/contextmenu/common/contextmenu.ts @@ -0,0 +1,45 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +export interface ICommonContextMenuItem { + label?: string; + + type?: 'normal' | 'separator' | 'submenu' | 'checkbox' | 'radio'; + + accelerator?: string; + + enabled?: boolean; + visible?: boolean; + checked?: boolean; +} + +export interface ISerializableContextMenuItem extends ICommonContextMenuItem { + id: number; + submenu?: ISerializableContextMenuItem[]; +} + +export interface IContextMenuItem extends ICommonContextMenuItem { + click?: (event: IContextMenuEvent) => void; + submenu?: IContextMenuItem[]; +} + +export interface IContextMenuEvent { + shiftKey?: boolean; + ctrlKey?: boolean; + altKey?: boolean; + metaKey?: boolean; +} + +export interface IPopupOptions { + x?: number; + y?: number; + positioningItem?: number; + onHide?: () => void; +} + +export const CONTEXT_MENU_CHANNEL = 'vscode:contextmenu'; +export const CONTEXT_MENU_CLOSE_CHANNEL = 'vscode:onCloseContextMenu'; \ No newline at end of file diff --git a/src/vs/base/parts/contextmenu/electron-browser/contextmenu.ts b/src/vs/base/parts/contextmenu/electron-browser/contextmenu.ts new file mode 100644 index 00000000000..f5e4d2b8dfe --- /dev/null +++ b/src/vs/base/parts/contextmenu/electron-browser/contextmenu.ts @@ -0,0 +1,50 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { ipcRenderer, Event } from 'electron'; +import { IContextMenuItem, ISerializableContextMenuItem, CONTEXT_MENU_CLOSE_CHANNEL, CONTEXT_MENU_CHANNEL, IPopupOptions, IContextMenuEvent } from 'vs/base/parts/contextmenu/common/contextmenu'; + +let onClickChannelIds = 0; + +export function popup(items: IContextMenuItem[], options?: IPopupOptions): void { + const processedItems: IContextMenuItem[] = []; + + const onClickChannel = `vscode:onContextMenu${onClickChannelIds++}`; + const onClickChannelHandler = (event: Event, itemId: number, context: IContextMenuEvent) => processedItems[itemId].click(context); + + ipcRenderer.once(onClickChannel, onClickChannelHandler); + ipcRenderer.once(CONTEXT_MENU_CLOSE_CHANNEL, () => { + ipcRenderer.removeListener(onClickChannel, onClickChannelHandler); + + if (options && options.onHide) { + options.onHide(); + } + }); + + ipcRenderer.send(CONTEXT_MENU_CHANNEL, items.map(item => createItem(item, processedItems)), onClickChannel, options); +} + +function createItem(item: IContextMenuItem, processedItems: IContextMenuItem[]): ISerializableContextMenuItem { + const serializableItem = { + id: processedItems.length, + label: item.label, + type: item.type, + accelerator: item.accelerator, + checked: item.checked, + enabled: typeof item.enabled === 'boolean' ? item.enabled : true, + visible: typeof item.visible === 'boolean' ? item.visible : true + } as ISerializableContextMenuItem; + + processedItems.push(item); + + // Submenu + if (Array.isArray(item.submenu)) { + serializableItem.submenu = item.submenu.map(submenuItem => createItem(submenuItem, processedItems)); + } + + return serializableItem; +} \ No newline at end of file diff --git a/src/vs/base/parts/contextmenu/electron-main/contextmenu.ts b/src/vs/base/parts/contextmenu/electron-main/contextmenu.ts new file mode 100644 index 00000000000..5afeaad9c1c --- /dev/null +++ b/src/vs/base/parts/contextmenu/electron-main/contextmenu.ts @@ -0,0 +1,65 @@ +/*--------------------------------------------------------------------------------------------- + * 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 { Menu, MenuItem, BrowserWindow, Event, ipcMain } from 'electron'; +import { ISerializableContextMenuItem, CONTEXT_MENU_CLOSE_CHANNEL, CONTEXT_MENU_CHANNEL, IPopupOptions } from 'vs/base/parts/contextmenu/common/contextmenu'; + +export function registerContextMenuListener(): void { + ipcMain.on(CONTEXT_MENU_CHANNEL, (event: Event, items: ISerializableContextMenuItem[], onClickChannel: string, options?: IPopupOptions) => { + const menu = createMenu(event, onClickChannel, items); + + menu.popup({ + window: BrowserWindow.fromWebContents(event.sender), + x: options ? options.x : void 0, + y: options ? options.y : void 0, + positioningItem: options ? options.positioningItem : void 0, + callback: () => { + event.sender.send(CONTEXT_MENU_CLOSE_CHANNEL); + } + }); + }); +} + +function createMenu(event: Event, onClickChannel: string, items: ISerializableContextMenuItem[]): Menu { + const menu = new Menu(); + + items.forEach(item => { + let menuitem: MenuItem; + + // Separator + if (item.type === 'separator') { + menuitem = new MenuItem({ + type: item.type, + }); + } + + // Sub Menu + else if (Array.isArray(item.submenu)) { + menuitem = new MenuItem({ + submenu: createMenu(event, onClickChannel, item.submenu), + label: item.label + }); + } + + // Normal Menu Item + else { + menuitem = new MenuItem({ + label: item.label, + type: item.type, + accelerator: item.accelerator, + checked: item.checked, + enabled: item.enabled, + visible: item.visible, + click: (menuItem, win, contextmenuEvent) => event.sender.send(onClickChannel, item.id, contextmenuEvent) + }); + } + + menu.append(menuitem); + }); + + return menu; +} \ No newline at end of file diff --git a/src/vs/code/electron-browser/processExplorer/processExplorerMain.ts b/src/vs/code/electron-browser/processExplorer/processExplorerMain.ts index 379eab77cf3..645bf682472 100644 --- a/src/vs/code/electron-browser/processExplorer/processExplorerMain.ts +++ b/src/vs/code/electron-browser/processExplorer/processExplorerMain.ts @@ -7,7 +7,7 @@ import 'vs/css!./media/processExplorer'; import { listProcesses, ProcessItem } from 'vs/base/node/ps'; -import { remote, webFrame, ipcRenderer, clipboard } from 'electron'; +import { webFrame, ipcRenderer, clipboard } from 'electron'; import { repeat } from 'vs/base/common/strings'; import { totalmem } from 'os'; import product from 'vs/platform/node/product'; @@ -15,6 +15,8 @@ import { localize } from 'vs/nls'; import { ProcessExplorerStyles, ProcessExplorerData } from 'vs/platform/issue/common/issue'; import * as browser from 'vs/base/browser/browser'; import * as platform from 'vs/base/common/platform'; +import { IContextMenuItem } from 'vs/base/parts/contextmenu/common/contextmenu'; +import { popup } from 'vs/base/parts/contextmenu/electron-browser/contextmenu'; let processList: any[]; let mapPidToWindowTitle = new Map(); @@ -137,29 +139,29 @@ function applyZoom(zoomLevel: number): void { function showContextMenu(e) { e.preventDefault(); - const menu = new remote.Menu(); + const items: IContextMenuItem[] = []; const pid = parseInt(e.currentTarget.id); if (pid && typeof pid === 'number') { - menu.append(new remote.MenuItem({ + items.push({ label: localize('killProcess', "Kill Process"), click() { process.kill(pid, 'SIGTERM'); } - })); + }); - menu.append(new remote.MenuItem({ + items.push({ label: localize('forceKillProcess', "Force Kill Process"), click() { process.kill(pid, 'SIGKILL'); } - })); + }); - menu.append(new remote.MenuItem({ + items.push({ type: 'separator' - })); + }); - menu.append(new remote.MenuItem({ + items.push({ label: localize('copy', "Copy"), click() { const row = document.getElementById(pid.toString()); @@ -167,9 +169,9 @@ function showContextMenu(e) { clipboard.writeText(row.innerText); } } - })); + }); - menu.append(new remote.MenuItem({ + items.push({ label: localize('copyAll', "Copy All"), click() { const processList = document.getElementById('process-list'); @@ -177,9 +179,9 @@ function showContextMenu(e) { clipboard.writeText(processList.innerText); } } - })); + }); } else { - menu.append(new remote.MenuItem({ + items.push({ label: localize('copyAll', "Copy All"), click() { const processList = document.getElementById('process-list'); @@ -187,10 +189,10 @@ function showContextMenu(e) { clipboard.writeText(processList.innerText); } } - })); + }); } - menu.popup({ window: remote.getCurrentWindow() }); + popup(items); } export function startup(data: ProcessExplorerData): void { @@ -206,7 +208,7 @@ export function startup(data: ProcessExplorerData): void { setInterval(() => { ipcRenderer.send('windowsInfoRequest'); - listProcesses(remote.process.pid).then(processes => { + listProcesses(data.pid).then(processes => { processList = getProcessList(processes); updateProcessInfo(processList); diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 5a56a7abf29..bb199729fac 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -67,6 +67,7 @@ import { ILabelService } from 'vs/platform/label/common/label'; import { CodeMenu } from 'vs/code/electron-main/menus'; import { hasArgs } from 'vs/platform/environment/node/argv'; import { RunOnceScheduler } from 'vs/base/common/async'; +import { registerContextMenuListener } from 'vs/base/parts/contextmenu/electron-main/contextmenu'; export class CodeApplication { @@ -104,6 +105,9 @@ export class CodeApplication { process.on('uncaughtException', err => this.onUnexpectedError(err)); process.on('unhandledRejection', (reason: any, promise: Promise) => errors.onUnexpectedError(reason)); + // Contextmenu via IPC support + registerContextMenuListener(); + app.on('will-quit', () => { this.logService.trace('App#will-quit: disposing resources'); diff --git a/src/vs/code/electron-main/windows.ts b/src/vs/code/electron-main/windows.ts index 5c9051ca65d..55d5cf9e53c 100644 --- a/src/vs/code/electron-main/windows.ts +++ b/src/vs/code/electron-main/windows.ts @@ -1182,6 +1182,7 @@ export class WindowsManager implements IWindowsMainService { const configuration: IWindowConfiguration = mixin({}, options.cli); // inherit all properties from CLI configuration.appRoot = this.environmentService.appRoot; configuration.machineId = this.machineId; + configuration.mainPid = process.pid; configuration.execPath = process.execPath; configuration.userEnv = assign({}, this.initialUserEnv, options.userEnv || {}); configuration.isInitialStartup = options.initialStartup; diff --git a/src/vs/platform/driver/electron-browser/driver.ts b/src/vs/platform/driver/electron-browser/driver.ts index 46a202f2c79..a2305e2d393 100644 --- a/src/vs/platform/driver/electron-browser/driver.ts +++ b/src/vs/platform/driver/electron-browser/driver.ts @@ -86,7 +86,7 @@ class WindowDriver implements IWindowDriver { private _click(selector: string, clickCount: number, xoffset?: number, yoffset?: number): TPromise { return this._getElementXY(selector, xoffset, yoffset).then(({ x, y }) => { - const webContents = electron.remote.getCurrentWebContents(); + const webContents: electron.WebContents = (electron as any).remote.getCurrentWebContents(); webContents.sendInputEvent({ type: 'mouseDown', x, y, button: 'left', clickCount } as any); return TPromise.timeout(10).then(() => { diff --git a/src/vs/platform/issue/common/issue.ts b/src/vs/platform/issue/common/issue.ts index 46d378dc8d4..fef600c10f5 100644 --- a/src/vs/platform/issue/common/issue.ts +++ b/src/vs/platform/issue/common/issue.ts @@ -74,6 +74,7 @@ export interface ProcessExplorerStyles extends WindowStyles { } export interface ProcessExplorerData extends WindowData { + pid: number; styles: ProcessExplorerStyles; } diff --git a/src/vs/platform/windows/common/windows.ts b/src/vs/platform/windows/common/windows.ts index 4b199d0e3e9..eedeaca472b 100644 --- a/src/vs/platform/windows/common/windows.ts +++ b/src/vs/platform/windows/common/windows.ts @@ -336,6 +336,8 @@ export interface IWindowConfiguration extends ParsedArgs { windowId: number; logLevel: LogLevel; + mainPid: number; + appRoot: string; execPath: string; isInitialStartup?: boolean; diff --git a/src/vs/workbench/services/contextview/electron-browser/contextmenuService.ts b/src/vs/workbench/services/contextview/electron-browser/contextmenuService.ts index 22429b85715..668c8fa75fa 100644 --- a/src/vs/workbench/services/contextview/electron-browser/contextmenuService.ts +++ b/src/vs/workbench/services/contextview/electron-browser/contextmenuService.ts @@ -12,13 +12,15 @@ import * as dom from 'vs/base/browser/dom'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { remote, webFrame } from 'electron'; +import { webFrame } from 'electron'; import { unmnemonicLabel } from 'vs/base/common/labels'; import { Event, Emitter } from 'vs/base/common/event'; import { INotificationService } from 'vs/platform/notification/common/notification'; -import { IContextMenuDelegate, ContextSubMenu, IEvent } from 'vs/base/browser/contextmenu'; +import { IContextMenuDelegate, ContextSubMenu, IContextMenuEvent } from 'vs/base/browser/contextmenu'; import { once } from 'vs/base/common/functional'; import { Disposable } from 'vs/base/common/lifecycle'; +import { IContextMenuItem } from 'vs/base/parts/contextmenu/common/contextmenu'; +import { popup } from 'vs/base/parts/contextmenu/electron-browser/contextmenu'; export class ContextMenuService extends Disposable implements IContextMenuService { @@ -38,101 +40,101 @@ export class ContextMenuService extends Disposable implements IContextMenuServic showContextMenu(delegate: IContextMenuDelegate): void { delegate.getActions().then(actions => { if (actions.length) { - setTimeout(() => { - const onHide = once(() => { - if (delegate.onHide) { - delegate.onHide(undefined); - } - - this._onDidContextMenu.fire(); - }); - - const menu = this.createMenu(delegate, actions, onHide); - const anchor = delegate.getAnchor(); - let x: number, y: number; - - if (dom.isHTMLElement(anchor)) { - let elementPosition = dom.getDomNodePagePosition(anchor); - - x = elementPosition.left; - y = elementPosition.top + elementPosition.height; - } else { - const pos = <{ x: number; y: number; }>anchor; - x = pos.x + 1; /* prevent first item from being selected automatically under mouse */ - y = pos.y; + const onHide = once(() => { + if (delegate.onHide) { + delegate.onHide(undefined); } - let zoom = webFrame.getZoomFactor(); - x *= zoom; - y *= zoom; - - menu.popup({ - window: remote.getCurrentWindow(), - x: Math.floor(x), - y: Math.floor(y), - positioningItem: delegate.autoSelectFirstItem ? 0 : void 0, - callback: () => onHide() - }); - }, 0); // https://github.com/Microsoft/vscode/issues/3638 - } - }); - } - - private createMenu(delegate: IContextMenuDelegate, entries: (IAction | ContextSubMenu)[], onHide: () => void): Electron.Menu { - const menu = new remote.Menu(); - const actionRunner = delegate.actionRunner || new ActionRunner(); - - entries.forEach(e => { - if (e instanceof Separator) { - menu.append(new remote.MenuItem({ type: 'separator' })); - } else if (e instanceof ContextSubMenu) { - const submenu = new remote.MenuItem({ - submenu: this.createMenu(delegate, e.entries, onHide), - label: unmnemonicLabel(e.label) + this._onDidContextMenu.fire(); }); - menu.append(submenu); - } else { - const options: Electron.MenuItemConstructorOptions = { - label: unmnemonicLabel(e.label), - checked: !!e.checked || !!e.radio, - type: !!e.checked ? 'checkbox' : !!e.radio ? 'radio' : void 0, - enabled: !!e.enabled, - click: (menuItem, win, event) => { + const menu = this.createMenu(delegate, actions, onHide); + const anchor = delegate.getAnchor(); + let x: number, y: number; - // To preserve pre-electron-2.x behaviour, we first trigger - // the onHide callback and then the action. - // Fixes https://github.com/Microsoft/vscode/issues/45601 - onHide(); + if (dom.isHTMLElement(anchor)) { + let elementPosition = dom.getDomNodePagePosition(anchor); - // Run action which will close the menu - this.runAction(actionRunner, e, delegate, event); - } - }; - - const keybinding = !!delegate.getKeyBinding ? delegate.getKeyBinding(e) : this.keybindingService.lookupKeybinding(e.id); - if (keybinding) { - const electronAccelerator = keybinding.getElectronAccelerator(); - if (electronAccelerator) { - options.accelerator = electronAccelerator; - } else { - const label = keybinding.getLabel(); - if (label) { - options.label = `${options.label} [${label}]`; - } - } + x = elementPosition.left; + y = elementPosition.top + elementPosition.height; + } else { + const pos = <{ x: number; y: number; }>anchor; + x = pos.x + 1; /* prevent first item from being selected automatically under mouse */ + y = pos.y; } - const item = new remote.MenuItem(options); + let zoom = webFrame.getZoomFactor(); + x *= zoom; + y *= zoom; - menu.append(item); + popup(menu, { + x: Math.floor(x), + y: Math.floor(y), + positioningItem: delegate.autoSelectFirstItem ? 0 : void 0, + onHide: () => onHide() + }); } }); - - return menu; } - private runAction(actionRunner: IActionRunner, actionToRun: IAction, delegate: IContextMenuDelegate, event: IEvent): void { + private createMenu(delegate: IContextMenuDelegate, entries: (IAction | ContextSubMenu)[], onHide: () => void): IContextMenuItem[] { + const actionRunner = delegate.actionRunner || new ActionRunner(); + + return entries.map(entry => this.createMenuItem(delegate, entry, actionRunner, onHide)); + } + + private createMenuItem(delegate: IContextMenuDelegate, entry: IAction | ContextSubMenu, actionRunner: IActionRunner, onHide: () => void): IContextMenuItem { + + // Separator + if (entry instanceof Separator) { + return { type: 'separator' } as IContextMenuItem; + } + + // Submenu + if (entry instanceof ContextSubMenu) { + return { + label: unmnemonicLabel(entry.label), + submenu: this.createMenu(delegate, entry.entries, onHide) + } as IContextMenuItem; + } + + // Normal Menu Item + else { + const item: IContextMenuItem = { + label: unmnemonicLabel(entry.label), + checked: !!entry.checked || !!entry.radio, + type: !!entry.checked ? 'checkbox' : !!entry.radio ? 'radio' : void 0, + enabled: !!entry.enabled, + click: event => { + + // To preserve pre-electron-2.x behaviour, we first trigger + // the onHide callback and then the action. + // Fixes https://github.com/Microsoft/vscode/issues/45601 + onHide(); + + // Run action which will close the menu + this.runAction(actionRunner, entry, delegate, event); + } + }; + + const keybinding = !!delegate.getKeyBinding ? delegate.getKeyBinding(entry) : this.keybindingService.lookupKeybinding(entry.id); + if (keybinding) { + const electronAccelerator = keybinding.getElectronAccelerator(); + if (electronAccelerator) { + item.accelerator = electronAccelerator; + } else { + const label = keybinding.getLabel(); + if (label) { + item.label = `${item.label} [${label}]`; + } + } + } + + return item; + } + } + + private runAction(actionRunner: IActionRunner, actionToRun: IAction, delegate: IContextMenuDelegate, event: IContextMenuEvent): void { /* __GDPR__ "workbenchActionExecuted" : { "id" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, diff --git a/src/vs/workbench/services/issue/electron-browser/workbenchIssueService.ts b/src/vs/workbench/services/issue/electron-browser/workbenchIssueService.ts index a3e9e3727bd..3ef280db960 100644 --- a/src/vs/workbench/services/issue/electron-browser/workbenchIssueService.ts +++ b/src/vs/workbench/services/issue/electron-browser/workbenchIssueService.ts @@ -5,7 +5,7 @@ 'use strict'; -import { IssueReporterStyles, IIssueService, IssueReporterData } from 'vs/platform/issue/common/issue'; +import { IssueReporterStyles, IIssueService, IssueReporterData, ProcessExplorerData } 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, editorBackground, editorForeground, listHoverBackground, listHoverForeground, listHighlightForeground, textLinkActiveForeground } from 'vs/platform/theme/common/colorRegistry'; @@ -14,6 +14,7 @@ import { IExtensionManagementService, IExtensionEnablementService, LocalExtensio import { webFrame } from 'electron'; import { assign } from 'vs/base/common/objects'; import { IWorkbenchIssueService } from 'vs/workbench/services/issue/common/issue'; +import { IWindowService } from 'vs/platform/windows/common/windows'; export class WorkbenchIssueService implements IWorkbenchIssueService { _serviceBrand: any; @@ -22,7 +23,8 @@ export class WorkbenchIssueService implements IWorkbenchIssueService { @IIssueService private issueService: IIssueService, @IThemeService private themeService: IThemeService, @IExtensionManagementService private extensionManagementService: IExtensionManagementService, - @IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService + @IExtensionEnablementService private extensionEnablementService: IExtensionEnablementService, + @IWindowService private windowService: IWindowService ) { } @@ -44,7 +46,8 @@ export class WorkbenchIssueService implements IWorkbenchIssueService { openProcessExplorer(): TPromise { const theme = this.themeService.getTheme(); - const data = { + const data: ProcessExplorerData = { + pid: this.windowService.getConfiguration().mainPid, zoomLevel: webFrame.getZoomLevel(), styles: { backgroundColor: theme.getColor(editorBackground) && theme.getColor(editorBackground).toString(),