| <?xml version="1.0" encoding="UTF-8" standalone="no"?> |
| <!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 http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Chapter 21. guacamole-common-js</title><link rel="stylesheet" type="text/css" href="gug.css" /><meta name="generator" content="DocBook XSL Stylesheets Vsnapshot" /><link rel="home" href="index.html" title="Guacamole Manual" /><link rel="up" href="developers-guide.html" title="Part II. Developer's Guide" /><link rel="prev" href="guacamole-common.html" title="Chapter 20. guacamole-common" /><link rel="next" href="guacamole-ext.html" title="Chapter 22. guacamole-ext" /> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, target-densitydpi=device-dpi"/> |
| </head><body> |
| <!-- CONTENT --> |
| |
| <div id="page"><div id="content"> |
| <div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Chapter 21. guacamole-common-js</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="guacamole-common.html">Prev</a> </td><th width="60%" align="center">Part II. Developer's Guide</th><td width="20%" align="right"> <a accesskey="n" href="guacamole-ext.html">Next</a></td></tr></table><hr /></div><div xml:lang="en" class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a id="guacamole-common-js"></a>Chapter 21. guacamole-common-js</h2></div></div></div><div class="toc"><p><strong>Table of Contents</strong></p><dl class="toc"><dt><span class="section"><a href="guacamole-common-js.html#guacamole-client">Guacamole client</a></span></dt><dt><span class="section"><a href="guacamole-common-js.html#http-tunnel">HTTP tunnel</a></span></dt><dt><span class="section"><a href="guacamole-common-js.html#input-abstraction">Input abstraction</a></span></dt><dd><dl><dt><span class="section"><a href="guacamole-common-js.html#guacamole-mouse">Mouse</a></span></dt><dt><span class="section"><a href="guacamole-common-js.html#guacamole-touch">Touch</a></span></dt><dt><span class="section"><a href="guacamole-common-js.html#guacamole-keyboard">Keyboard</a></span></dt></dl></dd><dt><span class="section"><a href="guacamole-common-js.html#on-screen-keyboard">On-screen keyboard</a></span></dt><dd><dl><dt><span class="section"><a href="guacamole-common-js.html#keyboard-layouts">Keyboard layouts</a></span></dt><dt><span class="section"><a href="guacamole-common-js.html#displaying-osk">Displaying the keyboard</a></span></dt><dt><span class="section"><a href="guacamole-common-js.html#styling-the-keyboard">Styling the keyboard</a></span></dt><dt><span class="section"><a href="guacamole-common-js.html#osk-event-handling">Handling key events</a></span></dt></dl></dd></dl></div><a id="idm46420845024048" class="indexterm"></a><a id="idm46420845022704" class="indexterm"></a><p>The Guacamole project provides a JavaScript API for interfacing with |
| other components that conform to the design of Guacamole, such as |
| projects using libguac or guacamole-common. This API is called |
| guacamole-common-js.</p><p>guacamole-common-js provides a JavaScript implementation of a |
| Guacamole client, as well as tunneling mechanisms for getting protocol |
| data out of JavaScript and into guacd or the server side of a web |
| application.</p><p>For convenience, it also provides mouse and keyboard abstraction objects that translate |
| JavaScript mouse, touch, and keyboard events into consistent data that Guacamole can more |
| easily digest. The extendable on-screen keyboard that was developed for the Guacamole web |
| application is also included.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="guacamole-client"></a>Guacamole client</h2></div></div></div><p>The main benefit to using the JavaScript API is the full Guacamole |
| client implementation, which implements all Guacamole instructions, |
| and makes use of the tunnel implementations provided by both the |
| JavaScript and Java APIs.</p><p>Using the Guacamole client is straightforward. The client, like |
| all other objects within the JavaScript API, is within the |
| <code class="code">Guacamole</code> namespace. It is instantiated given an |
| existing, unconnected tunnel:</p><div class="informalexample"><pre class="programlisting">var client = new Guacamole.Client(tunnel);</pre></div><p>Once you have the client, it won't immediately appear within the |
| DOM. You need to add its display element manually:</p><div class="informalexample"><pre class="programlisting">document.body.appendChild(client.getDisplay().getElement());</pre></div><p>At this point, the client will be visible, rendering all updates |
| as soon as they are received through the tunnel.</p><div class="informalexample"><pre class="programlisting">client.connect();</pre></div><p>It is possible to pass arbitrary data to the tunnel during |
| connection which can be used for authentication or for choosing a |
| particular connection. When the <code class="methodname">connect()</code> |
| function of the Guacamole client is called, it in turn calls the |
| <code class="methodname">connect()</code> function of the tunnel |
| originally given to the client, establishing a connection.</p><div class="important"><h3 class="title">Important</h3><p>When creating the <code class="classname">Guacamole.Client</code>, the |
| tunnel used must not already be connected. The |
| <code class="classname">Guacamole.Client</code> will call the |
| <code class="methodname">connect()</code> function for you when its |
| own <code class="methodname">connect()</code> function is invoked. If |
| the tunnel is already connected when it is given to the |
| <code class="classname">Guacamole.Client</code>, connection may not |
| work at all.</p></div><p>In general, all instructions available within the Guacamole |
| protocol are automatically handled by the Guacamole client, |
| including instructions related to audio and video. The only |
| instructions which you must handle yourself are "name" (used to name |
| the connection), "clipboard" (used to update clipboard data on the |
| client side), and "error" (used when something goes wrong |
| server-side). Each of these instructions has a corresponding event |
| handler; you need only supply functions to handle these events. If |
| any of these event handlers are left unset, the corresponding |
| instructions are simply ignored.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="http-tunnel"></a>HTTP tunnel</h2></div></div></div><p>Both the Java and JavaScript API implement corresponding ends of |
| an HTTP tunnel, based on |
| <code class="classname">XMLHttpRequest</code>.</p><p>The tunnel is a true stream - there is no polling. An initial |
| request is made from the JavaScript side, and this request is |
| handled on the Java side. While this request is open, data is |
| streamed along the connection, and instructions within this stream |
| are handled as soon as they are received by the client.</p><p>While data is being streamed along this existing connection, a |
| second connection attempt is made. Data continues to be streamed |
| along the original connection until the server receives and handles |
| the second request, at which point the original connection closes |
| and the stream is transferred to the new connection.</p><p>This process repeats, alternating between active streams, thus |
| creating an unbroken sequence of instructions, while also allowing |
| JavaScript to free any memory used by the previously active |
| connection.</p><p>The tunnel is created by supplying the relative URL to the |
| server-side tunnel servlet:</p><div class="informalexample"><pre class="programlisting">var tunnel = new Guacamole.Tunnel("tunnel");</pre></div><p>Once created, the tunnel can be passed to a |
| <code class="classname">Guacamole.Client</code> for use in a Guacamole |
| connection.</p><p>The tunnel actually takes care of the Guacamole protocol parsing |
| on behalf of the client, triggering "oninstruction" events for every |
| instruction received, splitting each element into elements of an |
| array so that the client doesn't have to.</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="input-abstraction"></a>Input abstraction</h2></div></div></div><p>Browsers can be rather finicky when it comes to keyboard and mouse |
| input, not to mention touch events. There is little agreement on |
| which keyboard events get fired when, and what detail about the |
| event is made available to JavaScript. Touch and mouse events can |
| also cause confusion, as most browsers will generate |
| <span class="emphasis"><em>both</em></span> events when the user touches the |
| screen (for compatibility with JavaScript code that only handles |
| mouse events), making it more difficult for applications to support |
| both mouse and touch independently.</p><p>The Guacamole JavaScript API abstracts mouse, keyboard, and touch |
| interaction, providing several helper objects which act as an |
| abstract interface between you and the browser events.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a id="guacamole-mouse"></a>Mouse</h3></div></div></div><p>Mouse event abstraction is provided by the |
| <code class="classname">Guacamole.Mouse</code> object. Given an |
| arbitrary DOM element, <code class="classname">Guacamole.Mouse</code> |
| triggers <span class="property">onmousedown</span>, |
| <span class="property">onmousemove</span>, and |
| <span class="property">onmouseup</span> events which are consistent |
| across browsers. This object only response. to true mouse |
| events. Mouse events which are actually the result of touch |
| events are ignored.</p><div class="informalexample"><pre class="programlisting">var element = document.getElementById("some-arbitrary-id"); |
| var mouse = new Guacamole.Mouse(element); |
| |
| mouse.onmousedown = |
| mouse.onmousemove = |
| mouse.onmouseup = function(state) { |
| |
| // Do something with the mouse state received ... |
| |
| };</pre></div><p>The handles of each event are given an instance of |
| <code class="classname">Guacamole.Mouse.State</code> which |
| represents the current state of the mouse, containing the state |
| of each button (including the scroll wheel) as well as the X and |
| Y coordinates of the pointer in pixels.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a id="guacamole-touch"></a>Touch</h3></div></div></div><p>Touch event abstraction is provided by either |
| <code class="classname">Guacamole.Touchpad</code> (emulates a |
| touchpad to generate artificial mouse events) or |
| <code class="classname">Guacamole.Touchscreen</code> (emulates a |
| touchscreen, again generating artificial mouse events). |
| Guacamole uses the touchpad emulation, as this provides the most |
| flexibility and mouse-like features, including scrollwheel and |
| clicking with different buttons, but your preferences may |
| differ.</p><div class="informalexample"><pre class="programlisting">var element = document.getElementById("some-arbitrary-id"); |
| var touch = new Guacamole.Touchpad(element); // or Guacamole.Touchscreen |
| |
| touch.onmousedown = |
| touch.onmousemove = |
| touch.onmouseup = function(state) { |
| |
| // Do something with the mouse state received ... |
| |
| };</pre></div><p>Note that even though these objects are touch-specific, they |
| still provide mouse events. The state object given to the event |
| handlers of each event is still an instance of |
| <code class="classname">Guacamole.Mouse.State</code>.</p><p>Ultimately, you could assign the same event handler to all the |
| events of both an instance of |
| <code class="classname">Guacamole.Mouse</code> as well as |
| <code class="classname">Guacamole.Touchscreen</code> or |
| <code class="classname">Guacamole.Touchpad</code>, and you would |
| magically gain mouse and touch support. This support, being |
| driven by the needs of remote desktop, is naturally geared |
| around the mouse and providing a reasonable means of interacting |
| with it. For an actual mouse, events are translated simply and |
| literally, while touch events go through additional emulation |
| and heuristics. From the perspective of the user and the code, |
| this is all transparent.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a id="guacamole-keyboard"></a>Keyboard</h3></div></div></div><p>Keyboard events in Guacamole are abstracted with the |
| <code class="classname">Guacamole.Keyboard</code> object as only |
| keyup and keydown events; there is no keypress like there is in |
| JavaScript. Further, all the craziness of keycodes vs. scancodes |
| vs. key identifiers normally present across browsers is |
| abstracted away. All your event handlers will see is an X11 |
| keysym, which represent every key unambiguously. Conveniently, |
| X11 keysyms are also what the Guacamole protocol requires, so if |
| you want to use <code class="classname">Guacamole.Keyboard</code> to |
| drive key events sent over the Guacamole protocol, everything |
| can be connected directly.</p><p>Just like the other input abstraction objects, |
| <code class="classname">Guacamole.Keyboard</code> requires a DOM |
| element as an event target. Only key events directed at this |
| element will be handled.</p><div class="informalexample"><pre class="programlisting">var keyboard = new Guacamole.Keyboard(document); |
| |
| keyboard.onkeydown = function(keysym) { |
| // Do something ... |
| }; |
| |
| keyboard.onkeyup = function(keysym) { |
| // Do something ... |
| };</pre></div><p>In this case, we are using <code class="classname">document</code> as |
| the event target, thus receiving all key events while the |
| browser window (or tab) has focus.</p></div></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="on-screen-keyboard"></a>On-screen keyboard</h2></div></div></div><p>The Guacamole JavaScript API also provides an extendable on-screen |
| keyboard, <code class="classname">Guacamole.OnScreenKeyboard</code>, which |
| requires the URL of an XML file describing the keyboard layout. The |
| on-screen keyboard object provides no hard-coded layout information; |
| the keyboard layout is described entirely within the XML layout |
| file.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a id="keyboard-layouts"></a>Keyboard layouts</h3></div></div></div><p>The keyboard layout XML included in the Guacamole web |
| application would be a good place to start regarding how these |
| layout files are written, but in general, the keyboard is simply |
| a set of rows or columns, denoted with <code class="code"><row></code> and |
| <code class="code"><column></code> tags respectively, where each can |
| be nested within the other as desired.</p><p>Each key is represented with a <code class="code"><key></code> tag, but |
| this is not what the user sees, nor what generates the key |
| event. Each key contains any number of <code class="code"><cap></code> |
| tags, which represent the visible part of the key. The cap |
| describes which X11 keysym will be sent when the key is pressed. |
| Each cap can be associated with any combination of arbitrary |
| modifier flags which dictate when that cap is active.</p><p>For example:</p><div class="informalexample"><pre class="programlisting"><keyboard lang="en_US" layout="example" size="5"> |
| <row> |
| <key size="4"> |
| <cap modifier="shift" keysym="0xFFE1">Shift</cap> |
| </key> |
| <key> |
| <cap>a</cap> |
| <cap if="shift">A</cap> |
| </key> |
| </row> |
| </keyboard></pre></div><p>Here we have a very simple keyboard which defines only two |
| keys: "shift" (a modifier) and the letter "a". When "shift" is |
| pressed, it sets the "shift" modifier, affecting other keys in |
| the keyboard. The "a" key has two caps: one lowercase (the |
| default) and one uppercase (which requires the shift modifier to |
| be active).</p><p>Notice that the shift key needed the keysym explicitly |
| specified, while the "a" key did not. This is because the |
| on-screen keyboard will automatically derive the correct keysym |
| from the text of the key cap if the text contains only a single |
| character.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a id="displaying-osk"></a>Displaying the keyboard</h3></div></div></div><p>Once you have a keyboard layout available, adding an on-screen |
| keyboard to your application is simple:</p><div class="informalexample"><pre class="programlisting">// Add keyboard to body |
| var keyboard = new Guacamole.OnScreenKeyboard("path/to/layout.xml"); |
| document.body.appendChild(keyboard.getElement()); |
| |
| // Set size of keyboard to 100 pixels |
| keyboard.resize(100);</pre></div><p>Here, we have explicitly specified the width of the keyboard |
| as 100 pixels. Normally, you would determine this by inspecting |
| the width of the containing component, or by deciding on a |
| reasonable width beforehand. Once the width is given, the height |
| of the keyboard is determined based on the arrangement of each |
| row.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a id="styling-the-keyboard"></a>Styling the keyboard</h3></div></div></div><p>While the <code class="classname">Guacamole.OnScreenKeyboard</code> |
| object will handle most of the layout, you will still need to |
| style everything yourself with CSS to get the elements to render |
| properly and the keys to change state when clicked or activated. |
| It defines several CSS classes, which you will need to manually |
| style to get things looking as desired:</p><div class="variablelist"><dl class="variablelist"><dt><span class="term"><code class="classname">guac-keyboard</code></span></dt><dd><p>This class is assigned to the root element |
| containing the entire keyboard, returned by |
| <code class="methodname">getElement()</code>,</p></dd><dt><span class="term"><code class="classname">guac-keyboard-row</code></span></dt><dd><p>Assigned to the <code class="code">div</code> elements which |
| contain each row.</p></dd><dt><span class="term"><code class="classname">guac-keyboard-column</code></span></dt><dd><p>Assigned to the <code class="code">div</code> elements which |
| contain each column.</p></dd><dt><span class="term"><code class="classname">guac-keyboard-gap</code></span></dt><dd><p>Assigned to any <code class="code">div</code> elements created |
| as a result of <code class="code"><gap></code> tags in the |
| keyboard layout. <code class="code"><gap></code> tags are |
| intended to behave as keys with no visible styling |
| or caps.</p></dd><dt><span class="term"><code class="classname">guac-keyboard-key-container</code></span></dt><dd><p>Assigned to the <code class="code">div</code> element which |
| contains a key, and provides that key with its |
| required dimensions. It is this element that will be |
| scaled relative to the size specified in the layout |
| XML and the size given to the <code class="code">resize()</code> |
| function.</p></dd><dt><span class="term"><code class="classname">guac-keyboard-key</code></span></dt><dd><p>Assigned to the <code class="code">div</code> element which |
| represents the actual key, not the cap. This element |
| will not directly contain text, but it will contain |
| all caps that this key can have. With clever CSS |
| rules, you can take advantage of this and cause |
| inactive caps to appear on the key in a corner (for |
| example), or hide them entirely.</p></dd><dt><span class="term"><code class="classname">guac-keyboard-cap</code></span></dt><dd><p>Assigned to the <code class="code">div</code> element |
| representing a key cap. Each cap is a child of its |
| corresponding key, and it is up to the author of the |
| CSS rules to hide or show or reposition each cap |
| appropriately. Each cap will contain the display |
| text defined within the <code class="code"><cap></code> |
| element in the layout XML.</p></dd><dt><span class="term"><code class="classname">guac-keyboard-requires-<em class="replaceable"><code>MODIFIER</code></em></code></span></dt><dd><p>Added to the cap element when that cap requires a |
| specific modifier.</p></dd><dt><span class="term"><code class="classname">guac-keyboard-uses-<em class="replaceable"><code>MODIFIER</code></em></code></span></dt><dd><p>Added to the key element when any cap contained |
| within it requires a specific modifier.</p></dd><dt><span class="term"><code class="classname">guac-keyboard-modifier-<em class="replaceable"><code>MODIFIER</code></em></code></span></dt><dd><p>Added to and removed from the root keyboard |
| element when a modifier key is activated or |
| deactivated respectively.</p></dd><dt><span class="term"><code class="classname">guac-keyboard-pressed</code></span></dt><dd><p>Added to and removed from any key element as it is |
| pressed and released respectively.</p></dd></dl></div><div class="important"><h3 class="title">Important</h3><p>The CSS rules required for the on-screen keyboard to work |
| as expected can be quite complex. Looking over the CSS rules |
| used by the on-screen keyboard in the Guacamole web |
| application would be a good place to start to see how the |
| appearance of each key can be driven through the simple |
| class changes described above.</p><p>Inspecting the elements of an active on-screen keyboard |
| within the Guacamole web application with the developer |
| tools of your favorite browser is also a good idea.</p></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a id="osk-event-handling"></a>Handling key events</h3></div></div></div><p>Key events generated by the on-screen keyboard are identical |
| to those of <code class="classname">Guacamole.Keyboard</code> in that |
| they consist only of a single X11 keysym. Only keyup and keydown |
| events exist, as before; there is no keypress event.</p><div class="informalexample"><pre class="programlisting">// Assuming we have an instance of Guacamole.OnScreenKeyboard already |
| // called "keyboard" |
| |
| keyboard.onkeydown = function(keysym) { |
| // Do something ... |
| }; |
| |
| keyboard.onkeyup = function(keysym) { |
| // Do something ... |
| };</pre></div></div></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="guacamole-common.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="developers-guide.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="guacamole-ext.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 20. <span class="package">guacamole-common</span> </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 22. guacamole-ext</td></tr></table></div> |
| |
| </div></div> |
| </body></html> |