diff --git a/src/test/test.js b/src/test/test.js index 1644e5800..12cd9dc24 100644 --- a/src/test/test.js +++ b/src/test/test.js @@ -377,6 +377,11 @@ describe('xterm.js', function() { stopPropagation: function() {}, type: 'keydown' } + var evKeyPress = { + preventDefault: function() {}, + stopPropagation: function() {}, + type: 'keypress' + } beforeEach(function() { xterm.handler = function() {}; @@ -387,6 +392,11 @@ describe('xterm.js', function() { bind: function() { return function () { return true; } } + }, + keypress: { + bind: function() { + return function () { return true; } + } } } }); @@ -403,13 +413,30 @@ describe('xterm.js', function() { assert.equal(xterm.keyDown(Object.assign({}, evKeyDown, { keyCode: 77 })), false); }); + it('should process the keypress event based on what the handler returns', function () { + assert.equal(xterm.keyPress(Object.assign({}, evKeyPress, { keyCode: 77 })), true); + xterm.attachCustomKeypressHandler(function (ev) { + return ev.keyCode === 77; + }); + assert.equal(xterm.keyPress(Object.assign({}, evKeyPress, { keyCode: 77 })), true); + xterm.attachCustomKeypressHandler(function (ev) { + return ev.keyCode !== 77; + }); + assert.equal(xterm.keyPress(Object.assign({}, evKeyPress, { keyCode: 77 })), false); + }); + it('should alive after reset(ESC c Full Reset (RIS))', function () { xterm.attachCustomKeydownHandler(function (ev) { return ev.keyCode !== 77; }); + xterm.attachCustomKeypressHandler(function (ev) { + return ev.keyCode !== 77; + }); assert.equal(xterm.keyDown(Object.assign({}, evKeyDown, { keyCode: 77 })), false); + assert.equal(xterm.keyPress(Object.assign({}, evKeyPress, { keyCode: 77 })), false); xterm.reset(); assert.equal(xterm.keyDown(Object.assign({}, evKeyDown, { keyCode: 77 })), false); + assert.equal(xterm.keyPress(Object.assign({}, evKeyPress, { keyCode: 77 })), false); }); }); diff --git a/src/xterm.js b/src/xterm.js index 0abcbeaeb..647d0c6dc 100644 --- a/src/xterm.js +++ b/src/xterm.js @@ -168,6 +168,7 @@ function Terminal(options) { this.scrollTop = 0; this.scrollBottom = this.rows - 1; this.customKeydownHandler = null; + this.customKeypressHandler = null; this.cursorBlinkInterval = null; // modes @@ -1316,6 +1317,18 @@ Terminal.prototype.attachCustomKeydownHandler = function(customKeydownHandler) { this.customKeydownHandler = customKeydownHandler; } +/** + * Attaches a custom keypress handler which is run before keys are processed, giving consumers of + * xterm.js ultimate control as to what keys should be processed by the terminal and what keys + * should not. + * @param {function} customKeypressHandler The custom KeyboardEvent handler to attach. This is a + * function that takes a KeyboardEvent, allowing consumers to stop propogation and/or prevent + * the default action. The function returns whether the event should be processed by xterm.js. + */ +Terminal.prototype.attachCustomKeypressHandler = function(customKeypressHandler) { + this.customKeypressHandler = customKeypressHandler; +} + /** * Attaches a http(s) link handler, forcing web links to behave differently to * regular tags. This will trigger a refresh as links potentially need to be @@ -1777,6 +1790,10 @@ Terminal.prototype.setgCharset = function(g, charset) { Terminal.prototype.keyPress = function(ev) { var key; + if (this.customKeypressHandler && this.customKeypressHandler(ev) === false) { + return false; + } + this.cancel(ev); if (ev.charCode) { @@ -1802,7 +1819,7 @@ Terminal.prototype.keyPress = function(ev) { this.showCursor(); this.handler(key); - return false; + return true; }; /** @@ -2236,9 +2253,11 @@ Terminal.prototype.reset = function() { this.options.rows = this.rows; this.options.cols = this.cols; var customKeydownHandler = this.customKeydownHandler; + var customKeypressHandler = this.customKeypressHandler; var cursorBlinkInterval = this.cursorBlinkInterval; Terminal.call(this, this.options); this.customKeydownHandler = customKeydownHandler; + this.customKeypressHandler = customKeypressHandler; this.cursorBlinkInterval = cursorBlinkInterval; this.refresh(0, this.rows - 1); this.viewport.syncScrollArea();