]> git.proxmox.com Git - mirror_novnc.git/commitdiff
QEMU RFB extension - rfb.js and input.js changes
authorDaniel Henrique Barboza <danielhb@linux.vnet.ibm.com>
Mon, 11 Apr 2016 10:11:05 +0000 (07:11 -0300)
committerDaniel Henrique Barboza <danielhb@linux.vnet.ibm.com>
Fri, 26 Aug 2016 20:34:39 +0000 (17:34 -0300)
In input.js, a new keyboard handler was added to deal exclusively
with the QEMU key event extension. '_onKeyPress()' signature
was changed to allow the same method to treat both cases.

The extension will only be enabled if the browser has support
for the KeyboardEvent.code property.

Changes in rfb.js:

- added a new extension code, QEMUExtendedKeyEvent, value -258.

- handleKeyPress now receives 'keyevent' instead of 'keysym' and
'down'. Both values are retrieved from keyevent as they were
in the previous signature. This method now can send QEMU RFB
extended key messages if the flag was set to 'true'.

- tests/test.rfb.js were changed folowing the onKeyPress() signature
change.

- added a new function to send the QEMU extended key message.

Signed-off-by: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com>
include/input.js
include/rfb.js
tests/test.rfb.js

index fa6ba44a14ab8f8802a6658030a84997a24560fc..eb4d18a318eba6b69ee3ff49be7e072cf9216cff 100644 (file)
@@ -51,10 +51,18 @@ var Keyboard, Mouse;
             if (this._onKeyPress) {
                 Util.Debug("onKeyPress " + (e.type == 'keydown' ? "down" : "up") +
                            ", keysym: " + e.keysym.keysym + "(" + e.keysym.keyname + ")");
-                this._onKeyPress(e.keysym.keysym, e.type == 'keydown');
+                this._onKeyPress(e);
             }
         },
 
+        setQEMUVNCKeyboardHandler: function () {
+            this._handler = new QEMUKeyEventDecoder(kbdUtil.ModifierSync(),
+                TrackQEMUKeyState(
+                    this._handleRfbEvent.bind(this)
+                )
+            );
+        },
+
         _handleKeyDown: function (e) {
             if (!this._focused) { return true; }
 
index bc5555ab7636fbb53ded4665aa90b0adffabb645..9935962c127d86db5f7f17f5122773df8a7d48c0 100644 (file)
@@ -58,7 +58,8 @@ var RFB;
             ['ExtendedDesktopSize', -308 ],
             ['xvp',                 -309 ],
             ['Fence',               -312 ],
-            ['ContinuousUpdates',   -313 ]
+            ['ContinuousUpdates',   -313 ],
+            ['QEMUExtendedKeyEvent', -258 ]
         ];
 
         this._encHandlers = {};
@@ -129,6 +130,9 @@ var RFB;
         this._viewportDragPos = {};
         this._viewportHasMoved = false;
 
+        // QEMU Extended Key Event support - default to false
+        this._qemuExtKeyEventSupported = false;
+
         // set the default value on user-facing properties
         Util.set_defaults(this, defaults, {
             'target': 'null',                       // VNC display rendering Canvas object
@@ -560,9 +564,22 @@ var RFB;
             }
         },
 
-        _handleKeyPress: function (keysym, down) {
+        _handleKeyPress: function (keyevent) {
             if (this._view_only) { return; } // View only, skip keyboard, events
-            RFB.messages.keyEvent(this._sock, keysym, down);
+
+            var down = (keyevent.type == 'keydown');
+            if (this._qemuExtKeyEventSupported) {
+                var scancode = XtScancode[keyevent.code];
+                if (scancode) {
+                    var keysym = keyevent.keysym;
+                    RFB.messages.QEMUExtendedKeyEvent(this._sock, keysym, down, scancode);
+                } else {
+                    Util.Error('Unable to find a xt scancode for code = ' + keyevent.code);
+                }
+            } else {
+                keysym = keyevent.keysym.keysym;
+                RFB.messages.keyEvent(this._sock, keysym, down);
+            }
         },
 
         _handleMouseButton: function (x, y, down, bmask) {
@@ -1348,6 +1365,42 @@ var RFB;
             sock.flush();
         },
 
+        QEMUExtendedKeyEvent: function (sock, keysym, down, keycode) {
+            function getRFBkeycode(xt_scancode) {
+                var upperByte = (keycode >> 8);
+                var lowerByte = (keycode & 0x00ff);
+                if (upperByte === 0xe0 && lowerByte < 0x7f) {
+                    lowerByte = lowerByte | 0x80;
+                    return lowerByte;
+                }
+                return xt_scancode
+            }
+
+            var buff = sock._sQ;
+            var offset = sock._sQlen;
+
+            buff[offset] = 255; // msg-type
+            buff[offset + 1] = 0; // sub msg-type
+
+            buff[offset + 2] = (down >> 8);
+            buff[offset + 3] = down;
+
+            buff[offset + 4] = (keysym >> 24);
+            buff[offset + 5] = (keysym >> 16);
+            buff[offset + 6] = (keysym >> 8);
+            buff[offset + 7] = keysym;
+
+            var RFBkeycode = getRFBkeycode(keycode)
+
+            buff[offset + 8] = (RFBkeycode >> 24);
+            buff[offset + 9] = (RFBkeycode >> 16);
+            buff[offset + 10] = (RFBkeycode >> 8);
+            buff[offset + 11] = RFBkeycode;
+
+            sock._sQlen += 12;
+            sock.flush();
+        },
+
         pointerEvent: function (sock, x, y, mask) {
             var buff = sock._sQ;
             var offset = sock._sQlen;
@@ -2259,6 +2312,16 @@ var RFB;
 
         compress_lo: function () {
             Util.Error("Server sent compress level pseudo-encoding");
-        }
+        },
+
+        QEMUExtendedKeyEvent: function () {
+            this._FBU.rects--;
+
+            var keyboardEvent = document.createEvent("keyboardEvent");
+            if (keyboardEvent.code !== undefined) {
+                this._qemuExtKeyEventSupported = true;
+                this._keyboard.setQEMUVNCKeyboardHandler();
+            }
+        },
     };
 })();
index 65ce5f882720972c74f85db29a7e8ea38ad9bd44..06eeebe3e67a7ae83657c6ec0c4a23f6c63b2291 100644 (file)
@@ -1927,7 +1927,11 @@ describe('Remote Frame Buffer Protocol Client', function() {
             });
 
             it('should send a key message on a key press', function () {
-                client._keyboard._onKeyPress(1234, 1);
+                var keyevent = {};
+                keyevent.type = 'keydown';
+                keyevent.keysym = {};
+                keyevent.keysym.keysym = 1234;
+                client._keyboard._onKeyPress(keyevent);
                 var key_msg = {_sQ: new Uint8Array(8), _sQlen: 0, flush: function () {}};
                 RFB.messages.keyEvent(key_msg, 1234, 1);
                 expect(client._sock).to.have.sent(key_msg._sQ);