diff --git a/OSSREADME.json b/OSSREADME.json index 5fe88517ee4..1c3d9cb2135 100644 --- a/OSSREADME.json +++ b/OSSREADME.json @@ -38,7 +38,7 @@ }, { "name": "chromium", - "version": "49.0.2623.75", + "version": "52.0.2743.82", "repositoryURL": "http://www.chromium.org/Home", "licenseDetail": [ "BSD License", @@ -74,20 +74,20 @@ }, { "name": "libchromiumcontent", - "version": "49.0.2623.75", + "version": "52.0.2743.82", "license": "MIT", "repositoryURL": "https://github.com/electron/libchromiumcontent", "isProd": true }, { "name": "nodejs", - "version": "5.10.0", + "version": "6.3.0", "repositoryURL": "https://github.com/nodejs/node", "isProd": true }, { "name": "electron", - "version": "0.37.6", + "version": "1.3.5", "license": "MIT", "repositoryURL": "https://github.com/electron/electron", "isProd": true diff --git a/appveyor.yml b/appveyor.yml index 67d80cae24f..3632e51d974 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,5 +1,5 @@ environment: - ATOM_SHELL_INTERNAL_RUN_AS_NODE: 1 + ELECTRON_RUN_AS_NODE: 1 VSCODE_BUILD_VERBOSE: true install: diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index 8df4cf8257b..1b6fda4d1de 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -230,6 +230,7 @@ function packageTask(platform, arch, opts) { if (platform === 'win32') { result = es.merge(result, gulp.src('resources/win32/bin/code.js', { base: 'resources/win32' })); + result = es.merge(result, gulp.src('resources/win32/bin/cat.exe', { base: 'resources/win32' })); result = es.merge(result, gulp.src('resources/win32/bin/code.cmd', { base: 'resources/win32' }) .pipe(replace('@@NAME@@', product.nameShort)) diff --git a/build/lib/watch/index.js b/build/lib/watch/index.js index 6c141221047..17cd6ab6646 100644 --- a/build/lib/watch/index.js +++ b/build/lib/watch/index.js @@ -3,11 +3,11 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -var es = require('event-stream'); +const es = require('event-stream'); /** Ugly hack for gulp-tsb */ function handleDeletions() { - return es.mapSync(function (f) { + return es.mapSync(f => { if (/\.ts$/.test(f.relative) && !f.contents) { f.contents = new Buffer(''); f.stat = { mtime: new Date() }; @@ -17,7 +17,9 @@ function handleDeletions() { }); } -var watch = process.platform === 'win32' ? require('./watch-win32') : require('gulp-watch'); +const watch = process.platform === 'win32' + ? require('./watch-win32') + : require('gulp-watch'); module.exports = function () { return watch.apply(null, arguments) diff --git a/build/lib/watch/package.json b/build/lib/watch/package.json index 47bf00b77f1..0d031340153 100644 --- a/build/lib/watch/package.json +++ b/build/lib/watch/package.json @@ -1,10 +1,10 @@ { - "name": "watch", - "version": "1.0.0", - "description": "", - "author": "Microsoft ", - "private": true, - "devDependencies": { - "gulp-watch": "^4.3.5" - } + "name": "watch", + "version": "1.0.0", + "description": "", + "author": "Microsoft ", + "private": true, + "devDependencies": { + "gulp-watch": "^4.3.9" + } } diff --git a/build/npm/preinstall.js b/build/npm/preinstall.js index 124013231d7..6a65998d3f6 100644 --- a/build/npm/preinstall.js +++ b/build/npm/preinstall.js @@ -3,11 +3,32 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -var win = "Please run '.\\scripts\\npm.bat install' instead."; -var nix = "Please run './scripts/npm.sh install' instead."; +const path = require('path'); +const cp = require('child_process'); if (process.env['npm_config_disturl'] !== 'https://atom.io/download/atom-shell') { console.error("You can't use plain npm to install Code's dependencies."); - console.error(/^win/.test(process.platform) ? win : nix); + console.error( + /^win/.test(process.platform) + ? "Please run '.\\scripts\\npm.bat install' instead." + : "Please run './scripts/npm.sh install' instead." + ); + process.exit(1); } + +// make sure we install gulp watch for the system installed +// node, since that is the driver of gulp +if (process.platform !== 'win32') { + const env = Object.assign({}, process.env); + + delete env['npm_config_disturl']; + delete env['npm_config_target']; + delete env['npm_config_runtime']; + + cp.spawnSync('npm', ['install'], { + cwd: path.join(path.dirname(__dirname), 'lib', 'watch'), + stdio: 'inherit', + env + }); +} \ No newline at end of file diff --git a/extensions/node-debug/node-debug.azure.json b/extensions/node-debug/node-debug.azure.json index 336a0c85e76..2a2679bd2eb 100644 --- a/extensions/node-debug/node-debug.azure.json +++ b/extensions/node-debug/node-debug.azure.json @@ -1,6 +1,6 @@ { "account": "monacobuild", "container": "debuggers", - "zip": "d643199/node-debug.zip", + "zip": "9263600/node-debug.zip", "output": "" } diff --git a/extensions/typescript/src/utils/electron.ts b/extensions/typescript/src/utils/electron.ts index a4e08453f9f..c0bda301689 100644 --- a/extensions/typescript/src/utils/electron.ts +++ b/extensions/typescript/src/utils/electron.ts @@ -48,7 +48,7 @@ function generatePatchedEnv(env:any, stdInPipeName:string, stdOutPipeName:string newEnv['STDIN_PIPE_NAME'] = stdInPipeName; newEnv['STDOUT_PIPE_NAME'] = stdOutPipeName; newEnv['STDERR_PIPE_NAME'] = stdErrPipeName; - newEnv['ATOM_SHELL_INTERNAL_RUN_AS_NODE'] = '1'; + newEnv['ELECTRON_RUN_AS_NODE'] = '1'; return newEnv; } diff --git a/extensions/typescript/src/utils/electronForkStart.ts b/extensions/typescript/src/utils/electronForkStart.ts index 46a12506041..83f75724002 100644 --- a/extensions/typescript/src/utils/electronForkStart.ts +++ b/extensions/typescript/src/utils/electronForkStart.ts @@ -31,7 +31,7 @@ var stdErrPipeName = process.env['STDERR_PIPE_NAME']; log('STDIN_PIPE_NAME: ' + stdInPipeName); log('STDOUT_PIPE_NAME: ' + stdOutPipeName); log('STDERR_PIPE_NAME: ' + stdErrPipeName); -log('ATOM_SHELL_INTERNAL_RUN_AS_NODE: ' + process.env['ATOM_SHELL_INTERNAL_RUN_AS_NODE']); +log('ELECTRON_RUN_AS_NODE: ' + process.env['ELECTRON_RUN_AS_NODE']); // stdout redirection to named pipe (function() { @@ -147,7 +147,7 @@ log('ATOM_SHELL_INTERNAL_RUN_AS_NODE: ' + process.env['ATOM_SHELL_INTERNAL_RUN_A delete process.env['STDIN_PIPE_NAME']; delete process.env['STDOUT_PIPE_NAME']; delete process.env['STDERR_PIPE_NAME']; - delete process.env['ATOM_SHELL_INTERNAL_RUN_AS_NODE']; + delete process.env['ELECTRON_RUN_AS_NODE']; require(program); diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 4266bd833e9..743ef15228f 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -414,7 +414,7 @@ "from": "vscode-textmate@2.1.1", "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-2.1.1.tgz" }, - "windows-mutex": { + "windows-mutex": { "version": "0.2.0", "from": "windows-mutex@>=0.2.0 <0.3.0", "resolved": "https://registry.npmjs.org/windows-mutex/-/windows-mutex-0.2.0.tgz" diff --git a/package.json b/package.json index 224945b0df9..ea947787c97 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.6.0", - "electronVersion": "0.37.6", + "electronVersion": "1.3.5", "distro": "3d44b35db8d394d6d7b2bc224675735a0a8f2704", "author": { "name": "Microsoft Corporation" @@ -69,7 +69,6 @@ "gulp-uglify": "^1.4.1", "gulp-util": "^3.0.6", "gulp-vinyl-zip": "^1.2.2", - "gulp-watch": "4.3.6", "innosetup-compiler": "^5.5.60", "is": "^3.1.0", "istanbul": "^0.3.17", diff --git a/resources/darwin/bin/code.sh b/resources/darwin/bin/code.sh index ac498810000..9dba3f8e378 100755 --- a/resources/darwin/bin/code.sh +++ b/resources/darwin/bin/code.sh @@ -7,5 +7,5 @@ function realpath() { /usr/bin/python -c "import os,sys; print os.path.realpath( CONTENTS="$(dirname "$(dirname "$(dirname "$(dirname "$(realpath "$0")")")")")" ELECTRON="$CONTENTS/MacOS/Electron" CLI="$CONTENTS/Resources/app/out/cli.js" -ATOM_SHELL_INTERNAL_RUN_AS_NODE=1 "$ELECTRON" "$CLI" "$@" +ELECTRON_RUN_AS_NODE=1 "$ELECTRON" "$CLI" "$@" exit $? \ No newline at end of file diff --git a/resources/linux/bin/code.sh b/resources/linux/bin/code.sh index 77fa49722f7..f0877aa4c9f 100755 --- a/resources/linux/bin/code.sh +++ b/resources/linux/bin/code.sh @@ -33,5 +33,5 @@ fi ELECTRON="$VSCODE_PATH/@@NAME@@" CLI="$VSCODE_PATH/resources/app/out/cli.js" -ATOM_SHELL_INTERNAL_RUN_AS_NODE=1 "$ELECTRON" "$CLI" "$@" +ELECTRON_RUN_AS_NODE=1 "$ELECTRON" "$CLI" "$@" exit $? \ No newline at end of file diff --git a/resources/win32/bin/cat.exe b/resources/win32/bin/cat.exe new file mode 100644 index 00000000000..f564baa192a Binary files /dev/null and b/resources/win32/bin/cat.exe differ diff --git a/resources/win32/bin/code.cmd b/resources/win32/bin/code.cmd index a975610eb31..2564a3234ba 100644 --- a/resources/win32/bin/code.cmd +++ b/resources/win32/bin/code.cmd @@ -1,6 +1,6 @@ @echo off setlocal set VSCODE_DEV= -set ATOM_SHELL_INTERNAL_RUN_AS_NODE=1 -call "%~dp0..\@@NAME@@.exe" "%~dp0..\resources\\app\\out\\cli.js" %* +set ELECTRON_RUN_AS_NODE=1 +call "%~dp0..\@@NAME@@.exe" "%~dp0..\resources\\app\\out\\cli.js" %* | cat endlocal \ No newline at end of file diff --git a/resources/win32/bin/code.sh b/resources/win32/bin/code.sh index 83f7bfea10c..49636eec1e2 100644 --- a/resources/win32/bin/code.sh +++ b/resources/win32/bin/code.sh @@ -11,5 +11,5 @@ if [ "$(expr substr $(uname -s) 1 9)" == "CYGWIN_NT" ]; then else CLI="$VSCODE_PATH/resources/app/out/cli.js" fi -ELECTRON_NO_ATTACH_CONSOLE=1 ATOM_SHELL_INTERNAL_RUN_AS_NODE=1 "$ELECTRON" "$CLI" "$@" +ELECTRON_RUN_AS_NODE=1 "$ELECTRON" "$CLI" "$@" | cat exit $? diff --git a/scripts/code-cli.sh b/scripts/code-cli.sh index 5823276e47f..9a4c03e31d4 100755 --- a/scripts/code-cli.sh +++ b/scripts/code-cli.sh @@ -30,7 +30,7 @@ function code() { CLI="$ROOT/out/cli.js" - ATOM_SHELL_INTERNAL_RUN_AS_NODE=1 \ + ELECTRON_RUN_AS_NODE=1 \ NODE_ENV=development \ VSCODE_DEV=1 \ ELECTRON_ENABLE_LOGGING=1 \ diff --git a/scripts/test-integration.bat b/scripts/test-integration.bat index 87dec89d1a1..16a617b5e11 100644 --- a/scripts/test-integration.bat +++ b/scripts/test-integration.bat @@ -1,10 +1,8 @@ @echo off setlocal -rem APPVEYOR Builds if not "%APPVEYOR%" == "" ( - set ELECTRON_NO_ATTACH_CONSOLE=1 - set ATOM_SHELL_INTERNAL_RUN_AS_NODE= + set ELECTRON_RUN_AS_NODE= ) :: Integration Tests diff --git a/scripts/test.bat b/scripts/test.bat index e55af32e6c0..bd7a7fe82cb 100644 --- a/scripts/test.bat +++ b/scripts/test.bat @@ -1,17 +1,7 @@ @echo off setlocal -set ATOM_SHELL_INTERNAL_RUN_AS_NODE=1 - -rem TFS Builds -if not "%BUILD_BUILDID%" == "" ( - set ELECTRON_NO_ATTACH_CONSOLE=1 -) - -rem APPVEYOR Builds -if not "%APPVEYOR%" == "" ( - set ELECTRON_NO_ATTACH_CONSOLE=1 -) +set ELECTRON_RUN_AS_NODE=1 pushd %~dp0\.. @@ -20,7 +10,15 @@ set NAMESHORT=%NAMESHORT: "=% set NAMESHORT=%NAMESHORT:"=%.exe set CODE=".build\electron\%NAMESHORT%" -%CODE% .\node_modules\mocha\bin\_mocha %* +rem TFS Builds +if not "%BUILD_BUILDID%" == "" ( + %CODE% .\node_modules\mocha\bin\_mocha %* +) + +rem Otherwise +if "%BUILD_BUILDID%" == "" ( + %CODE% .\node_modules\mocha\bin\_mocha %* | .\resources\win32\bin\cat +) popd endlocal diff --git a/scripts/test.sh b/scripts/test.sh index 5b6a7d2e39d..59bd5615b52 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -30,11 +30,11 @@ test -d out || ./node_modules/.bin/gulp compile # Unit Tests export VSCODE_DEV=1 if [[ "$OSTYPE" == "darwin"* ]]; then - cd $ROOT ; ulimit -n 4096 ; ATOM_SHELL_INTERNAL_RUN_AS_NODE=1 \ + cd $ROOT ; ulimit -n 4096 ; ELECTRON_RUN_AS_NODE=1 \ "$CODE" \ node_modules/mocha/bin/_mocha "$@" else - cd $ROOT ; ATOM_SHELL_INTERNAL_RUN_AS_NODE=1 \ + cd $ROOT ; ELECTRON_RUN_AS_NODE=1 \ "$CODE" \ node_modules/mocha/bin/_mocha "$@" fi diff --git a/src/typings/electron.d.ts b/src/typings/electron.d.ts index 938d88df290..cf4ce357304 100644 --- a/src/typings/electron.d.ts +++ b/src/typings/electron.d.ts @@ -1,4 +1,4 @@ -// Type definitions for Electron v1.2.5 +// Type definitions for Electron v1.3.4 // Project: http://electron.atom.io/ // Definitions by: jedmao , rhysd , Milan Burda // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped @@ -25,6 +25,23 @@ declare namespace Electron { sender: EventEmitter; } + type Point = { + x: number; + y: number; + } + + type Size = { + width: number; + height: number; + } + + type Rectangle = { + x: number; + y: number; + width: number; + height: number; + } + // https://github.com/electron/electron/blob/master/docs/api/app.md /** @@ -160,6 +177,12 @@ declare namespace Electron { * Emitted when the gpu process crashes. */ on(event: 'gpu-process-crashed', listener: Function): this; + /** + * Emitted when Chrome's accessibility support changes. + * + * Note: This API is only available on macOS and Windows. + */ + on(event: 'accessibility-support-changed', listener: (event: Event, accessibilitySupportEnabled: boolean) => void): this; on(event: string, listener: Function): this; /** * Try to close all windows. The before-quit event will first be emitted. @@ -273,28 +296,43 @@ declare namespace Electron { * Once registered, all links with your-protocol:// will be opened with the current executable. * The whole link, including protocol, will be passed to your application as a parameter. * + * On Windows you can provide optional parameters path, the path to your executable, + * and args, an array of arguments to be passed to your executable when it launches. + * + * @param protocol The name of your protocol, without ://. + * @param path Defaults to process.execPath. + * @param args Defaults to an empty array. + * * Note: This is only implemented on macOS and Windows. * On macOS, you can only register protocols that have been added to your app's info.plist. */ - setAsDefaultProtocolClient(protocol: string): void; + setAsDefaultProtocolClient(protocol: string, path?: string, args?: string[]): boolean; /** * Removes the current executable as the default handler for a protocol (aka URI scheme). * + * @param protocol The name of your protocol, without ://. + * @param path Defaults to process.execPath. + * @param args Defaults to an empty array. + * * Note: This is only implemented on macOS and Windows. */ - removeAsDefaultProtocolClient(protocol: string): void; + removeAsDefaultProtocolClient(protocol: string, path?: string, args?: string[]): boolean; /** + * @param protocol The name of your protocol, without ://. + * @param path Defaults to process.execPath. + * @param args Defaults to an empty array. + * * @returns Whether the current executable is the default handler for a protocol (aka URI scheme). * * Note: This is only implemented on macOS and Windows. */ - isDefaultProtocolClient(protocol: string): boolean; + isDefaultProtocolClient(protocol: string, path?: string, args?: string[]): boolean; /** * Adds tasks to the Tasks category of JumpList on Windows. * * Note: This API is only available on Windows. */ - setUserTasks(tasks: Task[]): void; + setUserTasks(tasks: Task[]): boolean; /** * This method makes your application a Single Instance Application instead of allowing * multiple instances of your app to run, this will ensure that only a single instance @@ -326,6 +364,8 @@ declare namespace Electron { getCurrentActivityType(): string; /** * Changes the Application User Model ID to id. + * + * Note: This is only implemented on Windows. */ setAppUserModelId(id: string): void; /** @@ -341,6 +381,33 @@ declare namespace Electron { * This method can only be called before app is ready. */ disableHardwareAcceleration(): void; + /** + * @returns whether current desktop environment is Unity launcher. (Linux) + * + * Note: This API is only available on Linux. + */ + isUnityRunning(): boolean; + /** + * Returns a Boolean, true if Chrome's accessibility support is enabled, false otherwise. + * This API will return true if the use of assistive technologies, such as screen readers, + * has been detected. + * See https://www.chromium.org/developers/design-documents/accessibility for more details. + * + * Note: This API is only available on macOS and Windows. + */ + isAccessibilitySupportEnabled(): boolean; + /** + * @returns an Object with the login item settings of the app. + * + * Note: This API is only available on macOS and Windows. + */ + getLoginItemSettings(): LoginItemSettings; + /** + * Set the app's login item settings. + * + * Note: This API is only available on macOS and Windows. + */ + setLoginItemSettings(settings: LoginItemSettings): void; commandLine: CommandLine; /** * Note: This API is only available on macOS. @@ -348,7 +415,7 @@ declare namespace Electron { dock: Dock; } - type AppPathName = 'home' | 'appData' | 'userData' | 'temp' | 'exe' | 'module' | 'desktop' | 'documents' | 'downloads' | 'music' | 'pictures' | 'videos' | 'pepperFlashSystemPlugin'; + type AppPathName = 'home'|'appData'|'userData'|'temp'|'exe'|'module'|'desktop'|'documents'|'downloads'|'music'|'pictures'|'videos'|'pepperFlashSystemPlugin'; interface ImportCertificateOptions { /** @@ -368,7 +435,7 @@ declare namespace Electron { * Note: This will not affect process.argv, and is mainly used by developers * to control some low-level Chromium behaviors. */ - appendSwitch(_switch: string, value?: string | number): void; + appendSwitch(_switch: string, value?: string): void; /** * Append an argument to Chromium's command line. The argument will quoted properly. * @@ -414,6 +481,20 @@ declare namespace Electron { * Note: This API is only available on macOS. */ getBadge(): string; + /** + * Sets the counter badge for current app. Setting the count to 0 will hide the badge. + * + * @returns True when the call succeeded, otherwise returns false. + * + * Note: This API is only available on macOS and Linux. + */ + setBadgeCount(count: number): boolean; + /** + * @returns The current value displayed in the counter badge. + * + * Note: This API is only available on macOS and Linux. + */ + getBadgeCount(): number; /** * Hides the dock icon. * @@ -426,6 +507,13 @@ declare namespace Electron { * Note: This API is only available on macOS. */ show(): void; + /** + * @returns Whether the dock icon is visible. + * The app.dock.show() call is asynchronous so this method might not return true immediately after that call. + * + * Note: This API is only available on macOS. + */ + isVisible(): boolean; /** * Sets the application dock menu. * @@ -472,6 +560,32 @@ declare namespace Electron { iconIndex?: number; } + interface LoginItemSettings { + /** + * True if the app is set to open at login. + */ + openAtLogin: boolean; + /** + * True if the app is set to open as hidden at login. This setting is only supported on macOS. + */ + openAsHidden: boolean; + /** + * True if the app was opened at login automatically. This setting is only supported on macOS. + */ + wasOpenedAtLogin?: boolean; + /** + * True if the app was opened as a hidden login item. This indicates that the app should not + * open any windows at startup. This setting is only supported on macOS. + */ + wasOpenedAsHidden?: boolean; + /** + * True if the app was opened as a login item that should restore the state from the previous session. + * This indicates that the app should restore the windows that were open the last time the app was closed. + * This setting is only supported on macOS. + */ + restoreState?: boolean; + } + // https://github.com/electron/electron/blob/master/docs/api/auto-updater.md /** @@ -504,6 +618,10 @@ declare namespace Electron { * Set the url and initialize the auto updater. */ setFeedURL(url: string, requestHeaders?: Headers): void; + /** + * @returns The current update feed URL. + */ + getFeedURL(): string; /** * Ask the server whether there is an update, you have to call setFeedURL * before using this API @@ -527,7 +645,7 @@ declare namespace Electron { * Emitted when the document changed its title, * calling event.preventDefault() would prevent the native window’s title to change. */ - on(event: 'page-title-updated', listener: (event: Event) => void): this; + on(event: 'page-title-updated', listener: (event: Event, title: string) => void): this; /** * Emitted when the window is going to be closed. It’s emitted before the beforeunload * and unload event of the DOM. Calling event.preventDefault() will cancel the close. @@ -629,6 +747,9 @@ declare namespace Electron { */ on(event: 'swipe', listener: (event: Event, direction: SwipeDirection) => void): this; on(event: string, listener: Function): this; + /** + * Creates a new BrowserWindow with native properties as set by the options. + */ constructor(options?: BrowserWindowOptions); /** * @returns All opened browser windows. @@ -703,6 +824,10 @@ declare namespace Electron { * @returns Whether the window is focused. */ isFocused(): boolean; + /** + * @returns Whether the window is destroyed. + */ + isDestroyed(): boolean; /** * Shows and gives focus to the window. */ @@ -764,7 +889,7 @@ declare namespace Electron { * * Note: This API is available only on macOS. */ - setAspectRatio(aspectRatio: number, extraSize?: Dimension): void; + setAspectRatio(aspectRatio: number, extraSize?: Size): void; /** * Resizes and moves the window to width, height, x, y. */ @@ -773,6 +898,14 @@ declare namespace Electron { * @returns The window's width, height, x and y values. */ getBounds(): Rectangle; + /** + * Resizes and moves the window's client area (e.g. the web page) to width, height, x, y. + */ + setContentBounds(options: Rectangle, animate?: boolean): void; + /** + * @returns The window's client area (e.g. the web page) width, height, x and y values. + */ + getContentBounds(): Rectangle; /** * Resizes the window to width and height. */ @@ -968,6 +1101,13 @@ declare namespace Electron { * @param callback Supplies the image that stores data of the snapshot. */ capturePage(rect: Rectangle, callback: (image: NativeImage) => void): void; + /** + * Captures the snapshot of page within rect, upon completion the callback + * will be called. Omitting the rect would capture the whole visible page. + * Note: Be sure to read documents on remote buffer in remote if you are going + * to use this API in renderer process. + * @param callback Supplies the image that stores data of the snapshot. + */ capturePage(callback: (image: NativeImage) => void): void; /** * Same as webContents.loadURL(url). @@ -990,7 +1130,13 @@ declare namespace Electron { * @param progress Valid range is [0, 1.0]. If < 0, the progress bar is removed. * If greater than 0, it becomes indeterminate. */ - setProgressBar(progress: number): void; + setProgressBar(progress: number, options?: { + /** + * Mode for the progress bar. + * Note: This is only implemented on Windows. + */ + mode: 'none' | 'normal' | 'indeterminate' | 'error' | 'paused' + }): void; /** * Sets a 16px overlay onto the current Taskbar icon, usually used to convey * some sort of application status or to passively notify the user. @@ -1014,8 +1160,23 @@ declare namespace Electron { * Add a thumbnail toolbar with a specified set of buttons to the thumbnail image * of a window in a taskbar button layout. * @returns Whether the thumbnail has been added successfully. + * + * Note: This API is available only on Windows. */ setThumbarButtons(buttons: ThumbarButton[]): boolean; + /** + * Sets the region of the window to show as the thumbnail image displayed when hovering + * over the window in the taskbar. You can reset the thumbnail to be the entire window + * by specifying an empty region: {x: 0, y: 0, width: 0, height: 0}. + * + * Note: This API is available only on Windows. + */ + setThumbnailClip(region: Rectangle): boolean; + /** + * Sets the toolTip that is displayed when hovering over the window thumbnail in the taskbar. + * Note: This API is available only on Windows. + */ + setThumbnailToolTip(toolTip: string): boolean; /** * Same as webContents.showDefinitionForSelection(). * Note: This API is available only on macOS. @@ -1258,12 +1419,17 @@ declare namespace Electron { defaultEncoding?: string; /** * Whether to throttle animations and timers when the page becomes background. - * Default: true + * Default: true. */ backgroundThrottling?: boolean; + /** + * Whether to enable offscreen rendering for the browser window. + * Default: false. + */ + offscreen?: boolean; } - interface BrowserWindowOptions extends Rectangle { + interface BrowserWindowOptions { /** * Window’s width in pixels. * Default: 800. @@ -1387,7 +1553,7 @@ declare namespace Electron { /** * The window icon, when omitted on Windows the executable’s icon would be used as window icon. */ - icon?: NativeImage | string; + icon?: NativeImage|string; /** * Whether window should be shown when created. * Default: true. @@ -1458,22 +1624,20 @@ declare namespace Electron { * The style of window title bar. */ titleBarStyle?: 'default' | 'hidden' | 'hidden-inset'; + /** + * Use WS_THICKFRAME style for frameless windows on Windows + */ + thickFrame?: boolean; /** * Settings of web page’s features. */ webPreferences?: WebPreferences; } - type BrowserWindowType = BrowserWindowTypeLinux | BrowserWindowTypeMac; + type BrowserWindowType = BrowserWindowTypeLinux | BrowserWindowTypeMac | BrowserWindowTypeWindows; type BrowserWindowTypeLinux = 'desktop' | 'dock' | 'toolbar' | 'splash' | 'notification'; type BrowserWindowTypeMac = 'desktop' | 'textured'; - - interface Rectangle { - x?: number; - y?: number; - width?: number; - height?: number; - } + type BrowserWindowTypeWindows = 'toolbar'; // https://github.com/electron/electron/blob/master/docs/api/clipboard.md @@ -1541,10 +1705,27 @@ declare namespace Electron { html?: string; image?: NativeImage; }, type?: ClipboardType): void; + /** + * @returns An Object containing title and url keys representing the bookmark in the clipboard. + * + * Note: This API is available on macOS and Windows. + */ + readBookmark(): Bookmark; + /** + * Writes the title and url into the clipboard as a bookmark. + * + * Note: This API is available on macOS and Windows. + */ + writeBookmark(title: string, url: string, type?: ClipboardType): void; } type ClipboardType = '' | 'selection'; + interface Bookmark { + title: string; + url: string; + } + // https://github.com/electron/electron/blob/master/docs/api/content-tracing.md /** @@ -1701,7 +1882,7 @@ declare namespace Electron { * An object you can define that will be sent along with the report. * Only string properties are sent correctly, nested objects are not supported. */ - extra?: { [prop: string]: string }; + extra?: {[prop: string]: string}; } interface CrashReport { @@ -1734,7 +1915,7 @@ declare namespace Electron { * The suggested size that thumbnail should be scaled. * Default: {width: 150, height: 150} */ - thumbnailSize?: Dimension; + thumbnailSize?: Size; } interface DesktopCapturerSource { @@ -1836,7 +2017,7 @@ declare namespace Electron { /** * Contains which features the dialog should use. */ - properties?: ('openFile' | 'openDirectory' | 'multiSelections' | 'createDirectory')[]; + properties?: ('openFile' | 'openDirectory' | 'multiSelections' | 'createDirectory' | 'showHiddenFiles')[]; } interface SaveDialogOptions { @@ -1920,6 +2101,11 @@ declare namespace Electron { * routine to determine the save path (Usually prompts a save dialog). */ setSavePath(path: string): void; + /** + * @returns The save path of the download item. + * This will be either the path set via downloadItem.setSavePath(path) or the path selected from the shown save dialog. + */ + getSavePath(): string; /** * Pauses the download. */ @@ -2125,8 +2311,8 @@ declare namespace Electron { } type MenuItemType = 'normal' | 'separator' | 'submenu' | 'checkbox' | 'radio'; - type MenuItemRole = 'undo' | 'redo' | 'cut' | 'copy' | 'paste' | 'pasteandmatchstyle' | 'selectall' | 'delete' | 'minimize' | 'close' | 'quit' | 'togglefullscreen'; - type MenuItemRoleMac = 'about' | 'hide' | 'hideothers' | 'unhide' | 'front' | 'zoom' | 'window' | 'help' | 'services'; + type MenuItemRole = 'undo' | 'redo' | 'cut' | 'copy' | 'paste' | 'pasteandmatchstyle' | 'selectall' | 'delete' | 'minimize' | 'close' | 'quit' | 'togglefullscreen' | 'resetzoom' | 'zoomin' | 'zoomout'; + type MenuItemRoleMac = 'about' | 'hide' | 'hideothers' | 'unhide' | 'startspeaking' | 'stopspeaking' | 'front' | 'zoom' | 'window' | 'help' | 'services'; interface MenuItemOptions { /** @@ -2192,7 +2378,7 @@ declare namespace Electron { * In Electron for the APIs that take images, you can pass either file paths * or NativeImage instances. When passing null, an empty image will be used. */ - icon?: NativeImage | string; + icon?: NativeImage|string; /** * If false, the menu item will be greyed out and unclickable. */ @@ -2209,7 +2395,7 @@ declare namespace Electron { * Should be specified for submenu type menu item, when it's specified the * type: 'submenu' can be omitted for the menu item */ - submenu?: Menu | MenuItemOptions[]; + submenu?: Menu|MenuItemOptions[]; /** * Unique within a single menu. If defined then it can be used as a reference * to this item by the position attribute. @@ -2270,7 +2456,7 @@ declare namespace Electron { * @param x Horizontal coordinate where the menu will be placed. * @param y Vertical coordinate where the menu will be placed. */ - popup(browserWindow?: BrowserWindow, x?: number, y?: number, select?: number): void; + popup(browserWindow?: BrowserWindow, x?: number, y?: number): void; /** * Appends the menuItem to the menu. */ @@ -2309,13 +2495,25 @@ declare namespace Electron { */ static createFromDataURL(dataURL: string): NativeImage; /** - * @returns Buffer Contains the image's PNG encoded data. + * @returns Buffer that contains the image's PNG encoded data. */ toPNG(): Buffer; /** - * @returns Buffer Contains the image's JPEG encoded data. + * @returns Buffer that contains the image's JPEG encoded data. */ toJPEG(quality: number): Buffer; + /** + * @returns Buffer that contains a copy of the image's raw bitmap pixel data. + */ + toBitmap(): Buffer; + /** + * @returns Buffer that contains the image's raw bitmap pixel data. + * + * The difference between getBitmap() and toBitmap() is, getBitmap() does not copy the bitmap data, + * so you have to use the returned Buffer immediately in current event loop tick, + * otherwise the data might be changed or destroyed. + */ + getBitmap(): Buffer; /** * @returns string The data URL of the image. */ @@ -2333,7 +2531,7 @@ declare namespace Electron { /** * @returns {} The size of the image. */ - getSize(): Dimension; + getSize(): Size; /** * Marks the image as template image. */ @@ -2556,10 +2754,10 @@ declare namespace Electron { * Unique identifier associated with the display. */ id: number; - bounds: Bounds; - workArea: Bounds; - size: Dimension; - workAreaSize: Dimension; + bounds: Rectangle; + workArea: Rectangle; + size: Size; + workAreaSize: Size; /** * Output device’s pixel scale factor. */ @@ -2571,23 +2769,6 @@ declare namespace Electron { touchSupport: 'available' | 'unavailable' | 'unknown'; } - type Bounds = { - x: number; - y: number; - width: number; - height: number; - } - - type Dimension = { - width: number; - height: number; - } - - type Point = { - x: number; - y: number; - } - type DisplayMetrics = 'bounds' | 'workArea' | 'scaleFactor' | 'rotation'; /** @@ -2627,7 +2808,7 @@ declare namespace Electron { /** * @returns The display that most closely intersects the provided bounds. */ - getDisplayMatching(rect: Bounds): Display; + getDisplayMatching(rect: Rectangle): Display; } // https://github.com/electron/electron/blob/master/docs/api/session.md @@ -2641,7 +2822,7 @@ declare namespace Electron { /** * @returns a new Session instance from partition string. */ - static fromPartition(partition: string): Session; + static fromPartition(partition: string, options?: FromPartitionOptions): Session; /** * @returns the default session object of the app. */ @@ -2680,7 +2861,7 @@ declare namespace Electron { /** * Sets the proxy settings. */ - setProxy(config: string, callback: Function): void; + setProxy(config: ProxyConfig, callback: Function): void; /** * Resolves the proxy information for url. */ @@ -2741,6 +2922,13 @@ declare namespace Electron { type Permission = 'media' | 'geolocation' | 'notifications' | 'midiSysex' | 'pointerLock' | 'fullscreen' | 'openExternal'; + interface FromPartitionOptions { + /** + * Whether to enable cache. + */ + cache?: boolean; + } + interface ClearStorageDataOptions { /** * Should follow window.location.origin’s representation scheme://host:port. @@ -2756,21 +2944,40 @@ declare namespace Electron { quotas?: ('temporary' | 'persistent' | 'syncable')[]; } + interface ProxyConfig { + /** + * The URL associated with the PAC file. + */ + pacScript: string; + /** + * Rules indicating which proxies to use. + */ + proxyRules: string; + /** + * Rules indicating which URLs should bypass the proxy settings. + */ + proxyBypassRules: string; + } + interface NetworkEmulationOptions { /** * Whether to emulate network outage. + * Default: false. */ offline?: boolean; /** * RTT in ms. + * Default: 0, which will disable latency throttling. */ latency?: number; /** * Download rate in Bps. + * Default: 0, which will disable download throttling. */ downloadThroughput?: number; /** * Upload rate in Bps. + * Default: 0, which will disable upload throttling. */ uploadThroughput?: number; } @@ -3116,6 +3323,62 @@ declare namespace Electron { * Play the beep sound. */ beep(): void; + /** + * Creates or updates a shortcut link at shortcutPath. + * + * Note: This API is available only on Windows. + */ + writeShortcutLink(shortcutPath: string, options: ShortcutLinkOptions): boolean; + /** + * Creates or updates a shortcut link at shortcutPath. + * + * Note: This API is available only on Windows. + */ + writeShortcutLink(shortcutPath: string, operation: 'create' | 'update' | 'replace', options: ShortcutLinkOptions): boolean; + /** + * Resolves the shortcut link at shortcutPath. + * An exception will be thrown when any error happens. + * + * Note: This API is available only on Windows. + */ + readShortcutLink(shortcutPath: string): ShortcutLinkOptions; + } + + interface ShortcutLinkOptions { + /** + * The target to launch from this shortcut. + */ + target: string; + /** + * The working directory. + * Default: empty. + */ + cwd?: string; + /** + * The arguments to be applied to target when launching from this shortcut. + * Default: empty. + */ + args?: string; + /** + * The description of the shortcut. + * Default: empty. + */ + description?: string; + /** + * The path to the icon, can be a DLL or EXE. icon and iconIndex have to be set together. + * Default: empty, which uses the target's icon. + */ + icon?: string; + /** + * The resource ID of icon when icon is a DLL or EXE. + * Default: 0. + */ + iconIndex?: number; + /** + * The Application User Model ID. + * Default: empty. + */ + appUserModelId?: string; } // https://github.com/electron/electron/blob/master/docs/api/system-preferences.md @@ -3130,6 +3393,26 @@ declare namespace Electron { * Note: This is only implemented on macOS. */ isDarkMode(): boolean; + /** + * @returns If the Swipe between pages setting is on. + * + * Note: This is only implemented on macOS. + */ + isSwipeTrackingFromScrollEventsEnabled(): boolean; + /** + * Posts event as native notifications of macOS. + * The userInfo contains the user information dictionary sent along with the notification. + * + * Note: This is only implemented on macOS. + */ + postNotification(event: string, userInfo: Object): void; + /** + * Posts event as native notifications of macOS. + * The userInfo contains the user information dictionary sent along with the notification. + * + * Note: This is only implemented on macOS. + */ + postLocalNotification(event: string, userInfo: Object): void; /** * Subscribes to native notifications of macOS, callback will be called when the corresponding event happens. * The id of the subscriber is returned, which can be used to unsubscribe the event. @@ -3177,17 +3460,17 @@ declare namespace Electron { * Emitted when the tray icon is clicked. * Note: The bounds payload is only implemented on macOS and Windows. */ - on(event: 'click', listener: (modifiers: Modifiers, bounds: Bounds) => void): this; + on(event: 'click', listener: (modifiers: Modifiers, bounds: Rectangle) => void): this; /** * Emitted when the tray icon is right clicked. * Note: This is only implemented on macOS and Windows. */ - on(event: 'right-click', listener: (modifiers: Modifiers, bounds: Bounds) => void): this; + on(event: 'right-click', listener: (modifiers: Modifiers, bounds: Rectangle) => void): this; /** * Emitted when the tray icon is double clicked. * Note: This is only implemented on macOS and Windows. */ - on(event: 'double-click', listener: (modifiers: Modifiers, bounds: Bounds) => void): this; + on(event: 'double-click', listener: (modifiers: Modifiers, bounds: Rectangle) => void): this; /** * Emitted when the tray balloon shows. * Note: This is only implemented on Windows. @@ -3213,6 +3496,11 @@ declare namespace Electron { * Note: This is only implemented on macOS */ on(event: 'drop-files', listener: (event: Event, files: string[]) => void): this; + /** + * Emitted when dragged text is dropped in the tray icon. + * Note: This is only implemented on macOS + */ + on(event: 'drop-text', listener: (event: Event, text: string) => void): this; /** * Emitted when a drag operation enters the tray icon. * Note: This is only implemented on macOS @@ -3232,7 +3520,7 @@ declare namespace Electron { /** * Creates a new tray icon associated with the image. */ - new (image: NativeImage | string): Tray; + new(image: NativeImage|string): Tray; /** * Destroys the tray icon immediately. */ @@ -3240,7 +3528,7 @@ declare namespace Electron { /** * Sets the image associated with this tray icon. */ - setImage(image: NativeImage | string): void; + setImage(image: NativeImage|string): void; /** * Sets the image associated with this tray icon when pressed. */ @@ -3255,10 +3543,10 @@ declare namespace Electron { */ setTitle(title: string): void; /** - * Sets whether the tray icon is highlighted when it is clicked. + * Sets when the tray's icon background becomes highlighted. * Note: This is only implemented on macOS. */ - setHighlightMode(highlight: boolean): void; + setHighlightMode(mode: 'selection' | 'always' | 'never'): void; /** * Displays a tray balloon. * Note: This is only implemented on Windows. @@ -3282,7 +3570,7 @@ declare namespace Electron { /** * @returns The bounds of this tray icon. */ - getBounds(): Bounds; + getBounds(): Rectangle; } interface Modifiers { @@ -3292,8 +3580,31 @@ declare namespace Electron { metaKey: boolean; } + interface DragItem { + /** + * The absolute path of the file to be dragged + */ + file: string; + /** + * The image showing under the cursor when dragging. + */ + icon: NativeImage; + } + // https://github.com/electron/electron/blob/master/docs/api/web-contents.md + interface WebContentsStatic { + /** + * @returns An array of all web contents. This will contain web contents for all windows, + * webviews, opened devtools, and devtools extension background pages. + */ + getAllWebContents(): WebContents[]; + /** + * @returns The web contents that is focused in this application, otherwise returns null. + */ + getFocusedWebContents(): WebContents; + } + /** * A WebContents is responsible for rendering and controlling a web page. */ @@ -3395,7 +3706,7 @@ declare namespace Electron { * navigation outside of the page. Examples of this occurring are when anchor links * are clicked or when the DOM hashchange event is triggered. */ - on(event: 'did-navigate-in-page', listener: (event: Event, url: string) => void): this; + on(event: 'did-navigate-in-page', listener: (event: Event, url: string, isMainFrame: boolean) => void): this; /** * Emitted when the renderer process has crashed. */ @@ -3472,9 +3783,9 @@ declare namespace Electron { /** * Emitted when the cursor’s type changes. * If the type parameter is custom, the image parameter will hold the custom cursor image - * in a NativeImage, and the scale will hold scaling information for the image. + * in a NativeImage, and scale, size and hotspot will hold additional information about the custom cursor. */ - on(event: 'cursor-changed', listener: (event: Event, type: CursorType, image?: NativeImage, scale?: number) => void): this; + on(event: 'cursor-changed', listener: (event: Event, type: CursorType, image?: NativeImage, scale?: number, size?: Size, hotspot?: Point) => void): this; /** * Emitted when there is a new context menu that needs to be handled. */ @@ -3487,6 +3798,10 @@ declare namespace Electron { * passing empty string to callback will cancel the request. */ on(event: 'select-bluetooth-device', listener: (event: Event, deviceList: BluetoothDevice[], callback: (deviceId: string) => void) => void): this; + /** + * Emitted when a new frame is generated. Only the dirty area is passed in the buffer. + */ + on(event: 'paint', listener: (event: Event, dirtyRect: Rectangle, image: NativeImage) => void): this; on(event: string, listener: Function): this; /** * Loads the url in the window. @@ -3597,47 +3912,74 @@ declare namespace Electron { */ isAudioMuted(): boolean; /** - * Executes Edit -> Undo command in page. + * Changes the zoom factor to the specified factor. + * Zoom factor is zoom percent divided by 100, so 300% = 3.0. + */ + setZoomFactor(factor: number): void; + /** + * Sends a request to get current zoom factor. + */ + getZoomFactor(callback: (zoomFactor: number) => void): void; + /** + * Changes the zoom level to the specified level. + * The original size is 0 and each increment above or below represents + * zooming 20% larger or smaller to default limits of 300% and 50% of original size, respectively. + */ + setZoomLevel(level: number): void; + /** + * Sends a request to get current zoom level. + */ + getZoomLevel(callback: (zoomLevel: number) => void): void; + /** + * Sets the maximum and minimum zoom level. + */ + setZoomLevelLimits(minimumLevel: number, maximumLevel: number): void; + /** + * Executes the editing command undo in web page. */ undo(): void; /** - * Executes Edit -> Redo command in page. + * Executes the editing command redo in web page. */ redo(): void; /** - * Executes Edit -> Cut command in page. + * Executes the editing command cut in web page. */ cut(): void; /** - * Executes Edit -> Copy command in page. + * Executes the editing command copy in web page. */ copy(): void; /** - * Executes Edit -> Paste command in page. + * Copy the image at the given position to the clipboard. + */ + copyImageAt(x: number, y: number): void; + /** + * Executes the editing command paste in web page. */ paste(): void; /** - * Executes Edit -> Paste and Match Style in page. + * Executes the editing command pasteAndMatchStyle in web page. */ pasteAndMatchStyle(): void; /** - * Executes Edit -> Delete command in page. + * Executes the editing command delete in web page. */ delete(): void; /** - * Executes Edit -> Select All command in page. + * Executes the editing command selectAll in web page. */ selectAll(): void; /** - * Executes Edit -> Unselect command in page. + * Executes the editing command unselect in web page. */ unselect(): void; /** - * Executes Edit -> Replace command in page. + * Executes the editing command replace in web page. */ replace(text: string): void; /** - * Executes Edit -> Replace Misspelling command in page. + * Executes the editing command replaceMisspelling in web page. */ replaceMisspelling(text: string): void; /** @@ -3739,16 +4081,12 @@ declare namespace Electron { * Begin subscribing for presentation events and captured frames, * The callback will be called when there is a presentation event. */ - beginFrameSubscription(callback: ( - /** - * The frameBuffer is a Buffer that contains raw pixel data. - * On most machines, the pixel data is effectively stored in 32bit BGRA format, - * but the actual representation depends on the endianness of the processor - * (most modern processors are little-endian, on machines with big-endian - * processors the data is in 32bit ARGB format). - */ - frameBuffer: Buffer - ) => void): void; + beginFrameSubscription(onlyDirty: boolean, callback: BeginFrameSubscriptionCallback): void; + /** + * Begin subscribing for presentation events and captured frames, + * The callback will be called when there is a presentation event. + */ + beginFrameSubscription(callback: BeginFrameSubscriptionCallback): void; /** * End subscribing for frame presentation events. */ @@ -3762,6 +4100,43 @@ declare namespace Electron { * Note: This API is available only on macOS. */ showDefinitionForSelection(): void; + /** + * @returns Whether offscreen rendering is enabled. + */ + isOffscreen(): boolean; + /** + * If offscreen rendering is enabled and not painting, start painting. + */ + startPainting(): void; + /** + * If offscreen rendering is enabled and painting, stop painting. + */ + stopPainting(): void; + /** + * If offscreen rendering is enabled returns whether it is currently painting. + */ + isPainting(): boolean; + /** + * If offscreen rendering is enabled sets the frame rate to the specified number. + * Only values between 1 and 60 are accepted. + */ + setFrameRate(fps: number): void; + /** + * If offscreen rendering is enabled returns the current frame rate. + */ + getFrameRate(): number; + /** + * Sets the item as dragging item for current drag-drop operation. + */ + startDrag(item: DragItem): void; + /** + * Captures a snapshot of the page within rect. + */ + capturePage(callback: (image: NativeImage) => void): void; + /** + * Captures a snapshot of the page within rect. + */ + capturePage(rect: Rectangle, callback: (image: NativeImage) => void): void; /** * @returns The unique ID of this WebContents. */ @@ -3786,6 +4161,24 @@ declare namespace Electron { debugger: Debugger; } + interface BeginFrameSubscriptionCallback { + ( + /** + * The frameBuffer is a Buffer that contains raw pixel data. + * On most machines, the pixel data is effectively stored in 32bit BGRA format, + * but the actual representation depends on the endianness of the processor + * (most modern processors are little-endian, on machines with big-endian + * processors the data is in 32bit ARGB format). + */ + frameBuffer: Buffer, + /** + * The dirtyRect is an object with x, y, width, height properties that describes which part of the page was repainted. + * If onlyDirty is set to true, frameBuffer will only contain the repainted area. onlyDirty defaults to false. + */ + dirtyRect?: Rectangle + ): void + } + interface ContextMenuParams { /** * x coordinate @@ -3825,76 +4218,76 @@ declare namespace Electron { */ mediaFlags: { /** - * Wether the media element has crashed. + * Whether the media element has crashed. */ inError: boolean; /** - * Wether the media element is paused. + * Whether the media element is paused. */ isPaused: boolean; /** - * Wether the media element is muted. + * Whether the media element is muted. */ isMuted: boolean; /** - * Wether the media element has audio. + * Whether the media element has audio. */ hasAudio: boolean; /** - * Wether the media element is looping. + * Whether the media element is looping. */ isLooping: boolean; /** - * Wether the media element's controls are visible. + * Whether the media element's controls are visible. */ isControlsVisible: boolean; /** - * Wether the media element's controls are toggleable. + * Whether the media element's controls are toggleable. */ canToggleControls: boolean; /** - * Wether the media element can be rotated. + * Whether the media element can be rotated. */ canRotate: boolean; } /** - * Wether the context menu was invoked on an image which has non-empty contents. + * Whether the context menu was invoked on an image which has non-empty contents. */ hasImageContents: boolean; /** - * Wether the context is editable. + * Whether the context is editable. */ isEditable: boolean; /** - * These flags indicate wether the renderer believes it is able to perform the corresponding action. + * These flags indicate whether the renderer believes it is able to perform the corresponding action. */ editFlags: { /** - * Wether the renderer believes it can undo. + * Whether the renderer believes it can undo. */ canUndo: boolean; /** - * Wether the renderer believes it can redo. + * Whether the renderer believes it can redo. */ canRedo: boolean; /** - * Wether the renderer believes it can cut. + * Whether the renderer believes it can cut. */ canCut: boolean; /** - * Wether the renderer believes it can copy + * Whether the renderer believes it can copy */ canCopy: boolean; /** - * Wether the renderer believes it can paste. + * Whether the renderer believes it can paste. */ canPaste: boolean; /** - * Wether the renderer believes it can delete. + * Whether the renderer believes it can delete. */ canDelete: boolean; /** - * Wether the renderer believes it can select all. + * Whether the renderer believes it can select all. */ canSelectAll: boolean; } @@ -3943,7 +4336,7 @@ declare namespace Electron { */ type StopFindInPageAtion = 'clearSelection' | 'keepSelection' | 'activateSelection'; - type CursorType = 'default' | 'crosshair' | 'pointer' | 'text' | 'wait' | 'help' | 'e-resize' | 'n-resize' | 'ne-resize' | 'nw-resize' | 's-resize' | 'se-resize' | 'sw-resize' | 'w-resize' | 'ns-resize' | 'ew-resize' | 'nesw-resize' | 'nwse-resize' | 'col-resize' | 'row-resize' | 'm-panning' | 'e-panning' | 'n-panning' | 'ne-panning' | 'nw-panning' | 's-panning' | 'se-panning' | 'sw-panning' | 'w-panning' | 'move' | 'vertical-text' | 'cell' | 'context-menu' | 'alias' | 'progress' | 'nodrop' | 'copy' | 'none' | 'not-allowed' | 'zoom-in' | 'zoom-out' | 'grab' | 'grabbing' | 'custom'; + type CursorType = 'default' | 'crosshair' | 'pointer' | 'text' | 'wait' | 'help' | 'e-resize' | 'n-resize' | 'ne-resize' | 'nw-resize' | 's-resize' | 'se-resize' | 'sw-resize' | 'w-resize' | 'ns-resize' | 'ew-resize' | 'nesw-resize' | 'nwse-resize' | 'col-resize' | 'row-resize' | 'm-panning' | 'e-panning' | 'n-panning' | 'ne-panning' | 'nw-panning' | 's-panning' | 'se-panning' |'sw-panning' | 'w-panning' | 'move' | 'vertical-text' | 'cell' | 'context-menu' | 'alias' | 'progress' | 'nodrop' | 'copy' | 'none' | 'not-allowed' | 'zoom-in' | 'zoom-out' | 'grab' | 'grabbing' | 'custom'; interface LoadURLOptions { /** @@ -3986,7 +4379,7 @@ declare namespace Electron { * Specify page size of the generated PDF. * Default: A4. */ - pageSize?: 'A3' | 'A4' | 'A5' | 'Legal' | 'Letter' | 'Tabloid' | Dimension; + pageSize?: 'A3' | 'A4' | 'A5' | 'Legal' | 'Letter' | 'Tabloid' | Size; /** * Whether to print CSS backgrounds. * Default: false. @@ -4006,10 +4399,33 @@ declare namespace Electron { interface Certificate { /** - * PEM encoded data + * PEM encoded data. + */ + data: string; + /** + * Issuer's Common Name. */ - data: Buffer; issuerName: string; + /** + * Subject's Common Name. + */ + subjectName: string; + /** + * Hex value represented string. + */ + serialNumber: string; + /** + * Start date of the certificate being valid in seconds. + */ + validStart: number; + /** + * End date of the certificate being valid in seconds. + */ + validExpiry: number; + /** + * Fingerprint of the certificate. + */ + fingerprint: string; } interface LoginRequest { @@ -4068,7 +4484,7 @@ declare namespace Electron { /** * Coordinates of first match region. */ - selectionArea?: Bounds; + selectionArea?: Rectangle; } interface DeviceEmulationParameters { @@ -4080,7 +4496,7 @@ declare namespace Electron { /** * Set the emulated screen size (screenPosition == mobile) */ - screenSize?: Dimension; + screenSize?: Size; /** * Position the view on the screen (screenPosition == mobile) * Default: {x: 0, y: 0} @@ -4094,7 +4510,7 @@ declare namespace Electron { /** * Set the emulated view size (empty means no override). */ - viewSize?: Dimension; + viewSize?: Size; /** * Whether emulated view should be scaled down if necessary to fit into available space * Default: false @@ -4139,7 +4555,7 @@ declare namespace Electron { wheelTicksY?: number; accelerationRatioX?: number; accelerationRatioY?: number; - hasPreciseScrollingDeltas?: number; + hasPreciseScrollingDeltas?: boolean; canScroll?: boolean; } @@ -4365,6 +4781,14 @@ declare namespace Electron { * @returns The title of guest page. */ getTitle(): string; + /** + * @returns Whether the web page is destroyed. + */ + isDestroyed(): boolean; + /** + * @returns Whether the web page is focused. + */ + isFocused(): boolean; /** * @returns Whether guest page is still loading resources. */ @@ -4416,7 +4840,7 @@ declare namespace Electron { /** * Navigates to the specified offset from the "current entry". */ - goToOffset(offset: boolean): void; + goToOffset(offset: number): void; /** * @returns Whether the renderer process has crashed. */ @@ -4556,6 +4980,14 @@ declare namespace Electron { * @returns The WebContents associated with this webview. */ getWebContents(): WebContents; + /** + * Captures a snapshot of the webview's page. Same as webContents.capturePage([rect, ]callback). + */ + capturePage(callback: (image: NativeImage) => void): void; + /** + * Captures a snapshot of the webview's page. Same as webContents.capturePage([rect, ]callback). + */ + capturePage(rect: Rectangle, callback: (image: NativeImage) => void): void; /** * Fired when a load has committed. This includes navigation within the current document * as well as subframe document-level loads, but does not include asynchronous resource loads. @@ -4634,14 +5066,14 @@ declare namespace Electron { * * Calling event.preventDefault() does NOT have any effect. */ - addEventListener(type: 'will-navigate', listener: (event: WebViewElement.NavigateEvent) => void, useCapture?: boolean): void; + addEventListener(type: 'will-navigate', listener: (event: WebViewElement.WillNavigateEvent) => void, useCapture?: boolean): void; /** * Emitted when a navigation is done. * * This event is not emitted for in-page navigations, such as clicking anchor links * or updating the window.location.hash. Use did-navigate-in-page event for this purpose. */ - addEventListener(type: 'did-navigate', listener: (event: WebViewElement.NavigateEvent) => void, useCapture?: boolean): void; + addEventListener(type: 'did-navigate', listener: (event: WebViewElement.DidNavigateEvent) => void, useCapture?: boolean): void; /** * Emitted when an in-page navigation happened. * @@ -4649,7 +5081,7 @@ declare namespace Electron { * navigation outside of the page. Examples of this occurring are when anchor links * are clicked or when the DOM hashchange event is triggered. */ - addEventListener(type: 'did-navigate-in-page', listener: (event: WebViewElement.NavigateEvent) => void, useCapture?: boolean): void; + addEventListener(type: 'did-navigate-in-page', listener: (event: WebViewElement.DidNavigateInPageEvent) => void, useCapture?: boolean): void; /** * Fired when the guest page attempts to close itself. */ @@ -4709,23 +5141,23 @@ declare namespace Electron { namespace WebViewElement { type Event = ElectronPrivate.GlobalEvent; - interface LoadCommitEvent extends Event { + interface LoadCommitEvent extends Event { url: string; isMainFrame: boolean; } - interface DidFailLoadEvent extends Event { + interface DidFailLoadEvent extends Event { errorCode: number; errorDescription: string; validatedURL: string; isMainFrame: boolean; } - interface DidFrameFinishLoadEvent extends Event { + interface DidFrameFinishLoadEvent extends Event { isMainFrame: boolean; } - interface DidGetResponseDetails extends Event { + interface DidGetResponseDetails extends Event { status: boolean; newURL: string; originalURL: string; @@ -4773,10 +5205,19 @@ declare namespace Electron { options: BrowserWindowOptions; } - interface NavigateEvent extends Event { + interface WillNavigateEvent extends Event { url: string; } + interface DidNavigateEvent extends Event { + url: string; + } + + interface DidNavigateInPageEvent extends Event { + url: string; + isMainFrame: boolean; + } + interface IpcMessageEvent extends Event { channel: string; args: any[]; @@ -4856,7 +5297,7 @@ declare namespace Electron { session: typeof Electron.Session; systemPreferences: Electron.SystemPreferences; Tray: Electron.Tray; - hideInternalModules(): void; + webContents: Electron.WebContentsStatic; } interface ElectronMainAndRenderer extends CommonElectron { @@ -4896,6 +5337,18 @@ interface File { // https://github.com/electron/electron/blob/master/docs/api/process.md declare namespace NodeJS { + + interface ProcessVersions { + /** + * Electron's version string. + */ + electron: string; + /** + * Chrome's version string. + */ + chrome: string; + } + interface Process { /** * Setting this to true can disable the support for asar archives in Node's built-in modules. diff --git a/src/vs/base/common/labels.ts b/src/vs/base/common/labels.ts index 96a51f345b1..3c37260ff8e 100644 --- a/src/vs/base/common/labels.ts +++ b/src/vs/base/common/labels.ts @@ -36,9 +36,13 @@ export class PathLabelProvider implements ILabelProvider { } } -export function getPathLabel(arg1: URI | string, arg2?: URI | string | IWorkspaceProvider): string { - let basepath = arg2 && getPath(arg2); - let absolutePath = getPath(arg1); +export function getPathLabel(resource: URI | string, basePathProvider?: URI | string | IWorkspaceProvider): string { + const absolutePath = getPath(resource); + if (!absolutePath) { + return null; + } + + const basepath = basePathProvider && getPath(basePathProvider); if (basepath && paths.isEqualOrParent(absolutePath, basepath)) { if (basepath === absolutePath) { @@ -48,7 +52,7 @@ export function getPathLabel(arg1: URI | string, arg2?: URI | string | IWorkspac return paths.normalize(strings.ltrim(absolutePath.substr(basepath.length), paths.nativeSep), true); } - if (platform.isWindows && absolutePath[1] === ':') { + if (platform.isWindows && absolutePath && absolutePath[1] === ':') { return paths.normalize(absolutePath.charAt(0).toUpperCase() + absolutePath.slice(1), true); } @@ -65,7 +69,7 @@ function getPath(arg1: URI | string | IWorkspaceProvider): string { } if (types.isFunction((arg1).getWorkspace)) { - let ws = (arg1).getWorkspace(); + const ws = (arg1).getWorkspace(); return ws ? ws.resource.fsPath : void 0; } diff --git a/src/vs/base/node/stdFork.ts b/src/vs/base/node/stdFork.ts index 3f5a4a3f7f3..4e20df2187e 100644 --- a/src/vs/base/node/stdFork.ts +++ b/src/vs/base/node/stdFork.ts @@ -49,7 +49,7 @@ function generatePatchedEnv(env:any, stdInPipeName:string, stdOutPipeName:string newEnv['STDIN_PIPE_NAME'] = stdInPipeName; newEnv['STDOUT_PIPE_NAME'] = stdOutPipeName; newEnv['STDERR_PIPE_NAME'] = stdErrPipeName; - newEnv['ATOM_SHELL_INTERNAL_RUN_AS_NODE'] = '1'; + newEnv['ELECTRON_RUN_AS_NODE'] = '1'; return newEnv; } diff --git a/src/vs/base/node/stdForkStart.js b/src/vs/base/node/stdForkStart.js index 0b1e7382fe5..92024acf6b8 100644 --- a/src/vs/base/node/stdForkStart.js +++ b/src/vs/base/node/stdForkStart.js @@ -33,7 +33,7 @@ var stdErrPipeName = process.env['STDERR_PIPE_NAME']; log('STDIN_PIPE_NAME: ' + stdInPipeName); log('STDOUT_PIPE_NAME: ' + stdOutPipeName); log('STDERR_PIPE_NAME: ' + stdErrPipeName); -log('ATOM_SHELL_INTERNAL_RUN_AS_NODE: ' + process.env['ATOM_SHELL_INTERNAL_RUN_AS_NODE']); +log('ELECTRON_RUN_AS_NODE: ' + process.env['ELECTRON_RUN_AS_NODE']); // stdout redirection to named pipe (function() { @@ -149,7 +149,7 @@ log('ATOM_SHELL_INTERNAL_RUN_AS_NODE: ' + process.env['ATOM_SHELL_INTERNAL_RUN_A delete process.env['STDIN_PIPE_NAME']; delete process.env['STDOUT_PIPE_NAME']; delete process.env['STDERR_PIPE_NAME']; - delete process.env['ATOM_SHELL_INTERNAL_RUN_AS_NODE']; + delete process.env['ELECTRON_RUN_AS_NODE']; require(program); diff --git a/src/vs/code/electron-main/main.ts b/src/vs/code/electron-main/main.ts index 0d0b3e365f0..e75241ab340 100644 --- a/src/vs/code/electron-main/main.ts +++ b/src/vs/code/electron-main/main.ts @@ -273,13 +273,13 @@ interface IEnv { function getUnixShellEnvironment(): TPromise { const promise = new TPromise((c, e) => { - const runAsNode = process.env['ATOM_SHELL_INTERNAL_RUN_AS_NODE']; + const runAsNode = process.env['ELECTRON_RUN_AS_NODE']; const noAttach = process.env['ELECTRON_NO_ATTACH_CONSOLE']; const mark = generateUuid().replace(/-/g, '').substr(0, 12); const regex = new RegExp(mark + '(.*)' + mark); const env = assign({}, process.env, { - ATOM_SHELL_INTERNAL_RUN_AS_NODE: '1', + ELECTRON_RUN_AS_NODE: '1', ELECTRON_NO_ATTACH_CONSOLE: '1' }); @@ -307,9 +307,9 @@ function getUnixShellEnvironment(): TPromise { const env = JSON.parse(rawStripped); if (runAsNode) { - env['ATOM_SHELL_INTERNAL_RUN_AS_NODE'] = runAsNode; + env['ELECTRON_RUN_AS_NODE'] = runAsNode; } else { - delete env['ATOM_SHELL_INTERNAL_RUN_AS_NODE']; + delete env['ELECTRON_RUN_AS_NODE']; } if (noAttach) { diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index b8bbfc60312..800d5554362 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -568,7 +568,7 @@ export class VSCodeWindow { return null; } - public getBounds(): Electron.Bounds { + public getBounds(): Electron.Rectangle { const pos = this.win.getPosition(); const dimension = this.win.getSize(); diff --git a/src/vs/code/node/cli.ts b/src/vs/code/node/cli.ts index 3a506b9d96a..18e6d60018c 100644 --- a/src/vs/code/node/cli.ts +++ b/src/vs/code/node/cli.ts @@ -31,7 +31,7 @@ export function main(argv: string[]): TPromise { if (args.help) { console.log(buildHelpMessage(product.nameLong, product.applicationName, pkg.version)); } else if (args.version) { - console.log(`${ pkg.version } (${ product.commit })`); + console.log(`${ pkg.version }\n${ product.commit }`); } else if (shouldSpawnCliProcess(args)) { const mainCli = new TPromise(c => require(['vs/code/node/cliProcessMain'], c)); return mainCli.then(cli => cli.main(args)); @@ -41,7 +41,7 @@ export function main(argv: string[]): TPromise { 'VSCODE_CLI': '1', 'ELECTRON_NO_ATTACH_CONSOLE': '1' }); - delete env['ATOM_SHELL_INTERNAL_RUN_AS_NODE']; + delete env['ELECTRON_RUN_AS_NODE']; let options = { detached: true, diff --git a/src/vs/editor/browser/viewParts/lineNumbers/lineNumbers.css b/src/vs/editor/browser/viewParts/lineNumbers/lineNumbers.css index 272e8c6fd1f..8bf1d15303d 100644 --- a/src/vs/editor/browser/viewParts/lineNumbers/lineNumbers.css +++ b/src/vs/editor/browser/viewParts/lineNumbers/lineNumbers.css @@ -12,7 +12,8 @@ cursor: default; } -.monaco-workbench .monaco-editor .margin-view-overlays .line-numbers { +/* disable until https://github.com/Microsoft/vscode/issues/8708 is fixed */ +/*.monaco-workbench .monaco-editor .margin-view-overlays .line-numbers { cursor: -webkit-image-set( url('flipped-cursor.svg') 1x, url('flipped-cursor-2x.svg') 2x @@ -24,7 +25,7 @@ url('flipped-cursor-mac.svg') 1x, url('flipped-cursor-mac-2x.svg') 2x ) 24 3, default; -} +}*/ .monaco-editor .margin-view-overlays .line-numbers.lh-odd { margin-top: 1px; diff --git a/src/vs/editor/contrib/find/browser/find.ts b/src/vs/editor/contrib/find/browser/find.ts index 6924b1dc3cf..06ddc371a85 100644 --- a/src/vs/editor/contrib/find/browser/find.ts +++ b/src/vs/editor/contrib/find/browser/find.ts @@ -25,7 +25,7 @@ class FindController extends CommonFindController implements IFindController { ) { super(editor, contextKeyService); - this._widget = this._register(new FindWidget(editor, this, this._state, contextViewService, keybindingService)); + this._widget = this._register(new FindWidget(editor, this, this._state, contextViewService, keybindingService, contextKeyService)); } protected _start(opts:IFindStartOptions): void { diff --git a/src/vs/editor/contrib/find/browser/findWidget.ts b/src/vs/editor/contrib/find/browser/findWidget.ts index ed0825ff8d9..bd692ce101e 100644 --- a/src/vs/editor/contrib/find/browser/findWidget.ts +++ b/src/vs/editor/contrib/find/browser/findWidget.ts @@ -22,6 +22,8 @@ import {ICodeEditor, IOverlayWidget, IOverlayWidgetPosition, OverlayWidgetPositi import {FIND_IDS, MATCHES_LIMIT} from 'vs/editor/contrib/find/common/findModel'; import {FindReplaceState, FindReplaceStateChangedEvent} from 'vs/editor/contrib/find/common/findState'; import {Range} from 'vs/editor/common/core/range'; +import {IContextKeyService, IContextKey} from 'vs/platform/contextkey/common/contextkey'; +import {CONTEXT_FIND_INPUT_FOCUSSED} from 'vs/editor/contrib/find/common/findController'; export interface IFindController { replace(): void; @@ -75,13 +77,15 @@ export class FindWidget extends Widget implements IOverlayWidget { private _isReplaceVisible: boolean; private _focusTracker: dom.IFocusTracker; + private _findInputFocussed: IContextKey; constructor( codeEditor: ICodeEditor, controller: IFindController, state: FindReplaceState, contextViewProvider: IContextViewProvider, - keybindingService: IKeybindingService + keybindingService: IKeybindingService, + contextKeyService: IContextKeyService ) { super(); this._codeEditor = codeEditor; @@ -112,8 +116,10 @@ export class FindWidget extends Widget implements IOverlayWidget { this._updateToggleSelectionFindButton(); } })); + this._findInputFocussed = CONTEXT_FIND_INPUT_FOCUSSED.bindTo(contextKeyService); this._focusTracker = this._register(dom.trackFocus(this._findInput.inputBox.inputElement)); this._focusTracker.addFocusListener(() => { + this._findInputFocussed.set(true); let selection = this._codeEditor.getSelection(); let currentMatch = this._state.currentMatch; if (selection.startLineNumber !== selection.endLineNumber) { @@ -123,6 +129,9 @@ export class FindWidget extends Widget implements IOverlayWidget { } } }); + this._focusTracker.addBlurListener(() => { + this._findInputFocussed.set(false); + }); this._codeEditor.addOverlayWidget(this); } diff --git a/src/vs/editor/contrib/find/common/findController.ts b/src/vs/editor/contrib/find/common/findController.ts index 8d0bd01fab0..4f3319fc4f3 100644 --- a/src/vs/editor/contrib/find/common/findController.ts +++ b/src/vs/editor/contrib/find/common/findController.ts @@ -14,7 +14,7 @@ import {Selection} from 'vs/editor/common/core/selection'; import * as strings from 'vs/base/common/strings'; import * as editorCommon from 'vs/editor/common/editorCommon'; import {editorAction, commonEditorContribution, ServicesAccessor, EditorAction, EditorCommand, CommonEditorRegistry} from 'vs/editor/common/editorCommonExtensions'; -import {FIND_IDS, FindModelBoundToEditorModel} from 'vs/editor/contrib/find/common/findModel'; +import {FIND_IDS, FindModelBoundToEditorModel, ToggleCaseSensitiveKeybinding, ToggleRegexKeybinding, ToggleWholeWordKeybinding, ShowPreviousFindTermKeybinding, ShowNextFindTermKeybinding} from 'vs/editor/contrib/find/common/findModel'; import {FindReplaceState, FindReplaceStateChangedEvent, INewFindReplaceState} from 'vs/editor/contrib/find/common/findState'; import {DocumentHighlightProviderRegistry} from 'vs/editor/common/modes'; import {RunOnceScheduler, Delayer} from 'vs/base/common/async'; @@ -36,6 +36,7 @@ export interface IFindStartOptions { export const CONTEXT_FIND_WIDGET_VISIBLE = new RawContextKey('findWidgetVisible', false); export const CONTEXT_FIND_WIDGET_NOT_VISIBLE: ContextKeyExpr = CONTEXT_FIND_WIDGET_VISIBLE.toNegated(); +export const CONTEXT_FIND_INPUT_FOCUSSED = new RawContextKey('findInputFocussed', false); export class CommonFindController extends Disposable implements editorCommon.IEditorContribution { @@ -920,8 +921,10 @@ CommonEditorRegistry.registerEditorCommand(new FindCommand({ kbOpts: { weight: CommonEditorRegistry.commandWeight(5), kbExpr: EditorContextKeys.Focus, - primary: KeyMod.Alt | KeyCode.KEY_C, - mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_C } + primary: ToggleCaseSensitiveKeybinding.primary, + mac: ToggleCaseSensitiveKeybinding.mac, + win: ToggleCaseSensitiveKeybinding.win, + linux: ToggleCaseSensitiveKeybinding.linux } })); @@ -932,8 +935,10 @@ CommonEditorRegistry.registerEditorCommand(new FindCommand({ kbOpts: { weight: CommonEditorRegistry.commandWeight(5), kbExpr: EditorContextKeys.Focus, - primary: KeyMod.Alt | KeyCode.KEY_W, - mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_W } + primary: ToggleWholeWordKeybinding.primary, + mac: ToggleWholeWordKeybinding.mac, + win: ToggleWholeWordKeybinding.win, + linux: ToggleWholeWordKeybinding.linux } })); @@ -944,8 +949,10 @@ CommonEditorRegistry.registerEditorCommand(new FindCommand({ kbOpts: { weight: CommonEditorRegistry.commandWeight(5), kbExpr: EditorContextKeys.Focus, - primary: KeyMod.Alt | KeyCode.KEY_R, - mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_R } + primary: ToggleRegexKeybinding.primary, + mac: ToggleRegexKeybinding.mac, + win: ToggleRegexKeybinding.win, + linux: ToggleRegexKeybinding.linux } })); @@ -988,8 +995,11 @@ CommonEditorRegistry.registerEditorCommand(new FindCommand({ handler: x => x.showPreviousFindTerm(), kbOpts: { weight: CommonEditorRegistry.commandWeight(5), - kbExpr: EditorContextKeys.Focus, - primary: KeyMod.Alt | KeyCode.UpArrow + kbExpr: ContextKeyExpr.and(CONTEXT_FIND_INPUT_FOCUSSED, EditorContextKeys.Focus), + primary: ShowPreviousFindTermKeybinding.primary, + mac: ShowPreviousFindTermKeybinding.mac, + win: ShowPreviousFindTermKeybinding.win, + linux: ShowPreviousFindTermKeybinding.linux } })); @@ -999,7 +1009,10 @@ CommonEditorRegistry.registerEditorCommand(new FindCommand({ handler: x => x.showNextFindTerm(), kbOpts: { weight: CommonEditorRegistry.commandWeight(5), - kbExpr: EditorContextKeys.Focus, - primary: KeyMod.Alt | KeyCode.DownArrow + kbExpr: ContextKeyExpr.and(CONTEXT_FIND_INPUT_FOCUSSED, EditorContextKeys.Focus), + primary: ShowNextFindTermKeybinding.primary, + mac: ShowNextFindTermKeybinding.mac, + win: ShowNextFindTermKeybinding.win, + linux: ShowNextFindTermKeybinding.linux } })); diff --git a/src/vs/editor/contrib/find/common/findModel.ts b/src/vs/editor/contrib/find/common/findModel.ts index 542e7c2234e..2a1e47da5ea 100644 --- a/src/vs/editor/contrib/find/common/findModel.ts +++ b/src/vs/editor/contrib/find/common/findModel.ts @@ -16,6 +16,27 @@ import {FindDecorations} from './findDecorations'; import {FindReplaceState, FindReplaceStateChangedEvent} from './findState'; import {ReplaceAllCommand} from './replaceAllCommand'; import {Selection} from 'vs/editor/common/core/selection'; +import {KeyCode, KeyMod} from 'vs/base/common/keyCodes'; +import {IKeybindings} from 'vs/platform/keybinding/common/keybinding'; + +export const ToggleCaseSensitiveKeybinding: IKeybindings = { + primary: KeyMod.Alt | KeyCode.KEY_C, + mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_C } +}; +export const ToggleWholeWordKeybinding: IKeybindings = { + primary: KeyMod.Alt | KeyCode.KEY_W, + mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_W } +}; +export const ToggleRegexKeybinding: IKeybindings = { + primary: KeyMod.Alt | KeyCode.KEY_R, + mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_R } +}; +export const ShowPreviousFindTermKeybinding: IKeybindings = { + primary: KeyMod.Alt | KeyCode.UpArrow +}; +export const ShowNextFindTermKeybinding: IKeybindings = { + primary: KeyMod.Alt | KeyCode.DownArrow +}; export const FIND_IDS = { StartFindAction: 'actions.find', @@ -43,16 +64,16 @@ export const MATCHES_LIMIT = 999; export class FindModelBoundToEditorModel { - private _editor:editorCommon.ICommonCodeEditor; - private _state:FindReplaceState; - private _toDispose:IDisposable[]; + private _editor: editorCommon.ICommonCodeEditor; + private _state: FindReplaceState; + private _toDispose: IDisposable[]; private _decorations: FindDecorations; - private _ignoreModelContentChanged:boolean; + private _ignoreModelContentChanged: boolean; - private _updateDecorationsScheduler:RunOnceScheduler; + private _updateDecorationsScheduler: RunOnceScheduler; private _isDisposed: boolean; - constructor(editor:editorCommon.ICommonCodeEditor, state:FindReplaceState) { + constructor(editor: editorCommon.ICommonCodeEditor, state: FindReplaceState) { this._editor = editor; this._state = state; this._toDispose = []; @@ -64,7 +85,7 @@ export class FindModelBoundToEditorModel { this._updateDecorationsScheduler = new RunOnceScheduler(() => this.research(false), 100); this._toDispose.push(this._updateDecorationsScheduler); - this._toDispose.push(this._editor.onDidChangeCursorPosition((e:editorCommon.ICursorPositionChangedEvent) => { + this._toDispose.push(this._editor.onDidChangeCursorPosition((e: editorCommon.ICursorPositionChangedEvent) => { if ( e.reason === editorCommon.CursorChangeReason.Explicit || e.reason === editorCommon.CursorChangeReason.Undo @@ -75,7 +96,7 @@ export class FindModelBoundToEditorModel { })); this._ignoreModelContentChanged = false; - this._toDispose.push(this._editor.onDidChangeModelRawContent((e:editorCommon.IModelContentChangedEvent) => { + this._toDispose.push(this._editor.onDidChangeModelRawContent((e: editorCommon.IModelContentChangedEvent) => { if (this._ignoreModelContentChanged) { return; } @@ -97,7 +118,7 @@ export class FindModelBoundToEditorModel { this._toDispose = dispose(this._toDispose); } - private _onStateChanged(e:FindReplaceStateChangedEvent): void { + private _onStateChanged(e: FindReplaceStateChangedEvent): void { if (this._isDisposed) { // The find model is disposed during a find state changed event return; @@ -111,8 +132,8 @@ export class FindModelBoundToEditorModel { } } - private static _getSearchRange(model:editorCommon.IModel, searchOnlyEditableRange:boolean, findScope:Range): Range { - let searchRange:Range; + private static _getSearchRange(model: editorCommon.IModel, searchOnlyEditableRange: boolean, findScope: Range): Range { + let searchRange: Range; if (searchOnlyEditableRange) { searchRange = model.getEditableRange(); @@ -128,7 +149,7 @@ export class FindModelBoundToEditorModel { return searchRange; } - private research(moveCursor:boolean, newFindScope?:Range): void { + private research(moveCursor: boolean, newFindScope?: Range): void { let findScope: Range = null; if (typeof newFindScope !== 'undefined') { findScope = newFindScope; @@ -169,7 +190,7 @@ export class FindModelBoundToEditorModel { return false; } - private _setCurrentFindMatch(match:Range): void { + private _setCurrentFindMatch(match: Range): void { let matchesPosition = this._decorations.setCurrentFindMatch(match); this._state.changeMatchInfo( matchesPosition, @@ -181,7 +202,7 @@ export class FindModelBoundToEditorModel { this._editor.revealRangeInCenterIfOutsideViewport(match); } - private _moveToPrevMatch(before:Position, isRecursed:boolean = false): void { + private _moveToPrevMatch(before: Position, isRecursed: boolean = false): void { if (this._cannotFind()) { return; } @@ -199,7 +220,7 @@ export class FindModelBoundToEditorModel { before = searchRange.getEndPosition(); } - let {lineNumber,column} = before; + let {lineNumber, column} = before; let model = this._editor.getModel(); let position = new Position(lineNumber, column); @@ -245,8 +266,8 @@ export class FindModelBoundToEditorModel { this._moveToPrevMatch(this._editor.getSelection().getStartPosition()); } - private _moveToNextMatch(nextMatch:Range): void - private _moveToNextMatch(after:Position): void + private _moveToNextMatch(nextMatch: Range): void + private _moveToNextMatch(after: Position): void private _moveToNextMatch(arg: any): void { let nextMatch = Range.isIRange(arg) ? arg : Position.isIPosition(arg) ? this._getNextMatch(arg) : null; if (nextMatch) { @@ -254,7 +275,7 @@ export class FindModelBoundToEditorModel { } } - private _getNextMatch(after:Position, isRecursed:boolean = false): Range { + private _getNextMatch(after: Position, isRecursed: boolean = false): Range { if (this._cannotFind()) { return null; } @@ -272,7 +293,7 @@ export class FindModelBoundToEditorModel { after = searchRange.getStartPosition(); } - let {lineNumber,column} = after; + let {lineNumber, column} = after; let model = this._editor.getModel(); let position = new Position(lineNumber, column); @@ -370,7 +391,7 @@ export class FindModelBoundToEditorModel { } } - private _findMatches(findScope: Range, limitResultCount:number): Range[] { + private _findMatches(findScope: Range, limitResultCount: number): Range[] { let searchRange = FindModelBoundToEditorModel._getSearchRange(this._editor.getModel(), this._state.isReplaceRevealed, findScope); return this._editor.getModel().findMatches(this._state.searchString, searchRange, this._state.isRegex, this._state.matchCase, this._state.wholeWord, limitResultCount); } @@ -385,7 +406,7 @@ export class FindModelBoundToEditorModel { // Get all the ranges (even more than the highlighted ones) let ranges = this._findMatches(findScope, Number.MAX_VALUE); - let replaceStrings:string[] = []; + let replaceStrings: string[] = []; for (let i = 0, len = ranges.length; i < len; i++) { replaceStrings.push(this.getReplaceString(ranges[i])); } @@ -409,7 +430,7 @@ export class FindModelBoundToEditorModel { this._editor.setSelections(ranges.map(r => new Selection(r.startLineNumber, r.startColumn, r.endLineNumber, r.endColumn))); } - private _executeEditorCommand(source:string, command:editorCommon.ICommand): void { + private _executeEditorCommand(source: string, command: editorCommon.ICommand): void { try { this._ignoreModelContentChanged = true; this._editor.executeCommand(source, command); diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 33044f955f6..6ac61419bc9 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -3498,9 +3498,10 @@ declare namespace vscode { * * @param name Optional human-readable string which will be used to represent the terminal in the UI. * @param shellPath Optional path to a custom shell executable to be used in the terminal. + * @param shellArgs Optional args for the custom shell executable, this does not work on Windows (see #8429) * @return A new Terminal. */ - export function createTerminal(name?: string, shellPath?: string): Terminal; + export function createTerminal(name?: string, shellPath?: string, shellArgs?: string[]): Terminal; } /** diff --git a/src/vs/workbench/api/node/extHost.api.impl.ts b/src/vs/workbench/api/node/extHost.api.impl.ts index 0533d77c825..8190d313b37 100644 --- a/src/vs/workbench/api/node/extHost.api.impl.ts +++ b/src/vs/workbench/api/node/extHost.api.impl.ts @@ -260,8 +260,8 @@ export class ExtHostAPIImplementation { createOutputChannel(name: string): vscode.OutputChannel { return extHostOutputService.createOutputChannel(name); }, - createTerminal(name?: string, shellPath?: string): vscode.Terminal { - return extHostTerminalService.createTerminal(name, shellPath); + createTerminal(name?: string, shellPath?: string, shellArgs?: string[]): vscode.Terminal { + return extHostTerminalService.createTerminal(name, shellPath, shellArgs); } }; diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index 287936c1410..1e10df02db2 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -153,7 +153,7 @@ export abstract class MainThreadOutputServiceShape { } export abstract class MainThreadTerminalServiceShape { - $createTerminal(name?: string, shellPath?: string): number { throw ni(); } + $createTerminal(name?: string, shellPath?: string, shellArgs?: string[]): TPromise { throw ni(); } $dispose(terminalId: number): void { throw ni(); } $hide(terminalId: number): void { throw ni(); } $sendText(terminalId: number, text: string, addNewLine: boolean): void { throw ni(); } diff --git a/src/vs/workbench/api/node/extHostTerminalService.ts b/src/vs/workbench/api/node/extHostTerminalService.ts index 74d0de54efa..2253748554b 100644 --- a/src/vs/workbench/api/node/extHostTerminalService.ts +++ b/src/vs/workbench/api/node/extHostTerminalService.ts @@ -10,18 +10,21 @@ import {MainContext, MainThreadTerminalServiceShape} from './extHost.protocol'; export class ExtHostTerminal implements vscode.Terminal { - public _name: string; - public _shellPath: string; - + private _name: string; private _id: number; private _proxy: MainThreadTerminalServiceShape; private _disposed: boolean; + private _queuedRequests: ApiRequest[] = []; - constructor(proxy: MainThreadTerminalServiceShape, id: number, name?: string, shellPath?: string) { + constructor(proxy: MainThreadTerminalServiceShape, name?: string, shellPath?: string, shellArgs?: string[]) { this._name = name; - this._shellPath = shellPath; this._proxy = proxy; - this._id = this._proxy.$createTerminal(name, shellPath); + this._proxy.$createTerminal(name, shellPath, shellArgs).then((id) => { + this._id = id; + this._queuedRequests.forEach((r) => { + r.run(this._proxy, this._id); + }); + }); } public get name(): string { @@ -31,26 +34,35 @@ export class ExtHostTerminal implements vscode.Terminal { public sendText(text: string, addNewLine: boolean = true): void { this._checkDisposed(); - this._proxy.$sendText(this._id, text, addNewLine); + this._queueApiRequest(this._proxy.$sendText, [text, addNewLine]); } public show(preserveFocus: boolean): void { this._checkDisposed(); - this._proxy.$show(this._id, preserveFocus); + this._queueApiRequest(this._proxy.$show, [preserveFocus]); } public hide(): void { this._checkDisposed(); - this._proxy.$hide(this._id); + this._queueApiRequest(this._proxy.$hide, []); } public dispose(): void { if (!this._disposed) { this._disposed = true; - this._proxy.$dispose(this._id); + this._queueApiRequest(this._proxy.$dispose, []); } } + private _queueApiRequest(callback: (...args: any[]) => void, args: any[]) { + let request: ApiRequest = new ApiRequest(callback, args); + if (!this._id) { + this._queuedRequests.push(request); + return; + } + request.run(this._proxy, this._id); + } + private _checkDisposed() { if (this._disposed) { throw new Error('Terminal has already been disposed'); @@ -66,7 +78,21 @@ export class ExtHostTerminalService { this._proxy = threadService.get(MainContext.MainThreadTerminalService); } - public createTerminal(name?: string, shellPath?: string): vscode.Terminal { - return new ExtHostTerminal(this._proxy, -1, name, shellPath); + public createTerminal(name?: string, shellPath?: string, shellArgs?: string[]): vscode.Terminal { + return new ExtHostTerminal(this._proxy, name, shellPath, shellArgs); } } + +class ApiRequest { + private _callback: (...args: any[]) => void; + private _args: any[]; + + constructor(callback: (...args: any[]) => void, args: any[]) { + this._callback = callback; + this._args = args; + } + + public run(proxy: MainThreadTerminalServiceShape, id: number) { + this._callback.apply(proxy, [id].concat(this._args)); + } +} \ No newline at end of file diff --git a/src/vs/workbench/api/node/mainThreadTerminalService.ts b/src/vs/workbench/api/node/mainThreadTerminalService.ts index 94d11f0aa92..6c9a57262ab 100644 --- a/src/vs/workbench/api/node/mainThreadTerminalService.ts +++ b/src/vs/workbench/api/node/mainThreadTerminalService.ts @@ -8,6 +8,7 @@ import {ITerminalService} from 'vs/workbench/parts/terminal/electron-browser/ter import {IPanelService} from 'vs/workbench/services/panel/common/panelService'; import {IPartService} from 'vs/workbench/services/part/common/partService'; import {MainThreadTerminalServiceShape} from './extHost.protocol'; +import {TPromise} from 'vs/base/common/winjs.base'; export class MainThreadTerminalService extends MainThreadTerminalServiceShape { @@ -19,8 +20,8 @@ export class MainThreadTerminalService extends MainThreadTerminalServiceShape { super(); } - public $createTerminal(name?: string, shellPath?: string): number { - return this.terminalService.createInstance(name, shellPath).id; + public $createTerminal(name?: string, shellPath?: string, shellArgs?: string[]): TPromise { + return TPromise.as(this.terminalService.createInstance(name, shellPath, shellArgs).id); } public $show(terminalId: number, preserveFocus: boolean): void { diff --git a/src/vs/workbench/browser/parts/editor/editorStatus.ts b/src/vs/workbench/browser/parts/editor/editorStatus.ts index 0324fd61340..a61faa1779b 100644 --- a/src/vs/workbench/browser/parts/editor/editorStatus.ts +++ b/src/vs/workbench/browser/parts/editor/editorStatus.ts @@ -662,9 +662,12 @@ export class ChangeModeAction extends Action { // All languages are valid picks const picks: IPickOpenEntry[] = languages.sort().map((lang, index) => { - return { + const languageModeId = this.modeService.getModeIdForLanguageName(lang.toLowerCase()); + const configureLabel = nls.localize('configuredLanguage', "Configured Language"); + + return { label: lang, - description: currentModeId === lang ? nls.localize('configuredLanguage', "Configured Language") : void 0 + description: currentModeId === lang ? `${languageModeId} (${configureLabel})` : languageModeId }; }); picks[0].separator = { border: true, label: nls.localize('languagesPicks', "languages") }; diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index d7f264091d7..2fc38e6fa79 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -607,7 +607,7 @@ export class DebugService implements debug.IDebugService { timeout: 1000 * 60 * 5, args: [`${ publisher }.${ type }`, JSON.stringify(data), aiKey], env: { - ATOM_SHELL_INTERNAL_RUN_AS_NODE: 1, + ELECTRON_RUN_AS_NODE: 1, PIPE_LOGGING: 'true', AMD_ENTRYPOINT: 'vs/workbench/parts/debug/node/telemetryApp' } diff --git a/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.ts b/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.ts index 1c19f36b60e..1786d1e0a9e 100644 --- a/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.ts +++ b/src/vs/workbench/parts/debug/electron-browser/rawDebugSession.ts @@ -25,6 +25,7 @@ import v8 = require('vs/workbench/parts/debug/node/v8Protocol'); import {IOutputService} from 'vs/workbench/parts/output/common/output'; import {ExtensionsChannelId} from 'vs/platform/extensionManagement/common/extensionManagement'; import {TerminalSupport} from 'vs/workbench/parts/debug/electron-browser/terminalSupport'; +import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; import {shell} from 'electron'; @@ -75,7 +76,8 @@ export class RawDebugSession extends v8.V8Protocol implements debug.IRawDebugSes @ITelemetryService private telemetryService: ITelemetryService, @IOutputService private outputService: IOutputService, @ITerminalService private terminalService: ITerminalService, - @IExternalTerminalService private nativeTerminalService: IExternalTerminalService + @IExternalTerminalService private nativeTerminalService: IExternalTerminalService, + @IConfigurationService private configurationService: IConfigurationService ) { super(); this.emittedStopped = false; @@ -348,7 +350,7 @@ export class RawDebugSession extends v8.V8Protocol implements debug.IRawDebugSes if (request.command === 'runInTerminal') { - TerminalSupport.runInTerminal(this.terminalService, this.nativeTerminalService, request.arguments, response).then(() => { + TerminalSupport.runInTerminal(this.terminalService, this.nativeTerminalService, this.configurationService, request.arguments, response).then(() => { this.sendResponse(response); }, e => { response.success = false; diff --git a/src/vs/workbench/parts/debug/electron-browser/terminalSupport.ts b/src/vs/workbench/parts/debug/electron-browser/terminalSupport.ts index 0abf4baf819..b8474a0018f 100644 --- a/src/vs/workbench/parts/debug/electron-browser/terminalSupport.ts +++ b/src/vs/workbench/parts/debug/electron-browser/terminalSupport.ts @@ -8,33 +8,40 @@ import platform = require('vs/base/common/platform'); import {TPromise} from 'vs/base/common/winjs.base'; import {ITerminalService, ITerminalInstance} from 'vs/workbench/parts/terminal/electron-browser/terminal'; import {ITerminalService as IExternalTerminalService} from 'vs/workbench/parts/execution/common/execution'; +import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; +export interface IIntegratedTerminalConfiguration { + terminal: { + integrated: { + shell: { + windows: string + } + } + }; +} + export class TerminalSupport { private static integratedTerminalInstance: ITerminalInstance; - public static runInTerminal(terminalService: ITerminalService, nativeTerminalService: IExternalTerminalService, args: DebugProtocol.RunInTerminalRequestArguments, response: DebugProtocol.RunInTerminalResponse): TPromise { + public static runInTerminal(terminalService: ITerminalService, nativeTerminalService: IExternalTerminalService, configurationService: IConfigurationService, args: DebugProtocol.RunInTerminalRequestArguments, response: DebugProtocol.RunInTerminalResponse): TPromise { if (args.kind === 'external') { return nativeTerminalService.runInTerminal(args.title, args.cwd, args.args, args.env); } - return this.runInIntegratedTerminal(terminalService, args); - } - - private static runInIntegratedTerminal(terminalService: ITerminalService, args: DebugProtocol.RunInTerminalRequestArguments): TPromise { if (!TerminalSupport.integratedTerminalInstance) { TerminalSupport.integratedTerminalInstance = terminalService.createInstance(args.title || nls.localize('debuggee', "debuggee")); } terminalService.setActiveInstance(TerminalSupport.integratedTerminalInstance); terminalService.showPanel(true); - const command = this.prepareCommand(args); + const command = this.prepareCommand(args, configurationService); TerminalSupport.integratedTerminalInstance.sendText(command, true); return TPromise.as(void 0); } - private static prepareCommand(args: DebugProtocol.RunInTerminalRequestArguments): string { + private static prepareCommand(args: DebugProtocol.RunInTerminalRequestArguments, configurationService: IConfigurationService): string { let command = ''; if (platform.isWindows) { @@ -44,21 +51,41 @@ export class TerminalSupport { return (s.indexOf(' ') >= 0 || s.indexOf('"') >= 0) ? `"${s}"` : s; }; - if (args.cwd) { - command += `cd ${quote(args.cwd)} && `; + const conf = configurationService.getConfiguration(); + + let isPowerShell = false; + if (conf.terminal && conf.terminal.integrated && conf.terminal.integrated.shell && conf.terminal.integrated.shell.windows) { + isPowerShell = conf.terminal.integrated.shell.windows.indexOf('PowerShell') >= 0; } - if (args.env) { - command += 'cmd /C "'; - for (let key in args.env) { - command += `set "${key}=${args.env[key]}" && `; + + if (isPowerShell) { + + if (args.cwd) { + command += `cd ${quote(args.cwd)}; `; + } + for (let a of args.args) { + command += `${quote(a)} `; + } + + } else { + + if (args.cwd) { + command += `cd ${quote(args.cwd)} && `; + } + if (args.env) { + command += 'cmd /C "'; + for (let key in args.env) { + command += `set "${key}=${args.env[key]}" && `; + } + } + for (let a of args.args) { + command += `${quote(a)} `; + } + if (args.env) { + command += '"'; } } - for (let a of args.args) { - command += `${quote(a)} `; - } - if (args.env) { - command += '"'; - } + } else { const quote = (s: string) => { s = s.replace(/\"/g, '\\"'); diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.ts index 195c970b017..ab5fab917dd 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionEditor.ts @@ -42,6 +42,7 @@ import { Keybinding } from 'vs/base/common/keyCodes'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement'; import { IMessageService } from 'vs/platform/message/common/message'; +import { IOpenerService } from 'vs/platform/opener/common/opener'; function renderBody(body: string): string { return ` @@ -140,7 +141,8 @@ export class ExtensionEditor extends BaseEditor { @IThemeService private themeService: IThemeService, @IWorkbenchEditorService private editorService: IWorkbenchEditorService, @IKeybindingService private keybindingService: IKeybindingService, - @IMessageService private messageService: IMessageService + @IMessageService private messageService: IMessageService, + @IOpenerService private openerService: IOpenerService ) { super(ExtensionEditor.ID, telemetryService); this._highlight = null; @@ -276,9 +278,9 @@ export class ExtensionEditor extends BaseEditor { webview.style(this.themeService.getColorTheme()); webview.contents = [body]; - const linkListener = webview.onDidClickLink(link => shell.openExternal(link.toString(true))); - const themeListener = this.themeService.onDidColorThemeChange(themeId => webview.style(themeId)); - this.contentDisposables.push(webview, linkListener, themeListener); + webview.onDidClickLink(link => this.openerService.open(link), null, this.contentDisposables); + this.themeService.onDidColorThemeChange(themeId => webview.style(themeId), null, this.contentDisposables); + this.contentDisposables.push(webview); }) .then(null, () => { const p = append(this.content, $('p')); diff --git a/src/vs/workbench/parts/files/browser/media/explorerviewlet.css b/src/vs/workbench/parts/files/browser/media/explorerviewlet.css index 5dbaac7ee5e..e0f99c3f6cd 100644 --- a/src/vs/workbench/parts/files/browser/media/explorerviewlet.css +++ b/src/vs/workbench/parts/files/browser/media/explorerviewlet.css @@ -15,6 +15,11 @@ line-height: 22px; } +.explorer-viewlet .explorer-item { + display: flex; /* this helps showing the overflow ellipsis (...) even though we use display:inline-block for the labels */ + flex-wrap: nowrap; +} + .explorer-viewlet .explorer-item-label, .explorer-viewlet .open-editor, .explorer-viewlet .editor-group { @@ -25,6 +30,7 @@ .explorer-viewlet .explorer-item-label, .explorer-viewlet .explorer-item .monaco-inputbox { display: inline-block; /* required for icons support :before rule */ + flex: 1; } .explorer-viewlet .explorer-open-editors .monaco-tree .monaco-tree-row > .content { diff --git a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts index 70e41699ed8..e80253e0029 100644 --- a/src/vs/workbench/parts/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/parts/files/browser/views/explorerViewer.ts @@ -398,19 +398,19 @@ export class FileRenderer extends ActionsRenderer implements IRenderer { const name = dotSegments[0]; // file.txt => "file", .dockerfile => "", file.some.txt => "file" if (name) { - classes.push(`${name.toLowerCase()}-name-file-icon`); + classes.push(`${this.cssEscape(name.toLowerCase())}-name-file-icon`); } const extensions = dotSegments.splice(1); if (extensions.length > 0) { for (let i = 0; i < extensions.length; i++) { - classes.push(`${extensions.slice(i).join('.').toLowerCase()}-ext-file-icon`); // add each combination of all found extensions if more than one + classes.push(`${this.cssEscape(extensions.slice(i).join('.').toLowerCase())}-ext-file-icon`); // add each combination of all found extensions if more than one } } const langId = this.modeService.getModeIdByFilenameOrFirstLine(fsPath); if (langId) { - classes.push(`${langId}-lang-file-icon`); + classes.push(`${this.cssEscape(langId)}-lang-file-icon`); } return classes; @@ -422,11 +422,15 @@ export class FileRenderer extends ActionsRenderer implements IRenderer { const classes = ['folder-icon']; if (basename) { - classes.push(`${basename.toLowerCase()}-name-folder-icon`); + classes.push(`${this.cssEscape(basename.toLowerCase())}-name-folder-icon`); } return classes; } + + private cssEscape(val: string): string { + return val.replace(/\s/g, '\\$&'); // make sure to not introduce CSS classes from files that contain whitespace + } } // Explorer Accessibility Provider diff --git a/src/vs/workbench/parts/git/electron-browser/electronGitService.ts b/src/vs/workbench/parts/git/electron-browser/electronGitService.ts index 59e84d0d967..fa51cb29a32 100644 --- a/src/vs/workbench/parts/git/electron-browser/electronGitService.ts +++ b/src/vs/workbench/parts/git/electron-browser/electronGitService.ts @@ -158,7 +158,7 @@ function createRemoteRawGitService(gitPath: string, execPath: string, workspaceR timeout: 1000 * 60, args: [path, workspaceRoot, encoding, execPath, version], env: { - ATOM_SHELL_INTERNAL_RUN_AS_NODE: 1, + ELECTRON_RUN_AS_NODE: 1, PIPE_LOGGING: 'true', AMD_ENTRYPOINT: 'vs/workbench/parts/git/node/gitApp', VERBOSE_LOGGING: String(verbose) diff --git a/src/vs/workbench/parts/search/browser/search.contribution.ts b/src/vs/workbench/parts/search/browser/search.contribution.ts index e5215a75ab6..9819545ae25 100644 --- a/src/vs/workbench/parts/search/browser/search.contribution.ts +++ b/src/vs/workbench/parts/search/browser/search.contribution.ts @@ -25,11 +25,12 @@ import {IKeybindings} from 'vs/platform/keybinding/common/keybinding'; import {IQuickOpenService} from 'vs/workbench/services/quickopen/common/quickOpenService'; import {IViewletService} from 'vs/workbench/services/viewlet/common/viewletService'; import {KeyMod, KeyCode} from 'vs/base/common/keyCodes'; -import {OpenSearchViewletAction, ReplaceInFilesAction, ShowNextSearchTermAction, ShowPreviousSearchTermAction, FocusNextInputAction, FocusPreviousInputAction} from 'vs/workbench/parts/search/browser/searchActions'; +import * as searchActions from 'vs/workbench/parts/search/browser/searchActions'; import * as Constants from 'vs/workbench/parts/search/common/constants'; import { registerContributions as replaceContributions } from 'vs/workbench/parts/search/browser/replaceContributions'; import { registerContributions as searchWidgetContributions } from 'vs/workbench/parts/search/browser/searchWidget'; import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; +import { ToggleCaseSensitiveKeybinding, ToggleRegexKeybinding, ToggleWholeWordKeybinding, ShowPreviousFindTermKeybinding, ShowNextFindTermKeybinding } from 'vs/editor/contrib/find/common/findModel'; replaceContributions(); searchWidgetContributions(); @@ -118,13 +119,13 @@ const openSearchViewletKb: IKeybindings = { }; (Registry.as(ActionExtensions.WorkbenchActions)).registerWorkbenchAction( - new SyncActionDescriptor(OpenSearchViewletAction, OpenSearchViewletAction.ID, OpenSearchViewletAction.LABEL, openSearchViewletKb), + new SyncActionDescriptor(searchActions.OpenSearchViewletAction, searchActions.OpenSearchViewletAction.ID, searchActions.OpenSearchViewletAction.LABEL, openSearchViewletKb), 'View: Show Search', nls.localize('view', "View") ); (Registry.as(ActionExtensions.WorkbenchActions)).registerWorkbenchAction( - new SyncActionDescriptor(ReplaceInFilesAction, ReplaceInFilesAction.ID, ReplaceInFilesAction.LABEL, { + new SyncActionDescriptor(searchActions.ReplaceInFilesAction, searchActions.ReplaceInFilesAction.ID, searchActions.ReplaceInFilesAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_H }), 'Replace in Files' @@ -165,22 +166,22 @@ registry.registerWorkbenchAction(new SyncActionDescriptor(ShowAllSymbolsAction, primary: KeyMod.CtrlCmd | KeyCode.KEY_T }), 'Show All Symbols'); -registry.registerWorkbenchAction(new SyncActionDescriptor(ShowNextSearchTermAction, ShowNextSearchTermAction.ID, ShowNextSearchTermAction.LABEL, { - primary: KeyMod.Alt | KeyCode.DownArrow -}, ContextKeyExpr.and(Constants.SearchViewletVisibleKey, Constants.SearchInputBoxFocussedKey)), ''); +registry.registerWorkbenchAction(new SyncActionDescriptor(searchActions.ShowNextSearchTermAction, searchActions.ShowNextSearchTermAction.ID, searchActions.ShowNextSearchTermAction.LABEL, ShowNextFindTermKeybinding, ContextKeyExpr.and(Constants.SearchViewletVisibleKey, Constants.SearchInputBoxFocussedKey)), ''); -registry.registerWorkbenchAction(new SyncActionDescriptor(ShowPreviousSearchTermAction, ShowPreviousSearchTermAction.ID, ShowPreviousSearchTermAction.LABEL, { - primary: KeyMod.Alt | KeyCode.UpArrow -}, ContextKeyExpr.and(Constants.SearchViewletVisibleKey, Constants.SearchInputBoxFocussedKey)), ''); +registry.registerWorkbenchAction(new SyncActionDescriptor(searchActions.ShowPreviousSearchTermAction, searchActions.ShowPreviousSearchTermAction.ID, searchActions.ShowPreviousSearchTermAction.LABEL, ShowPreviousFindTermKeybinding, ContextKeyExpr.and(Constants.SearchViewletVisibleKey, Constants.SearchInputBoxFocussedKey)), ''); -registry.registerWorkbenchAction(new SyncActionDescriptor(FocusNextInputAction, FocusNextInputAction.ID, FocusNextInputAction.LABEL, { +registry.registerWorkbenchAction(new SyncActionDescriptor(searchActions.FocusNextInputAction, searchActions.FocusNextInputAction.ID, searchActions.FocusNextInputAction.LABEL, { primary: KeyCode.DownArrow }, ContextKeyExpr.and(Constants.SearchViewletVisibleKey, Constants.InputBoxFocussedKey)), ''); -registry.registerWorkbenchAction(new SyncActionDescriptor(FocusPreviousInputAction, FocusPreviousInputAction.ID, FocusPreviousInputAction.LABEL, { +registry.registerWorkbenchAction(new SyncActionDescriptor(searchActions.FocusPreviousInputAction, searchActions.FocusPreviousInputAction.ID, searchActions.FocusPreviousInputAction.LABEL, { primary: KeyCode.UpArrow }, ContextKeyExpr.and(Constants.SearchViewletVisibleKey, Constants.InputBoxFocussedKey, Constants.SearchInputBoxFocussedKey.toNegated())), ''); +registry.registerWorkbenchAction(new SyncActionDescriptor(searchActions.ToggleCaseSensitiveAction, Constants.ToggleCaseSensitiveActionId, '', ToggleCaseSensitiveKeybinding, ContextKeyExpr.and(Constants.SearchViewletVisibleKey, Constants.SearchInputBoxFocussedKey)), ''); +registry.registerWorkbenchAction(new SyncActionDescriptor(searchActions.ToggleWholeWordAction, Constants.ToggleWholeWordActionId, '', ToggleWholeWordKeybinding, ContextKeyExpr.and(Constants.SearchViewletVisibleKey, Constants.SearchInputBoxFocussedKey)), ''); +registry.registerWorkbenchAction(new SyncActionDescriptor(searchActions.ToggleRegexAction, Constants.ToggleRegexActionId, '', ToggleRegexKeybinding, ContextKeyExpr.and(Constants.SearchViewletVisibleKey, Constants.SearchInputBoxFocussedKey)), ''); + // Configuration const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); configurationRegistry.registerConfiguration({ diff --git a/src/vs/workbench/parts/search/browser/searchActions.ts b/src/vs/workbench/parts/search/browser/searchActions.ts index a0660b81c59..ec7c97d3bb3 100644 --- a/src/vs/workbench/parts/search/browser/searchActions.ts +++ b/src/vs/workbench/parts/search/browser/searchActions.ts @@ -39,6 +39,45 @@ export function appendKeyBindingLabel(label: string, keyBinding: any, keyBinding return label + ' (' + keyBindingService2.getLabelFor(keyBinding) + ')'; } +export class ToggleCaseSensitiveAction extends Action { + + constructor(id: string, label: string, @IViewletService private viewletService: IViewletService) { + super(id, label); + } + + public run(): TPromise { + let searchViewlet = this.viewletService.getActiveViewlet(); + searchViewlet.toggleCaseSensitive(); + return TPromise.as(null); + } +} + +export class ToggleWholeWordAction extends Action { + + constructor(id: string, label: string, @IViewletService private viewletService: IViewletService) { + super(id, label); + } + + public run(): TPromise { + let searchViewlet = this.viewletService.getActiveViewlet(); + searchViewlet.toggleWholeWords(); + return TPromise.as(null); + } +} + +export class ToggleRegexAction extends Action { + + constructor(id: string, label: string, @IViewletService private viewletService: IViewletService) { + super(id, label); + } + + public run(): TPromise { + let searchViewlet = this.viewletService.getActiveViewlet(); + searchViewlet.toggleRegex(); + return TPromise.as(null); + } +} + export class ShowNextSearchTermAction extends Action { public static ID = 'search.history.showNext'; diff --git a/src/vs/workbench/parts/search/browser/searchViewlet.ts b/src/vs/workbench/parts/search/browser/searchViewlet.ts index d33bd665e66..9f251cce6af 100644 --- a/src/vs/workbench/parts/search/browser/searchViewlet.ts +++ b/src/vs/workbench/parts/search/browser/searchViewlet.ts @@ -617,6 +617,21 @@ export class SearchViewlet extends Viewlet { return dom.hasClass(this.queryDetails, 'more'); } + public toggleCaseSensitive(): void { + this.searchWidget.searchInput.setCaseSensitive(!this.searchWidget.searchInput.getCaseSensitive()); + this.onQueryChanged(true, true); + } + + public toggleWholeWords(): void { + this.searchWidget.searchInput.setWholeWords(!this.searchWidget.searchInput.getWholeWords()); + this.onQueryChanged(true, true); + } + + public toggleRegex(): void { + this.searchWidget.searchInput.setRegex(!this.searchWidget.searchInput.getRegex()); + this.onQueryChanged(true, true); + } + public toggleFileTypes(moveFocus?: boolean, show?: boolean, skipLayout?: boolean, reverse?: boolean): void { let cls = 'more'; show = typeof show === 'undefined' ? !dom.hasClass(this.queryDetails, cls) : Boolean(show); diff --git a/src/vs/workbench/parts/search/browser/searchWidget.ts b/src/vs/workbench/parts/search/browser/searchWidget.ts index b6827643e92..3b66bedd7b6 100644 --- a/src/vs/workbench/parts/search/browser/searchWidget.ts +++ b/src/vs/workbench/parts/search/browser/searchWidget.ts @@ -201,7 +201,10 @@ export class SearchWidget extends Widget { let inputOptions: IFindInputOptions = { label: nls.localize('label.Search', 'Search: Type Search Term and press Enter to search or Escape to cancel'), validation: (value: string) => this.validatSearchInput(value), - placeholder: nls.localize('search.placeHolder', "Search") + placeholder: nls.localize('search.placeHolder', "Search"), + appendCaseSensitiveLabel: appendKeyBindingLabel('', this.keyBindingService2.lookupKeybindings(Constants.ToggleCaseSensitiveActionId)[0], this.keyBindingService2), + appendWholeWordsLabel: appendKeyBindingLabel('', this.keyBindingService2.lookupKeybindings(Constants.ToggleWholeWordActionId)[0], this.keyBindingService2), + appendRegexLabel: appendKeyBindingLabel('', this.keyBindingService2.lookupKeybindings(Constants.ToggleRegexActionId)[0], this.keyBindingService2) }; let searchInputContainer= dom.append(parent, dom.$('.search-container.input-box')); @@ -350,7 +353,7 @@ export class SearchWidget extends Widget { export function registerContributions() { KeybindingsRegistry.registerCommandAndKeybindingRule({id: ReplaceAllAction.ID, weight: KeybindingsRegistry.WEIGHT.workbenchContrib(), - when: ContextKeyExpr.and(ContextKeyExpr.has('searchViewletVisible'), Constants.ReplaceActiveKey, CONTEXT_FIND_WIDGET_NOT_VISIBLE), + when: ContextKeyExpr.and(Constants.SearchViewletVisibleKey, Constants.ReplaceActiveKey, CONTEXT_FIND_WIDGET_NOT_VISIBLE), primary: KeyMod.Alt | KeyMod.CtrlCmd | KeyCode.Enter, handler: accessor => { if (isSearchViewletFocussed(accessor.get(IViewletService))) { diff --git a/src/vs/workbench/parts/search/common/constants.ts b/src/vs/workbench/parts/search/common/constants.ts index 94d8751d55f..678d59c02dd 100644 --- a/src/vs/workbench/parts/search/common/constants.ts +++ b/src/vs/workbench/parts/search/common/constants.ts @@ -7,6 +7,11 @@ import {RawContextKey} from 'vs/platform/contextkey/common/contextkey'; export const VIEWLET_ID = 'workbench.view.search'; +export const ToggleCaseSensitiveActionId = 'toggleSearchCaseSensitive'; +export const ToggleWholeWordActionId = 'toggleSearchWholeWord'; +export const ToggleRegexActionId = 'toggleSearchRegex'; + + export const SearchViewletVisibleKey = new RawContextKey('searchViewletVisible', true); export const InputBoxFocussedKey = new RawContextKey('inputBoxFocus', false); export const SearchInputBoxFocussedKey = new RawContextKey('searchInputBoxFocus', false); diff --git a/src/vs/workbench/parts/terminal/electron-browser/media/terminal.css b/src/vs/workbench/parts/terminal/electron-browser/media/terminal.css index 132831e836b..35c4f0f5188 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/media/terminal.css +++ b/src/vs/workbench/parts/terminal/electron-browser/media/terminal.css @@ -22,6 +22,7 @@ display: flex; padding: 0 20px; flex-grow: 1; + width: 100%; } .monaco-workbench .panel.integrated-terminal .terminal-wrapper { diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminal.ts b/src/vs/workbench/parts/terminal/electron-browser/terminal.ts index 794b7a2ce95..1c558a60f49 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminal.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminal.ts @@ -62,7 +62,7 @@ export interface ITerminalService { onInstanceTitleChanged: Event; terminalInstances: ITerminalInstance[]; - createInstance(name?: string, shellPath?: string): ITerminalInstance; + createInstance(name?: string, shellPath?: string, shellArgs?: string[]): ITerminalInstance; getInstanceFromId(terminalId: number): ITerminalInstance; getInstanceLabels(): string[]; getActiveInstance(): ITerminalInstance; diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts index 9f622245cae..1db5b02b6c5 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalActions.ts @@ -47,6 +47,9 @@ export class KillTerminalAction extends Action { let terminalInstance = this.terminalService.getActiveInstance(); if (terminalInstance) { this.terminalService.getActiveInstance().dispose(); + if (this.terminalService.terminalInstances.length > 0) { + this.terminalService.showPanel(true); + } } return TPromise.as(void 0); } diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts index f895e8ee838..47e7ac5cc06 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalInstance.ts @@ -38,6 +38,7 @@ export class TerminalInstance implements ITerminalInstance { public get onTitleChanged(): Event { return this._onTitleChanged.event; } private isExiting: boolean = false; + private isVisible: boolean = false; private toDispose: lifecycle.IDisposable[] = []; private skipTerminalKeybindings: Keybinding[] = []; private process: cp.ChildProcess; @@ -52,13 +53,13 @@ export class TerminalInstance implements ITerminalInstance { private container: HTMLElement, private workspace: IWorkspace, name: string, - shellPath: string, + shell: IShell, @IKeybindingService private keybindingService: IKeybindingService, @IMessageService private messageService: IMessageService ) { this._id = TerminalInstance.ID_COUNTER++; this._onTitleChanged = new Emitter(); - this.createProcess(workspace, name, shellPath); + this.createProcess(workspace, name, shell); if (container) { this.attachToElement(container); @@ -74,6 +75,7 @@ export class TerminalInstance implements ITerminalInstance { throw new Error('The terminal instance has already been attached to a container'); } + this.container = container; this.wrapperElement = document.createElement('div'); DOM.addClass(this.wrapperElement, 'terminal-wrapper'); this.xtermElement = document.createElement('div'); @@ -139,6 +141,7 @@ export class TerminalInstance implements ITerminalInstance { this.container.appendChild(this.wrapperElement); this.layout(new Dimension(this.container.offsetWidth, this.container.offsetHeight)); + this.setVisible(this.isVisible); } public copySelection(): void { @@ -195,7 +198,10 @@ export class TerminalInstance implements ITerminalInstance { } public setVisible(visible: boolean): void { - DOM.toggleClass(this.wrapperElement, 'active', visible); + this.isVisible = visible; + if (this.wrapperElement) { + DOM.toggleClass(this.wrapperElement, 'active', visible); + } } public scrollDown(): void { @@ -210,9 +216,11 @@ export class TerminalInstance implements ITerminalInstance { return typeof data === 'string' ? data.replace(TerminalInstance.EOL_REGEX, os.EOL) : data; } - private createProcess(workspace: IWorkspace, name?: string, shellPath?: string) { + private createProcess(workspace: IWorkspace, name: string, shell: IShell) { let locale = this.configHelper.isSetLocaleVariables() ? platform.locale : undefined; - let shell = shellPath ? { executable: shellPath, args: [] } : this.configHelper.getShell(); + if (!shell.executable) { + shell = this.configHelper.getShell(); + } let env = TerminalInstance.createTerminalEnv(process.env, shell, workspace, locale); this._title = name ? name : ''; this.process = cp.fork('./terminalProcess', [], { @@ -244,9 +252,11 @@ export class TerminalInstance implements ITerminalInstance { let env = TerminalInstance.cloneEnv(parentEnv); env['PTYPID'] = process.pid.toString(); env['PTYSHELL'] = shell.executable; - shell.args.forEach((arg, i) => { - env[`PTYSHELLARG${i}`] = arg; - }); + if (shell.args) { + shell.args.forEach((arg, i) => { + env[`PTYSHELLARG${i}`] = arg; + }); + } env['PTYCWD'] = TerminalInstance.sanitizeCwd(workspace ? workspace.resource.fsPath : os.homedir()); if (locale) { env['LANG'] = TerminalInstance.getLangEnvVariable(locale); diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts index 5a6b61185ad..333101d492d 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalPanel.ts @@ -72,6 +72,8 @@ export class TerminalPanel extends Panel { this.updateTheme(); this.updateConfig(); + // Force another layout (first is setContainers) since config has changed + this.layout(new Dimension(this.terminalContainer.offsetWidth, this.terminalContainer.offsetHeight)); return TPromise.as(void 0); } diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalProcess.js b/src/vs/workbench/parts/terminal/electron-browser/terminalProcess.js index 5b383f8f17b..9b38c52dd7f 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalProcess.js +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalProcess.js @@ -65,7 +65,7 @@ function getArgs() { function cleanEnv() { var keys = [ - 'ATOM_SHELL_INTERNAL_RUN_AS_NODE', + 'ELECTRON_RUN_AS_NODE', 'PTYCWD', 'PTYPID', 'PTYSHELL' diff --git a/src/vs/workbench/parts/terminal/electron-browser/terminalService.ts b/src/vs/workbench/parts/terminal/electron-browser/terminalService.ts index b9bc29f817d..5c91bb1ff06 100644 --- a/src/vs/workbench/parts/terminal/electron-browser/terminalService.ts +++ b/src/vs/workbench/parts/terminal/electron-browser/terminalService.ts @@ -14,7 +14,7 @@ import { IPartService } from 'vs/workbench/services/part/common/partService'; import { ITerminalInstance, ITerminalService, KEYBINDING_CONTEXT_TERMINAL_FOCUS, TERMINAL_PANEL_ID } from 'vs/workbench/parts/terminal/electron-browser/terminal'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { TPromise } from 'vs/base/common/winjs.base'; -import { TerminalConfigHelper } from 'vs/workbench/parts/terminal/electron-browser/terminalConfigHelper'; +import { TerminalConfigHelper, IShell } from 'vs/workbench/parts/terminal/electron-browser/terminalConfigHelper'; import { TerminalInstance } from 'vs/workbench/parts/terminal/electron-browser/terminalInstance'; export class TerminalService implements ITerminalService { @@ -51,7 +51,11 @@ export class TerminalService implements ITerminalService { this._configHelper = this.instantiationService.createInstance(TerminalConfigHelper, platform.platform); } - public createInstance(name?: string, shellPath?: string): ITerminalInstance { + public createInstance(name?: string, shellPath?: string, shellArgs?: string[]): ITerminalInstance { + let shell: IShell = { + executable: shellPath, + args: shellArgs + }; let terminalInstance = this.instantiationService.createInstance(TerminalInstance, this.terminalFocusContextKey, this.onTerminalInstanceDispose.bind(this), @@ -59,7 +63,7 @@ export class TerminalService implements ITerminalService { this.terminalContainer, this.workspaceContextService.getWorkspace(), name, - shellPath); + shell); terminalInstance.addDisposable(terminalInstance.onTitleChanged(this._onInstanceTitleChanged.fire, this._onInstanceTitleChanged)); this.terminalInstances.push(terminalInstance); if (this.terminalInstances.length === 1) { @@ -139,11 +143,11 @@ export class TerminalService implements ITerminalService { } public setContainers(panelContainer: Builder, terminalContainer: HTMLElement): void { + this._configHelper.panelContainer = panelContainer; this.terminalContainer = terminalContainer; this._terminalInstances.forEach(terminalInstance => { terminalInstance.attachToElement(this.terminalContainer); }); - this._configHelper.panelContainer = panelContainer; } public showPanel(focus?: boolean): TPromise { @@ -151,7 +155,6 @@ export class TerminalService implements ITerminalService { let panel = this.panelService.getActivePanel(); if (!panel || panel.getId() !== TERMINAL_PANEL_ID) { return this.panelService.openPanel(TERMINAL_PANEL_ID, focus).then(() => { - panel = this.panelService.getActivePanel(); if (focus) { this.getActiveInstance().focus(true); } diff --git a/src/vs/workbench/services/contextview/electron-browser/contextmenuService.ts b/src/vs/workbench/services/contextview/electron-browser/contextmenuService.ts index a5956e04643..d6a9ab0da6c 100644 --- a/src/vs/workbench/services/contextview/electron-browser/contextmenuService.ts +++ b/src/vs/workbench/services/contextview/electron-browser/contextmenuService.ts @@ -54,7 +54,7 @@ export class ContextMenuService implements IContextMenuService { x *= zoom; y *= zoom; - menu.popup(remote.getCurrentWindow(), Math.floor(x), Math.floor(y), -1 /* no item selected by default */); + menu.popup(remote.getCurrentWindow(), Math.floor(x), Math.floor(y)); if (delegate.onHide) { delegate.onHide(undefined); }