diff --git a/docs/KEYBINDINGS.md b/docs/KEYBINDINGS.md index 782da6eb..b133d291 100644 --- a/docs/KEYBINDINGS.md +++ b/docs/KEYBINDINGS.md @@ -89,7 +89,7 @@ Here is an example: | `paragraphHeading6` | CmdOrCtrl+6 | Set line as heading 6 | | `paragraphUpgradeHeading` | CmdOrCtrl+= | Upgrade a heading | | `paragraphDegradeHeading` | CmdOrCtrl+- | Degrade a heading | -| `paragraphTable` | CmdOrCtrl+T | Insert a table | +| `paragraphTable` | CmdOrCtrl+Shift+T | Insert a table | | `paragraphCodeFence` | CmdOrCtrl+Alt+C | Insert a code block | | `paragraphQuoteBlock` | CmdOrCtrl+Alt+Q | Insert a quote block | | `paragraphMathBlock` | CmdOrCtrl+Alt+M | Insert a math block | diff --git a/src/main/keyboard/shortcutHandler.js b/src/main/keyboard/shortcutHandler.js index 3a732ef3..90927a7e 100644 --- a/src/main/keyboard/shortcutHandler.js +++ b/src/main/keyboard/shortcutHandler.js @@ -27,7 +27,7 @@ class Keybindings { // File menu ['fileNewFile', 'CmdOrCtrl+N'], - ['fileNewTab', 'CmdOrCtrl+Shift+T'], + ['fileNewTab', 'CmdOrCtrl+T'], ['fileOpenFile', 'CmdOrCtrl+O'], ['fileOpenFolder', 'CmdOrCtrl+Shift+O'], ['fileSave', 'CmdOrCtrl+S'], @@ -66,7 +66,7 @@ class Keybindings { ['paragraphHeading6', 'CmdOrCtrl+6'], ['paragraphUpgradeHeading', 'CmdOrCtrl+='], ['paragraphDegradeHeading', 'CmdOrCtrl+-'], - ['paragraphTable', 'CmdOrCtrl+T'], + ['paragraphTable', 'CmdOrCtrl+Shift+T'], ['paragraphCodeFence', 'CmdOrCtrl+Alt+C'], ['paragraphQuoteBlock', 'CmdOrCtrl+Alt+Q'], ['paragraphMathBlock', 'CmdOrCtrl+Alt+M'], @@ -110,11 +110,11 @@ class Keybindings { ['tabsSwitchToRight', 'CmdOrCtrl+PageDown'] ]) - // fix non-US keyboards + // Fix non-US keyboards this.mnemonics = new Map() this._fixLayout() - // load user-defined keybindings + // Load user-defined keybindings this._loadLocalKeybindings() } @@ -156,13 +156,13 @@ class Keybindings { // --- private -------------------------------- _fixLayout () { - // fix wrong virtual key mapping on non-QWERTY layouts + // Fix wrong virtual key mapping on non-QWERTY layouts electronLocalshortcut.updateVirtualKeys(getVirtualLetters()) - // fix broken shortcuts and dead keys + // Fix broken shortcuts and dead keys const lang = getKeyboardLanguage() switch (lang) { - // fix aidou and inline code + // Fix aidou and inline code case 'ch': case 'de': case 'dk': @@ -176,7 +176,7 @@ class Keybindings { } break - // fix aidou only + // Fix aidou only case 'es': case 'fr': case 'hr': @@ -188,7 +188,7 @@ class Keybindings { } break - // custom layouts + // Custom layouts case 'bg': if (!isOsx) { this.mnemonics.set('CmdOrCtrl+/', 'CmdOrCtrl+8') @@ -202,7 +202,7 @@ class Keybindings { this.mnemonics.set('CmdOrCtrl+/', 'CmdOrCtrl+7') } - // fix dead backquote key on layouts like German + // Fix dead backquote key on layouts like German _fixInlineCode () { this.keys.set('formatInlineCode', 'CmdOrCtrl+Shift+B') } @@ -230,40 +230,49 @@ class Keybindings { const value = json[key] if (typeof value === 'string') { if (value.length === 0) { - // unset key - this.keys.set(key, '') + // Unset key + userAccelerators.set(key, '') } else if (isAccelerator(value)) { - // id / accelerator userAccelerators.set(key, value) } } } } + // Check for duplicate user shortcuts + for (const [keyA, valueA] of userAccelerators) { + for (const [keyB, valueB] of userAccelerators) { + if (keyA !== keyB && this._isEqualAccelerator(valueA, valueB)) { + const err = `Invalid keybindings.json configuration: Duplicate value for "${keyA}" and "${keyB}"!` + console.log(err) + log.error(err) + return + } + } + } + if (userAccelerators.size === 0) { return } - // deep clone shortcuts and unset user shortcuts + // Deep clone shortcuts const accelerators = new Map(this.keys) - userAccelerators.forEach((value, key) => { - accelerators.set(key, '') - }) - // check for duplicate shortcuts + // Check for duplicate shortcuts for (const [userKey, userValue] of userAccelerators) { for (const [key, value] of accelerators) { if (this._isEqualAccelerator(value, userValue)) { - const err = `Invalid keybindings.json configuration: Duplicate key ${userKey} - ${key}` - console.log(err) - log.error(err) - return + // Unset default key + accelerators.set(key, '') + + // A accelerator should only exist once in the default map. + break } } accelerators.set(userKey, userValue) } - // update key bindings + // Update key bindings this.keys = accelerators } @@ -280,6 +289,10 @@ class Keybindings { const keysA = a.split('+') const keysB = b.split('+') + if (keysA.length !== keysB.length) { + return false + } + const intersection = new Set([...keysA, ...keysB]) return intersection.size === keysB.length } @@ -314,6 +327,7 @@ const callMenuCallback = (menuInfo, win) => { const menus = Menu.getApplicationMenu() menuItem = menus.getMenuItemById(id) } + // Allow all shortcuts/menus without id and only enabled menus with id (GH#980). if (!menuItem || menuItem.enabled !== false) { click(menuItem, win) diff --git a/src/main/menu/templates/file.js b/src/main/menu/templates/file.js index 78f91383..56f8d2d7 100755 --- a/src/main/menu/templates/file.js +++ b/src/main/menu/templates/file.js @@ -10,14 +10,14 @@ export default function (keybindings, userPreference, recentlyUsedFiles) { label: '&File', submenu: [{ label: 'New Tab', - accelerator: keybindings.getAccelerator('fileNewFile'), + accelerator: keybindings.getAccelerator('fileNewTab'), click (menuItem, browserWindow) { actions.newBlankTab(browserWindow) showTabBar(browserWindow) } }, { label: 'New Window', - accelerator: keybindings.getAccelerator('fileNewTab'), + accelerator: keybindings.getAccelerator('fileNewFile'), click (menuItem, browserWindow) { actions.newEditorWindow() } diff --git a/src/main/preferences/index.js b/src/main/preferences/index.js index c856accd..cbc6dbab 100644 --- a/src/main/preferences/index.js +++ b/src/main/preferences/index.js @@ -31,6 +31,7 @@ class Preference extends EventEmitter { * */ constructor (paths) { + // TODO: Preferences should not loaded if global.MARKTEXT_SAFE_MODE is set. super() const { preferencesPath } = paths