Commit c96f9003 authored by Joel Martin's avatar Joel Martin

Refactor keyboard event handling.

This is part of addressing issue #21 - non-US keyboard layouts.

There are several challenges when dealing with keyboard events:
  - The meaning and use of keyCode, charCode and which depends on
    both the browser and the event type (keyDown/Up vs keyPress).
  - We cannot automatically determine the keyboard layout
  - The keyDown and keyUp events have a keyCode value that has not
    been translated by modifier keys.
  - The keyPress event has a translated (for layout and modifiers)
    character code but the attribute containing it differs. keyCode
    contains the translated value in WebKit (Chrome/Safari), Opera
    11 and IE9. charCode contains the value in WebKit and Firefox.
    The which attribute contains the value on WebKit, Firefox and
    Opera 11.
  - The keyDown/Up keyCode value indicates (sort of) the physical
    key was pressed but only for standard US layout. On a US
    keyboard, the '-' and '_' characters are on the same key and
    generate a keyCode value of 189. But on an AZERTY keyboard even
    though they are different physical keys they both still
    generate a keyCode of 189!
  - To prevent a key event from propagating to the browser and
    causing unwanted default actions (such as closing a tab,
    opening a menu, shifting focus, etc) we must suppress this
    event in both keyDown and keyPress because not all key strokes
    generate on a keyPress event. Also, in WebKit and IE9
    suppressing the keyDown prevents a keyPress but other browsers
    still generated a keyPress even if keyDown is suppressed.

For safe key events, we wait until the keyPress event before
reporting a key down event. For unsafe key events, we report a key
down event when the keyDown event fires and we suppress any further
actions (including keyPress).

In order to report a key up event that matches what we reported
for the key down event, we keep a list of keys that are currently
down. When the keyDown event happens, we add the key event to the
list. If it is a safe key event, then we update the which attribute
in the most recent item on the list when we received a keyPress
event (keyPress should immediately follow keyDown). When we
received a keyUp event we search for the event on the list with
a matching keyCode and we report the character code using the value
in the 'which' attribute that was stored with that key.

