提交 7975b1b6 编写于 作者: B Benjamin Pasero

Do not use electron's remote in event handlers (fixes #3072)

上级 91338eda
......@@ -145,12 +145,12 @@ export class ToggleDevToolsAction extends Action {
public static ID = 'workbench.action.toggleDevTools';
public static LABEL = nls.localize('toggleDevTools', "Toggle Developer Tools");
constructor(id: string, label: string) {
constructor(id: string, label: string, @IWindowService private windowService: IWindowService) {
super(id, label);
}
public run(): TPromise<boolean> {
remote.getCurrentWindow().webContents.toggleDevTools();
ipc.send('vscode:toggleDevTools', this.windowService.getWindowId());
return TPromise.as(true);
}
......
......@@ -16,11 +16,11 @@
var electron = require('electron');
var remote = electron.remote;
var ipc = electron.ipcRenderer;
var windowId = remote.getCurrentWindow().id;
function onError(error, enableDeveloperTools) {
if (enableDeveloperTools) {
remote.getCurrentWindow().webContents.openDevTools();
remote.getCurrentWindow().show();
ipc.send('vscode:openDevTools', windowId);
}
console.error('[uncaught exception]: ' + error);
......@@ -88,9 +88,9 @@
window.addEventListener('keydown', function(e) {
var key = extractKey(e);
if (key === TOGGLE_DEV_TOOLS_KB) {
remote.getCurrentWindow().toggleDevTools();
ipc.send('vscode:toggleDevTools', windowId);
} else if (key === RELOAD_KB) {
ipc.send('vscode:reloadWindow', remote.getCurrentWindow().id);
ipc.send('vscode:reloadWindow', windowId);
}
});
}
......@@ -186,20 +186,25 @@
'enableTypeScriptServiceModeForJS': !!process.env['CODE_TSJS'] || !!process.env['VSCODE_TSJS']
};
var programStart = remote.getGlobal('programStart');
var vscodeStart = remote.getGlobal('vscodeStart');
var timers = window.MonacoEnvironment.timers = {
start: new Date(programStart || vscodeStart),
start: new Date()
};
if (programStart) {
timers.beforeProgram = new Date(programStart);
timers.afterProgram = new Date(vscodeStart);
if (configuration.enablePerformance) {
var programStart = remote.getGlobal('programStart');
var vscodeStart = remote.getGlobal('vscodeStart');
if (programStart) {
timers.beforeProgram = new Date(programStart);
timers.afterProgram = new Date(vscodeStart);
}
timers.vscodeStart = new Date(vscodeStart);
timers.start = new Date(programStart || vscodeStart);
}
timers.vscodeStart = new Date(vscodeStart);
timers.beforeLoad = new Date();
require([
'vs/workbench/workbench.main',
'vs/nls!vs/workbench/workbench.main',
......
......@@ -28,6 +28,8 @@ import win = require('vs/workbench/electron-browser/window');
import {ipcRenderer as ipc, webFrame, remote} from 'electron';
const currentWindow = remote.getCurrentWindow();
const TextInputActions: IAction[] = [
new Action('undo', nls.localize('undo', "Undo"), null, true, () => document.execCommand('undo') && TPromise.as(true)),
new Action('redo', nls.localize('redo', "Redo"), null, true, () => document.execCommand('redo') && TPromise.as(true)),
......@@ -58,7 +60,7 @@ export class ElectronIntegration {
public integrate(shellContainer: HTMLElement): void {
// Register the active window
let activeWindow = this.instantiationService.createInstance(win.ElectronWindow, remote.getCurrentWindow(), shellContainer);
let activeWindow = this.instantiationService.createInstance(win.ElectronWindow, currentWindow, shellContainer);
this.windowService.registerWindow(activeWindow);
// Support runAction event
......
......@@ -20,6 +20,8 @@ import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';
import {ipcRenderer as ipc, shell, remote} from 'electron';
const dialog = remote.dialog;
export interface IWindowConfiguration {
window: {
openFilesInNewWindow: boolean;
......@@ -30,6 +32,7 @@ export interface IWindowConfiguration {
export class ElectronWindow {
private win: Electron.BrowserWindow;
private windowId: number;
constructor(
win: Electron.BrowserWindow,
......@@ -41,6 +44,7 @@ export class ElectronWindow {
@IViewletService private viewletService: IViewletService
) {
this.win = win;
this.windowId = win.id;
this.registerListeners();
}
......@@ -49,18 +53,13 @@ export class ElectronWindow {
// React to editor input changes (Mac only)
if (platform.platform === platform.Platform.Mac) {
this.eventService.addListener(EventType.EDITOR_INPUT_CHANGED, (e: EditorEvent) => {
// if we dont use setTimeout() here for some reason there is an issue when switching between 2 files side by side
// with the mac trackpad where the editor would think the user wants to select. to reproduce, have 2 files, click
// into the non-focussed one and move the mouse down and see the editor starts to select lines.
setTimeout(() => {
let fileInput = workbenchEditorCommon.asFileEditorInput(e.editorInput, true);
if (fileInput) {
this.win.setRepresentedFilename(fileInput.getResource().fsPath);
} else {
this.win.setRepresentedFilename('');
}
}, 0);
let fileInput = workbenchEditorCommon.asFileEditorInput(e.editorInput, true);
let representedFilename = '';
if (fileInput) {
representedFilename = fileInput.getResource().fsPath;
}
ipc.send('vscode:setRepresentedFilename', this.windowId, representedFilename);
});
}
......@@ -155,36 +154,34 @@ export class ElectronWindow {
}
public reload(): void {
ipc.send('vscode:reloadWindow', this.win.id);
ipc.send('vscode:reloadWindow', this.windowId);
}
public showMessageBox(options: Electron.Dialog.ShowMessageBoxOptions): number {
return remote.dialog.showMessageBox(this.win, options);
return dialog.showMessageBox(this.win, options);
}
public setFullScreen(fullscreen: boolean): void {
this.win.setFullScreen(fullscreen);
public showSaveDialog(options: Electron.Dialog.SaveDialogOptions, callback?: (fileName: string) => void): string {
return dialog.showSaveDialog(this.win, options, callback);
}
public openDevTools(): void {
this.win.webContents.openDevTools();
public setFullScreen(fullscreen: boolean): void {
ipc.send('vscode:setFullScreen', this.windowId, fullscreen); // handled from browser process
}
public isFullScreen(): boolean {
return this.win.isFullScreen();
public openDevTools(): void {
ipc.send('vscode:openDevTools', this.windowId); // handled from browser process
}
public setMenuBarVisibility(visible: boolean): void {
this.win.setMenuBarVisibility(visible);
ipc.send('vscode:setMenuBarVisibility', this.windowId, visible); // handled from browser process
}
public focus(): void {
if (!this.win.isFocused()) {
this.win.focus();
}
ipc.send('vscode:focusWindow', this.windowId); // handled from browser process
}
public flashFrame(): void {
this.win.flashFrame(!this.win.isFocused());
ipc.send('vscode:flashFrame', this.windowId); // handled from browser process
}
}
\ No newline at end of file
......@@ -222,6 +222,79 @@ export class WindowsManager {
}
});
ipc.on('vscode:setFullScreen', (event, windowId: number, fullscreen: boolean) => {
env.log('IPC#vscode:setFullScreen');
let vscodeWindow = this.getWindowById(windowId);
if (vscodeWindow) {
vscodeWindow.win.setFullScreen(fullscreen);
}
});
ipc.on('vscode:toggleDevTools', (event, windowId: number) => {
env.log('IPC#vscode:toggleDevTools');
let vscodeWindow = this.getWindowById(windowId);
if (vscodeWindow) {
vscodeWindow.win.webContents.toggleDevTools();
}
});
ipc.on('vscode:openDevTools', (event, windowId: number) => {
env.log('IPC#vscode:openDevTools');
let vscodeWindow = this.getWindowById(windowId);
if (vscodeWindow) {
vscodeWindow.win.webContents.openDevTools();
vscodeWindow.win.show();
}
});
ipc.on('vscode:setRepresentedFilename', (event, windowId: number, fileName: string) => {
env.log('IPC#vscode:setRepresentedFilename');
let vscodeWindow = this.getWindowById(windowId);
if (vscodeWindow) {
vscodeWindow.win.setRepresentedFilename(fileName);
}
});
ipc.on('vscode:setMenuBarVisibility', (event, windowId: number, visibility: boolean) => {
env.log('IPC#vscode:setMenuBarVisibility');
let vscodeWindow = this.getWindowById(windowId);
if (vscodeWindow) {
vscodeWindow.win.setMenuBarVisibility(visibility);
}
});
ipc.on('vscode:flashFrame', (event, windowId: number) => {
env.log('IPC#vscode:flashFrame');
let vscodeWindow = this.getWindowById(windowId);
if (vscodeWindow) {
vscodeWindow.win.flashFrame(!vscodeWindow.win.isFocused());
}
});
ipc.on('vscode:focusWindow', (event, windowId: number) => {
env.log('IPC#vscode:focusWindow');
let vscodeWindow = this.getWindowById(windowId);
if (vscodeWindow) {
vscodeWindow.win.focus();
}
});
ipc.on('vscode:setDocumentEdited', (event, windowId: number, edited: boolean) => {
env.log('IPC#vscode:setDocumentEdited');
let vscodeWindow = this.getWindowById(windowId);
if (vscodeWindow && vscodeWindow.win.isDocumentEdited() !== edited) {
vscodeWindow.win.setDocumentEdited(edited);
}
});
ipc.on('vscode:toggleMenuBar', (event, windowId: number) => {
env.log('IPC#vscode:toggleMenuBar');
......
......@@ -14,6 +14,7 @@ import {asFileEditorInput} from 'vs/workbench/common/editor';
import errors = require('vs/base/common/errors');
import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService';
import URI from 'vs/base/common/uri';
import {IWindowService} from 'vs/workbench/services/window/electron-browser/windowService';
import {EventType as WorkbenchEventType} from 'vs/workbench/common/events';
import {IUntitledEditorService} from 'vs/workbench/services/untitled/common/untitledEditorService';
import {IPartService} from 'vs/workbench/services/part/common/partService';
......@@ -23,7 +24,7 @@ import {IEventService} from 'vs/platform/event/common/event';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import {ILifecycleService} from 'vs/platform/lifecycle/common/lifecycle';
import {ipcRenderer as ipc, remote} from 'electron';
import {ipcRenderer as ipc} from 'electron';
export interface IPath {
filePath: string;
......@@ -51,7 +52,8 @@ export class FileTracker implements IWorkbenchContribution {
@IWorkbenchEditorService private editorService: IWorkbenchEditorService,
@IInstantiationService private instantiationService: IInstantiationService,
@IUntitledEditorService private untitledEditorService: IUntitledEditorService,
@ILifecycleService private lifecycleService: ILifecycleService
@ILifecycleService private lifecycleService: ILifecycleService,
@IWindowService private windowService: IWindowService
) {
this.toUnbind = [];
this.isDocumentedEdited = false;
......@@ -59,8 +61,7 @@ export class FileTracker implements IWorkbenchContribution {
// Make sure to reset any previous state
if (plat.platform === plat.Platform.Mac) {
let win = remote.getCurrentWindow();
win.setDocumentEdited(false);
ipc.send('vscode:setDocumentEdited', this.windowService.getWindowId(), false); // handled from browser process
}
this.registerListeners();
......@@ -185,16 +186,10 @@ export class FileTracker implements IWorkbenchContribution {
private updateDocumentEdited(): void {
if (plat.platform === plat.Platform.Mac) {
process.nextTick(() => {
let win = remote.getCurrentWindow();
let isDirtyIndicated = win.isDocumentEdited();
let hasDirtyFiles = this.textFileService.isDirty();
this.isDocumentedEdited = hasDirtyFiles;
if (hasDirtyFiles !== isDirtyIndicated) {
win.setDocumentEdited(hasDirtyFiles);
}
});
let hasDirtyFiles = this.textFileService.isDirty();
this.isDocumentedEdited = hasDirtyFiles;
ipc.send('vscode:setDocumentEdited', this.windowService.getWindowId(), hasDirtyFiles); // handled from browser process
}
}
......
......@@ -24,13 +24,10 @@ import {ILifecycleService} from 'vs/platform/lifecycle/common/lifecycle';
import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry';
import {IConfigurationService} from 'vs/platform/configuration/common/configuration';
import {IModeService} from 'vs/editor/common/services/modeService';
import {remote} from 'electron';
import {IWindowService} from 'vs/workbench/services/window/electron-browser/windowService';
export class TextFileService extends AbstractTextFileService {
private modeService: IModeService;
constructor(
@IWorkspaceContextService contextService: IWorkspaceContextService,
@IInstantiationService instantiationService: IInstantiationService,
......@@ -40,9 +37,11 @@ export class TextFileService extends AbstractTextFileService {
@ITelemetryService telemetryService: ITelemetryService,
@IConfigurationService configurationService: IConfigurationService,
@IEventService eventService: IEventService,
@IModeService modeService: IModeService
@IModeService private modeService: IModeService,
@IWindowService private windowService: IWindowService
) {
super(contextService, instantiationService, configurationService, telemetryService, lifecycleService, eventService);
this.modeService = modeService;
this.init();
......@@ -188,7 +187,7 @@ export class TextFileService extends AbstractTextFileService {
cancelId: buttons.indexOf(cancel)
};
const choice = remote.dialog.showMessageBox(remote.getCurrentWindow(), opts);
const choice = this.windowService.getWindow().showMessageBox(opts);
return buttons[choice].result;
}
......@@ -359,14 +358,14 @@ export class TextFileService extends AbstractTextFileService {
private promptForPathAsync(defaultPath?: string): TPromise<string> {
return new TPromise<string>((c, e) => {
remote.dialog.showSaveDialog(remote.getCurrentWindow(), this.getSaveDialogOptions(defaultPath ? paths.normalize(defaultPath, true) : void 0), (path) => {
this.windowService.getWindow().showSaveDialog(this.getSaveDialogOptions(defaultPath ? paths.normalize(defaultPath, true) : void 0), (path) => {
c(path);
});
});
}
private promptForPathSync(defaultPath?: string): string {
return remote.dialog.showSaveDialog(remote.getCurrentWindow(), this.getSaveDialogOptions(defaultPath ? paths.normalize(defaultPath, true) : void 0));
return this.windowService.getWindow().showSaveDialog(this.getSaveDialogOptions(defaultPath ? paths.normalize(defaultPath, true) : void 0));
}
private getSaveDialogOptions(defaultPath?: string): Electron.Dialog.SaveDialogOptions {
......
......@@ -19,7 +19,9 @@ import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingServic
import {remote} from 'electron';
export class ContextMenuService implements IContextMenuService {
public serviceId = IContextMenuService;
private telemetryService: ITelemetryService;
private messageService: IMessageService;
private keybindingService: IKeybindingService;
......@@ -36,61 +38,63 @@ export class ContextMenuService implements IContextMenuService {
return TPromise.as(null);
}
let menu = new remote.Menu();
let actionToRun: actions.IAction = null;
actions.forEach(a => {
if (a instanceof Separator) {
menu.append(new remote.MenuItem({ type: 'separator' }));
return TPromise.timeout(0).then(() => { // https://github.com/Microsoft/vscode/issues/3638
let menu = new remote.Menu();
let actionToRun: actions.IAction = null;
actions.forEach(a => {
if (a instanceof Separator) {
menu.append(new remote.MenuItem({ type: 'separator' }));
} else {
const keybinding = !!delegate.getKeyBinding ? delegate.getKeyBinding(a) : undefined;
const accelerator = keybinding && this.keybindingService.getElectronAcceleratorFor(keybinding);
const item = new remote.MenuItem({
label: a.label,
checked: a.checked,
accelerator,
enabled: a.enabled,
click: () => {
actionToRun = a;
}
});
menu.append(item);
}
});
const anchor = delegate.getAnchor();
let x: number, y: number;
if (dom.isHTMLElement(anchor)) {
const $anchor = $(<HTMLElement>anchor);
const elementPosition = $anchor.getPosition();
const elementSize = $anchor.getTotalSize();
x = elementPosition.left;
y = elementPosition.top + elementSize.height;
} else {
const keybinding = !!delegate.getKeyBinding ? delegate.getKeyBinding(a) : undefined;
const accelerator = keybinding && this.keybindingService.getElectronAcceleratorFor(keybinding);
const item = new remote.MenuItem({
label: a.label,
checked: a.checked,
accelerator,
enabled: a.enabled,
click: () => {
actionToRun = a;
}
});
menu.append(item);
const pos = <{ x: number; y: number; }>anchor;
x = pos.x;
y = pos.y;
}
});
const anchor = delegate.getAnchor();
let x: number, y: number;
if (dom.isHTMLElement(anchor)) {
const $anchor = $(<HTMLElement>anchor);
const elementPosition = $anchor.getPosition();
const elementSize = $anchor.getTotalSize();
x = elementPosition.left;
y = elementPosition.top + elementSize.height;
} else {
const pos = <{ x: number; y: number; }>anchor;
x = pos.x;
y = pos.y;
}
menu.popup(remote.getCurrentWindow(), Math.floor(x), Math.floor(y));
menu.popup(remote.getCurrentWindow(), Math.floor(x), Math.floor(y));
if (delegate.onHide) {
delegate.onHide(false);
}
if (delegate.onHide) {
delegate.onHide(false);
}
if (!actionToRun) {
return;
}
if (!actionToRun) {
return;
}
this.telemetryService.publicLog('workbenchActionExecuted', { id: actionToRun.id, from: 'contextMenu' });
this.telemetryService.publicLog('workbenchActionExecuted', { id: actionToRun.id, from: 'contextMenu' });
const context = delegate.getActionsContext ? delegate.getActionsContext() : null;
return actionToRun.run(context) || TPromise.as(null);
const context = delegate.getActionsContext ? delegate.getActionsContext() : null;
return actionToRun.run(context) || TPromise.as(null);
});
})
.done(null, e => this.messageService.show(severity.Error, e));
.done(null, e => this.messageService.show(severity.Error, e));
}
}
\ No newline at end of file
......@@ -11,6 +11,8 @@ import Event, {Emitter} from 'vs/base/common/event';
import {ipcRenderer as ipc, remote} from 'electron';
const windowId = remote.getCurrentWindow().id;
export var IWindowService = createDecorator<IWindowService>('windowService');
export interface IWindowServices {
......@@ -40,10 +42,12 @@ export class WindowService implements IWindowService {
public serviceId = IWindowService;
private win: ElectronWindow;
private windowId: number;
private _onBroadcast: Emitter<IBroadcast>;
constructor() {
this._onBroadcast = new Emitter<IBroadcast>();
this.windowId = windowId;
this.registerListeners();
}
......@@ -59,7 +63,7 @@ export class WindowService implements IWindowService {
}
public getWindowId(): number {
return remote.getCurrentWindow().id;
return this.windowId;
}
public getWindow(): ElectronWindow {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册