diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index dabac01f5ab3917b4d3354b5027ed60951afc594..af5a5fe1fc3eab3045b3f8aef72b432e562c8b28 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -268,6 +268,7 @@ function packageTask(platform, arch, opts) { .pipe(util.cleanNodeModule('oniguruma', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['**/*.node'])) .pipe(util.cleanNodeModule('windows-mutex', ['binding.gyp', 'build/**', 'src/**'], ['**/*.node'])) .pipe(util.cleanNodeModule('native-keymap', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['**/*.node'])) + .pipe(util.cleanNodeModule('windows-foreground-love', ['binding.gyp', 'build/**', 'src/**'], ['**/*.node'])) .pipe(util.cleanNodeModule('gc-signals', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['**/*.node', 'src/index.js'])) .pipe(util.cleanNodeModule('pty.js', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['build/Release/**'])); diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 0b3fd12858e0a531a43f60415413823f7a6a51d5..0a9e33916cff043f8db48d661f58ae21b38f166f 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -414,6 +414,11 @@ "from": "vscode-textmate@2.2.0", "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-2.2.0.tgz" }, + "windows-foreground-love": { + "version": "0.1.0", + "from": "windows-foreground-love@0.1.0", + "resolved": "https://registry.npmjs.org/windows-foreground-love/-/windows-foreground-love-0.1.0.tgz" + }, "windows-mutex": { "version": "0.2.0", "from": "windows-mutex@>=0.2.0 <0.3.0", diff --git a/package.json b/package.json index 8ad3c9f600fdab72af705ffba6683598ca5ff5eb..98f8977c72632127367323524560964564860dae 100644 --- a/package.json +++ b/package.json @@ -108,6 +108,7 @@ } }, "optionalDependencies": { + "windows-foreground-love": "0.1.0", "windows-mutex": "^0.2.0", "fsevents": "0.3.8" } diff --git a/src/typings/windows-foreground-love.d.ts b/src/typings/windows-foreground-love.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..f7d20f13aef8ef5acefd4112f3eba8053325a271 --- /dev/null +++ b/src/typings/windows-foreground-love.d.ts @@ -0,0 +1,10 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +declare module 'windows-foreground-love' { + + export function allowSetForegroundWindow(pid?: number): boolean; + +} \ No newline at end of file diff --git a/src/vs/code/electron-main/launch.ts b/src/vs/code/electron-main/launch.ts index c708a942011ad07ec624da0a7bea2a03916e5bba..185cd639486e0f749e5d72832f4c14906300f1a2 100644 --- a/src/vs/code/electron-main/launch.ts +++ b/src/vs/code/electron-main/launch.ts @@ -21,10 +21,12 @@ export interface IStartArguments { export interface ILaunchService { start(args: ParsedArgs, userEnv: IProcessEnvironment): TPromise; + getMainProcessId(): TPromise; } export interface ILaunchChannel extends IChannel { call(command: 'start', arg: IStartArguments): TPromise; + call(command: 'get-main-process-id', arg: null): TPromise; call(command: string, arg: any): TPromise; } @@ -33,10 +35,13 @@ export class LaunchChannel implements ILaunchChannel { constructor(private service: ILaunchService) { } call(command: string, arg: any): TPromise { - const { args, userEnv } = arg as IStartArguments; - switch (command) { - case 'start': return this.service.start(args, userEnv); + case 'start': + const { args, userEnv } = arg as IStartArguments; + return this.service.start(args, userEnv); + + case 'get-main-process-id': + return this.service.getMainProcessId(); } } } @@ -48,6 +53,10 @@ export class LaunchChannelClient implements ILaunchService { start(args: ParsedArgs, userEnv: IProcessEnvironment): TPromise { return this.channel.call('start', { args, userEnv }); } + + getMainProcessId(): TPromise { + return this.channel.call('get-main-process-id', null); + } } export class LaunchService implements ILaunchService { @@ -105,4 +114,9 @@ export class LaunchService implements ILaunchService { return TPromise.as(null); } + + getMainProcessId(): TPromise { + this.logService.log('Received request for process ID from other instance.'); + return TPromise.as(process.pid); + } } \ No newline at end of file diff --git a/src/vs/code/electron-main/main.ts b/src/vs/code/electron-main/main.ts index 8a1798c023dbf70019fb61775575a8ebca9c203b..da2755debb656f6acebf488c4d451d28678d618e 100644 --- a/src/vs/code/electron-main/main.ts +++ b/src/vs/code/electron-main/main.ts @@ -299,7 +299,22 @@ function setupIPC(accessor: ServicesAccessor): TPromise { const channel = client.getChannel('launch'); const service = new LaunchChannelClient(channel); - return service.start(environmentService.args, process.env) + let promise = TPromise.as(null); + if (platform.isWindows) { + promise = service.getMainProcessId() + .then(processId => { + logService.log('Sending some foreground love to the running instance:', processId); + try { + const { allowSetForegroundWindow } = require.__$__nodeRequire('windows-foreground-love'); + allowSetForegroundWindow(processId); + } catch (e) { + // noop + } + }); + } + + return promise + .then(() => service.start(environmentService.args, process.env)) .then(() => client.dispose()) .then(() => TPromise.wrapError('Sent env to running instance. Terminating...')); },