From 44f6ddd62aa2e878ac8d4743ccd771a4d4fdadf6 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 6 Jan 2016 09:34:41 +0100 Subject: [PATCH 1/9] TypeError: Cannot read property 'friendlyMessage' of null (fixes #1816) --- src/vs/workbench/electron-browser/shell.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/electron-browser/shell.ts b/src/vs/workbench/electron-browser/shell.ts index bdcbe6b01fd..5343088beb9 100644 --- a/src/vs/workbench/electron-browser/shell.ts +++ b/src/vs/workbench/electron-browser/shell.ts @@ -517,7 +517,7 @@ export class WorkbenchShell { console.error(errorMsg); // Show to user if friendly message provided - if (error.friendlyMessage && this.messageService) { + if (error && error.friendlyMessage && this.messageService) { this.messageService.show(Severity.Error, error.friendlyMessage); } } From 0d8b4f69f122d2b2d2ebb7d295d83b4d484258c2 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 6 Jan 2016 09:45:29 +0100 Subject: [PATCH 2/9] AutoSave setting is lost (fixes #1762) --- .../workbench/electron-browser/integration.ts | 16 ++++++- src/vs/workbench/electron-main/windows.ts | 48 +++++++++++++++++-- 2 files changed, 57 insertions(+), 7 deletions(-) diff --git a/src/vs/workbench/electron-browser/integration.ts b/src/vs/workbench/electron-browser/integration.ts index a34af0d9a39..a2b34c156ba 100644 --- a/src/vs/workbench/electron-browser/integration.ts +++ b/src/vs/workbench/electron-browser/integration.ts @@ -130,13 +130,25 @@ export class ElectronIntegration { ipc.on('vscode:showAutoSaveInfo', () => { this.messageService.show( Severity.Info, { - message: nls.localize('autoSaveInfo', "The **File | Auto Save** option moved into settings. Please configure **files.autoSaveDelay: 1** to restore the old behavior."), + message: nls.localize('autoSaveInfo', "The **File | Auto Save** option moved into settings and **files.autoSaveDelay: 1** will be added to preserve it."), actions: [ CloseAction, this.instantiationService.createInstance(OpenGlobalSettingsAction, OpenGlobalSettingsAction.ID, OpenGlobalSettingsAction.LABEL) ] - }); + }); }); + + ipc.on('vscode:showAutoSaveError', () => { + this.messageService.show( + Severity.Warning, { + message: nls.localize('autoSaveError', "Unable to write to settings. Please add **files.autoSaveDelay: 1** to settings.json."), + actions: [ + CloseAction, + this.instantiationService.createInstance(OpenGlobalSettingsAction, OpenGlobalSettingsAction.ID, OpenGlobalSettingsAction.LABEL) + ] + }); + }); + } private resolveKeybindings(actionIds: string[]): TPromise<{ id: string; binding: number; }[]> { diff --git a/src/vs/workbench/electron-main/windows.ts b/src/vs/workbench/electron-main/windows.ts index b174d2c82f2..06effaaba99 100644 --- a/src/vs/workbench/electron-main/windows.ts +++ b/src/vs/workbench/electron-main/windows.ts @@ -23,6 +23,7 @@ import window = require('vs/workbench/electron-main/window'); import lifecycle = require('vs/workbench/electron-main/lifecycle'); import nls = require('vs/nls'); import paths = require('vs/base/common/paths'); +import json = require('vs/base/common/json'); import arrays = require('vs/base/common/arrays'); import objects = require('vs/base/common/objects'); import storage = require('vs/workbench/electron-main/storage'); @@ -175,10 +176,7 @@ export class WindowsManager { eventEmitter.emit(EventTypes.READY, win); // TODO@Ben remove me in a couple of versions - if (storage.getItem('autoSaveDelay') === 1000) { - storage.removeItem('autoSaveDelay'); - win.send('vscode:showAutoSaveInfo'); - } + this.migrateAutoSave(win); } }); @@ -342,6 +340,46 @@ export class WindowsManager { }); } + private migrateAutoSave(win: window.VSCodeWindow): void { + if (storage.getItem('autoSaveDelay') === 1000) { + storage.removeItem('autoSaveDelay'); + win.send('vscode:showAutoSaveInfo'); + + try { + + // Initial settings file + if (!fs.existsSync(env.appSettingsPath)) { + fs.writeFileSync(env.appSettingsPath, JSON.stringify({ 'files.autoSaveDelay': 1 }, null, ' ')); + } + + // Update existing settings file + else { + const settingsRaw = fs.readFileSync(env.appSettingsPath).toString(); + const lastClosing = settingsRaw.lastIndexOf('}'); + const errors = []; + const res = json.parse(settingsRaw, errors); + + // We found a closing '}' and the JSON does not contain errors + if (lastClosing > 0 && !errors.length) { + const hasOtherKeys = Object.getOwnPropertyNames(res).length > 0; + + const migratedSettings = settingsRaw.substring(0, lastClosing) + '\n // Migrated from previous File | Auto Save setting:\n' + (hasOtherKeys ? ' , "files.autoSaveDelay": 1\n' : ' "files.autoSaveDelay": 1\n') + '}'; + + fs.writeFileSync(env.appSettingsPath, migratedSettings); + } + + // Otherwise inform user that we cannot migrate the settings + else { + win.send('vscode:showAutoSaveError'); + } + } + } catch (error) { + env.log(error); + win.send('vscode:showAutoSaveError'); + } + } + } + public reload(win: window.VSCodeWindow, cli?: env.ICommandLineArguments): void { // Only reload when the window has not vetoed this @@ -600,7 +638,7 @@ export class WindowsManager { recentPaths.unshift(workspacePath); } - // Clear those dupes + // Clear those dupes recentPaths = arrays.distinct(recentPaths); // Make sure it is bounded From b592ee4f1b5839ba3c900f81d0153c98244ff3ea Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 6 Jan 2016 09:48:46 +0100 Subject: [PATCH 3/9] Extract isFullWidthCharacter in strings.ts --- src/vs/base/common/strings.ts | 46 +++++++++++++++++++ .../characterHardWrappingLineMapper.ts | 45 +----------------- 2 files changed, 47 insertions(+), 44 deletions(-) diff --git a/src/vs/base/common/strings.ts b/src/vs/base/common/strings.ts index b3a9c91bd5e..b914a83c85f 100644 --- a/src/vs/base/common/strings.ts +++ b/src/vs/base/common/strings.ts @@ -417,6 +417,52 @@ export function commonSuffixLength(a: string, b: string): number { // return 0xDC00 <= chrCode && chrCode <= 0xDFFF; //} +export function isFullWidthCharacter(charCode:number): boolean { + // Do a cheap trick to better support wrapping of wide characters, treat them as 2 columns + // http://jrgraphix.net/research/unicode_blocks.php + // 2E80 — 2EFF CJK Radicals Supplement + // 2F00 — 2FDF Kangxi Radicals + // 2FF0 — 2FFF Ideographic Description Characters + // 3000 — 303F CJK Symbols and Punctuation + // 3040 — 309F Hiragana + // 30A0 — 30FF Katakana + // 3100 — 312F Bopomofo + // 3130 — 318F Hangul Compatibility Jamo + // 3190 — 319F Kanbun + // 31A0 — 31BF Bopomofo Extended + // 31F0 — 31FF Katakana Phonetic Extensions + // 3200 — 32FF Enclosed CJK Letters and Months + // 3300 — 33FF CJK Compatibility + // 3400 — 4DBF CJK Unified Ideographs Extension A + // 4DC0 — 4DFF Yijing Hexagram Symbols + // 4E00 — 9FFF CJK Unified Ideographs + // A000 — A48F Yi Syllables + // A490 — A4CF Yi Radicals + // AC00 — D7AF Hangul Syllables + // [IGNORE] D800 — DB7F High Surrogates + // [IGNORE] DB80 — DBFF High Private Use Surrogates + // [IGNORE] DC00 — DFFF Low Surrogates + // [IGNORE] E000 — F8FF Private Use Area + // F900 — FAFF CJK Compatibility Ideographs + // [IGNORE] FB00 — FB4F Alphabetic Presentation Forms + // [IGNORE] FB50 — FDFF Arabic Presentation Forms-A + // [IGNORE] FE00 — FE0F Variation Selectors + // [IGNORE] FE20 — FE2F Combining Half Marks + // [IGNORE] FE30 — FE4F CJK Compatibility Forms + // [IGNORE] FE50 — FE6F Small Form Variants + // [IGNORE] FE70 — FEFF Arabic Presentation Forms-B + // FF00 — FFEF Halfwidth and Fullwidth Forms + // [https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms] + // of which FF01 - FF5E fullwidth ASCII of 21 to 7E + // [IGNORE] and FF65 - FFDC halfwidth of Katakana and Hangul + // [IGNORE] FFF0 — FFFF Specials + return ( + (charCode >= 0x2E80 && charCode <= 0xD7AF) + || (charCode >= 0xF900 && charCode <= 0xFAFF) + || (charCode >= 0xFF01 && charCode <= 0xFF5E) + ); +} + /** * Computes the difference score for two strings. More similar strings have a higher score. * We use largest common subsequence dynamic programming approach but penalize in the end for length differences. diff --git a/src/vs/editor/common/viewModel/characterHardWrappingLineMapper.ts b/src/vs/editor/common/viewModel/characterHardWrappingLineMapper.ts index 258426bc5b9..14cc6c8a224 100644 --- a/src/vs/editor/common/viewModel/characterHardWrappingLineMapper.ts +++ b/src/vs/editor/common/viewModel/characterHardWrappingLineMapper.ts @@ -126,51 +126,8 @@ export class CharacterHardWrappingLineMapperFactory implements ILineMapperFactor niceBreakVisibleColumn = 0; } - // Do a cheap trick to better support wrapping of wide characters, treat them as 2 columns - // http://jrgraphix.net/research/unicode_blocks.php - // 2E80 — 2EFF CJK Radicals Supplement - // 2F00 — 2FDF Kangxi Radicals - // 2FF0 — 2FFF Ideographic Description Characters - // 3000 — 303F CJK Symbols and Punctuation - // 3040 — 309F Hiragana - // 30A0 — 30FF Katakana - // 3100 — 312F Bopomofo - // 3130 — 318F Hangul Compatibility Jamo - // 3190 — 319F Kanbun - // 31A0 — 31BF Bopomofo Extended - // 31F0 — 31FF Katakana Phonetic Extensions - // 3200 — 32FF Enclosed CJK Letters and Months - // 3300 — 33FF CJK Compatibility - // 3400 — 4DBF CJK Unified Ideographs Extension A - // 4DC0 — 4DFF Yijing Hexagram Symbols - // 4E00 — 9FFF CJK Unified Ideographs - // A000 — A48F Yi Syllables - // A490 — A4CF Yi Radicals - // AC00 — D7AF Hangul Syllables - // [IGNORE] D800 — DB7F High Surrogates - // [IGNORE] DB80 — DBFF High Private Use Surrogates - // [IGNORE] DC00 — DFFF Low Surrogates - // [IGNORE] E000 — F8FF Private Use Area - // F900 — FAFF CJK Compatibility Ideographs - // [IGNORE] FB00 — FB4F Alphabetic Presentation Forms - // [IGNORE] FB50 — FDFF Arabic Presentation Forms-A - // [IGNORE] FE00 — FE0F Variation Selectors - // [IGNORE] FE20 — FE2F Combining Half Marks - // [IGNORE] FE30 — FE4F CJK Compatibility Forms - // [IGNORE] FE50 — FE6F Small Form Variants - // [IGNORE] FE70 — FEFF Arabic Presentation Forms-B - // FF00 — FFEF Halfwidth and Fullwidth Forms - // [https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms] - // of which FF01 - FF5E fullwidth ASCII of 21 to 7E - // [IGNORE] and FF65 - FFDC halfwidth of Katakana and Hangul - // [IGNORE] FFF0 — FFFF Specials - var charColumnSize = 1; - if ( - (charCode >= 0x2E80 && charCode <= 0xD7AF) - || (charCode >= 0xF900 && charCode <= 0xFAFF) - || (charCode >= 0xFF01 && charCode <= 0xFF5E) - ) { + if (Strings.isFullWidthCharacter(charCode)) { charColumnSize = columnsForFullWidthChar; } From a585c0851626f5c3d59491a8198dbc33006ecc34 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 6 Jan 2016 09:54:24 +0100 Subject: [PATCH 4/9] Fixes #1811 --- .../electron-browser/pluginKeybindingService.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/services/keybinding/electron-browser/pluginKeybindingService.ts b/src/vs/workbench/services/keybinding/electron-browser/pluginKeybindingService.ts index 9a8e9eafb47..31b314bec2b 100644 --- a/src/vs/workbench/services/keybinding/electron-browser/pluginKeybindingService.ts +++ b/src/vs/workbench/services/keybinding/electron-browser/pluginKeybindingService.ts @@ -520,9 +520,12 @@ export default class PluginWorkbenchKeybindingService extends WorkbenchKeybindin } protected _invokeHandler(commandId: string, args: any): TPromise { - return this._pluginService.activateByEvent('onCommand:' + commandId).then(_ => { - return super._invokeHandler(commandId, args); - }); + if (this._pluginService) { + return this._pluginService.activateByEvent('onCommand:' + commandId).then(_ => { + return super._invokeHandler(commandId, args); + }); + } + return TPromise.as(null); } private _asCommandRule(isBuiltin: boolean, idx:number, binding: ContributedKeyBinding): ICommandRule { From 6ca1835c92d9e630fdba0ebe8d74a987e76914fc Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 6 Jan 2016 10:15:41 +0100 Subject: [PATCH 5/9] Extract code dealing with native-keymap in its own file --- .../electron-browser/nativeKeymap.ts | 416 +++++++++++++++++ .../pluginKeybindingService.ts | 419 +----------------- 2 files changed, 420 insertions(+), 415 deletions(-) create mode 100644 src/vs/workbench/services/keybinding/electron-browser/nativeKeymap.ts diff --git a/src/vs/workbench/services/keybinding/electron-browser/nativeKeymap.ts b/src/vs/workbench/services/keybinding/electron-browser/nativeKeymap.ts new file mode 100644 index 00000000000..2aa72ecf66d --- /dev/null +++ b/src/vs/workbench/services/keybinding/electron-browser/nativeKeymap.ts @@ -0,0 +1,416 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import * as nativeKeymap from 'native-keymap'; +import {KeyCode, Keybinding, IKeyBindingLabelProvider, MacUIKeyLabelProvider, ClassicUIKeyLabelProvider} from 'vs/base/common/keyCodes'; +import {lookupKeyCode, setExtractKeyCode} from 'vs/base/browser/keyboardEvent'; +import Platform = require('vs/base/common/platform'); + +let getNativeKeymap = (function() { + let called = false; + let result: nativeKeymap.INativeKeyMap[]; + + return function getNativeKeymap() { + if (!called) { + called = true; + result = nativeKeymap.getKeyMap(); + } + return result; + }; +})(); + +// See https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx +// See https://github.com/alexandrudima/vscode-keyboard/blob/master/deps/chromium/keyboard_codes_win.h +const NATIVE_KEY_CODE_TO_KEY_CODE: {[nativeKeyCode:string]:KeyCode;} = { + VKEY_BACK: KeyCode.Backspace, + VKEY_TAB: KeyCode.Tab, + VKEY_CLEAR: KeyCode.Unknown, // MISSING + VKEY_RETURN: KeyCode.Enter, + VKEY_SHIFT: KeyCode.Shift, + VKEY_CONTROL: KeyCode.Ctrl, + VKEY_MENU: KeyCode.Alt, + VKEY_PAUSE: KeyCode.PauseBreak, + VKEY_CAPITAL: KeyCode.CapsLock, + VKEY_KANA: KeyCode.Unknown, // MISSING + VKEY_HANGUL: KeyCode.Unknown, // MISSING + VKEY_JUNJA: KeyCode.Unknown, // MISSING + VKEY_FINAL: KeyCode.Unknown, // MISSING + VKEY_HANJA: KeyCode.Unknown, // MISSING + VKEY_KANJI: KeyCode.Unknown, // MISSING + VKEY_ESCAPE: KeyCode.Escape, + VKEY_CONVERT: KeyCode.Unknown, // MISSING + VKEY_NONCONVERT: KeyCode.Unknown, // MISSING + VKEY_ACCEPT: KeyCode.Unknown, // MISSING + VKEY_MODECHANGE: KeyCode.Unknown, // MISSING + VKEY_SPACE: KeyCode.Space, + VKEY_PRIOR: KeyCode.PageUp, + VKEY_NEXT: KeyCode.PageDown, + VKEY_END: KeyCode.End, + VKEY_HOME: KeyCode.Home, + VKEY_LEFT: KeyCode.LeftArrow, + VKEY_UP: KeyCode.UpArrow, + VKEY_RIGHT: KeyCode.RightArrow, + VKEY_DOWN: KeyCode.DownArrow, + VKEY_SELECT: KeyCode.Unknown, // MISSING + VKEY_PRINT: KeyCode.Unknown, // MISSING + VKEY_EXECUTE: KeyCode.Unknown, // MISSING + VKEY_SNAPSHOT: KeyCode.Unknown, // MISSING + VKEY_INSERT: KeyCode.Insert, + VKEY_DELETE: KeyCode.Delete, + VKEY_HELP: KeyCode.Unknown, // MISSING + VKEY_0: KeyCode.KEY_0, + VKEY_1: KeyCode.KEY_1, + VKEY_2: KeyCode.KEY_2, + VKEY_3: KeyCode.KEY_3, + VKEY_4: KeyCode.KEY_4, + VKEY_5: KeyCode.KEY_5, + VKEY_6: KeyCode.KEY_6, + VKEY_7: KeyCode.KEY_7, + VKEY_8: KeyCode.KEY_8, + VKEY_9: KeyCode.KEY_9, + VKEY_A: KeyCode.KEY_A, + VKEY_B: KeyCode.KEY_B, + VKEY_C: KeyCode.KEY_C, + VKEY_D: KeyCode.KEY_D, + VKEY_E: KeyCode.KEY_E, + VKEY_F: KeyCode.KEY_F, + VKEY_G: KeyCode.KEY_G, + VKEY_H: KeyCode.KEY_H, + VKEY_I: KeyCode.KEY_I, + VKEY_J: KeyCode.KEY_J, + VKEY_K: KeyCode.KEY_K, + VKEY_L: KeyCode.KEY_L, + VKEY_M: KeyCode.KEY_M, + VKEY_N: KeyCode.KEY_N, + VKEY_O: KeyCode.KEY_O, + VKEY_P: KeyCode.KEY_P, + VKEY_Q: KeyCode.KEY_Q, + VKEY_R: KeyCode.KEY_R, + VKEY_S: KeyCode.KEY_S, + VKEY_T: KeyCode.KEY_T, + VKEY_U: KeyCode.KEY_U, + VKEY_V: KeyCode.KEY_V, + VKEY_W: KeyCode.KEY_W, + VKEY_X: KeyCode.KEY_X, + VKEY_Y: KeyCode.KEY_Y, + VKEY_Z: KeyCode.KEY_Z, + VKEY_LWIN: KeyCode.Meta, + VKEY_COMMAND: KeyCode.Meta, + VKEY_RWIN: KeyCode.Meta, + VKEY_APPS: KeyCode.Unknown, // MISSING + VKEY_SLEEP: KeyCode.Unknown, // MISSING + VKEY_NUMPAD0: KeyCode.NUMPAD_0, + VKEY_NUMPAD1: KeyCode.NUMPAD_1, + VKEY_NUMPAD2: KeyCode.NUMPAD_2, + VKEY_NUMPAD3: KeyCode.NUMPAD_3, + VKEY_NUMPAD4: KeyCode.NUMPAD_4, + VKEY_NUMPAD5: KeyCode.NUMPAD_5, + VKEY_NUMPAD6: KeyCode.NUMPAD_6, + VKEY_NUMPAD7: KeyCode.NUMPAD_7, + VKEY_NUMPAD8: KeyCode.NUMPAD_8, + VKEY_NUMPAD9: KeyCode.NUMPAD_9, + VKEY_MULTIPLY: KeyCode.NUMPAD_MULTIPLY, + VKEY_ADD: KeyCode.NUMPAD_ADD, + VKEY_SEPARATOR: KeyCode.NUMPAD_SEPARATOR, + VKEY_SUBTRACT: KeyCode.NUMPAD_SUBTRACT, + VKEY_DECIMAL: KeyCode.NUMPAD_DECIMAL, + VKEY_DIVIDE: KeyCode.NUMPAD_DIVIDE, + VKEY_F1: KeyCode.F1, + VKEY_F2: KeyCode.F2, + VKEY_F3: KeyCode.F3, + VKEY_F4: KeyCode.F4, + VKEY_F5: KeyCode.F5, + VKEY_F6: KeyCode.F6, + VKEY_F7: KeyCode.F7, + VKEY_F8: KeyCode.F8, + VKEY_F9: KeyCode.F9, + VKEY_F10: KeyCode.F10, + VKEY_F11: KeyCode.F11, + VKEY_F12: KeyCode.F12, + VKEY_F13: KeyCode.F13, + VKEY_F14: KeyCode.F14, + VKEY_F15: KeyCode.F15, + VKEY_F16: KeyCode.F16, + VKEY_F17: KeyCode.F17, + VKEY_F18: KeyCode.F18, + VKEY_F19: KeyCode.F19, + VKEY_F20: KeyCode.Unknown, // MISSING + VKEY_F21: KeyCode.Unknown, // MISSING + VKEY_F22: KeyCode.Unknown, // MISSING + VKEY_F23: KeyCode.Unknown, // MISSING + VKEY_F24: KeyCode.Unknown, // MISSING + VKEY_NUMLOCK: KeyCode.NumLock, + VKEY_SCROLL: KeyCode.ScrollLock, + VKEY_LSHIFT: KeyCode.Shift, + VKEY_RSHIFT: KeyCode.Shift, + VKEY_LCONTROL: KeyCode.Ctrl, + VKEY_RCONTROL: KeyCode.Ctrl, + VKEY_LMENU: KeyCode.Unknown, // MISSING + VKEY_RMENU: KeyCode.Unknown, // MISSING + VKEY_BROWSER_BACK: KeyCode.Unknown, // MISSING + VKEY_BROWSER_FORWARD: KeyCode.Unknown, // MISSING + VKEY_BROWSER_REFRESH: KeyCode.Unknown, // MISSING + VKEY_BROWSER_STOP: KeyCode.Unknown, // MISSING + VKEY_BROWSER_SEARCH: KeyCode.Unknown, // MISSING + VKEY_BROWSER_FAVORITES: KeyCode.Unknown, // MISSING + VKEY_BROWSER_HOME: KeyCode.Unknown, // MISSING + VKEY_VOLUME_MUTE: KeyCode.Unknown, // MISSING + VKEY_VOLUME_DOWN: KeyCode.Unknown, // MISSING + VKEY_VOLUME_UP: KeyCode.Unknown, // MISSING + VKEY_MEDIA_NEXT_TRACK: KeyCode.Unknown, // MISSING + VKEY_MEDIA_PREV_TRACK: KeyCode.Unknown, // MISSING + VKEY_MEDIA_STOP: KeyCode.Unknown, // MISSING + VKEY_MEDIA_PLAY_PAUSE: KeyCode.Unknown, // MISSING + VKEY_MEDIA_LAUNCH_MAIL: KeyCode.Unknown, // MISSING + VKEY_MEDIA_LAUNCH_MEDIA_SELECT: KeyCode.Unknown, // MISSING + VKEY_MEDIA_LAUNCH_APP1: KeyCode.Unknown, // MISSING + VKEY_MEDIA_LAUNCH_APP2: KeyCode.Unknown, // MISSING + VKEY_OEM_1: KeyCode.US_SEMICOLON, + VKEY_OEM_PLUS: KeyCode.US_EQUAL, + VKEY_OEM_COMMA: KeyCode.US_COMMA, + VKEY_OEM_MINUS: KeyCode.US_MINUS, + VKEY_OEM_PERIOD: KeyCode.US_DOT, + VKEY_OEM_2: KeyCode.US_SLASH, + VKEY_OEM_3: KeyCode.US_BACKTICK, + VKEY_OEM_4: KeyCode.US_OPEN_SQUARE_BRACKET, + VKEY_OEM_5: KeyCode.US_BACKSLASH, + VKEY_OEM_6: KeyCode.US_CLOSE_SQUARE_BRACKET, + VKEY_OEM_7: KeyCode.US_QUOTE, + VKEY_OEM_8: KeyCode.Unknown, // MISSING + VKEY_OEM_102: KeyCode.Unknown, // MISSING + VKEY_PROCESSKEY: KeyCode.Unknown, // MISSING + VKEY_PACKET: KeyCode.Unknown, // MISSING + VKEY_DBE_SBCSCHAR: KeyCode.Unknown, // MISSING + VKEY_DBE_DBCSCHAR: KeyCode.Unknown, // MISSING + VKEY_ATTN: KeyCode.Unknown, // MISSING + VKEY_CRSEL: KeyCode.Unknown, // MISSING + VKEY_EXSEL: KeyCode.Unknown, // MISSING + VKEY_EREOF: KeyCode.Unknown, // MISSING + VKEY_PLAY: KeyCode.Unknown, // MISSING + VKEY_ZOOM: KeyCode.Unknown, // MISSING + VKEY_NONAME: KeyCode.Unknown, // MISSING + VKEY_PA1: KeyCode.Unknown, // MISSING + VKEY_OEM_CLEAR: KeyCode.Unknown, // MISSING + VKEY_UNKNOWN: KeyCode.Unknown, + + // Windows does not have a specific key code for AltGr. We use the unused + // VK_OEM_AX to represent AltGr, matching the behaviour of Firefox on Linux. + VKEY_ALTGR: KeyCode.Unknown, // MISSING +}; + +// See http://www.w3.org/TR/DOM-Level-3-Events/#h-optionally-fixed-virtual-key-codes +// See issue #1302: Chromium has implemented section B.2.4 of DOM Level 3 Events on mac +// This is bad news because we cannot trust the event's keyCode to be the actual pressed key. +// Here we try to find out the actual pressed key by "undoing" their massaging + +// Key Character Virtual Key Code +// Semicolon ';' 186 +// Colon ':' 186 +// Equals sign '=' 187 +// Plus '+' 187 +// Comma ',' 188 +// Less than sign '<' 188 +// Minus '-' 189 +// Underscore '_' 189 +// Period '.' 190 +// Greater than sign '>' 190 +// Forward slash '/' 191 +// Question mark '?' 191 +// Backtick '`' 192 +// Tilde '~' 192 +// Opening square bracket '[' 219 +// Opening curly brace '{' 219 +// Backslash '\' 220 +// Pipe '|' 220 +// Closing square bracket ']' 221 +// Closing curly brace '}' 221 +// Single quote ''' 222 +// Double quote '"' 222 + +interface IFixedVirtualKeyCodeElement { + char:string; + virtualKeyCode:number; +} + +let _b24_fixedVirtualKeyCodes: IFixedVirtualKeyCodeElement[] = [ + { char: ';', virtualKeyCode: 186 }, + { char: ':', virtualKeyCode: 186 }, + { char: '=', virtualKeyCode: 187 }, + { char: '+', virtualKeyCode: 187 }, + { char: ',', virtualKeyCode: 188 }, + { char: '<', virtualKeyCode: 188 }, + { char: '-', virtualKeyCode: 189 }, + { char: '_', virtualKeyCode: 189 }, + { char: '.', virtualKeyCode: 190 }, + { char: '>', virtualKeyCode: 190 }, + { char: '/', virtualKeyCode: 191 }, + { char: '?', virtualKeyCode: 191 }, + { char: '`', virtualKeyCode: 192 }, + { char: '~', virtualKeyCode: 192 }, + { char: '[', virtualKeyCode: 219 }, + { char: '{', virtualKeyCode: 219 }, + { char: '\\', virtualKeyCode: 220 }, + { char: '|', virtualKeyCode: 220 }, + { char: ']', virtualKeyCode: 221 }, + { char: '}', virtualKeyCode: 221 }, + { char: '\'', virtualKeyCode: 222 }, + { char: '"', virtualKeyCode: 222 }, +]; +let _b24_interestingChars: {[char:string]:boolean;} = Object.create(null); +_b24_fixedVirtualKeyCodes.forEach(el => _b24_interestingChars[el.char] = true); + +let _b24_interestingVirtualKeyCodes: {[virtualKeyCode:number]:boolean;} = Object.create(null); +_b24_fixedVirtualKeyCodes.forEach(el => _b24_interestingVirtualKeyCodes[el.virtualKeyCode] = true); + +interface IUnfixedVirtualKeyCodeMap { + [char:string]: KeyCode; +} +let _b24_getActualKeyCodeMap = (function() { + let result: IUnfixedVirtualKeyCodeMap = null; + return function() { + if (!result) { + result = Object.create(null); + + let nativeMappings = getNativeKeymap(); + + for (let i = 0, len = nativeMappings.length; i < len; i++) { + let nativeMapping = nativeMappings[i]; + + if (nativeMapping.value && _b24_interestingChars[nativeMapping.value]) { + // console.log(nativeMapping.value + " is made by " + nativeMapping.key_code); + let keyCode = NATIVE_KEY_CODE_TO_KEY_CODE[nativeMapping.key_code]; + if (keyCode && keyCode !== KeyCode.Unknown) { + if (!result[nativeMapping.value] || result[nativeMapping.value] > keyCode) { + result[nativeMapping.value] = keyCode; + } + } + } + + if (nativeMapping.withShift && _b24_interestingChars[nativeMapping.withShift]) { + // console.log(nativeMapping.withShift + " is made by " + nativeMapping.key_code); + let keyCode = NATIVE_KEY_CODE_TO_KEY_CODE[nativeMapping.key_code]; + if (keyCode && keyCode !== KeyCode.Unknown) { + if (!result[nativeMapping.withShift] || result[nativeMapping.withShift] > keyCode) { + result[nativeMapping.withShift] = keyCode; + } + } + } + } + } + return result; + }; +})(); + +setExtractKeyCode((e:KeyboardEvent) => { + if (e.charCode) { + // "keypress" events mostly + let char = String.fromCharCode(e.charCode).toUpperCase(); + return KeyCode.fromString(char); + } + + if (Platform.isMacintosh && _b24_interestingVirtualKeyCodes[e.keyCode] && typeof (e).keyIdentifier === 'string') { + let keyIdentifier:string = (e).keyIdentifier; + let strCharCode = keyIdentifier.substr(2); + try { + let charCode = parseInt(strCharCode, 16); + let char = String.fromCharCode(charCode); + let unfixMap = _b24_getActualKeyCodeMap(); + if (unfixMap[char]) { + return unfixMap[char]; + } + // console.log(keyIdentifier + ' => ' + char); + } catch(err) { + } + } + // _b24_getActualKeyCodeMap(); + // console.log('injected!!!'); + + return lookupKeyCode(e); +}); + +let nativeLabelProvider:IKeyBindingLabelProvider = null; +export function getNativeLabelProvider(): IKeyBindingLabelProvider { + if (!nativeLabelProvider) { + // See https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx + // See https://github.com/alexandrudima/vscode-keyboard/blob/master/deps/chromium/keyboard_codes_win.h + let interestingKeyCodes:{[vkeyCode:string]:boolean;} = { + VKEY_OEM_1: true, + VKEY_OEM_PLUS: true, + VKEY_OEM_COMMA: true, + VKEY_OEM_MINUS: true, + VKEY_OEM_PERIOD: true, + VKEY_OEM_2: true, + VKEY_OEM_3: true, + VKEY_OEM_4: true, + VKEY_OEM_5: true, + VKEY_OEM_6: true, + VKEY_OEM_7: true, + }; + + let remaps:string[] = []; + for (let i = 0, len = KeyCode.MAX_VALUE; i < len; i++) { + remaps[i] = null; + } + + let nativeMappings = getNativeKeymap(); + let hadRemap = false; + for (let i = 0, len = nativeMappings.length; i < len; i++) { + let nativeMapping = nativeMappings[i]; + + if (interestingKeyCodes[nativeMapping.key_code]) { + let newValue = nativeMapping.value || nativeMapping.withShift; + if (newValue.length > 0) { + hadRemap = true; + remaps[NATIVE_KEY_CODE_TO_KEY_CODE[nativeMapping.key_code]] = newValue; + } else { + // console.warn('invalid remap for ', nativeMapping); + } + } + } + + if (hadRemap) { + for (let interestingKeyCode in interestingKeyCodes) { + if (interestingKeyCodes.hasOwnProperty(interestingKeyCode)) { + let keyCode = NATIVE_KEY_CODE_TO_KEY_CODE[interestingKeyCode]; + remaps[keyCode] = remaps[keyCode] || ''; + } + } + } + + if (Platform.isMacintosh) { + nativeLabelProvider = new NativeMacUIKeyLabelProvider(remaps); + } else { + nativeLabelProvider = new NativeClassicUIKeyLabelProvider(remaps); + } + } + return nativeLabelProvider; +} + +class NativeMacUIKeyLabelProvider extends MacUIKeyLabelProvider { + constructor(private remaps:string[]) { + super(); + } + + public getLabelForKey(keyCode:KeyCode): string { + if (this.remaps[keyCode] !== null) { + return this.remaps[keyCode]; + } + return super.getLabelForKey(keyCode); + } +} + +class NativeClassicUIKeyLabelProvider extends ClassicUIKeyLabelProvider { + constructor(private remaps:string[]) { + super(); + } + + public getLabelForKey(keyCode:KeyCode): string { + if (this.remaps[keyCode] !== null) { + return this.remaps[keyCode]; + } + return super.getLabelForKey(keyCode); + } +} diff --git a/src/vs/workbench/services/keybinding/electron-browser/pluginKeybindingService.ts b/src/vs/workbench/services/keybinding/electron-browser/pluginKeybindingService.ts index 31b314bec2b..242f9835429 100644 --- a/src/vs/workbench/services/keybinding/electron-browser/pluginKeybindingService.ts +++ b/src/vs/workbench/services/keybinding/electron-browser/pluginKeybindingService.ts @@ -15,11 +15,10 @@ import {IOSupport} from 'vs/platform/keybinding/common/commonKeybindingResolver' import {WorkbenchKeybindingService} from 'vs/workbench/services/keybinding/browser/keybindingService'; import {ICommandRule, KeybindingsRegistry} from 'vs/platform/keybinding/common/keybindingsRegistry'; import {IJSONSchema} from 'vs/base/common/jsonSchema'; -import {KeyCode, Keybinding, IKeyBindingLabelProvider, MacUIKeyLabelProvider, ClassicUIKeyLabelProvider} from 'vs/base/common/keyCodes'; -import * as nativeKeymap from 'native-keymap'; +import {Keybinding, IKeyBindingLabelProvider} from 'vs/base/common/keyCodes'; import Platform = require('vs/base/common/platform'); import {IHTMLContentElement} from 'vs/base/common/htmlContent'; -import {lookupKeyCode, setExtractKeyCode} from 'vs/base/browser/keyboardEvent'; +import {getNativeLabelProvider} from 'vs/workbench/services/keybinding/electron-browser/nativeKeymap'; interface ContributedKeyBinding { command: string; @@ -108,327 +107,6 @@ let keybindingsExtPoint = PluginsRegistry.registerExtensionPoint' 190 -// Forward slash '/' 191 -// Question mark '?' 191 -// Backtick '`' 192 -// Tilde '~' 192 -// Opening square bracket '[' 219 -// Opening curly brace '{' 219 -// Backslash '\' 220 -// Pipe '|' 220 -// Closing square bracket ']' 221 -// Closing curly brace '}' 221 -// Single quote ''' 222 -// Double quote '"' 222 - -interface IFixedVirtualKeyCodeElement { - char:string; - virtualKeyCode:number; -} - -let _b24_fixedVirtualKeyCodes: IFixedVirtualKeyCodeElement[] = [ - { char: ';', virtualKeyCode: 186 }, - { char: ':', virtualKeyCode: 186 }, - { char: '=', virtualKeyCode: 187 }, - { char: '+', virtualKeyCode: 187 }, - { char: ',', virtualKeyCode: 188 }, - { char: '<', virtualKeyCode: 188 }, - { char: '-', virtualKeyCode: 189 }, - { char: '_', virtualKeyCode: 189 }, - { char: '.', virtualKeyCode: 190 }, - { char: '>', virtualKeyCode: 190 }, - { char: '/', virtualKeyCode: 191 }, - { char: '?', virtualKeyCode: 191 }, - { char: '`', virtualKeyCode: 192 }, - { char: '~', virtualKeyCode: 192 }, - { char: '[', virtualKeyCode: 219 }, - { char: '{', virtualKeyCode: 219 }, - { char: '\\', virtualKeyCode: 220 }, - { char: '|', virtualKeyCode: 220 }, - { char: ']', virtualKeyCode: 221 }, - { char: '}', virtualKeyCode: 221 }, - { char: '\'', virtualKeyCode: 222 }, - { char: '"', virtualKeyCode: 222 }, -]; -let _b24_interestingChars: {[char:string]:boolean;} = Object.create(null); -_b24_fixedVirtualKeyCodes.forEach(el => _b24_interestingChars[el.char] = true); - -let _b24_interestingVirtualKeyCodes: {[virtualKeyCode:number]:boolean;} = Object.create(null); -_b24_fixedVirtualKeyCodes.forEach(el => _b24_interestingVirtualKeyCodes[el.virtualKeyCode] = true); - -interface IUnfixedVirtualKeyCodeMap { - [char:string]: KeyCode; -} -let _b24_getActualKeyCodeMap = (function() { - let result: IUnfixedVirtualKeyCodeMap = null; - return function() { - if (!result) { - result = Object.create(null); - - let nativeMappings = getNativeKeymap(); - - for (let i = 0, len = nativeMappings.length; i < len; i++) { - let nativeMapping = nativeMappings[i]; - - if (nativeMapping.value && _b24_interestingChars[nativeMapping.value]) { - // console.log(nativeMapping.value + " is made by " + nativeMapping.key_code); - let keyCode = NATIVE_KEY_CODE_TO_KEY_CODE[nativeMapping.key_code]; - if (keyCode && keyCode !== KeyCode.Unknown) { - if (!result[nativeMapping.value] || result[nativeMapping.value] > keyCode) { - result[nativeMapping.value] = keyCode; - } - } - } - - if (nativeMapping.withShift && _b24_interestingChars[nativeMapping.withShift]) { - // console.log(nativeMapping.withShift + " is made by " + nativeMapping.key_code); - let keyCode = NATIVE_KEY_CODE_TO_KEY_CODE[nativeMapping.key_code]; - if (keyCode && keyCode !== KeyCode.Unknown) { - if (!result[nativeMapping.withShift] || result[nativeMapping.withShift] > keyCode) { - result[nativeMapping.withShift] = keyCode; - } - } - } - } - } - return result; - }; -})(); - -setExtractKeyCode((e:KeyboardEvent) => { - if (e.charCode) { - // "keypress" events mostly - let char = String.fromCharCode(e.charCode).toUpperCase(); - return KeyCode.fromString(char); - } - - if (Platform.isMacintosh && _b24_interestingVirtualKeyCodes[e.keyCode] && typeof (e).keyIdentifier === 'string') { - let keyIdentifier:string = (e).keyIdentifier; - let strCharCode = keyIdentifier.substr(2); - try { - let charCode = parseInt(strCharCode, 16); - let char = String.fromCharCode(charCode); - let unfixMap = _b24_getActualKeyCodeMap(); - if (unfixMap[char]) { - return unfixMap[char]; - } - // console.log(keyIdentifier + ' => ' + char); - } catch(err) { - } - } - // _b24_getActualKeyCodeMap(); - // console.log('injected!!!'); - - return lookupKeyCode(e); -}); export default class PluginWorkbenchKeybindingService extends WorkbenchKeybindingService { @@ -456,13 +134,11 @@ export default class PluginWorkbenchKeybindingService extends WorkbenchKeybindin } public getLabelFor(keybinding:Keybinding): string { - this._ensureNativeKeymap(); - return keybinding.toCustomLabel(this._nativeLabelProvider); + return keybinding.toCustomLabel(getNativeLabelProvider()); } public getHTMLLabelFor(keybinding:Keybinding): IHTMLContentElement[] { - this._ensureNativeKeymap(); - return keybinding.toCustomHTMLLabel(this._nativeLabelProvider); + return keybinding.toCustomHTMLLabel(getNativeLabelProvider()); } public getElectronAcceleratorFor(keybinding:Keybinding): string { @@ -555,91 +231,4 @@ export default class PluginWorkbenchKeybindingService extends WorkbenchKeybindin return desc; } - - private _gotNativeKeymap = false; - private _nativeLabelProvider:IKeyBindingLabelProvider = null; - private _ensureNativeKeymap(): void { - if (this._gotNativeKeymap) { - return; - } - this._gotNativeKeymap = true; - - // See https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx - // See https://github.com/alexandrudima/vscode-keyboard/blob/master/deps/chromium/keyboard_codes_win.h - let interestingKeyCodes:{[vkeyCode:string]:boolean;} = { - VKEY_OEM_1: true, - VKEY_OEM_PLUS: true, - VKEY_OEM_COMMA: true, - VKEY_OEM_MINUS: true, - VKEY_OEM_PERIOD: true, - VKEY_OEM_2: true, - VKEY_OEM_3: true, - VKEY_OEM_4: true, - VKEY_OEM_5: true, - VKEY_OEM_6: true, - VKEY_OEM_7: true, - }; - - let remaps:string[] = []; - for (let i = 0, len = KeyCode.MAX_VALUE; i < len; i++) { - remaps[i] = null; - } - - let nativeMappings = getNativeKeymap(); - let hadRemap = false; - for (let i = 0, len = nativeMappings.length; i < len; i++) { - let nativeMapping = nativeMappings[i]; - - if (interestingKeyCodes[nativeMapping.key_code]) { - let newValue = nativeMapping.value || nativeMapping.withShift; - if (newValue.length > 0) { - hadRemap = true; - remaps[NATIVE_KEY_CODE_TO_KEY_CODE[nativeMapping.key_code]] = newValue; - } else { - // console.warn('invalid remap for ', nativeMapping); - } - } - } - - if (hadRemap) { - for (let interestingKeyCode in interestingKeyCodes) { - if (interestingKeyCodes.hasOwnProperty(interestingKeyCode)) { - let keyCode = NATIVE_KEY_CODE_TO_KEY_CODE[interestingKeyCode]; - remaps[keyCode] = remaps[keyCode] || ''; - } - } - } - - if (Platform.isMacintosh) { - this._nativeLabelProvider = new NativeMacUIKeyLabelProvider(remaps); - } else { - this._nativeLabelProvider = new NativeClassicUIKeyLabelProvider(remaps); - } - } -} - -class NativeMacUIKeyLabelProvider extends MacUIKeyLabelProvider { - constructor(private remaps:string[]) { - super(); - } - - public getLabelForKey(keyCode:KeyCode): string { - if (this.remaps[keyCode] !== null) { - return this.remaps[keyCode]; - } - return super.getLabelForKey(keyCode); - } -} - -class NativeClassicUIKeyLabelProvider extends ClassicUIKeyLabelProvider { - constructor(private remaps:string[]) { - super(); - } - - public getLabelForKey(keyCode:KeyCode): string { - if (this.remaps[keyCode] !== null) { - return this.remaps[keyCode]; - } - return super.getLabelForKey(keyCode); - } } From f78180e124004464b15896d902feef07a596d42f Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 6 Jan 2016 10:33:37 +0100 Subject: [PATCH 6/9] Merge WorkbenchKeybindingService into PluginWorkbenchKeybindingService --- src/vs/workbench/electron-browser/shell.ts | 6 +- .../keybinding/browser/keybindingService.ts | 100 ------------------ ...bindingService.ts => keybindingService.ts} | 95 +++++++++++++++-- 3 files changed, 90 insertions(+), 111 deletions(-) delete mode 100644 src/vs/workbench/services/keybinding/browser/keybindingService.ts rename src/vs/workbench/services/keybinding/electron-browser/{pluginKeybindingService.ts => keybindingService.ts} (71%) diff --git a/src/vs/workbench/electron-browser/shell.ts b/src/vs/workbench/electron-browser/shell.ts index 5343088beb9..0bfba0af255 100644 --- a/src/vs/workbench/electron-browser/shell.ts +++ b/src/vs/workbench/electron-browser/shell.ts @@ -40,7 +40,7 @@ import {ConfigurationService} from 'vs/workbench/services/configuration/node/con import {FileService} from 'vs/workbench/services/files/electron-browser/fileService'; import {SearchService} from 'vs/workbench/services/search/node/searchService'; import {LifecycleService} from 'vs/workbench/services/lifecycle/electron-browser/lifecycleService'; -import PluginWorkbenchKeybindingService from 'vs/workbench/services/keybinding/electron-browser/pluginKeybindingService'; +import {WorkbenchKeybindingService} from 'vs/workbench/services/keybinding/electron-browser/keybindingService'; import {MainThreadService} from 'vs/workbench/services/thread/electron-browser/threadService'; import {MarkerService} from 'vs/platform/markers/common/markerService'; import {IActionsService} from 'vs/platform/actions/common/actions'; @@ -164,7 +164,7 @@ export class WorkbenchShell { private themeService: IThemeService; private contextService: WorkspaceContextService; private telemetryService: ElectronTelemetryService; - private keybindingService: PluginWorkbenchKeybindingService; + private keybindingService: WorkbenchKeybindingService; private container: HTMLElement; private toUnbind: { (): void; }[]; @@ -275,7 +275,7 @@ export class WorkbenchShell { let enableTelemetry = this.configuration.env.isBuilt && !this.configuration.env.pluginDevelopmentPath ? !!this.configuration.env.enableTelemetry : false; this.telemetryService = new ElectronTelemetryService(this.storageService, { enableTelemetry: enableTelemetry, version: this.configuration.env.version, commitHash: this.configuration.env.commitHash }); - this.keybindingService = new PluginWorkbenchKeybindingService(this.contextService, eventService, this.telemetryService, window); + this.keybindingService = new WorkbenchKeybindingService(this.contextService, eventService, this.telemetryService, window); this.messageService = new MessageService(this.contextService, this.windowService, this.telemetryService, this.keybindingService); this.keybindingService.setMessageService(this.messageService); diff --git a/src/vs/workbench/services/keybinding/browser/keybindingService.ts b/src/vs/workbench/services/keybinding/browser/keybindingService.ts deleted file mode 100644 index 5de1bb2f1a5..00000000000 --- a/src/vs/workbench/services/keybinding/browser/keybindingService.ts +++ /dev/null @@ -1,100 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -'use strict'; - -import nls = require('vs/nls'); -import {Registry} from 'vs/platform/platform'; -import {KeybindingService} from 'vs/platform/keybinding/browser/keybindingServiceImpl'; -import {OptionsChangeEvent, EventType} from 'vs/workbench/common/events'; -import {IEventService} from 'vs/platform/event/common/event'; -import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; -import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; -import {IKeybindingItem, IUserFriendlyKeybinding} from 'vs/platform/keybinding/common/keybindingService'; -import {IOSupport} from 'vs/platform/keybinding/common/commonKeybindingResolver'; -import * as JSONContributionRegistry from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; -import {IJSONSchema} from 'vs/base/common/jsonSchema'; - -export abstract class WorkbenchKeybindingService extends KeybindingService { - private contextService: IWorkspaceContextService; - private eventService: IEventService; - private telemetryService: ITelemetryService; - private toDispose: Function; - - constructor(contextService: IWorkspaceContextService, eventService: IEventService, telemetryService: ITelemetryService, domNode: HTMLElement) { - this.contextService = contextService; - super(domNode); - this.eventService = eventService; - this.telemetryService = telemetryService; - this.toDispose = this.eventService.addListener(EventType.WORKBENCH_OPTIONS_CHANGED, (e) => this.onOptionsChanged(e)); - } - - public customKeybindingsCount(): number { - let opts = this.contextService.getOptions(); - if (opts.globalSettings && opts.globalSettings.keybindings && Array.isArray(opts.globalSettings.keybindings)) { - return opts.globalSettings.keybindings.length; - } - return 0; - } - - protected _getExtraKeybindings(isFirstTime: boolean): IKeybindingItem[] { - let extras: IUserFriendlyKeybinding[] = []; - let opts = this.contextService.getOptions(); - if (opts.globalSettings && opts.globalSettings.keybindings) { - if (!isFirstTime) { - let cnt = 0; - if (Array.isArray(opts.globalSettings.keybindings)) { - cnt = opts.globalSettings.keybindings.length; - } - this.telemetryService.publicLog('customKeybindingsChanged', { - keyCount: cnt - }); - } - if (Array.isArray(opts.globalSettings.keybindings)) { - extras = opts.globalSettings.keybindings; - } - } - return extras.map((k, i) => IOSupport.readKeybindingItem(k, i)); - } - - private onOptionsChanged(e: OptionsChangeEvent): void { - if (e.key === 'globalSettings') { - this.updateResolver(); - } - } - - public dispose(): void { - this.toDispose(); - } -} - -let schemaId = 'local://schemas/keybindings'; -let schema : IJSONSchema = { - 'id': schemaId, - 'type': 'array', - 'title': nls.localize('keybindings.json.title', "Keybindings configuration"), - 'items': { - 'required': ['key'], - 'type': 'object', - 'default': { 'key': '{{_}}', 'command': '{{_}}', 'when': '{{_}}' }, - 'properties': { - 'key': { - 'type': 'string', - 'description': nls.localize('keybindings.json.key', 'Key or key sequence (separated by space)'), - }, - 'command': { - 'description': nls.localize('keybindings.json.command', 'Name of the command to execute'), - }, - 'when': { - 'type': 'string', - 'description': nls.localize('keybindings.json.when', 'Condition when the key is active.') - } - } - } -}; - -let schemaRegistry = Registry.as(JSONContributionRegistry.Extensions.JSONContribution); -schemaRegistry.registerSchema(schemaId, schema); -schemaRegistry.addSchemaFileAssociation('inmemory://defaults/keybindings.json', schemaId); -schemaRegistry.addSchemaFileAssociation('%APP_SETTINGS_HOME%/keybindings.json', schemaId); \ No newline at end of file diff --git a/src/vs/workbench/services/keybinding/electron-browser/pluginKeybindingService.ts b/src/vs/workbench/services/keybinding/electron-browser/keybindingService.ts similarity index 71% rename from src/vs/workbench/services/keybinding/electron-browser/pluginKeybindingService.ts rename to src/vs/workbench/services/keybinding/electron-browser/keybindingService.ts index 242f9835429..4a4da378adf 100644 --- a/src/vs/workbench/services/keybinding/electron-browser/pluginKeybindingService.ts +++ b/src/vs/workbench/services/keybinding/electron-browser/keybindingService.ts @@ -6,19 +6,23 @@ import nls = require('vs/nls'); import {TPromise} from 'vs/base/common/winjs.base'; +import {IJSONSchema} from 'vs/base/common/jsonSchema'; +import {IHTMLContentElement} from 'vs/base/common/htmlContent'; +import {Registry} from 'vs/platform/platform'; import {IEventService} from 'vs/platform/event/common/event'; +import * as JSONContributionRegistry from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; import {ITelemetryService} from 'vs/platform/telemetry/common/telemetry'; import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; import {PluginsRegistry, IMessageCollector} from 'vs/platform/plugins/common/pluginsRegistry'; import {IPluginService} from 'vs/platform/plugins/common/plugins'; import {IOSupport} from 'vs/platform/keybinding/common/commonKeybindingResolver'; -import {WorkbenchKeybindingService} from 'vs/workbench/services/keybinding/browser/keybindingService'; +import {KeybindingService} from 'vs/platform/keybinding/browser/keybindingServiceImpl'; +import {IKeybindingItem, IUserFriendlyKeybinding} from 'vs/platform/keybinding/common/keybindingService'; import {ICommandRule, KeybindingsRegistry} from 'vs/platform/keybinding/common/keybindingsRegistry'; -import {IJSONSchema} from 'vs/base/common/jsonSchema'; -import {Keybinding, IKeyBindingLabelProvider} from 'vs/base/common/keyCodes'; -import Platform = require('vs/base/common/platform'); -import {IHTMLContentElement} from 'vs/base/common/htmlContent'; +import {Keybinding} from 'vs/base/common/keyCodes'; +import * as Platform from 'vs/base/common/platform'; import {getNativeLabelProvider} from 'vs/workbench/services/keybinding/electron-browser/nativeKeymap'; +import {OptionsChangeEvent, EventType} from 'vs/workbench/common/events'; interface ContributedKeyBinding { command: string; @@ -107,14 +111,21 @@ let keybindingsExtPoint = PluginsRegistry.registerExtensionPoint this.onOptionsChanged(e)); this._eventService = eventService; keybindingsExtPoint.setHandler((extensions) => { let commandAdded = false; @@ -133,6 +144,44 @@ export default class PluginWorkbenchKeybindingService extends WorkbenchKeybindin this._pluginService = pluginService; } + public customKeybindingsCount(): number { + let opts = this.contextService.getOptions(); + if (opts.globalSettings && opts.globalSettings.keybindings && Array.isArray(opts.globalSettings.keybindings)) { + return opts.globalSettings.keybindings.length; + } + return 0; + } + + protected _getExtraKeybindings(isFirstTime: boolean): IKeybindingItem[] { + let extras: IUserFriendlyKeybinding[] = []; + let opts = this.contextService.getOptions(); + if (opts.globalSettings && opts.globalSettings.keybindings) { + if (!isFirstTime) { + let cnt = 0; + if (Array.isArray(opts.globalSettings.keybindings)) { + cnt = opts.globalSettings.keybindings.length; + } + this.telemetryService.publicLog('customKeybindingsChanged', { + keyCount: cnt + }); + } + if (Array.isArray(opts.globalSettings.keybindings)) { + extras = opts.globalSettings.keybindings; + } + } + return extras.map((k, i) => IOSupport.readKeybindingItem(k, i)); + } + + private onOptionsChanged(e: OptionsChangeEvent): void { + if (e.key === 'globalSettings') { + this.updateResolver(); + } + } + + public dispose(): void { + this.toDispose(); + } + public getLabelFor(keybinding:Keybinding): string { return keybinding.toCustomLabel(getNativeLabelProvider()); } @@ -232,3 +281,33 @@ export default class PluginWorkbenchKeybindingService extends WorkbenchKeybindin return desc; } } + +let schemaId = 'local://schemas/keybindings'; +let schema : IJSONSchema = { + 'id': schemaId, + 'type': 'array', + 'title': nls.localize('keybindings.json.title', "Keybindings configuration"), + 'items': { + 'required': ['key'], + 'type': 'object', + 'default': { 'key': '{{_}}', 'command': '{{_}}', 'when': '{{_}}' }, + 'properties': { + 'key': { + 'type': 'string', + 'description': nls.localize('keybindings.json.key', 'Key or key sequence (separated by space)'), + }, + 'command': { + 'description': nls.localize('keybindings.json.command', 'Name of the command to execute'), + }, + 'when': { + 'type': 'string', + 'description': nls.localize('keybindings.json.when', 'Condition when the key is active.') + } + } + } +}; + +let schemaRegistry = Registry.as(JSONContributionRegistry.Extensions.JSONContribution); +schemaRegistry.registerSchema(schemaId, schema); +schemaRegistry.addSchemaFileAssociation('inmemory://defaults/keybindings.json', schemaId); +schemaRegistry.addSchemaFileAssociation('%APP_SETTINGS_HOME%/keybindings.json', schemaId); From 220078fa94836f12010b89ae961d55c754cab29e Mon Sep 17 00:00:00 2001 From: isidor Date: Wed, 6 Jan 2016 10:45:26 +0100 Subject: [PATCH 7/9] debug: remove Source.fromUri and always try to match source to a source from the active stack trace. fixes #1793 --- src/vs/workbench/parts/debug/common/debugModel.ts | 8 ++++---- src/vs/workbench/parts/debug/common/debugSource.ts | 7 ------- .../parts/debug/electron-browser/debugService.ts | 3 +-- .../parts/debug/test/common/debugSource.test.ts | 10 ---------- 4 files changed, 5 insertions(+), 23 deletions(-) diff --git a/src/vs/workbench/parts/debug/common/debugModel.ts b/src/vs/workbench/parts/debug/common/debugModel.ts index 31658b83a62..824c5f3d3db 100644 --- a/src/vs/workbench/parts/debug/common/debugModel.ts +++ b/src/vs/workbench/parts/debug/common/debugModel.ts @@ -376,7 +376,7 @@ export class Model extends ee.EventEmitter implements debug.IModel { } public addBreakpoints(rawData: debug.IRawBreakpoint[]): void { - this.breakpoints = this.breakpoints.concat(rawData.map(rawBp => new Breakpoint(Source.fromUri(rawBp.uri), rawBp.lineNumber, rawBp.enabled, rawBp.condition))); + this.breakpoints = this.breakpoints.concat(rawData.map(rawBp => new Breakpoint(new Source(Source.toRawSource(rawBp.uri, this)), rawBp.lineNumber, rawBp.enabled, rawBp.condition))); this.breakpointsActivated = true; this.emit(debug.ModelEvents.BREAKPOINTS_UPDATED); } @@ -610,10 +610,10 @@ export class Model extends ee.EventEmitter implements debug.IModel { this.threads[data.threadId].callStack = data.callStack.map( (rsf, level) => { if (!rsf) { - return new StackFrame(data.threadId, 0, Source.fromUri(uri.parse('unknown')), nls.localize('unknownStack', "Unknown stack location"), undefined, undefined); + return new StackFrame(data.threadId, 0, new Source({ name: 'unknown' }), nls.localize('unknownStack', "Unknown stack location"), undefined, undefined); } - - return new StackFrame(data.threadId, rsf.id, rsf.source ? new Source(rsf.source) : Source.fromUri(uri.parse('unknown')), rsf.name, rsf.line, rsf.column); + + return new StackFrame(data.threadId, rsf.id, rsf.source ? new Source(rsf.source) : new Source({ name: 'unknown' }), rsf.name, rsf.line, rsf.column); }); this.threads[data.threadId].stoppedReason = data.stoppedReason; diff --git a/src/vs/workbench/parts/debug/common/debugSource.ts b/src/vs/workbench/parts/debug/common/debugSource.ts index e3ab15902fd..6347f2eb49b 100644 --- a/src/vs/workbench/parts/debug/common/debugSource.ts +++ b/src/vs/workbench/parts/debug/common/debugSource.ts @@ -52,13 +52,6 @@ export class Source { { path: paths.normalize(uri.fsPath, true) }; } - public static fromUri(uri: uri): Source { - return new Source({ - name: Source.getName(uri), - path: uri.fsPath, - }); - } - private static getName(uri: uri): string { const uriStr = uri.toString(); return uriStr.substr(uriStr.lastIndexOf('/') + 1); diff --git a/src/vs/workbench/parts/debug/electron-browser/debugService.ts b/src/vs/workbench/parts/debug/electron-browser/debugService.ts index b6608db1fb4..8105d9bb691 100644 --- a/src/vs/workbench/parts/debug/electron-browser/debugService.ts +++ b/src/vs/workbench/parts/debug/electron-browser/debugService.ts @@ -110,7 +110,6 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService private registerListeners(eventService: IEventService, lifecycleService: ILifecycleService): void { this.toDispose.push(eventService.addListener2(EventType.FILE_CHANGES, (e: FileChangesEvent) => this.onFileChanges(e))); - if (this.taskService) { this.toDispose.push(this.taskService.addListener2(TaskServiceEvents.Active, (e: TaskEvent) => { this.lastTaskEvent = e; @@ -312,7 +311,7 @@ export class DebugService extends ee.EventEmitter implements debug.IDebugService private loadBreakpoints(): debug.IBreakpoint[] { try { return JSON.parse(this.storageService.get(DEBUG_BREAKPOINTS_KEY, StorageScope.WORKSPACE, '[]')).map((breakpoint: any) => { - return new model.Breakpoint(breakpoint.source.raw ? new Source(breakpoint.source.raw) : Source.fromUri(uri.parse(breakpoint.source.uri)), + return new model.Breakpoint(new Source(breakpoint.source.raw ? breakpoint.source.raw : { path: uri.parse(breakpoint.source.uri).fsPath, name: breakpoint.source.name }), breakpoint.desiredLineNumber || breakpoint.lineNumber, breakpoint.enabled, breakpoint.condition); }); } catch (e) { diff --git a/src/vs/workbench/parts/debug/test/common/debugSource.test.ts b/src/vs/workbench/parts/debug/test/common/debugSource.test.ts index 089e04af7e2..592b6b51dcf 100644 --- a/src/vs/workbench/parts/debug/test/common/debugSource.test.ts +++ b/src/vs/workbench/parts/debug/test/common/debugSource.test.ts @@ -9,16 +9,6 @@ import { Source } from 'vs/workbench/parts/debug/common/debugSource'; suite('Debug - Source', () => { - test('from uri', () => { - const u = uri.file('/a/b/c/d'); - const source = Source.fromUri(u); - - assert.equal(source.available, true); - assert.equal(source.inMemory, false); - assert.equal(source.uri.toString(), u.toString()); - assert.equal(source.name, 'd'); - }); - test('from raw source', () => { const rawSource = { name: 'zz', From acf007bf8f7c5355a6501bdacbfc18208b4405eb Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 6 Jan 2016 10:46:51 +0100 Subject: [PATCH 8/9] Update links to new native-keymap repo location --- .../services/keybinding/electron-browser/nativeKeymap.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/services/keybinding/electron-browser/nativeKeymap.ts b/src/vs/workbench/services/keybinding/electron-browser/nativeKeymap.ts index 2aa72ecf66d..208dbddd709 100644 --- a/src/vs/workbench/services/keybinding/electron-browser/nativeKeymap.ts +++ b/src/vs/workbench/services/keybinding/electron-browser/nativeKeymap.ts @@ -23,7 +23,7 @@ let getNativeKeymap = (function() { })(); // See https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx -// See https://github.com/alexandrudima/vscode-keyboard/blob/master/deps/chromium/keyboard_codes_win.h +// See https://github.com/Microsoft/node-native-keymap/blob/master/deps/chromium/keyboard_codes_win.h const NATIVE_KEY_CODE_TO_KEY_CODE: {[nativeKeyCode:string]:KeyCode;} = { VKEY_BACK: KeyCode.Backspace, VKEY_TAB: KeyCode.Tab, @@ -335,7 +335,7 @@ let nativeLabelProvider:IKeyBindingLabelProvider = null; export function getNativeLabelProvider(): IKeyBindingLabelProvider { if (!nativeLabelProvider) { // See https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx - // See https://github.com/alexandrudima/vscode-keyboard/blob/master/deps/chromium/keyboard_codes_win.h + // See https://github.com/Microsoft/node-native-keymap/blob/master/deps/chromium/keyboard_codes_win.h let interestingKeyCodes:{[vkeyCode:string]:boolean;} = { VKEY_OEM_1: true, VKEY_OEM_PLUS: true, From 23321a1f4b802cb7c7b02d6e28e8d219443a5339 Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Wed, 6 Jan 2016 10:53:50 +0100 Subject: [PATCH 9/9] update node-debug --- extensions/node-debug/node-debug.azure.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/node-debug/node-debug.azure.json b/extensions/node-debug/node-debug.azure.json index 45dbe718e6e..229c05461c8 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": "2985e20/node-debug.zip", + "zip": "b5b96dd/node-debug.zip", "output": "" }