summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2017-07-06 12:53:31 +0200
committerPierre Ossman <ossman@cendio.se>2017-07-06 13:00:00 +0200
commit7cac5c8e9f5526c2594150305fe94faeef11550f (patch)
tree00fa3bc592de06f9ef00d961c3c4fb7b370679f2
parent7e79dfe425c0245b37f70eb694fa5a4bc687892b (diff)
downloadnovnc-7cac5c8e9f5526c2594150305fe94faeef11550f.tar.gz
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.
-rw-r--r--core/input/devices.js41
-rw-r--r--tests/test.keyboard.js40
2 files changed, 81 insertions, 0 deletions
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() {