Today's reading finishes our look into the mechanics of implementing user interfaces, by examining input in more detail. We'll look mainly at keyboard and mouse input, but also multitouch interfaces like those on modern smartphones and tablets. This reading has two key ideas for thinking about input. First, that **state machines** are a great way to think about and implement tricky input handling (like direct manipulation operations). Second, that events **propagate** through the view tree, and by understanding this process, you can make good design choices about where to attach the listeners that handle them.
Raw Input Events
- The usual input hardware has state:
- ~100 keys on the keyboard (down or up)
- (x,y) mouse cursor position on the screen
- one, two, or three mouse buttons (down or up)
- A "raw" input event occurs when this state changes
Input Event | jQuery Event |
key pressed or released | `keydown`, `keyup` |
mouse moved | `mousemove` |
button pressed or released | `mousedown`, `mouseup` |
There are two major categories of input events: raw and translated.
A raw event comes from a state transition in the input hardware. Mouse movements, mouse button down and up, and keyboard key down and up are the raw events seen in almost every capable GUI system. A toolkit that does not provide separate events for down and up is poorly designed, and makes it difficult or impossible to implement input effects like drag-and-drop or game controls. And yet some toolkits like that did exist at one time, particularly in the bad old days of handheld and mobile phone programming.
Translated Events
- Raw events are translated into higher-level events
Input Event | jQuery Event |
Clicking | `click` |
Double-clicking | `dblclick` |
Character typed | `keypress` |
Entering or exiting an object's bounding box | `mouseenter`, `mouseleave` |
For many GUI components, the raw events are too low-level, and must be translated into higher-level events. For example, a mouse button press and release is translated into a mouse click event -- assuming the mouse didn't move much between press and release - if it did, these events would be interpreted as a drag rather than a click, so a click event isn't produced.
Key down and up events are translated into character-typed events, which take modifiers (Shift/Ctrl/Alt) and input methods (e.g., entering for Chinese characters on a standard keyboard) into account to produce a Unicode character rather than a physical keyboard key. In addition, if you hold a key down, multiple character-typed events may be generated by an autorepeat mechanism (usually built into the operating system or GUI toolkit). When a mouse movement causes the mouse to enter or leave a component's bounding box, entry and exit events are generated, so that the component can give feedback - e.g., visually highlighting a button, or changing the mouse cursor to a text I-bar or a pointing finger.
State Machines Translate Events
Here's our first example of using state machines for input handling. Inside the GUI toolkit, a state machine is handling the translation of raw events into higher-level events. Here's how the click event is generated - after a mousedown and mouseup, as long as the mouse hasn't moved (much) between those two events. Question for you: what is the threshold on your favorite GUI toolkit? If it's measured in pixels, how large is it? Does the mouse exiting the bounding box of the graphical object trigger the threshold regardless of pixel distance?
In this case, the raw events (down, up, move) are still delivered to your application, along with the translated event (click). This means that if your application is handling both the raw events and the translated events, it has to be prepared to expect this. This often comes up with double-click, for example: your application will see two click events before it sees the double-click event. As a result, you can't make click do something incompatible with double-click.
But occasionally, low-level events are **consumed** in the process of translating them to higher-level events. It's a difference you have to pay attention to in your particular toolkit.
Keyboard Focus
- An object in the view tree has the keyboard focus
Input event | jQuery event |
Keyboard focus gained or lost | `focusin`, `focusout` |
- Changing keyboard focus
- by user input event: e.g., mouse down, Tab
- programmatically by a method call
- Not all HTML elements can have keyboard focus by default