Defer handling of keypress via JS event queue.
authorMichael Jumper <zhangmaike@users.sourceforge.net>
Mon, 14 May 2012 16:17:15 +0000 (09:17 -0700)
committerMichael Jumper <zhangmaike@users.sourceforge.net>
Mon, 14 May 2012 16:17:15 +0000 (09:17 -0700)
src/main/resources/keyboard.js

index fd81341..08597ff 100644 (file)
@@ -265,79 +265,74 @@ Guacamole.Keyboard = function(element) {
     }
 
 
-    var KEYDOWN = 1;
-    var KEYPRESS = 2;
+    var keydown_code = null;
 
-    var keySymSource = null;
+    var deferred_keypress = null;
+    var keydown_keysym = null;
+    var keypress_keysym = null;
 
-    // When key pressed
-    var keydownCode = null;
-    element.onkeydown = function(e) {
-
-        // Only intercept if handler set
-        if (!guac_keyboard.onkeydown) return true;
+    function fireKeyPress() {
 
-        var keynum;
-        if (window.event) keynum = window.event.keyCode;
-        else if (e.which) keynum = e.which;
+        // Prefer keysym from keypress
+        var keysym = keypress_keysym || keydown_keysym;
+        var keynum = keydown_code;
 
-        // Ctrl/Alt/Shift
-        if (keynum == 16)      guac_keyboard.modifiers.shift = true;
-        else if (keynum == 17) guac_keyboard.modifiers.ctrl  = true;
-        else if (keynum == 18) guac_keyboard.modifiers.alt   = true;
+        if (keydownChar[keynum] != keysym) {
 
-        // If keysym is defined for given key code, key events can come from
-        // KEYDOWN.
-        var keysym = getKeySymFromKeyCode(keynum);
-        if (keysym)
-            keySymSource = KEYDOWN;
+            // If this button is already pressed, release first
+            var lastKeyDownChar = keydownChar[keydown_code];
+            if (lastKeyDownChar)
+                sendKeyReleased(lastKeyDownChar);
 
-        // Otherwise, if modifier keys are held down, try to get from keyIdentifier
-        else if ((guac_keyboard.modifiers.ctrl || guac_keyboard.modifiers.alt) && e.keyIdentifier) {
+            // Send event
+            keydownChar[keynum] = keysym;
+            sendKeyPressed(keysym);
 
-            // Get keysym from keyIdentifier
-            keysym = getKeySymFromKeyIdentifier(guac_keyboard.modifiers.shift, e.keyIdentifier);
+            // Clear old key repeat, if any.
+            stopRepeat();
 
-            // Get keysyms and events from KEYDOWN
-            keySymSource = KEYDOWN;
+            // Start repeating (if not a modifier key) after a short delay
+            if (keynum != 16 && keynum != 17 && keynum != 18)
+                repeatKeyTimeoutId = setTimeout(function() { startRepeat(keysym); }, 500);
 
         }
 
-        // Otherwise, resort to KEYPRESS
-        else
-            keySymSource = KEYPRESS;
+        // Done with deferred key event
+        deferred_keypress = null;
 
-        keydownCode = keynum;
-
-        // Ignore key if we don't need to use KEYPRESS.
-        // Send key event here
-        if (keySymSource == KEYDOWN) {
+    }
 
-            if (keydownChar[keynum] != keysym) {
+    // When key pressed
+    element.onkeydown = function(e) {
 
-                // Send event
-                keydownChar[keynum] = keysym;
-                var returnValue = sendKeyPressed(keysym);
+        // Only intercept if handler set
+        if (!guac_keyboard.onkeydown) return true;
 
-                // Clear old key repeat, if any.
-                stopRepeat();
+        var keynum;
+        if (window.event) keynum = window.event.keyCode;
+        else if (e.which) keynum = e.which;
 
-                // Start repeating (if not a modifier key) after a short delay
-                if (keynum != 16 && keynum != 17 && keynum != 18)
-                    repeatKeyTimeoutId = setTimeout(function() { startRepeat(keysym); }, 500);
+        // Ctrl/Alt/Shift
+        if (keynum == 16)      guac_keyboard.modifiers.shift = true;
+        else if (keynum == 17) guac_keyboard.modifiers.ctrl  = true;
+        else if (keynum == 18) guac_keyboard.modifiers.alt   = true;
 
-                // Use return code provided by handler
-                return returnValue;
+        // Try to get keysym from keycode
+        keydown_keysym = getKeySymFromKeyCode(keynum);
 
-            }
+        // Also try to get get keysym from keyIdentifier
+        if (e.keyIdentifier)
+            keydown_keysym = getKeySymFromKeyIdentifier(guac_keyboard.modifiers.shift, e.keyIdentifier);
 
-            // Default to canceling event if no keypress is being sent, but
-            // source of events is keydown.
-            return false;
+        // Set keycode which will be associated with any future keypress
+        keydown_code = keynum;
 
-        }
+        // Defer handling of event until after any other pending
+        // key events.
+        if (!deferred_keypress)
+            deferred_keypress = window.setTimeout(fireKeyPress, 0);
 
-        return true;
+        return false;
 
     };
 
@@ -353,30 +348,13 @@ Guacamole.Keyboard = function(element) {
         if (window.event) keynum = window.event.keyCode;
         else if (e.which) keynum = e.which;
 
-        var keysym = getKeySymFromCharCode(keynum);
-        if (keysym && keydownChar[keynum] != keysym) {
+        keypress_keysym = getKeySymFromCharCode(keynum);
 
-            // If this button already pressed, release first
-            var lastKeyDownChar = keydownChar[keydownCode];
-            if (lastKeyDownChar)
-                sendKeyReleased(lastKeyDownChar);
-
-            keydownChar[keydownCode] = keysym;
-
-            // Clear old key repeat, if any.
-            stopRepeat();
-
-            // Send key event
-            var returnValue = sendKeyPressed(keysym);
-
-            // Start repeating (if not a modifier key) after a short delay
-            repeatKeyTimeoutId = setTimeout(function() { startRepeat(keysym); }, 500);
-
-            return returnValue;
-        }
+        // Defer handling of event until after any other pending
+        // key events.
+        if (!deferred_keypress)
+            deferred_keypress = window.setTimeout(fireKeyPress, 0);
 
-        // Default to canceling event if no keypress is being sent, but
-        // source of events is keypress.
         return false;
 
     };