diff --git a/lib/hterm.js b/lib/hterm.js index 9700c789..ec6851c6 100644 --- a/lib/hterm.js +++ b/lib/hterm.js @@ -1,4 +1,5 @@ import {hterm, lib} from 'hterm-umdjs'; +import fromCharCode from './utils/key-code'; const selection = require('./utils/selection'); @@ -39,6 +40,8 @@ hterm.Terminal.prototype.copySelectionToClipboard = function () { // hyperterm and not the terminal itself const oldKeyDown = hterm.Keyboard.prototype.onKeyDown_; hterm.Keyboard.prototype.onKeyDown_ = function (e) { + const modifierKeysConf = this.terminal.modifierKeys; + /** * Add fixes for U.S. International PC Keyboard layout * These keys are sent through as 'Dead' keys, as they're used as modifiers. @@ -58,7 +61,7 @@ hterm.Keyboard.prototype.onKeyDown_ = function (e) { return; } // This key is also a tilde on all tested keyboards - if (e.code === 'KeyN' && e.altKey === true) { + if (e.code === 'KeyN' && e.altKey === true && modifierKeysConf.altIsMeta === false) { this.terminal.onVTKeystroke('~'); return; } @@ -80,11 +83,11 @@ hterm.Keyboard.prototype.onKeyDown_ = function (e) { return; } // Italian keyboard layout - if (e.code === 'Digit9' && e.altKey === true) { + if (e.code === 'Digit9' && e.altKey === true && modifierKeysConf.altIsMeta === false) { this.terminal.onVTKeystroke('`'); return; } - if (e.code === 'Digit8' && e.altKey === true) { + if (e.code === 'Digit8' && e.altKey === true && modifierKeysConf.altIsMeta === false) { this.terminal.onVTKeystroke('ยด'); // To fix issue with changing the terminal prompt e.preventDefault(); @@ -102,21 +105,27 @@ hterm.Keyboard.prototype.onKeyDown_ = function (e) { console.warn('Uncaught dead key on international keyboard', e); } - const modifierKeysConf = this.terminal.modifierKeys; if (e.altKey && - e.code !== 'alt' && - e.code !== 'altLeft' && - e.code !== 'altRight' && + e.which !== 16 && // Ignore other modifer keys + e.which !== 17 && + e.which !== 18 && + e.which !== 91 && modifierKeysConf.altIsMeta) { - this.terminal.onVTKeystroke('\x1b' + String.fromCharCode(e.keyCode)); + const char = fromCharCode(e); + this.terminal.onVTKeystroke('\x1b' + char); e.preventDefault(); } if (e.metaKey && e.code !== 'MetaLeft' && e.code !== 'MetaRight' && + e.which !== 16 && + e.which !== 17 && + e.which !== 18 && + e.which !== 91 && modifierKeysConf.cmdIsMeta) { - this.terminal.onVTKeystroke('\x1b' + String.fromCharCode(e.keyCode)); + const char = fromCharCode(e); + this.terminal.onVTKeystroke('\x1b' + char); e.preventDefault(); } diff --git a/lib/utils/key-code.js b/lib/utils/key-code.js new file mode 100644 index 00000000..835a5b43 --- /dev/null +++ b/lib/utils/key-code.js @@ -0,0 +1,79 @@ +/** + * Keyboard event keyCodes have proven to be really unreliable. + * This util function will cover most of the edge cases where + * String.fromCharCode() will not work + */ + +const _toAscii = { + '188': '44', + '109': '45', + '190': '46', + '191': '47', + '192': '96', + '220': '92', + '222': '39', + '221': '93', + '219': '91', + '173': '45', + '187': '61', // IE Key codes + '186': '59', // IE Key codes + '189': '45' // IE Key codes +}; + +const _shiftUps = { + '96': '~', + '49': '!', + '50': '@', + '51': '#', + '52': '$', + '53': '%', + '54': '^', + '55': '&', + '56': '*', + '57': '(', + '48': ')', + '45': '_', + '61': '+', + '91': '{', + '93': '}', + '92': '|', + '59': ':', + '39': '\'', + '44': '<', + '46': '>', + '47': '?' +}; + +const _arrowKeys = { + '38': '', + '40': '', + '39': '', + '37': '' +}; + +/** + * This fn takes a keyboard event and returns + * the character that was pressed. This fn + * purposely doens't take into account if the alt/meta + * key was pressed. + */ +export default function fromCharCode(e) { + let code = String(e.which); + + if ({}.hasOwnProperty.call(_arrowKeys, code)) { + return _arrowKeys[code]; + } + + if ({}.hasOwnProperty.call(_toAscii, code)) { + code = _toAscii[code]; + } + + const char = String.fromCharCode(code); + if (e.shiftKey) { + if ({}.hasOwnProperty.call(_shiftUps, code)) { + return _shiftUps[code]; + } + return char.toUpperCase(); + } + return char.toLowerCase(); +}