1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
|
Enable Keyboard Events
======================
Previous versions of Enable had just one keyboard event, a 'key_pressed'
event. This event conflated which key(s) were physically being pressed
with the text which should be generated by that keypress. All the underlying
windowing/event systems have a way of distinguishing these two pieces of
information, either by issuing separate events for each (Wx, Pyglet, Vtk), or
by storing them as different attributes on the event object (Qt).
In addition, there was no way to detect a key-up event. This is a comparatively
minor use case, but potentially useful for doing things like toggling pointer
states to indicate different mouse behaviour when modifiers keys are pressed.
New Events
----------
key_pressed:
We will keep the 'key_pressed' event. However the semantics will change so
that it will keep track of the physical key being pressed rather than the
text being entered. Thus pressing the 'a' key with the shift key down will
result in an event with the 'character' attribute set to 'a', instead of 'A'
as it would be now. The lower-case version of the character will be the
canonical representation of the key, since that will cause minimal problems
with existing event handlers in Enable and Chaco.
The character mapping will be used as it is now to map special keys to
standard strings (like right arrow generating the string 'right').
In addition, events will now be generated by pressing modifier keys by
themselves (eg. pressing shift will generate an event).
Most Chaco code will continue to use key_pressed as the primary event to
listen to, it will just work more consistently than it did before. Some
code may need to change to reflect the change in what the character
attribute returns (XXX or we add a 'key' attribute and deprecate the
'character' attribute).
On Wx this event will be generated by EVT_KEY_DOWN, on Qt, this event
will be generated by keyPressEvent, but will access the 'key()' attribute
rather than the 'text()' attribute.
key_released:
We will introduce a new 'key_released' event, which is essentially the
mirror image of the 'key_pressed' event.
On Wx this event will be generated by EVT_KEY_UP, on Qt, this event
will be generated by keyReleaseEvent, but will access the 'key()' attribute
rather than the 'text()' attribute.
character:
We will introduce a new 'character' event, which will hold the
unicode characters, if any, that are generated by the key press
event. It is possible that this event may also be generated by
other mechanisms in the future, like pasting text. The event may
hold multiple characters.
This event will not be generated if the key_pressed event is handled.
This is largely because this is the way that wx works, but it also makes
a certain amount of sense from an interaction modelling point of view.
This will never do key mapping to standard Enable names for non-printable
characters: if there is no appropriate unicode representation, no event
will be emitted.
The handful of Enable widgets which expect actual text input will be
changed to use the character event instead of the key_pressed event.
On Wx this event will be generated by EVT_CHAR, on Qt, this event
will be generated by keyPressEvent, but will access the 'text()' attribute
rather than the 'key()' attribute.
Why Three Events?
-----------------
Qt's two-event model is generally nicer and cleaner, but adapting the other
backends to use that model would require holding global state from EVT_KEY_DOWN
(or its equivalent) to fold in to the Enable event generated from EVT_CHAR.
This seems potentially fragile. The other alternative would be to try to work
out from the EVT_KEY_DOWN what text would be generated, and that seems even more
fragile.
On the other hand, adapting Qt to a 3-event model is straightforward: on
keyPressedEvent we generate a 'key_pressed' event, and if text() is non-empty,
we subsequently also emit a 'character' event.
|