Previously we identified keys in keyboard events by the 'key' property
if it was set, and 'keyCode' otherwise.
This turns out to be problematic as Firefox no longer leaves 'key'
undefined (so we fall back to using 'keyCode'), but instead sets 'key'
to 'MozPrintableKey' for all printable keys.
This meant that when (printable) keys are released, we can't match it
against the corresponding keydown event, and instead just send a keyup
event for the last keydown received.
Now, if both 'key' and 'keyCode' are set, use the concatenation of both.
Otherwise prefer 'keyCode', as that is at least unique for every key.
This should let us release the right keys on keyup events.
When shortcut modifiers (modifier keys such as CTRL, which do not participate in
composing character input) are pressed, we try to suppress the keypress
event, as browsers do not reliably generate it. This means that
subsequent key events are decoded only based on the keydown event.
Due to a type error (comparing a string to a number), shift was
mistakenly treated as a shortcut modifier, preventing text input which
relied on shift, such as _ and %, from being generated.