]> git.proxmox.com Git - mirror_novnc.git/commitdiff
Fallback for missing keypress events
authorPierre Ossman <ossman@cendio.se>
Thu, 6 Jul 2017 10:53:31 +0000 (12:53 +0200)
committerPierre Ossman <ossman@cendio.se>
Thu, 6 Jul 2017 11:00:00 +0000 (13:00 +0200)
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.

core/input/devices.js
tests/test.keyboard.js

index 6409f74b391a7e9848c23d61c29746a5bc3aa141..b530fc2ab23ec86a05caa5833b496db2d908cc6e 100644 (file)
@@ -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; }
index a42168e0187b5d5210f4498b5983ce6b2bae8a9b..268ff5a5f9fc62b53de7005ba238f45095f385fe 100644 (file)
@@ -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() {