From: Pierre Ossman Date: Thu, 6 Jul 2017 10:53:31 +0000 (+0200) Subject: Fallback for missing keypress events X-Git-Tag: v1.0.0~103^2~1 X-Git-Url: https://git.proxmox.com/?a=commitdiff_plain;h=7cac5c8e9f5526c2594150305fe94faeef11550f;p=mirror_novnc.git Fallback for missing keypress events IE and Edge have some corner cases (e.g. Ctrl+key) where we get insufficient information in the keydown event, and we never get a keypress event. Try to make a guess of the key in those cases. --- diff --git a/core/input/devices.js b/core/input/devices.js index 6409f74..b530fc2 100644 --- a/core/input/devices.js +++ b/core/input/devices.js @@ -187,6 +187,10 @@ Keyboard.prototype = { // just check for the presence of that field) if (!keysym && (!e.key || isIE() || isEdge())) { this._pendingKey = code; + // However we might not get a keypress event if the key + // is non-printable, which needs some special fallback + // handling + setTimeout(this._handleKeyPressTimeout.bind(this), 10, e); return; } @@ -229,6 +233,43 @@ Keyboard.prototype = { this._sendKeyEvent(keysym, code, true); }, + _handleKeyPressTimeout: function (e) { + if (!this._focused) { return; } + + // Did someone manage to sort out the key already? + if (this._pendingKey === null) { + return; + } + + var code, keysym; + + code = this._pendingKey; + this._pendingKey = null; + + // We have no way of knowing the proper keysym with the + // information given, but the following are true for most + // layouts + if ((e.keyCode >= 0x30) && (e.keyCode <= 0x39)) { + // Digit + keysym = e.keyCode; + } else if ((e.keyCode >= 0x41) && (e.keyCode <= 0x5a)) { + // Character (A-Z) + var char = String.fromCharCode(e.keyCode); + // A feeble attempt at the correct case + if (e.shiftKey) + char = char.toUpperCase(); + else + char = char.toLowerCase(); + keysym = char.charCodeAt(); + } else { + // Unknown, give up + keysym = 0; + } + + this._keyDownList[code] = keysym; + + this._sendKeyEvent(keysym, code, true); + }, _handleKeyUp: function (e) { if (!this._focused) { return; } diff --git a/tests/test.keyboard.js b/tests/test.keyboard.js index a42168e..268ff5a 100644 --- a/tests/test.keyboard.js +++ b/tests/test.keyboard.js @@ -92,6 +92,46 @@ describe('Key Event Handling', function() { kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', keyCode: 0x41})); kbd._handleKeyPress(keyevent('keypress', {charCode: 0x61})); }); + it('should guess key if no keypress and numeric key', function(done) { + var kbd = new Keyboard({ + onKeyEvent: function(keysym, code, down) { + expect(keysym).to.be.equal(0x32); + expect(code).to.be.equal('Digit2'); + expect(down).to.be.equal(true); + done(); + }}); + kbd._handleKeyDown(keyevent('keydown', {code: 'Digit2', keyCode: 0x32})); + }); + it('should guess key if no keypress and alpha key', function(done) { + var kbd = new Keyboard({ + onKeyEvent: function(keysym, code, down) { + expect(keysym).to.be.equal(0x61); + expect(code).to.be.equal('KeyA'); + expect(down).to.be.equal(true); + done(); + }}); + kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', keyCode: 0x41, shiftKey: false})); + }); + it('should guess key if no keypress and alpha key (with shift)', function(done) { + var kbd = new Keyboard({ + onKeyEvent: function(keysym, code, down) { + expect(keysym).to.be.equal(0x41); + expect(code).to.be.equal('KeyA'); + expect(down).to.be.equal(true); + done(); + }}); + kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', keyCode: 0x41, shiftKey: true})); + }); + it('should not guess key if no keypress and unknown key', function(done) { + var kbd = new Keyboard({ + onKeyEvent: function(keysym, code, down) { + expect(keysym).to.be.equal(0); + expect(code).to.be.equal('KeyA'); + expect(down).to.be.equal(true); + done(); + }}); + kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', keyCode: 0x09})); + }); }); describe('suppress the right events at the right time', function() {