From 94f5cf05f37191ec028781bd486fbf22a460e515 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 26 Jan 2017 17:59:25 +0100 Subject: [PATCH] Send keyboard events from single place This makes it easier to handle any needed variations, like different types of messages. --- app/ui.js | 12 +++++----- core/rfb.js | 57 ++++++++++++++++++++++++++--------------------- tests/test.rfb.js | 18 +++++++++++---- 3 files changed, 51 insertions(+), 36 deletions(-) diff --git a/app/ui.js b/app/ui.js index cd0901b..b53aaea 100644 --- a/app/ui.js +++ b/app/ui.js @@ -1516,7 +1516,7 @@ const UI = { // Send the key events for (i = 0; i < backspaces; i++) { - UI.rfb.sendKey(KeyTable.XK_BackSpace); + UI.rfb.sendKey(KeyTable.XK_BackSpace, "Backspace"); } for (i = newLen - inputs; i < newLen; i++) { UI.rfb.sendKey(keysyms.lookup(newValue.charCodeAt(i))); @@ -1573,7 +1573,7 @@ const UI = { }, sendEsc: function() { - UI.rfb.sendKey(KeyTable.XK_Escape); + UI.rfb.sendKey(KeyTable.XK_Escape, "Escape"); }, sendTab: function() { @@ -1583,10 +1583,10 @@ const UI = { toggleCtrl: function() { var btn = document.getElementById('noVNC_toggle_ctrl_button'); if (btn.classList.contains("noVNC_selected")) { - UI.rfb.sendKey(KeyTable.XK_Control_L, false); + UI.rfb.sendKey(KeyTable.XK_Control_L, "ControlLeft", false); btn.classList.remove("noVNC_selected"); } else { - UI.rfb.sendKey(KeyTable.XK_Control_L, true); + UI.rfb.sendKey(KeyTable.XK_Control_L, "ControlLeft", true); btn.classList.add("noVNC_selected"); } }, @@ -1594,10 +1594,10 @@ const UI = { toggleAlt: function() { var btn = document.getElementById('noVNC_toggle_alt_button'); if (btn.classList.contains("noVNC_selected")) { - UI.rfb.sendKey(KeyTable.XK_Alt_L, false); + UI.rfb.sendKey(KeyTable.XK_Alt_L, "AltLeft", false); btn.classList.remove("noVNC_selected"); } else { - UI.rfb.sendKey(KeyTable.XK_Alt_L, true); + UI.rfb.sendKey(KeyTable.XK_Alt_L, "AltLeft", true); btn.classList.add("noVNC_selected"); } }, diff --git a/core/rfb.js b/core/rfb.js index 9afe9e5..7f55123 100644 --- a/core/rfb.js +++ b/core/rfb.js @@ -298,12 +298,13 @@ RFB.prototype = { if (this._rfb_connection_state !== 'connected' || this._view_only) { return false; } Log.Info("Sending Ctrl-Alt-Del"); - RFB.messages.keyEvent(this._sock, KeyTable.XK_Control_L, 1); - RFB.messages.keyEvent(this._sock, KeyTable.XK_Alt_L, 1); - RFB.messages.keyEvent(this._sock, KeyTable.XK_Delete, 1); - RFB.messages.keyEvent(this._sock, KeyTable.XK_Delete, 0); - RFB.messages.keyEvent(this._sock, KeyTable.XK_Alt_L, 0); - RFB.messages.keyEvent(this._sock, KeyTable.XK_Control_L, 0); + this.sendKey(KeyTable.XK_Control_L, "ControlLeft", true); + this.sendKey(KeyTable.XK_Alt_L, "AltLeft", true); + this.sendKey(KeyTable.XK_Delete, "Delete", true); + this.sendKey(KeyTable.XK_Delete, "Delete", false); + this.sendKey(KeyTable.XK_Alt_L, "AltLeft", false); + this.sendKey(KeyTable.XK_Control_L, "ControlLeft", false); + return true; }, @@ -328,16 +329,33 @@ RFB.prototype = { // Send a key press. If 'down' is not specified then send a down key // followed by an up key. - sendKey: function (keysym, down) { + sendKey: function (keysym, code, down) { if (this._rfb_connection_state !== 'connected' || this._view_only) { return false; } - if (typeof down !== 'undefined') { + + if (down === undefined) { + this.sendKey(keysym, code, true); + this.sendKey(keysym, code, false); + return true; + } + + if (this._qemuExtKeyEventSupported) { + var scancode = XtScancode[code]; + + if (scancode === undefined) { + Log.Error('Unable to find a xt scancode for code: ' + code); + // FIXME: not in the spec, but this is what + // gtk-vnc does + scancode = 0; + } + + Log.Info("Sending key (" + (down ? "down" : "up") + "): keysym " + keysym + ", scancode " + scancode); + + RFB.messages.QEMUExtendedKeyEvent(this._sock, keysym, down, scancode); + } else { Log.Info("Sending keysym (" + (down ? "down" : "up") + "): " + keysym); RFB.messages.keyEvent(this._sock, keysym, down ? 1 : 0); - } else { - Log.Info("Sending keysym (down + up): " + keysym); - RFB.messages.keyEvent(this._sock, keysym, 1); - RFB.messages.keyEvent(this._sock, keysym, 0); } + return true; }, @@ -647,21 +665,8 @@ RFB.prototype = { }, _handleKeyPress: function (keyevent) { - if (this._view_only) { return; } // View only, skip keyboard, events - 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 { - Log.Error('Unable to find a xt scancode for code = ' + keyevent.code); - } - } else { - keysym = keyevent.keysym; - RFB.messages.keyEvent(this._sock, keysym, down); - } + this.sendKey(keyevent.keysym, keyevent.code, down); }, _handleMouseButton: function (x, y, down, bmask) { diff --git a/tests/test.rfb.js b/tests/test.rfb.js index c8035f4..70504a5 100644 --- a/tests/test.rfb.js +++ b/tests/test.rfb.js @@ -193,7 +193,7 @@ describe('Remote Frame Buffer Protocol Client', function() { it('should send a single key with the given code and state (down = true)', function () { var expected = {_sQ: new Uint8Array(8), _sQlen: 0, flush: function () {}}; RFB.messages.keyEvent(expected, 123, 1); - client.sendKey(123, true); + client.sendKey(123, 'Key123', true); expect(client._sock).to.have.sent(expected._sQ); }); @@ -201,21 +201,29 @@ describe('Remote Frame Buffer Protocol Client', function() { var expected = {_sQ: new Uint8Array(16), _sQlen: 0, flush: function () {}}; RFB.messages.keyEvent(expected, 123, 1); RFB.messages.keyEvent(expected, 123, 0); - client.sendKey(123); + client.sendKey(123, 'Key123'); expect(client._sock).to.have.sent(expected._sQ); }); it('should not send the key if we are not in a normal state', function () { client._rfb_connection_state = "broken"; - client.sendKey(123); + client.sendKey(123, 'Key123'); expect(client._sock.flush).to.not.have.been.called; }); it('should not send the key if we are set as view_only', function () { client._view_only = true; - client.sendKey(123); + client.sendKey(123, 'Key123'); expect(client._sock.flush).to.not.have.been.called; }); + + it('should send QEMU extended events if supported', function () { + client._qemuExtKeyEventSupported = true; + var expected = {_sQ: new Uint8Array(12), _sQlen: 0, flush: function () {}}; + RFB.messages.QEMUExtendedKeyEvent(expected, 0x20, true, 0x0039); + client.sendKey(0x20, 'Space', true); + expect(client._sock).to.have.sent(expected._sQ); + }); }); describe('#clipboardPasteFrom', function () { @@ -2012,6 +2020,8 @@ describe('Remote Frame Buffer Protocol Client', function() { client._sock.open('ws://', 'binary'); client._sock._websocket._open(); sinon.spy(client._sock, 'flush'); + client._rfb_connection_state = 'connected'; + client._view_only = false; }); it('should send a key message on a key press', function () { -- 2.39.2