From 52c70b080626c18a8d1167bad7513a0cfb6f3545 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 14 May 2012 13:21:43 -0700 Subject: [PATCH] Only cancel keydown if not typable. Release Ctrl and Alt if actually typing a character via keypress (if they are not functioning as Ctrl or Alt). Cancel keydown if Ctrl or Alt (but not both) are held, even if we expect the character to be typable. --- src/main/resources/keyboard.js | 52 ++++++++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/src/main/resources/keyboard.js b/src/main/resources/keyboard.js index 526af2f..6787af8 100644 --- a/src/main/resources/keyboard.js +++ b/src/main/resources/keyboard.js @@ -381,6 +381,29 @@ Guacamole.Keyboard = function(element) { // Done with deferred key event deferred_keypress = null; + keypress_keysym = null; + keydown_keysym = null; + keydown_code = null; + + } + + function isTypable(keyIdentifier) { + + // Find unicode prefix + var unicodePrefixLocation = keyIdentifier.indexOf("U+"); + if (unicodePrefixLocation == -1) + return false; + + // Parse codepoint value + var hex = keyIdentifier.substring(unicodePrefixLocation+2); + var codepoint = parseInt(hex, 16); + + // If control character, not typable + if (codepoint <= 0x1F) return false; + if (codepoint >= 0x7F && codepoint <= 0x9F) return false; + + // Otherwise, typable + return true; } @@ -388,7 +411,7 @@ Guacamole.Keyboard = function(element) { element.onkeydown = function(e) { // Only intercept if handler set - if (!guac_keyboard.onkeydown) return true; + if (!guac_keyboard.onkeydown) return; var keynum; if (window.event) keynum = window.event.keyCode; @@ -403,8 +426,22 @@ Guacamole.Keyboard = function(element) { keydown_keysym = getKeySymFromKeyCode(keynum); // Also try to get get keysym from keyIdentifier - if (e.keyIdentifier) - keydown_keysym = getKeySymFromKeyIdentifier(guac_keyboard.modifiers.shift, e.keyIdentifier); + if (e.keyIdentifier) { + + keydown_keysym = keydown_keysym || + getKeySymFromKeyIdentifier(guac_keyboard.modifiers.shift, e.keyIdentifier); + + // Prevent default if non-typable character or if modifier combination + // likely to be eaten by browser otherwise (NOTE: We must not prevent + // default for Ctrl+Alt, as that combination is commonly used for + // AltGr. If we receive AltGr, we need to handle keypress, which + // means we cannot cancel keydown). + if (!isTypable(e.keyIdentifier) + || ( guac_keyboard.modifiers.ctrl && !guac_keyboard.modifiers.alt) + || (!guac_keyboard.modifiers.ctrl && guac_keyboard.modifiers.alt)) + e.preventDefault(); + + } // Set keycode which will be associated with any future keypress keydown_code = keynum; @@ -414,8 +451,6 @@ Guacamole.Keyboard = function(element) { if (!deferred_keypress) deferred_keypress = window.setTimeout(fireKeyPress, 0); - return false; - }; // When key pressed @@ -424,14 +459,17 @@ Guacamole.Keyboard = function(element) { // Only intercept if handler set if (!guac_keyboard.onkeydown) return true; - if (keySymSource != KEYPRESS) return false; - var keynum; if (window.event) keynum = window.event.keyCode; else if (e.which) keynum = e.which; keypress_keysym = getKeySymFromCharCode(keynum); + // If event identified as a typable character (keypress involved) + // then release Ctrl and Alt (if pressed) + if (guac_keyboard.modifiers.ctrl) sendKeyReleased(0xFFE3); + if (guac_keyboard.modifiers.alt) sendKeyReleased(0xFFE9); + // Defer handling of event until after any other pending // key events. if (!deferred_keypress) -- 1.7.10.4