summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsamhed <samuel@cendio.se>2014-04-04 17:45:04 +0200
committersamhed <samuel@cendio.se>2014-04-04 17:45:04 +0200
commit0bb6a8c50e969846c5854b3c5f4805bf3d53224f (patch)
treeb91fa0843afa4fc4d966268309c69974bced971e
parentde8edde4a0531b0ab3bdd983736133dd39162b10 (diff)
downloadnovnc-0bb6a8c50e969846c5854b3c5f4805bf3d53224f.tar.gz
Fixes issue 344 - problem with backspace on Android.
-rw-r--r--include/ui.js90
1 files changed, 66 insertions, 24 deletions
diff --git a/include/ui.js b/include/ui.js
index bc5c997..f6afccc 100644
--- a/include/ui.js
+++ b/include/ui.js
@@ -13,6 +13,7 @@
// Load supporting scripts
window.onscriptsload = function () { UI.load(); };
+window.onload = function () { UI.keyboardinputReset(); };
Util.load_scripts(["webutil.js", "base64.js", "websock.js", "des.js",
"keysymdef.js", "keyboard.js", "input.js", "display.js",
"jsunzip.js", "rfb.js", "keysym.js"]);
@@ -26,6 +27,8 @@ popupStatusOpen : false,
clipboardOpen: false,
keyboardVisible: false,
hideKeyboardTimeout: null,
+lastKeyboardinput: null,
+defaultKeyboardinputLen: 100,
extraKeysVisible: false,
ctrlOn: false,
altOn: false,
@@ -807,7 +810,8 @@ showKeyboard: function() {
l = kbi.value.length;
if(UI.keyboardVisible === false) {
kbi.focus();
- kbi.setSelectionRange(l, l); // Move the caret to the end
+ try { kbi.setSelectionRange(l, l); } // Move the caret to the end
+ catch (err) {} // setSelectionRange is undefined in Google Chrome
UI.keyboardVisible = true;
skb.className = "noVNC_status_button_selected";
} else if(UI.keyboardVisible === true) {
@@ -828,33 +832,71 @@ keepKeyboard: function() {
}
},
-// When keypress events are left uncought, catch the input events from
-// the keyboardinput element instead and send the corresponding key events.
+keyboardinputReset: function() {
+ var kbi = $D('keyboardinput');
+ kbi.value = Array(UI.defaultKeyboardinputLen).join("_");
+ UI.lastKeyboardinput = kbi.value;
+},
+
+// When normal keyboard events are left uncought, use the input events from
+// the keyboardinput element instead and generate the corresponding key events.
+// This code is required since some browsers on Android are inconsistent in
+// sending keyCodes in the normal keyboard events when using on screen keyboards.
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
- }
+ var newValue, oldValue, newLen, oldLen;
+ newValue = event.target.value;
+ oldValue = UI.lastKeyboardinput;
+
+ try {
+ // Try to check caret position since whitespace at the end
+ // will not be considered by value.length in some browsers
+ newLen = Math.max(event.target.selectionStart, newValue.length);
+ } catch (err) {
+ // selectionStart is undefined in Google Chrome
+ newLen = newValue.length;
+ }
+ oldLen = oldValue.length;
+
+ var backspaces;
+ var inputs = newLen - oldLen;
+ if (inputs < 0)
+ backspaces = -inputs;
+ else
+ backspaces = 0;
+
+ // Compare the old string with the new to account for
+ // text-corrections or other input that modify existing text
+ for (var i = 0; i < Math.min(oldLen, newLen); i++) {
+ if (newValue.charAt(i) != oldValue.charAt(i)) {
+ inputs = newLen - i;
+ backspaces = oldLen - i;
+ break;
}
}
- // 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 = '\u00a0';
+ // Send the key events
+ for (var i = 0; i < backspaces; i++)
+ UI.rfb.sendKey(XK_BackSpace);
+ for (var i = newLen - inputs; i < newLen; i++)
+ UI.rfb.sendKey(newValue.charCodeAt(i));
+
+ // Control the text content length in the keyboardinput element
+ if (newLen > 2 * UI.defaultKeyboardinputLen) {
+ UI.keyboardinputReset();
+ } else if (newLen < 1) {
+ // There always have to be some text in the keyboardinput
+ // element with which backspace can interact.
+ UI.keyboardinputReset();
+ // This sometimes causes the keyboard to disappear for a second
+ // but it is required for the android keyboard to recognize that
+ // text has been added to the field
+ event.target.blur();
+ // This has to be ran outside of the input handler in order to work
+ setTimeout(function() { UI.keepKeyboard(); }, 0);
+
+ } else {
+ UI.lastKeyboardinput = newValue;
+ }
},
keyInputBlur: function() {