For character codes above 255 we use a character code to keysym lookup
table. This is generated using the util/u2x11 script contributed by
Colin Dean (xvpsource.org).
parent d1bd5ec7
This diff is collapsed.
...@@ -29,17 +29,22 @@ ...@@ -29,17 +29,22 @@
var width = 400, height = 200; var width = 400, height = 200;
var iterations; var iterations;
var newline = "\n";
if (Util.Engine.trident) {
var newline = "<br>\n";
}
function message(str) { function message(str) {
console.log(str); console.log(str);
cell = $D('messages'); cell = $D('messages');
cell.innerHTML += msg_cnt + ": " + str + "\n"; cell.innerHTML += msg_cnt + ": " + str + newline;
cell.scrollTop = cell.scrollHeight; cell.scrollTop = cell.scrollHeight;
msg_cnt++;
} }
function mouseButton(x, y, down, bmask) { function mouseButton(x, y, down, bmask) {
msg = 'mouse x,y: ' + x + ',' + y + ' down: ' + down; msg = 'mouse x,y: ' + x + ',' + y + ' down: ' + down;
msg += ' bmask: ' + bmask; msg += ' bmask: ' + bmask;
console.log(msg);
message(msg); message(msg);
} }
...@@ -48,9 +53,11 @@ ...@@ -48,9 +53,11 @@
//console.log(msg); //console.log(msg);
} }
function keyPress(keysym, down) { function keyPress(keysym, down, e) {
msg = "keyPress keysym: " + keysym + " down: " + down; var d = down ? "down" : " up ";
console.log(msg); msg = "keyPress " + d + " keysym: " + keysym +
" (key: " + e.keyCode + ", char: " + e.charCode +
", which: " + e.which +")";
message(msg); message(msg);
} }
......
<!DOCTYPE html>
<html>
<head><title>Input Test</title></head>
<body>
<br><br>
Canvas:<br>
<canvas id="canvas" width="640" height="20"
style="border-style: dotted; border-width: 1px;">
Canvas not supported.
</canvas>
<br>
Results:<br>
<textarea id="messages" style="font-size: 9;" cols=80 rows=25></textarea>
</body>
<!--
<script type='text/javascript'
src='http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js'></script>
-->
<script src="../include/util.js"></script>
<script src="../include/webutil.js"></script>
<script src="../include/base64.js"></script>
<script src="../include/canvas.js"></script>
<script>
var msg_cnt = 0;
var width = 400, height = 200;
var canvas;
function message(str) {
console.log(str);
msg_cnt++;
cell = $D('messages');
cell.innerHTML += msg_cnt + ": " + str + "\n";
cell.scrollTop = cell.scrollHeight;
}
function keyDown(evt) {
var e = (evt ? evt : window.event);
msg = "Dn: key:" + e.keyCode + " char:" + e.charCode + " which:" + e.which + " id:" + e.keyIdentifier + " ksym:" + getKeysym(evt) + " alt:" + e.altKey + " shift:" + e.shiftKey + " ctrl:" + e.ctrlKey;
message(msg);
if (e.stopPropagation) { e.stopPropagation(); }
else { e.cancelBubble = true; }
/*
if (e.preventDefault) { Util.Debug("here1"); e.preventDefault(); }
else { Util.Debug("here2"); e.returnValue = false; }
*/
return false;
}
function keyPress(evt) {
var e = (evt ? evt : window.event);
msg = "Pr: key:" + e.keyCode + " char:" + e.charCode + " which:" + e.which + " id:" + e.keyIdentifier + " ksym:" + getKeysym(evt) + " alt:" + e.altKey + " shift:" + e.shiftKey + " ctrl:" + e.ctrlKey;
message(msg);
if (e.stopPropagation) { e.stopPropagation(); }
else { e.cancelBubble = true; }
if (e.preventDefault) { e.preventDefault(); }
else { e.returnValue = false; }
return false;
}
function keyUp(evt) {
var e = (evt ? evt : window.event);
msg = "Up: key:" + e.keyCode + " char:" + e.charCode + " which:" + e.which + " id:" + e.keyIdentifier + " ksym:" + getKeysym(evt) + " alt:" + e.altKey + " shift:" + e.shiftKey + " ctrl:" + e.ctrlKey;
message(msg);
/*
if (e.stopPropagation) { e.stopPropagation(); }
else { e.cancelBubble = true; }
if (e.preventDefault) { e.preventDefault(); }
else { e.returnValue = false; }
return false;
*/
}
window.onload = function() {
var c = $D('canvas');
canvas = new Canvas({'target' : c});
canvas.resize(width, height, true);
//canvas.start(keyPress);
Util.addEvent(document, 'keydown', keyDown);
Util.addEvent(document, 'keyup', keyUp);
Util.addEvent(document, 'keypress', keyPress);
message("Canvas initialized");
}
</script>
</html>
#!/bin/bash
#
# Convert "U+..." commented entries in /usr/include/X11/keysymdef.h
# into JavaScript for use by noVNC. Note this is likely to produce
# a few duplicate properties with clashing values, that will need
# resolving manually.
#
# Colin Dean <colin@xvpsource.org>
#
regex="^#define[ \t]+XK_[A-Za-z0-9_]+[ \t]+0x([0-9a-fA-F]+)[ \t]+\/\*[ \t]+U\+([0-9a-fA-F]+)[ \t]+[^*]+.[ \t]+\*\/[ \t]*$"
echo "unicodeTable = {"
while read line; do
if echo "${line}" | egrep -qs "${regex}"; then
x11=$(echo "${line}" | sed -r "s/${regex}/\1/")
vnc=$(echo "${line}" | sed -r "s/${regex}/\2/")
if echo "${vnc}" | egrep -qs "^00[2-9A-F][0-9A-F]$"; then
: # skip ISO Latin-1 (U+0020 to U+00FF) as 1-to-1 mapping
else
# note 1-to-1 is possible (e.g. for Euro symbol, U+20AC)
echo " 0x${vnc} : 0x${x11},"
fi
fi
done < /usr/include/X11/keysymdef.h | uniq
echo "};"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment