Handle repeated key events correctly.

- No leaking memory.
 - Make the viewer side be in charge of handling repeated key events.
This commit is contained in:
Hirokazu Takahashi 2012-09-26 16:21:10 +09:00
parent 70dae7d4f3
commit 0820c08dfc
2 changed files with 40 additions and 46 deletions

View File

@ -18,7 +18,7 @@ function Keyboard(defaults) {
var that = {}, // Public API methods var that = {}, // Public API methods
conf = {}, // Configuration attributes conf = {}, // Configuration attributes
keyDownList = []; // List of depressed keys keyDownMap = {}; // List of depressed keys
// (even if they are happy) // (even if they are happy)
// Configuration attributes // Configuration attributes
@ -198,12 +198,15 @@ function getKeysym(evt) {
return keysym; return keysym;
} }
function show_keyDownList(kind) { function show_keyDownMap(kind) {
var c; var c = 0;
var msg = "keyDownList (" + kind + "):\n"; var keyCode, fevt;
for (c = 0; c < keyDownList.length; c++) { var msg = "keyDownMap (" + kind + "):\n";
msg = msg + " " + c + " - keyCode: " + keyDownList[c].keyCode + for (keyCode in keyDownMap) {
" - which: " + keyDownList[c].which + "\n"; fevt = getKeyEvent(keyCode, false);
msg = msg + " " + c + " - keyCode: " + fevt.keyCode +
" - which: " + fevt.which + "\n";
c++;
} }
Util.Debug(msg); Util.Debug(msg);
} }
@ -221,20 +224,15 @@ function copyKeyEvent(evt) {
} }
function pushKeyEvent(fevt) { function pushKeyEvent(fevt) {
keyDownList.push(fevt); keyDownMap[fevt.keyCode] = fevt;
} }
function getKeyEvent(keyCode, pop) { function getKeyEvent(keyCode, pop) {
var i, fevt = null; var fevt = keyDownMap[keyCode];
for (i = keyDownList.length-1; i >= 0; i--) { if (typeof(fevt) === 'undefined') {
if (keyDownList[i].keyCode === keyCode) { fevt = null;
if ((typeof(pop) !== "undefined") && (pop)) { } else if ((typeof(pop) !== "undefined") && (pop)) {
fevt = keyDownList.splice(i, 1)[0]; delete keyDownMap[keyCode];
} else {
fevt = keyDownList[i];
}
break;
}
} }
return fevt; return fevt;
} }
@ -318,16 +316,11 @@ function onKeyDown(e) {
" (onKeyDown key: " + evt.keyCode + " (onKeyDown key: " + evt.keyCode +
", which: " + evt.which + ")"); ", which: " + evt.which + ")");
conf.onKeyPress(keysym, 1, evt); conf.onKeyPress(keysym, 1, evt);
pushKeyEvent(fevt);
} }
suppress = true; suppress = true;
} }
if (! ignoreKeyEvent(evt)) {
// Add it to the list of depressed keys
pushKeyEvent(fevt);
//show_keyDownList('down');
}
if (suppress) { if (suppress) {
// Suppress bubbling/default actions // Suppress bubbling/default actions
Util.stopEvent(e); Util.stopEvent(e);
@ -344,7 +337,7 @@ function onKeyPress(e) {
return true; return true;
} }
var evt = (e ? e : window.event), var evt = (e ? e : window.event),
kdlen = keyDownList.length, keysym = null; kdlen = keyDownMap.length, keysym = null;
//Util.Debug("onKeyPress kC:" + evt.keyCode + " cC:" + evt.charCode + " w:" + evt.which); //Util.Debug("onKeyPress kC:" + evt.keyCode + " cC:" + evt.charCode + " w:" + evt.which);
if (((evt.which !== "undefined") && (evt.which === 0)) || if (((evt.which !== "undefined") && (evt.which === 0)) ||
@ -361,23 +354,17 @@ function onKeyPress(e) {
keysym = getKeysym(evt); keysym = getKeysym(evt);
// Modify the the which attribute in the depressed keys list so //show_keyDownMap('press');
// that the keyUp event will be able to have the character code
// translation available.
if (kdlen > 0) {
keyDownList[kdlen-1].keysym = keysym;
} else {
Util.Warn("keyDownList empty when keyPress triggered");
}
//show_keyDownList('press');
// Send the translated keysym // Send the translated keysym
if (conf.onKeyPress && (keysym > 0)) { if (conf.onKeyPress && (keysym > 0)) {
Util.Debug("onKeyPress down, keysym: " + keysym + Util.Debug("onKeyPress down, keysym: " + keysym +
" (onKeyPress key: " + evt.keyCode + " (onKeyPress key: " + evt.keyCode +
", which: " + evt.which + ")"); ", which: " + evt.which + ")");
conf.onKeyPress(keysym, 1, evt); Util.Debug("onKeyPress up, keysym: " + keysym +
" (onKeyPress key: " + evt.keyCode +
", which: " + evt.which + ")");
conf.onKeyPress(keysym, 2, evt);
} }
// Stop keypress events just in case // Stop keypress events just in case
@ -397,12 +384,12 @@ function onKeyUp(e) {
if (fevt) { if (fevt) {
keysym = fevt.keysym; keysym = fevt.keysym;
} else { } else {
Util.Warn("Key event (keyCode = " + evt.keyCode + //Util.Debug("Key event (keyCode = " + evt.keyCode +
") not found on keyDownList"); // ") not found on keyDownMap");
keysym = 0; keysym = 0;
} }
//show_keyDownList('up'); //show_keyDownMap('up');
if (conf.onKeyPress && (keysym > 0)) { if (conf.onKeyPress && (keysym > 0)) {
//Util.Debug("keyPress up, keysym: " + keysym + //Util.Debug("keyPress up, keysym: " + keysym +
@ -418,12 +405,9 @@ function onKeyUp(e) {
function allKeysUp() { function allKeysUp() {
Util.Debug(">> Keyboard.allKeysUp"); Util.Debug(">> Keyboard.allKeysUp");
if (keyDownList.length > 0) { var keyCode, keysym, fevt;
Util.Info("Releasing pressed/down keys"); for (keyCode in keyDownMap) {
} fevt = getKeyEvent(keyCode, true);
var i, keysym, fevt = null;
for (i = keyDownList.length-1; i >= 0; i--) {
fevt = keyDownList.splice(i, 1)[0];
keysym = fevt.keysym; keysym = fevt.keysym;
if (conf.onKeyPress && (keysym > 0)) { if (conf.onKeyPress && (keysym > 0)) {
Util.Debug("allKeysUp, keysym: " + keysym + Util.Debug("allKeysUp, keysym: " + keysym +

View File

@ -601,7 +601,17 @@ keyPress = function(keysym, down) {
if (conf.view_only) { return; } // View only, skip keyboard events if (conf.view_only) { return; } // View only, skip keyboard events
arr = keyEvent(keysym, down); if (down === 2) {
// keypress event
// Send a keyup event here to avoid letting the server side generate
// repeated-key events. Otherwise, both sides will independently
// generate key down and press events against the same key.
arr = keyEvent(keysym, 1);
arr = arr.concat(keyEvent(keysym, 0));
} else {
// keydown or keyup event
arr = keyEvent(keysym, down);
}
arr = arr.concat(fbUpdateRequests()); arr = arr.concat(fbUpdateRequests());
ws.send(arr); ws.send(arr);
}; };