Table of Contents
Key Event Handling
Introduction
Key event handling is an area where browsers extremely differ. To be able to do predictable key event handling in different browsers we define our own model for key event handling and map the browser models to it.
Key event handling is so hard because of five shortcomings:
- Key code vs. Char code: Key events return codes for the actual key that is pressed (the key code) and the character that will be printed on screen (char code). These codes are represented as numbers and it is sometimes hard to figure out if a given code is to be understood as a key code or rather a char code. This is a severe problem because some numbers can be interpreted as either key code or char code. For example in key press events in Opera it cannot be decided whether the returned code is a key code or a char code.
- Keyboard layout matters: The key code of keys that require the shift key on some keyboard layouts are not reliable. The key code that is generated depends on the current language-specific keyboard layout of the user. The key "#" for example can be reached on a German keyboard layout without the shift key and generates the key code 35, while the same character composed with Shift+3 on an American layout produces a key code of 51.
- Repeated key events: If the user keeps pressing a key the browsers fires some events repeatedly. Normally, only the keypress event is expected to be repeated, but no other events. Under Windows however, both Internet Explorer and Firefox repeat the keydown event as well.
- Incomplete event sequences: Not every browser fires for every key the complete event sequence of keydown, keypress and keyup. Internet Explorer does not fire keypress events if the corresponding key is non-printable (i.e. function key F1). Firefox does not fire keypress events for modifier keys (i.e. Ctrl or Alt) and Safari does not fire any key events for modifier keys at all.
- Char code not for all events: Char codes can only reliably be detected in keypress events. Only Safari also sets the char code in keyup and keydown events. The good news is that the character code in keypress events is reliable and always represents the Unicode number of the character that would be printed on the screen.
Result
Because of all these browser incompatibilities qooxdoo defines its own key event model. It guarantees unified behavior across Internet Explorer, Firefox and - where possible - Safari and Opera.
We map the keyCode and charCode property of the browser's key event object to a keyIdentifier for keydown, keypress and keyup events. The keyIdentifier contains a textual representation of the pressed key.
If a key is printable a keyinput event is fired along with a keypress event. In keyinput events the "charCode" property of the event object is set to the Unicode number of the character that would have been printed on screen.
qooxdoo supports the following key events:
keydown: Fires when a key is pressed.keyIdentifieris set.keypress: Fires repeatedly while the key is held down.keyIdentifieris set.keyinput: Fires repeatedly while the key is held down and the key is printable.charCodeis set.keyup: Fires when a key is released.keyIdentifieris set.
For any key press those events are always fired in this order. While the user holds down a key, the keypress event is fired repeatedly. In cases where the key has a printable output a input event is fired repeatedly as well.
The key event object returned by keydown, keypress and keyup events has a "keyIdentifier" property. It contains a string describing the pressed key. The keyIdentifier contains one of the strings defined in the key identifier white list (see below) or Unidentified.
The key event object returned by keyinput has a keyIdentifier property as well. It contains the Unicode number of the resulting character after the operating system has munged the pressed key with the active modification keys (e.g. Numpad, Shift, Ctrl, Alt, …).
As a relief to every application developer a white list of characters exists that can be detected reliably across all supported browsers and platforms. Such a list is needed because not every "keydown" and "keyup" sends out a usable key code.
White list (for keyup and keydown)
- non-printable special keys (e.g. PageUp, F1, Del, Insert, …)
- a-z / A-Z (always sends uppercase)
- 0-9
- + - * /
For the full list, see the qx.event.type.KeyEvent, documentation for the keyIdentifer property, which can be found here in the API documentation.
Firefox issues
If the Alt key under Mac OS X is used to compose a character, no valid key codes are set. Only the keyinput has usable information. Unfortunately, almost all character keys are thus unusable in combination with the Alt key. This means that key commands like Alt+A will not work. Special keys (e.g F1, Up, Down, …) however do generate usable key codes if Alt is pressed.
Safari issues
Modifier keys (Shift, Alt, …) do not fire any events. You can detect modifier keys in combination with other keys but you cannot detect an independent modifier key press.
Opera issues
Opera is the most broken browser concerning keyboard events. It supports enough to use the keyboard for navigation but complex key commands cannot be detected.
- All key combinations containing the Alt key cannot be detected.
- The modifier flags are only set in keypress events. This makes
qx.client.Commandin Opera unable to catch most interesting keyboard shortcuts. - Opera sets only the keyCode property of the DOM event. Because of that, it is not possible to decide if the code in
keypressevents is a key code or a char code. Since both codes may overlap, collisions may occur. In need for a consistent solution, the current key handler implementation always prefers the special keys over the normal keys. For example, "s" and "F5" both have a code of 115 in Opera. In this case qooxdoo would prefer "F5" over the "s" key.
Differences to the old key handler
The new key handler is compatible with the old one, with one minor exception:
keydown events in Internet Explorer and the Windows version of Firefox do no longer repeatedly fire keydown events while a key is held down. This is consistent with all other browsers and also Firefox on non-Windows platforms. If your code relies on repeated keydown events you have to convert it to use keypress or keyinput events instead.
With the old handler it was necessary to use "keydown" because Internet Explorer did not repeat "keypress" events for special keys. This worked with IE and the Windows version of Firefox but with no other browser. The new key handler solves this by "converting" the repeated "keydown" events into "keypress" events on-the-fly.
keyIdentifier property when working with KeyEvents. This property is always reliable and works consistently across all supported browsers.
keyCode support is deprecated and will be removed in a further release.
