Fix key bindings (#1406)

This commit is contained in:
Felix Häusler 2019-09-30 18:59:01 +02:00 committed by GitHub
parent a68fb82eb3
commit 134d55a99e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 41 additions and 26 deletions

View File

@ -89,7 +89,7 @@ Here is an example:
| `paragraphHeading6` | <kbd>CmdOrCtrl</kbd>+<kbd>6</kbd> | Set line as heading 6 | | `paragraphHeading6` | <kbd>CmdOrCtrl</kbd>+<kbd>6</kbd> | Set line as heading 6 |
| `paragraphUpgradeHeading` | <kbd>CmdOrCtrl</kbd>+<kbd>=</kbd> | Upgrade a heading | | `paragraphUpgradeHeading` | <kbd>CmdOrCtrl</kbd>+<kbd>=</kbd> | Upgrade a heading |
| `paragraphDegradeHeading` | <kbd>CmdOrCtrl</kbd>+<kbd>-</kbd> | Degrade a heading | | `paragraphDegradeHeading` | <kbd>CmdOrCtrl</kbd>+<kbd>-</kbd> | Degrade a heading |
| `paragraphTable` | <kbd>CmdOrCtrl</kbd>+<kbd>T</kbd> | Insert a table | | `paragraphTable` | <kbd>CmdOrCtrl</kbd>+<kbd>Shift</kbd>+<kbd>T</kbd> | Insert a table |
| `paragraphCodeFence` | <kbd>CmdOrCtrl</kbd>+<kbd>Alt</kbd>+<kbd>C</kbd> | Insert a code block | | `paragraphCodeFence` | <kbd>CmdOrCtrl</kbd>+<kbd>Alt</kbd>+<kbd>C</kbd> | Insert a code block |
| `paragraphQuoteBlock` | <kbd>CmdOrCtrl</kbd>+<kbd>Alt</kbd>+<kbd>Q</kbd> | Insert a quote block | | `paragraphQuoteBlock` | <kbd>CmdOrCtrl</kbd>+<kbd>Alt</kbd>+<kbd>Q</kbd> | Insert a quote block |
| `paragraphMathBlock` | <kbd>CmdOrCtrl</kbd>+<kbd>Alt</kbd>+<kbd>M</kbd> | Insert a math block | | `paragraphMathBlock` | <kbd>CmdOrCtrl</kbd>+<kbd>Alt</kbd>+<kbd>M</kbd> | Insert a math block |

View File

@ -27,7 +27,7 @@ class Keybindings {
// File menu // File menu
['fileNewFile', 'CmdOrCtrl+N'], ['fileNewFile', 'CmdOrCtrl+N'],
['fileNewTab', 'CmdOrCtrl+Shift+T'], ['fileNewTab', 'CmdOrCtrl+T'],
['fileOpenFile', 'CmdOrCtrl+O'], ['fileOpenFile', 'CmdOrCtrl+O'],
['fileOpenFolder', 'CmdOrCtrl+Shift+O'], ['fileOpenFolder', 'CmdOrCtrl+Shift+O'],
['fileSave', 'CmdOrCtrl+S'], ['fileSave', 'CmdOrCtrl+S'],
@ -66,7 +66,7 @@ class Keybindings {
['paragraphHeading6', 'CmdOrCtrl+6'], ['paragraphHeading6', 'CmdOrCtrl+6'],
['paragraphUpgradeHeading', 'CmdOrCtrl+='], ['paragraphUpgradeHeading', 'CmdOrCtrl+='],
['paragraphDegradeHeading', 'CmdOrCtrl+-'], ['paragraphDegradeHeading', 'CmdOrCtrl+-'],
['paragraphTable', 'CmdOrCtrl+T'], ['paragraphTable', 'CmdOrCtrl+Shift+T'],
['paragraphCodeFence', 'CmdOrCtrl+Alt+C'], ['paragraphCodeFence', 'CmdOrCtrl+Alt+C'],
['paragraphQuoteBlock', 'CmdOrCtrl+Alt+Q'], ['paragraphQuoteBlock', 'CmdOrCtrl+Alt+Q'],
['paragraphMathBlock', 'CmdOrCtrl+Alt+M'], ['paragraphMathBlock', 'CmdOrCtrl+Alt+M'],
@ -110,11 +110,11 @@ class Keybindings {
['tabsSwitchToRight', 'CmdOrCtrl+PageDown'] ['tabsSwitchToRight', 'CmdOrCtrl+PageDown']
]) ])
// fix non-US keyboards // Fix non-US keyboards
this.mnemonics = new Map() this.mnemonics = new Map()
this._fixLayout() this._fixLayout()
// load user-defined keybindings // Load user-defined keybindings
this._loadLocalKeybindings() this._loadLocalKeybindings()
} }
@ -156,13 +156,13 @@ class Keybindings {
// --- private -------------------------------- // --- private --------------------------------
_fixLayout () { _fixLayout () {
// fix wrong virtual key mapping on non-QWERTY layouts // Fix wrong virtual key mapping on non-QWERTY layouts
electronLocalshortcut.updateVirtualKeys(getVirtualLetters()) electronLocalshortcut.updateVirtualKeys(getVirtualLetters())
// fix broken shortcuts and dead keys // Fix broken shortcuts and dead keys
const lang = getKeyboardLanguage() const lang = getKeyboardLanguage()
switch (lang) { switch (lang) {
// fix aidou and inline code // Fix aidou and inline code
case 'ch': case 'ch':
case 'de': case 'de':
case 'dk': case 'dk':
@ -176,7 +176,7 @@ class Keybindings {
} }
break break
// fix aidou only // Fix aidou only
case 'es': case 'es':
case 'fr': case 'fr':
case 'hr': case 'hr':
@ -188,7 +188,7 @@ class Keybindings {
} }
break break
// custom layouts // Custom layouts
case 'bg': case 'bg':
if (!isOsx) { if (!isOsx) {
this.mnemonics.set('CmdOrCtrl+/', 'CmdOrCtrl+8') this.mnemonics.set('CmdOrCtrl+/', 'CmdOrCtrl+8')
@ -202,7 +202,7 @@ class Keybindings {
this.mnemonics.set('CmdOrCtrl+/', 'CmdOrCtrl+7') this.mnemonics.set('CmdOrCtrl+/', 'CmdOrCtrl+7')
} }
// fix dead backquote key on layouts like German // Fix dead backquote key on layouts like German
_fixInlineCode () { _fixInlineCode () {
this.keys.set('formatInlineCode', 'CmdOrCtrl+Shift+B') this.keys.set('formatInlineCode', 'CmdOrCtrl+Shift+B')
} }
@ -230,40 +230,49 @@ class Keybindings {
const value = json[key] const value = json[key]
if (typeof value === 'string') { if (typeof value === 'string') {
if (value.length === 0) { if (value.length === 0) {
// unset key // Unset key
this.keys.set(key, '') userAccelerators.set(key, '')
} else if (isAccelerator(value)) { } else if (isAccelerator(value)) {
// id / accelerator
userAccelerators.set(key, value) 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) { if (userAccelerators.size === 0) {
return return
} }
// deep clone shortcuts and unset user shortcuts // Deep clone shortcuts
const accelerators = new Map(this.keys) 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 [userKey, userValue] of userAccelerators) {
for (const [key, value] of accelerators) { for (const [key, value] of accelerators) {
if (this._isEqualAccelerator(value, userValue)) { if (this._isEqualAccelerator(value, userValue)) {
const err = `Invalid keybindings.json configuration: Duplicate key ${userKey} - ${key}` // Unset default key
console.log(err) accelerators.set(key, '')
log.error(err)
return // A accelerator should only exist once in the default map.
break
} }
} }
accelerators.set(userKey, userValue) accelerators.set(userKey, userValue)
} }
// update key bindings // Update key bindings
this.keys = accelerators this.keys = accelerators
} }
@ -280,6 +289,10 @@ class Keybindings {
const keysA = a.split('+') const keysA = a.split('+')
const keysB = b.split('+') const keysB = b.split('+')
if (keysA.length !== keysB.length) {
return false
}
const intersection = new Set([...keysA, ...keysB]) const intersection = new Set([...keysA, ...keysB])
return intersection.size === keysB.length return intersection.size === keysB.length
} }
@ -314,6 +327,7 @@ const callMenuCallback = (menuInfo, win) => {
const menus = Menu.getApplicationMenu() const menus = Menu.getApplicationMenu()
menuItem = menus.getMenuItemById(id) menuItem = menus.getMenuItemById(id)
} }
// Allow all shortcuts/menus without id and only enabled menus with id (GH#980). // Allow all shortcuts/menus without id and only enabled menus with id (GH#980).
if (!menuItem || menuItem.enabled !== false) { if (!menuItem || menuItem.enabled !== false) {
click(menuItem, win) click(menuItem, win)

View File

@ -10,14 +10,14 @@ export default function (keybindings, userPreference, recentlyUsedFiles) {
label: '&File', label: '&File',
submenu: [{ submenu: [{
label: 'New Tab', label: 'New Tab',
accelerator: keybindings.getAccelerator('fileNewFile'), accelerator: keybindings.getAccelerator('fileNewTab'),
click (menuItem, browserWindow) { click (menuItem, browserWindow) {
actions.newBlankTab(browserWindow) actions.newBlankTab(browserWindow)
showTabBar(browserWindow) showTabBar(browserWindow)
} }
}, { }, {
label: 'New Window', label: 'New Window',
accelerator: keybindings.getAccelerator('fileNewTab'), accelerator: keybindings.getAccelerator('fileNewFile'),
click (menuItem, browserWindow) { click (menuItem, browserWindow) {
actions.newEditorWindow() actions.newEditorWindow()
} }

View File

@ -31,6 +31,7 @@ class Preference extends EventEmitter {
* *
*/ */
constructor (paths) { constructor (paths) {
// TODO: Preferences should not loaded if global.MARKTEXT_SAFE_MODE is set.
super() super()
const { preferencesPath } = paths const { preferencesPath } = paths