blob: 8613df3e5d32f2bb254efe1ac6b209b7aa97520c [file] [log] [blame]
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="copyright" content="Copyright (c) 2012, 2019 EclipseSource. This page is made available under license. For full details see the LEGAL in the documentation book that contains this page."/>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>Key and Mouse Event Handling in RAP</title>
<link rel="stylesheet" href="../../../PRODUCT_PLUGIN/book.css" type="text/css"/>
</head>
<body>
<h1>Key and Mouse Event Handling in RAP</h1>
<p>
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 controls. 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.
</p>
<p>
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.
</p>
<h2 id="mouse">Mouse Events</h2>
<p>
All mouse event types using in the
<em><a href="../reference/api/org/eclipse/swt/events/MouseListener.html">MouseListener</a></em>
interface are almost fully supported. (They can only detect the first three mouse buttons.)
They are:
</p>
<ul>
<li><em><a href="../reference/api/org/eclipse/swt/SWT.html#MouseDown">MouseDown</a></em></li>
<li><em><a href="../reference/api/org/eclipse/swt/SWT.html#MouseUp">MouseUp</a></em></li>
<li><em><a href="../reference/api/org/eclipse/swt/SWT.html#MouseDoubleClick">MouseDoubleClick</a></em></li>
</ul>
<p>
However, all other event mouse event types, used in
<em><a href="../reference/api/org/eclipse/swt/events/MouseTrackListener.html">MouseTrackListener</a></em>
and <em>MouseWheelListener</em>, are unsupported by the Java event API. Namely:
</p>
<ul>
<li><em><a href="../reference/api/org/eclipse/swt/SWT.html#MouseMove">MouseMove</a></em></li>
<li><em><a href="../reference/api/org/eclipse/swt/SWT.html#MouseEnter">MouseEnter</a></em></li>
<li><em><a href="../reference/api/org/eclipse/swt/SWT.html#MouseExit">MouseExit</a></em></li>
<li><em><a href="../reference/api/org/eclipse/swt/SWT.html#MouseWheel">MouseWheel</a></em></li>
</ul>
<p>
These can not be reasonably implemented as server-side events because the network latency would make them
barely usable. They are supported by <a href="scripting.html">ClientListener</a> though.
</p>
<p id ="mouse_filter">
Mouse events are only sent to the server (and only cause traffic) if they are fired on
widgets that have a <em><a href="../reference/api/org/eclipse/swt/events/MouseListener.html">MouseListener</a></em>
or
<a href="../reference/api/org/eclipse/swt/widgets/Listener.html">untyped listener</a>
for a mouse event attached.
As a side-effect, using a
<a href="../reference/api/org/eclipse/swt/widgets/Display.html#addFilter-int, org.eclipse.swt.widgets.Listener-">display filter</a>
does not work like in SWT.
Example:
</p>
<pre class="lang-java">display.addFilter( SWT.MouseDown, new Listener() { ... } );</pre>
<p>
This would catch all mouse events in SWT, but in RWT it will only receive those which
targets already have a mouse listener.
</p>
<h2 id="traverse">Traverse Events</h2>
<p>
Before we discuss key events, it is important to note that there are also
<q><a href="../reference/api/org/eclipse/swt/events/TraverseEvent.html">traverse events</a></q>,
which are related. Traverse events are fired <em>before</em> 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 <strong>not supported</strong> in RWT. (See
<a href="#prevent">"Prevent Default Operation"</a> for a workaround.)
</p>
<h2 id="key">Key Events</h2>
<h3>Event Order and Latency</h3>
<p>
There are two type of key events,
<em><a href="../reference/api/org/eclipse/swt/SWT.html#KeyDown">KeyDown</a></em>
and
<em><a href="../reference/api/org/eclipse/swt/SWT.html#KeyUp">KeyUp</a></em>.
In SWT, <em>KeyDown</em> is fired after pressing the key, then after a short delay
fired repeatedly until the key is released. Then <em>KeyUp</em> is fired. <br/>
In RWT, <em>KeyUp</em> is fired immediately after <em>KeyDown</em>, 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):
</p>
<table border = "1" cellpadding = "5" cellspacing = "0">
<tr>
<th align="left" >SWT</th>
<td style="padding:4px"><em>KeyDown</em></td>
<td>delay</td>
<td style="padding:4px"><em>KeyDown</em></td>
<td style="padding:4px"><em>KeyDown</em></td>
<td style="padding:4px"><em>KeyUp</em></td>
</tr>
<tr>
<th align="left" >RWT</th>
<td style="padding:4px"><em>KeyDown</em><br/><em>KeyUp</em></td>
<td>delay</td>
<td style="padding:4px"><em>KeyDown</em><br/><em>KeyUp</em></td>
<td style="padding:4px"><em>KeyDown</em><br/><em>KeyUp</em></td>
<td style="padding:4px">-</td>
</tr>
</table>
<p>
A key event is sent to the server immediately when the key is pressed (not on release).
This requests triggers both the <em>KeyDown</em> and <em>KeyUp</em> 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.<br/> If no latency is not acceptable at all, the key events would have
to be <a href="scripting.html">processed on the client</a> directly,
or a <a href="custom-widget.html">custom widget</a> has to be used.
</p>
<h3 id="prevent">Prevent Default Operation (CANCEL_KEYS)</h3>
<p>
The <em>KeyEvent</em> object has a
<em><a href="../reference/api/org/eclipse/swt/events/KeyEvent.html#doit">doit</a></em>
field (as do
<a href="../reference/api/org/eclipse/swt/widgets/Event.html#doit">untyped events</a>),
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
<em><a href="../reference/api/org/eclipse/swt/widgets/Text.html">Text</a></em>
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.
</p>
<p>
As an alternative, the <q>Cancel Keys</q> 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
<em><a href="../reference/api/org/eclipse/rap/rwt/RWT.html#CANCEL_KEYS">
RWT.CANCEL_KEYS</a></em> constant:
</p>
<pre class="lang-java">
widget.setData( RWT.CANCEL_KEYS, new String[] { &quot;CTRL+1&quot;, &quot;CTRL+2&quot; } ); </pre>
<p>
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 <q><code>CTRL+F</code></q> 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.
</p>
<p>
<em>Additional Notes:</em>
</p>
<ul>
<li>Valid patterns to identify key combinations are documented on the
<em><a href="../reference/api/org/eclipse/rap/rwt/RWT.html#ACTIVE_KEYS">RWT.ACTIVE_KEYS</a></em> constant.
</li>
<li>Browser-shortcuts of the pattern <q><code>ALT+[letter]</code></q> can often not be suppressed.</li>
<li>The Cancel Keys do not influence the key event handling. That means it works whether a
listener is attached or not, and canceled keys are still fired as an SWT key event.</li>
<li>This approach is single-sourcing capable. Since the <em>doit</em> field still
exists in RWT, and the list is attached using only
<em><a href="../reference/api/org/eclipse/swt/widgets/Widget.html#setData-java.lang.String-java.lang.Object-">setData</a></em>, both mechanisms
can be used in parallel.</li>
<li>An alternative to Cancel Keys is using a <a href = "scripting.html">ClientListener</a>,
which fully supports the <code><a href="../reference/jsdoc/symbols/Event.html#doit">doit</a></code> flag
for key events. This is useful if you wish to cancel keys depending on more complex
patterns that just a static list.</li>
</ul>
<h3 id="active" >Reduce Traffic (ACTIVE_KEYS)</h3>
<p>
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 <q>Active Keys</q> feature can help you.
Exactly like with <a href="#prevent">cancel keys</a>, active keys lets you attach a list of keys or key-combinations to a
widget (using <em><a href="../reference/api/org/eclipse/rap/rwt/RWT.html#ACTIVE_KEYS">RWT.ACTIVE_KEYS</a></em>).
As result, only key events that match
a combination on this list will be issued, drastically reducing traffic.
</p>
<p>
<em>Additional Notes:</em>
</p>
<ul>
<li>Valid patterns to identify key combinations are documented on the
<em><a href="../reference/api/org/eclipse/rap/rwt/RWT.html#ACTIVE_KEYS">RWT.ACTIVE_KEYS</a></em> constant.
</li>
<li>Unlike Cancel Keys, Active Keys are only relevant if a key listener is attached.</li>
<li>Despite the naming, Active Keys and Cancel Keys can be freely combined. They do not influence each other.</li>
<li>This approach is also single-sourcing capable, as long as the key listener does
not rely on the preselection of the Active Keys feature.</li>
</ul>
<h3 id="global">Global Key Event Handling (Keybindings)</h3>
<p>
Both <q>Active Keys</q> and <q>Cancel Keys</q> can also be used on an instance of
<em><a href="../reference/api/org/eclipse/swt/widgets/Display.html">Display</a></em>,
which is useful to allow keybindings ("shortcuts"). Active Keys work slightly different in
that case. Like with mouse events (see <a href="#mouse_filter">above</a>), a
<a href="../reference/api/org/eclipse/swt/widgets/Display.html#addFilter-int, org.eclipse.swt.widgets.Listener-">display filter</a>
usually catches
only key events when their target has a listener attached.
However, attaching a list of Active Keys to display
will result in <i>all</i> 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.
</p>
<p>
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
<em><a href="../reference/api/org/eclipse/swt/SWT.html#KeyDown">SWT.KeyDown</a></em>
has to be <a href="../reference/api/org/eclipse/swt/widgets/Display.html#addFilter-int, org.eclipse.swt.widgets.Listener-">added</a>,
where the pressed key combination has to be determined and handled.
</p>
<p>
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,
<q><code>SHIFT+[arrow key]</code></q> 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
<q><code>CTRL+TAB</code></q>
and <q><code>ALT+TAB</code></q> <strong>can not be used</strong>.
They will never be fired and can not be canceled.
</p>
<h3>Summary:</h3>
<p>
A key event will be issued if any if this is true:
</p>
<ul>
<li>The key combination is in the displays Active Keys list.</li>
<li>The focused widget has a key listener attached and no Active Keys list.</li>
<li>The focused widget has a key listener attached and the key combination is its Active Keys list.</li>
</ul>
<p>
A key event will cancelled if the browser supports it, and any if this is true:
</p>
<ul>
<li>The key combination is in the displays Cancel Keys list.</li>
<li>The focused widget has a Cancel Keys list and the key combination is in it.</li>
<li>A ClientListener sets the <code>doit</code> flag to false.</li>
</ul>
<h3>Mnemonics and Accelerators</h3>
<p>
Mnemonics and accelerators provide simpler alternatives to implementing shortcuts
via <a href="#global">global key event handling</a>, but will also influence
conventional key events.
</p>
<p>
Accelerators are shortcuts that can be associated with <em>MenuItem</em> widgets
using the method
<em><a href="../reference/api/org/eclipse/swt/widgets/MenuItem.html#setAccelerator-int-">MenuItem#setAccelerator</a></em>.
Entering the shortcut will fire a <em>Selection</em> event on the associated
<em>MenuItem</em>. The shortcuts will also be added to the displays <a href="#global">current
ACTIVE_KEYS list</a>. <strong>Take care not to overwrite them.</strong>
</p>
<p>
Mnemonics are a simple method to select widgets using the keyboard.
Any character in a widgets text can be made a mnemonic by inserting an ampersand character
(<code>&amp;</code>) before it. A list of supported widgets can be found
<a href="../reference/api/org/eclipse/rap/rwt/RWT.html#MNEMONIC_ACTIVATOR">here</a>.
</p>
<p>
Mnemonics must be enabled for the UISession by setting the modifier key or key-combination that
makes the mnemonics visible:
</p>
<pre class="lang-java">
display.setData( RWT.MNEMONIC_ACTIVATOR, "CTRL+ALT" );
</pre>
<p>
Any combination of <em>CTRL</em>, <em>SHIFT</em> and <em>ALT</em> is valid,
but <em>ALT</em> should not be used by itself since the browser may reserve this key for itself.
Holding the mnemonic activator will underline all onscreen mnemonic characters,
and pressing the matching key will then select or focus the associated widget.
</p>
<p>
Mnemonics have a higher priority than key bindings, accelerators or key events. This also means
that <strong>no key events will be fired for a key combination that triggers
a mnemnoic</strong>.
</p>
</body>
</html>