| <?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[] { "CTRL+1", "CTRL+2" } ); </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>&</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> |