From ca9a9964a053f6cbb3f66a536941905858b146fd Mon Sep 17 00:00:00 2001 From: Phil Driscoll Date: Thu, 13 Jun 2013 11:10:04 +0100 Subject: [PATCH 01/11] Fix onMouseDisable so that clicks outside the canvas are propagated --- include/input.js | 6 +++--- include/util.js | 8 +++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/include/input.js b/include/input.js index b996c7d5..3b2443a0 100644 --- a/include/input.js +++ b/include/input.js @@ -611,9 +611,9 @@ function onMouseDisable(e) { evt = (e ? e : window.event); pos = Util.getEventPosition(e, conf.target, conf.scale); /* Stop propagation if inside canvas area */ - if ((pos.x >= 0) && (pos.y >= 0) && - (pos.x < conf.target.offsetWidth) && - (pos.y < conf.target.offsetHeight)) { + if ((pos.realx >= 0) && (pos.realy >= 0) && + (pos.realx < conf.target.offsetWidth) && + (pos.realy < conf.target.offsetHeight)) { //Util.Debug("mouse event disabled"); Util.stopEvent(e); return false; diff --git a/include/util.js b/include/util.js index dd1f252f..8893591c 100644 --- a/include/util.js +++ b/include/util.js @@ -298,9 +298,11 @@ Util.getEventPosition = function (e, obj, scale) { if (typeof scale === "undefined") { scale = 1; } - var x = Math.max(Math.min(docX - pos.x, obj.width-1), 0); - var y = Math.max(Math.min(docY - pos.y, obj.height-1), 0); - return {'x': x / scale, 'y': y / scale}; + var realx = docX - pos.x; + var realy = docY - pos.y; + var x = Math.max(Math.min(realx, obj.width-1), 0); + var y = Math.max(Math.min(realy, obj.height-1), 0); + return {'x': x / scale, 'y': y / scale, 'realx': realx / scale, 'realy': realy / scale}; }; From dfcedffc16a278815f56b78d6543f524fd4ba1cc Mon Sep 17 00:00:00 2001 From: samhed Date: Mon, 22 Jul 2013 15:46:59 +0200 Subject: [PATCH 02/11] Make noVNC follow the RFB protocol and keep only one outstanding framebufferUpdate request at a time. --- include/rfb.js | 51 +++++++++++++------------------------------------- 1 file changed, 13 insertions(+), 38 deletions(-) diff --git a/include/rfb.js b/include/rfb.js index 16ae76d5..c15bc30d 100644 --- a/include/rfb.js +++ b/include/rfb.js @@ -103,7 +103,6 @@ var that = {}, // Public API methods fb_height = 0, fb_name = "", - last_req_time = 0, rre_chunk_sz = 100, timing = { @@ -148,9 +147,6 @@ Util.conf_defaults(conf, that, defaults, [ ['viewportDrag', 'rw', 'bool', false, 'Move the viewport on mouse drags'], - ['check_rate', 'rw', 'int', 217, 'Timing (ms) of send/receive check'], - ['fbu_req_rate', 'rw', 'int', 1413, 'Timing (ms) of frameBufferUpdate requests'], - // Callback functions ['onUpdateState', 'rw', 'func', function() { }, 'onUpdateState(rfb, state, oldstate, statusMsg): RFB state update/change '], @@ -569,44 +565,18 @@ function genDES(password, challenge) { return (new DES(passwd)).encrypt(challenge); } -function flushClient() { - if (mouse_arr.length > 0) { - //send(mouse_arr.concat(fbUpdateRequests())); - ws.send(mouse_arr); - setTimeout(function() { - ws.send(fbUpdateRequests()); - }, 50); - - mouse_arr = []; - return true; - } else { - return false; - } -} - // overridable for testing checkEvents = function() { - var now; - if (rfb_state === 'normal' && !viewportDragging) { - if (! flushClient()) { - now = new Date().getTime(); - if (now > last_req_time + conf.fbu_req_rate) { - last_req_time = now; - ws.send(fbUpdateRequests()); - } - } + if (rfb_state === 'normal' && !viewportDragging && mouse_arr.length > 0) { + ws.send(mouse_arr); + mouse_arr = []; } - setTimeout(checkEvents, conf.check_rate); }; keyPress = function(keysym, down) { - var arr; - if (conf.view_only) { return; } // View only, skip keyboard events - arr = keyEvent(keysym, down); - arr = arr.concat(fbUpdateRequests()); - ws.send(arr); + ws.send(keyEvent(keysym, down)); }; mouseButton = function(x, y, down, bmask) { @@ -633,7 +603,8 @@ mouseButton = function(x, y, down, bmask) { mouse_arr = mouse_arr.concat( pointerEvent(display.absX(x), display.absY(y)) ); - flushClient(); + ws.send(mouse_arr); + mouse_arr = []; }; mouseMove = function(x, y) { @@ -656,7 +627,9 @@ mouseMove = function(x, y) { if (conf.view_only) { return; } // View only, skip mouse events mouse_arr = mouse_arr.concat( - pointerEvent(display.absX(x), display.absY(y)) ); + pointerEvent(display.absX(x), display.absY(y))); + + checkEvents(); }; @@ -905,8 +878,7 @@ init_msg = function() { timing.pixels = 0; ws.send(response); - /* Start pushing/polling */ - setTimeout(checkEvents, conf.check_rate); + checkEvents(); if (conf.encrypt) { updateState('normal', "Connected (encrypted) to: " + fb_name); @@ -934,6 +906,9 @@ normal_msg = function() { switch (msg_type) { case 0: // FramebufferUpdate ret = framebufferUpdate(); // false means need more data + if (ret) { + ws.send(fbUpdateRequests()); + } break; case 1: // SetColourMapEntries Util.Debug("SetColourMapEntries"); From c39df031d865c9abbd8d9e394f4116dc161285da Mon Sep 17 00:00:00 2001 From: Anton Lundin Date: Fri, 2 Aug 2013 09:56:15 +0200 Subject: [PATCH 03/11] clearTimeout instead of clearInterval for timers We create timeouts, not intervals. Then we need to clear them with clearTimeout. --- include/rfb.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/rfb.js b/include/rfb.js index 16ae76d5..5258f09d 100644 --- a/include/rfb.js +++ b/include/rfb.js @@ -403,7 +403,7 @@ updateState = function(state, statusMsg) { } if (msgTimer) { - clearInterval(msgTimer); + clearTimeout(msgTimer); msgTimer = null; } @@ -444,13 +444,13 @@ updateState = function(state, statusMsg) { if (connTimer && (rfb_state !== 'connect')) { Util.Debug("Clearing connect timer"); - clearInterval(connTimer); + clearTimeout(connTimer); connTimer = null; } if (disconnTimer && (rfb_state !== 'disconnect')) { Util.Debug("Clearing disconnect timer"); - clearInterval(disconnTimer); + clearTimeout(disconnTimer); disconnTimer = null; } From 76e262134e5ba795f9cc77dcfb8dad5ece99ea70 Mon Sep 17 00:00:00 2001 From: samhed Date: Thu, 29 Aug 2013 13:38:12 +0200 Subject: [PATCH 04/11] * Removed fbu-requests from the places I missed earlier. * Added a few clarifying comments. --- include/rfb.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/include/rfb.js b/include/rfb.js index c15bc30d..53c38796 100644 --- a/include/rfb.js +++ b/include/rfb.js @@ -595,7 +595,6 @@ mouseButton = function(x, y, down, bmask) { return; } else { viewportDragging = false; - ws.send(fbUpdateRequests()); // Force immediate redraw } } @@ -873,7 +872,7 @@ init_msg = function() { response = pixelFormat(); response = response.concat(clientEncodings()); - response = response.concat(fbUpdateRequests()); + response = response.concat(fbUpdateRequests()); // initial fbu-request timing.fbu_rt_start = (new Date()).getTime(); timing.pixels = 0; ws.send(response); @@ -907,6 +906,7 @@ normal_msg = function() { case 0: // FramebufferUpdate ret = framebufferUpdate(); // false means need more data if (ret) { + // only allow one outstanding fbu-request at a time ws.send(fbUpdateRequests()); } break; @@ -1571,8 +1571,6 @@ encHandlers.DesktopSize = function set_desktopsize() { conf.onFBResize(that, fb_width, fb_height); display.resize(fb_width, fb_height); timing.fbu_rt_start = (new Date()).getTime(); - // Send a new non-incremental request - ws.send(fbUpdateRequests()); FBU.bytes = 0; FBU.rects -= 1; @@ -1798,7 +1796,6 @@ that.sendCtrlAltDel = function() { arr = arr.concat(keyEvent(0xFFFF, 0)); // Delete arr = arr.concat(keyEvent(0xFFE9, 0)); // Alt arr = arr.concat(keyEvent(0xFFE3, 0)); // Control - arr = arr.concat(fbUpdateRequests()); ws.send(arr); }; @@ -1815,7 +1812,6 @@ that.sendKey = function(code, down) { arr = arr.concat(keyEvent(code, 1)); arr = arr.concat(keyEvent(code, 0)); } - arr = arr.concat(fbUpdateRequests()); ws.send(arr); }; From 968431dd46246ea03d9d4c7f5c7be03ad7b0c88b Mon Sep 17 00:00:00 2001 From: samhed Date: Tue, 17 Sep 2013 15:01:52 +0200 Subject: [PATCH 05/11] Catch input events to make the onscreen keyboard work in chrome on android. --- include/ui.js | 45 ++++++++++++++++++++++++++++++++++++++++----- vnc.html | 2 +- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/include/ui.js b/include/ui.js index b933d312..1dfc67cf 100644 --- a/include/ui.js +++ b/include/ui.js @@ -155,7 +155,8 @@ addMouseHandlers: function() { $D("noVNC_mouse_button2").onclick = function () { UI.setMouseButton(4); }; $D("noVNC_mouse_button4").onclick = function () { UI.setMouseButton(0); }; $D("showKeyboard").onclick = UI.showKeyboard; - //$D("keyboardinput").onkeydown = function (event) { onKeyDown(event); }; + + $D("keyboardinput").oninput = UI.keyInput; $D("keyboardinput").onblur = UI.keyInputBlur; $D("sendCtrlAltDelButton").onclick = UI.sendCtrlAltDel; @@ -701,17 +702,51 @@ setViewDrag: function(drag) { // On touch devices, show the OS keyboard showKeyboard: function() { + var kbi, skb, l; + kbi = $D('keyboardinput'); + skb = $D('showKeyboard'); + l = kbi.value.length; if(UI.keyboardVisible === false) { - $D('keyboardinput').focus(); + kbi.focus(); + kbi.setSelectionRange(l, l); // Move the caret to the end UI.keyboardVisible = true; - $D('showKeyboard').className = "noVNC_status_button_selected"; + skb.className = "noVNC_status_button_selected"; } else if(UI.keyboardVisible === true) { - $D('keyboardinput').blur(); - $D('showKeyboard').className = "noVNC_status_button"; + kbi.blur(); + skb.className = "noVNC_status_button"; UI.keyboardVisible = false; } }, +// When keypress events are left uncought, catch the input events from +// the keyboardinput element instead and send the corresponding key events. +keyInput: function(event) { + var elem, input, len; + elem = $D('keyboardinput'); + input = event.target.value; + len = (elem.selectionStart > input.length) ? elem.selectionStart : input.length; + + if (len < 1) { // something removed? + UI.rfb.sendKey(0xff08); // send BACKSPACE + } else if (len > 1) { // new input? + for (var i = len-1; i > 0; i -= 1) { + // HTML does not consider trailing whitespaces as a part of the string + // and they are therefore undefined. + if (input[len-i] !== undefined) { + UI.rfb.sendKey(input.charCodeAt(len-i)); // send charCode + } else { + UI.rfb.sendKey(0x0020); // send SPACE + } + } + } + + // In order to be able to delete text which has been written in + // another session there has to always be text in the + // keyboardinput element with which backspace can interact. + // We also need to reset the input field text to avoid overflow. + elem.value = "x"; +}, + keyInputBlur: function() { $D('showKeyboard').className = "noVNC_status_button"; //Weird bug in iOS if you change keyboardVisible diff --git a/vnc.html b/vnc.html index 66b70259..89349f22 100644 --- a/vnc.html +++ b/vnc.html @@ -67,7 +67,7 @@ id="showKeyboard" class="noVNC_status_button" value="Keyboard" title="Show Keyboard"/> + id="keyboardinput" class="" value=" "/> From eb955f8c20b64991e90b2b6f04148a98f1fb9321 Mon Sep 17 00:00:00 2001 From: John Dewey Date: Sat, 21 Sep 2013 12:19:09 -0700 Subject: [PATCH 06/11] The https check should come first A similar change was made to ui.js in #252. --- vnc_auto.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vnc_auto.html b/vnc_auto.html index 2aa21889..bd905ffa 100644 --- a/vnc_auto.html +++ b/vnc_auto.html @@ -128,12 +128,12 @@ // if port == 80 (or 443) then it won't be present and should be // set manually if (!port) { - if (window.location.protocol.substring(0,4) == 'http') { - port = 80; - } - else if (window.location.protocol.substring(0,5) == 'https') { + if (window.location.protocol.substring(0,5) == 'https') { port = 443; } + else if (window.location.protocol.substring(0,4) == 'http') { + port = 80; + } } // If a token variable is passed in, set the parameter in a cookie. From 82744aa8ee760520dafad8a3bd299879927d3398 Mon Sep 17 00:00:00 2001 From: John Dewey Date: Sat, 21 Sep 2013 12:19:59 -0700 Subject: [PATCH 07/11] Removed trailing white space terds --- vnc_auto.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vnc_auto.html b/vnc_auto.html index bd905ffa..7704bf69 100644 --- a/vnc_auto.html +++ b/vnc_auto.html @@ -2,7 +2,7 @@ -