Most SWT widgets provide distinctive events that are well suited for typical use cases of that widget, like selection events and modify events. These events should, if possible, always be favored over key and mouse events, which are available on all widgets. Not only are the more specific events fired at the appropriate times and provide all relevant informations, but they can also be more optimized by the RAP framework regarding performance, network-traffic and compatibility. Still, key and mouse events are sometimes necessary to use, especially when adding or modifying widget-behavior, or for global event handling.
Due to their diverse nature, differing implementation, and the high frequency in which they may be fired, key and mouse events are a major challenge in a web-environment, especially with a client-server architecture like RAP. While RWT provides a SWT-like API for key and mouse events, some specifics should be noted.
All mouse event types using in the MouseListener interface are almost fully supported. (They can only detect the first three mouse buttons.) They are:
However, all other event mouse event types, used in MouseTrackListener and MouseWheelListener, are unsupported/missing. Namely:
They can not be reasonably implemented because the network latency would make them barely usable. They are mostly supported in RAP ClientScripting though.
Mouse events are only sent to the server (and only cause traffic) if they are fired on widgets that have a MouseListener or untyped listener for a mouse event attached. As a side-effect, using a display filter does not work like in SWT. Example:
display.addFilter( SWT.MouseDown, new Listener() { ... } );
This would catch all mouse events in SWT, but in RWT it will only receive those which targets already have a mouse listener.
Before we discuss key events, it is important to note that there are also
traverse events
,
which are related. Traverse events are fired before a key event, and only for keys
that can change the focus. (For example Escape, Tab, Arrows.) The idea is that you can
prevent or manipulate the focus change, but that is not supported in RWT. (See
"Prevent Default Operation" for a workaround.)
There are two type of key events,
KeyDown
and
KeyUp.
In SWT, KeyDown is fired after pressing the key, then after a short delay
fired repeatedly until the key is released. Then KeyUp is fired.
In RWT, KeyUp is fired immediately after KeyDown, even if the key
is not released. After the short delay, both events are fired repeatedly until the key is
released. An Example for pressing and holding a key in SWT and RWT (read left to right):
SWT | KeyDown | delay | KeyDown | KeyDown | KeyUp |
---|---|---|---|---|---|
RWT | KeyDown KeyUp |
delay | KeyDown KeyUp |
KeyDown KeyUp |
- |
A key event is sent to the server immediately when the key is pressed (not on release).
This requests triggers both the KeyDown and KeyUp event.
If a key is held down, or when typing very fast, the new key events may be put into a queue
on the client until the current key event is finished being processed. This also increases the
latency a bit.
If no latency is not acceptable at all, the key events would have
to be processed on the client directly,
or a custom widget has to be used.
The KeyEvent object has a doit field (as do untyped events), which is true by default. In SWT, this field can be set to false to prevent the default operation associated with pressing or releasing this key, like inserting a character in a Text widget. RAP supported this in a limited capacity until 1.4, but support was discontinued in 1.5. The reason for this was that it worked unreliably and prevented a number of bugs from being fixed.
As an alternative, the Cancel Keys
feature was introduced. It is slightly less flexible,
but very powerful and still single-sourcing capable. Instead of reacting to a key event,
it allows to attach a list of keys or key-combinations to a widget using the
RWT.CANCEL_KEYS constant:
widget.setData( RWT.CANCEL_KEYS, new String[] { "CTRL+1", "CTRL+2" } );
When the given key-combination is pressed while
the widget is focused, the operation is canceled. It also cancels operations that could only
be prevented on traverse events in SWT. Event more importantly, it is possible to
suppress most (not all) browser shortcuts that way, which would otherwise be triggered at
the same moment that your key listener is executed. For example
usually opens
and focuses a search-dialog in the browser, but the RAP application might want to use it
to focus its own search-field.
CTRL+F
Additional Notes:
ALT+[letter]
can often not be suppressed.
As explained above, each keystroke creates at least one HTTP-request. Obviously this can
create a lot of traffic. If this is a concern, the Active Keys
feature can help you.
Exactly like with cancel keys, active keys lets you attach a list of keys or key-combinations to a
widget (using RWT.ACTIVE_KEYS).
As result, only key events that match
a combination on this list will be issued, drastically reducing traffic.
Additional Notes:
Both Active Keys
and Cancel Keys
can also be used on an instance of
Display,
which is useful to allow keybindings ("shortcuts"). Active Keys work slightly different in
that case. Like with mouse events (see above), a
display filter
usually catches
only key events when their target has a listener attached.
However, attaching a list of Active Keys to display
will result in all key events that match a list entry to be fired, regardless
of the focused widget. Likewise, a list of Cancel Keys attached to the display is always
in effect.
To implement global shortcuts, one would first attach a list of all shortcuts as Active Keys to display. The same list can then be used again for Cancel Keys to prevent any undesired operations to be triggered by any of the keys. Then a filter for SWT.KeyDown has to be added, where the pressed key combination has to be determined and handled.
The combinations for global shortcuts should be carefully chosen, so they
do not to interfere any of the core functionality of a widget or the browser. For example,
is not a good choice, since this is used by many widgets for selection.
Similarly, many users might be accustomed to use F5 to reload the page. The combinations
SHIFT+[arrow key]
and CTRL+TAB
can not be used.
They will never be fired and can not be canceled.
ALT+TAB
A key event will be issued if any if this is true:
A key event will cancelled if the browser supports it, and any if this is true: