Fixes issue 344 - problem with backspace on Android.

This commit is contained in:
samhed 2014-04-04 17:45:04 +02:00
parent 32359bb6a1
commit 7a92e38f37

View File

@ -13,6 +13,7 @@
// Load supporting scripts // Load supporting scripts
window.onscriptsload = function () { UI.load(); }; window.onscriptsload = function () { UI.load(); };
window.onload = function () { UI.keyboardinputReset(); };
Util.load_scripts(["webutil.js", "base64.js", "websock.js", "des.js", Util.load_scripts(["webutil.js", "base64.js", "websock.js", "des.js",
"keysymdef.js", "keyboard.js", "input.js", "display.js", "keysymdef.js", "keyboard.js", "input.js", "display.js",
"jsunzip.js", "rfb.js", "keysym.js"]); "jsunzip.js", "rfb.js", "keysym.js"]);
@ -26,6 +27,8 @@ popupStatusOpen : false,
clipboardOpen: false, clipboardOpen: false,
keyboardVisible: false, keyboardVisible: false,
hideKeyboardTimeout: null, hideKeyboardTimeout: null,
lastKeyboardinput: null,
defaultKeyboardinputLen: 100,
extraKeysVisible: false, extraKeysVisible: false,
ctrlOn: false, ctrlOn: false,
altOn: false, altOn: false,
@ -807,7 +810,8 @@ showKeyboard: function() {
l = kbi.value.length; l = kbi.value.length;
if(UI.keyboardVisible === false) { if(UI.keyboardVisible === false) {
kbi.focus(); 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; UI.keyboardVisible = true;
skb.className = "noVNC_status_button_selected"; skb.className = "noVNC_status_button_selected";
} else if(UI.keyboardVisible === true) { } else if(UI.keyboardVisible === true) {
@ -828,33 +832,71 @@ keepKeyboard: function() {
} }
}, },
// When keypress events are left uncought, catch the input events from keyboardinputReset: function() {
// the keyboardinput element instead and send the corresponding key events. var kbi = $D('keyboardinput');
keyInput: function(event) { kbi.value = Array(UI.defaultKeyboardinputLen).join("_");
var elem, input, len; UI.lastKeyboardinput = kbi.value;
elem = $D('keyboardinput'); },
input = event.target.value;
len = (elem.selectionStart > input.length) ? elem.selectionStart : input.length;
if (len < 1) { // something removed? // When normal keyboard events are left uncought, use the input events from
UI.rfb.sendKey(0xff08); // send BACKSPACE // the keyboardinput element instead and generate the corresponding key events.
} else if (len > 1) { // new input? // This code is required since some browsers on Android are inconsistent in
for (var i = len-1; i > 0; i -= 1) { // sending keyCodes in the normal keyboard events when using on screen keyboards.
// HTML does not consider trailing whitespaces as a part of the string keyInput: function(event) {
// and they are therefore undefined. var newValue, oldValue, newLen, oldLen;
if (input[len-i] !== undefined) { newValue = event.target.value;
UI.rfb.sendKey(input.charCodeAt(len-i)); // send charCode oldValue = UI.lastKeyboardinput;
} else {
UI.rfb.sendKey(0x0020); // send SPACE 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 // Send the key events
// another session there has to always be text in the for (var i = 0; i < backspaces; i++)
// keyboardinput element with which backspace can interact. UI.rfb.sendKey(XK_BackSpace);
// We also need to reset the input field text to avoid overflow. for (var i = newLen - inputs; i < newLen; i++)
elem.value = '\u00a0'; 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() { keyInputBlur: function() {