doc/gug/guacamole-common-js.html (460 lines of code) (raw):

<!DOCTYPE html> <html class="writer-html5" lang="en" > <head> <meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>guacamole-common-js &mdash; Apache Guacamole Manual v1.5.5</title> <link rel="stylesheet" href="_static/pygments.css" type="text/css" /> <link rel="stylesheet" href="_static/css/theme.css" type="text/css" /> <link rel="stylesheet" href="_static/tabs.css" type="text/css" /> <link rel="stylesheet" href="_static/gug.css" type="text/css" /> <!--[if lt IE 9]> <script src="_static/js/html5shiv.min.js"></script> <![endif]--> <script src="_static/jquery.js?v=5d32c60e"></script> <script src="_static/_sphinx_javascript_frameworks_compat.js?v=2cd50e6c"></script> <script src="_static/documentation_options.js?v=5929fcd5"></script> <script src="_static/doctools.js?v=888ff710"></script> <script src="_static/sphinx_highlight.js?v=dc90522c"></script> <script src="_static/tabs.js?v=3ee01567"></script> <script src="_static/js/theme.js"></script> <link rel="index" title="Index" href="genindex.html" /> <link rel="search" title="Search" href="search.html" /> <link rel="next" title="guacamole-ext" href="guacamole-ext.html" /> <link rel="prev" title="guacamole-common" href="guacamole-common.html" /> </head> <body class="wy-body-for-nav"> <div class="wy-grid-for-nav"> <nav data-toggle="wy-nav-shift" class="wy-nav-side"> <div class="wy-side-scroll"> <div class="wy-side-nav-search" > <a href="index.html" class="icon icon-home"> Apache Guacamole </a> <div class="version"> 1.5.5 </div> <div role="search"> <form id="rtd-search-form" class="wy-form" action="search.html" method="get"> <input type="text" name="q" placeholder="Search docs" aria-label="Search docs" /> <input type="hidden" name="check_keywords" value="yes" /> <input type="hidden" name="area" value="default" /> </form> </div> </div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu"> <p class="caption" role="heading"><span class="caption-text">Overview</span></p> <ul> <li class="toctree-l1"><a class="reference internal" href="introduction.html">Introduction</a></li> </ul> <p class="caption" role="heading"><span class="caption-text">User's Guide</span></p> <ul> <li class="toctree-l1"><a class="reference internal" href="guacamole-architecture.html">Implementation and architecture</a></li> <li class="toctree-l1"><a class="reference internal" href="installing-guacamole.html">Installing Guacamole natively</a></li> <li class="toctree-l1"><a class="reference internal" href="guacamole-docker.html">Installing Guacamole with Docker</a></li> <li class="toctree-l1"><a class="reference internal" href="reverse-proxy.html">Proxying Guacamole</a></li> <li class="toctree-l1"><a class="reference internal" href="configuring-guacamole.html">Configuring Guacamole</a></li> <li class="toctree-l1"><a class="reference internal" href="jdbc-auth.html">Database authentication</a></li> <li class="toctree-l1"><a class="reference internal" href="ldap-auth.html">LDAP authentication</a></li> <li class="toctree-l1"><a class="reference internal" href="vault.html">Retrieving secrets from a vault</a></li> <li class="toctree-l1"><a class="reference internal" href="duo-auth.html">Duo two-factor authentication</a></li> <li class="toctree-l1"><a class="reference internal" href="totp-auth.html">TOTP two-factor authentication</a></li> <li class="toctree-l1"><a class="reference internal" href="header-auth.html">HTTP header authentication</a></li> <li class="toctree-l1"><a class="reference internal" href="json-auth.html">Encrypted JSON authentication</a></li> <li class="toctree-l1"><a class="reference internal" href="cas-auth.html">CAS Authentication</a></li> <li class="toctree-l1"><a class="reference internal" href="openid-auth.html">OpenID Connect Authentication</a></li> <li class="toctree-l1"><a class="reference internal" href="saml-auth.html">SAML Authentication</a></li> <li class="toctree-l1"><a class="reference internal" href="radius-auth.html">RADIUS Authentication</a></li> <li class="toctree-l1"><a class="reference internal" href="adhoc-connections.html">Ad-hoc Connections</a></li> <li class="toctree-l1"><a class="reference internal" href="using-guacamole.html">Using Guacamole</a></li> <li class="toctree-l1"><a class="reference internal" href="recording-playback.html">Viewing session recordings in-browser</a></li> <li class="toctree-l1"><a class="reference internal" href="administration.html">Administration</a></li> <li class="toctree-l1"><a class="reference internal" href="troubleshooting.html">Troubleshooting</a></li> </ul> <p class="caption" role="heading"><span class="caption-text">Developer's Guide</span></p> <ul class="current"> <li class="toctree-l1"><a class="reference internal" href="guacamole-protocol.html">The Guacamole protocol</a></li> <li class="toctree-l1"><a class="reference internal" href="libguac.html">libguac</a></li> <li class="toctree-l1"><a class="reference internal" href="guacamole-common.html">guacamole-common</a></li> <li class="toctree-l1 current"><a class="current reference internal" href="#">guacamole-common-js</a><ul> <li class="toctree-l2"><a class="reference internal" href="#guacamole-client">Guacamole client</a></li> <li class="toctree-l2"><a class="reference internal" href="#http-tunnel">HTTP tunnel</a></li> <li class="toctree-l2"><a class="reference internal" href="#input-abstraction">Input abstraction</a><ul> <li class="toctree-l3"><a class="reference internal" href="#mouse">Mouse</a></li> <li class="toctree-l3"><a class="reference internal" href="#touch">Touch</a></li> <li class="toctree-l3"><a class="reference internal" href="#keyboard">Keyboard</a></li> </ul> </li> <li class="toctree-l2"><a class="reference internal" href="#on-screen-keyboard">On-screen keyboard</a><ul> <li class="toctree-l3"><a class="reference internal" href="#keyboard-layouts">Keyboard layouts</a></li> <li class="toctree-l3"><a class="reference internal" href="#displaying-the-keyboard">Displaying the keyboard</a></li> <li class="toctree-l3"><a class="reference internal" href="#styling-the-keyboard">Styling the keyboard</a></li> <li class="toctree-l3"><a class="reference internal" href="#handling-key-events">Handling key events</a></li> </ul> </li> </ul> </li> <li class="toctree-l1"><a class="reference internal" href="guacamole-ext.html">guacamole-ext</a></li> <li class="toctree-l1"><a class="reference internal" href="custom-protocols.html">Adding new protocols</a></li> <li class="toctree-l1"><a class="reference internal" href="custom-auth.html">Custom authentication</a></li> <li class="toctree-l1"><a class="reference internal" href="event-listeners.html">Event listeners</a></li> <li class="toctree-l1"><a class="reference internal" href="writing-you-own-guacamole-app.html">Writing your own Guacamole application</a></li> </ul> <p class="caption" role="heading"><span class="caption-text">Appendices</span></p> <ul> <li class="toctree-l1"><a class="reference internal" href="protocol-reference.html">Guacamole protocol reference</a></li> </ul> </div> </div> </nav> <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu" > <i data-toggle="wy-nav-top" class="fa fa-bars"></i> <a href="index.html">Apache Guacamole</a> </nav> <div class="wy-nav-content"> <div class="rst-content"> <div role="navigation" aria-label="Page navigation"> <ul class="wy-breadcrumbs"> <li><a href="index.html" class="icon icon-home" aria-label="Home"></a></li> <li class="breadcrumb-item active">guacamole-common-js</li> <li class="wy-breadcrumbs-aside"> <a href="_sources/guacamole-common-js.md.txt" rel="nofollow"> View page source</a> </li> </ul> <hr/> </div> <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article"> <div itemprop="articleBody"> <section id="guacamole-common-js"> <h1>guacamole-common-js<a class="headerlink" href="#guacamole-common-js" title="Link to this heading"></a></h1> <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> <section id="guacamole-client"> <h2>Guacamole client<a class="headerlink" href="#guacamole-client" title="Link to this heading"></a></h2> <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="docutils literal notranslate"><span class="pre">Guacamole</span></code> namespace. It is instantiated given an existing, unconnected tunnel:</p> <div class="highlight-javascript notranslate"><div class="highlight"><pre><span></span><span class="kd">var</span><span class="w"> </span><span class="nx">client</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Guacamole</span><span class="p">.</span><span class="nx">Client</span><span class="p">(</span><span class="nx">tunnel</span><span class="p">);</span> </pre></div> </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="highlight-javascript notranslate"><div class="highlight"><pre><span></span><span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">client</span><span class="p">.</span><span class="nx">getDisplay</span><span class="p">().</span><span class="nx">getElement</span><span class="p">());</span> </pre></div> </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="highlight-javascript notranslate"><div class="highlight"><pre><span></span><span class="nx">client</span><span class="p">.</span><span class="nx">connect</span><span class="p">();</span> </pre></div> </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="docutils literal notranslate"><span class="pre">connect()</span></code> function of the Guacamole client is called, it in turn calls the <code class="docutils literal notranslate"><span class="pre">connect()</span></code> function of the tunnel originally given to the client, establishing a connection.</p> <div class="admonition important"> <p class="admonition-title">Important</p> <p>When creating the <code class="docutils literal notranslate"><span class="pre">Guacamole.Client</span></code>, the tunnel used must not already be connected. The <code class="docutils literal notranslate"><span class="pre">Guacamole.Client</span></code> will call the <code class="docutils literal notranslate"><span class="pre">connect()</span></code> function for you when its own <code class="docutils literal notranslate"><span class="pre">connect()</span></code> function is invoked. If the tunnel is already connected when it is given to the <code class="docutils literal notranslate"><span class="pre">Guacamole.Client</span></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> </section> <section id="http-tunnel"> <h2>HTTP tunnel<a class="headerlink" href="#http-tunnel" title="Link to this heading"></a></h2> <p>Both the Java and JavaScript API implement corresponding ends of an HTTP tunnel, based on <code class="docutils literal notranslate"><span class="pre">XMLHttpRequest</span></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="highlight-javascript notranslate"><div class="highlight"><pre><span></span><span class="kd">var</span><span class="w"> </span><span class="nx">tunnel</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Guacamole</span><span class="p">.</span><span class="nx">Tunnel</span><span class="p">(</span><span class="s2">&quot;tunnel&quot;</span><span class="p">);</span> </pre></div> </div> <p>Once created, the tunnel can be passed to a <code class="docutils literal notranslate"><span class="pre">Guacamole.Client</span></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> </section> <section id="input-abstraction"> <h2>Input abstraction<a class="headerlink" href="#input-abstraction" title="Link to this heading"></a></h2> <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 <em>both</em> 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> <section id="mouse"> <span id="guacamole-mouse"></span><h3>Mouse<a class="headerlink" href="#mouse" title="Link to this heading"></a></h3> <p>Mouse event abstraction is provided by the <code class="docutils literal notranslate"><span class="pre">Guacamole.Mouse</span></code> object. Given an arbitrary DOM element, <code class="docutils literal notranslate"><span class="pre">Guacamole.Mouse</span></code> triggers onmousedown, onmousemove, and onmouseup events which are consistent across browsers. This object only responds to true mouse events. Mouse events which are actually the result of touch events are ignored.</p> <div class="highlight-javascript notranslate"><div class="highlight"><pre><span></span><span class="kd">var</span><span class="w"> </span><span class="nx">element</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s2">&quot;some-arbitrary-id&quot;</span><span class="p">);</span> <span class="kd">var</span><span class="w"> </span><span class="nx">mouse</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Guacamole</span><span class="p">.</span><span class="nx">Mouse</span><span class="p">(</span><span class="nx">element</span><span class="p">);</span> <span class="nx">mouse</span><span class="p">.</span><span class="nx">onmousedown</span><span class="w"> </span><span class="o">=</span> <span class="nx">mouse</span><span class="p">.</span><span class="nx">onmousemove</span><span class="w"> </span><span class="o">=</span> <span class="nx">mouse</span><span class="p">.</span><span class="nx">onmouseup</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="p">(</span><span class="nx">state</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="c1">// Do something with the mouse state received ...</span> <span class="p">};</span> </pre></div> </div> <p>The handles of each event are given an instance of <code class="docutils literal notranslate"><span class="pre">Guacamole.Mouse.State</span></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> </section> <section id="touch"> <span id="guacamole-touch"></span><h3>Touch<a class="headerlink" href="#touch" title="Link to this heading"></a></h3> <p>Touch event abstraction is provided by either <code class="docutils literal notranslate"><span class="pre">Guacamole.Touchpad</span></code> (emulates a touchpad to generate artificial mouse events) or <code class="docutils literal notranslate"><span class="pre">Guacamole.Touchscreen</span></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="highlight-javascript notranslate"><div class="highlight"><pre><span></span><span class="kd">var</span><span class="w"> </span><span class="nx">element</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s2">&quot;some-arbitrary-id&quot;</span><span class="p">);</span> <span class="kd">var</span><span class="w"> </span><span class="nx">touch</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Guacamole</span><span class="p">.</span><span class="nx">Touchpad</span><span class="p">(</span><span class="nx">element</span><span class="p">);</span><span class="w"> </span><span class="c1">// or Guacamole.Touchscreen</span> <span class="nx">touch</span><span class="p">.</span><span class="nx">onmousedown</span><span class="w"> </span><span class="o">=</span> <span class="nx">touch</span><span class="p">.</span><span class="nx">onmousemove</span><span class="w"> </span><span class="o">=</span> <span class="nx">touch</span><span class="p">.</span><span class="nx">onmouseup</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="p">(</span><span class="nx">state</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="c1">// Do something with the mouse state received ...</span> <span class="p">};</span> </pre></div> </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="docutils literal notranslate"><span class="pre">Guacamole.Mouse.State</span></code>.</p> <p>Ultimately, you could assign the same event handler to all the events of both an instance of <code class="docutils literal notranslate"><span class="pre">Guacamole.Mouse</span></code> as well as <code class="docutils literal notranslate"><span class="pre">Guacamole.Touchscreen</span></code> or <code class="docutils literal notranslate"><span class="pre">Guacamole.Touchpad</span></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> </section> <section id="keyboard"> <span id="guacamole-keyboard"></span><h3>Keyboard<a class="headerlink" href="#keyboard" title="Link to this heading"></a></h3> <p>Keyboard events in Guacamole are abstracted with the <code class="docutils literal notranslate"><span class="pre">Guacamole.Keyboard</span></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="docutils literal notranslate"><span class="pre">Guacamole.Keyboard</span></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="docutils literal notranslate"><span class="pre">Guacamole.Keyboard</span></code> requires a DOM element as an event target. Only key events directed at this element will be handled.</p> <div class="highlight-javascript notranslate"><div class="highlight"><pre><span></span><span class="kd">var</span><span class="w"> </span><span class="nx">keyboard</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Guacamole</span><span class="p">.</span><span class="nx">Keyboard</span><span class="p">(</span><span class="nb">document</span><span class="p">);</span> <span class="nx">keyboard</span><span class="p">.</span><span class="nx">onkeydown</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="p">(</span><span class="nx">keysym</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="c1">// Do something ...</span> <span class="p">};</span> <span class="nx">keyboard</span><span class="p">.</span><span class="nx">onkeyup</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="p">(</span><span class="nx">keysym</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="c1">// Do something ...</span> <span class="p">};</span> </pre></div> </div> <p>In this case, we are using <code class="docutils literal notranslate"><span class="pre">document</span></code> as the event target, thus receiving all key events while the browser window (or tab) has focus.</p> </section> </section> <section id="on-screen-keyboard"> <h2>On-screen keyboard<a class="headerlink" href="#on-screen-keyboard" title="Link to this heading"></a></h2> <p>The Guacamole JavaScript API also provides an extendable on-screen keyboard, <code class="docutils literal notranslate"><span class="pre">Guacamole.OnScreenKeyboard</span></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> <section id="keyboard-layouts"> <h3>Keyboard layouts<a class="headerlink" href="#keyboard-layouts" title="Link to this heading"></a></h3> <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="docutils literal notranslate"><span class="pre">&lt;row&gt;</span></code> and <code class="docutils literal notranslate"><span class="pre">&lt;column&gt;</span></code> tags respectively, where each can be nested within the other as desired.</p> <p>Each key is represented with a <code class="docutils literal notranslate"><span class="pre">&lt;key&gt;</span></code> tag, but this is not what the user sees, nor what generates the key event. Each key contains any number of <code class="docutils literal notranslate"><span class="pre">&lt;cap&gt;</span></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="highlight-xml notranslate"><div class="highlight"><pre><span></span><span class="nt">&lt;keyboard</span><span class="w"> </span><span class="na">lang=</span><span class="s">&quot;en_US&quot;</span><span class="w"> </span><span class="na">layout=</span><span class="s">&quot;example&quot;</span><span class="w"> </span><span class="na">size=</span><span class="s">&quot;5&quot;</span><span class="nt">&gt;</span> <span class="w"> </span><span class="nt">&lt;row&gt;</span> <span class="w"> </span><span class="nt">&lt;key</span><span class="w"> </span><span class="na">size=</span><span class="s">&quot;4&quot;</span><span class="nt">&gt;</span> <span class="w"> </span><span class="nt">&lt;cap</span><span class="w"> </span><span class="na">modifier=</span><span class="s">&quot;shift&quot;</span><span class="w"> </span><span class="na">keysym=</span><span class="s">&quot;0xFFE1&quot;</span><span class="nt">&gt;</span>Shift<span class="nt">&lt;/cap&gt;</span> <span class="w"> </span><span class="nt">&lt;/key&gt;</span> <span class="w"> </span><span class="nt">&lt;key&gt;</span> <span class="w"> </span><span class="nt">&lt;cap&gt;</span>a<span class="nt">&lt;/cap&gt;</span> <span class="w"> </span><span class="nt">&lt;cap</span><span class="w"> </span><span class="na">if=</span><span class="s">&quot;shift&quot;</span><span class="nt">&gt;</span>A<span class="nt">&lt;/cap&gt;</span> <span class="w"> </span><span class="nt">&lt;/key&gt;</span> <span class="w"> </span><span class="nt">&lt;/row&gt;</span> <span class="nt">&lt;/keyboard&gt;</span> </pre></div> </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> </section> <section id="displaying-the-keyboard"> <span id="displaying-osk"></span><h3>Displaying the keyboard<a class="headerlink" href="#displaying-the-keyboard" title="Link to this heading"></a></h3> <p>Once you have a keyboard layout available, adding an on-screen keyboard to your application is simple:</p> <div class="highlight-javascript notranslate"><div class="highlight"><pre><span></span><span class="c1">// Add keyboard to body</span> <span class="kd">var</span><span class="w"> </span><span class="nx">keyboard</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Guacamole</span><span class="p">.</span><span class="nx">OnScreenKeyboard</span><span class="p">(</span><span class="s2">&quot;path/to/layout.xml&quot;</span><span class="p">);</span> <span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">keyboard</span><span class="p">.</span><span class="nx">getElement</span><span class="p">());</span> <span class="c1">// Set size of keyboard to 100 pixels</span> <span class="nx">keyboard</span><span class="p">.</span><span class="nx">resize</span><span class="p">(</span><span class="mf">100</span><span class="p">);</span> </pre></div> </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> </section> <section id="styling-the-keyboard"> <h3>Styling the keyboard<a class="headerlink" href="#styling-the-keyboard" title="Link to this heading"></a></h3> <p>While the <code class="docutils literal notranslate"><span class="pre">Guacamole.OnScreenKeyboard</span></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> <dl class="simple myst"> <dt><code class="docutils literal notranslate"><span class="pre">guac-keyboard</span></code></dt><dd><p>This class is assigned to the root element containing the entire keyboard, returned by <code class="docutils literal notranslate"><span class="pre">getElement()</span></code>,</p> </dd> <dt><code class="docutils literal notranslate"><span class="pre">guac-keyboard-row</span></code></dt><dd><p>Assigned to the <code class="docutils literal notranslate"><span class="pre">div</span></code> elements which contain each row.</p> </dd> <dt><code class="docutils literal notranslate"><span class="pre">guac-keyboard-column</span></code></dt><dd><p>Assigned to the <code class="docutils literal notranslate"><span class="pre">div</span></code> elements which contain each column.</p> </dd> <dt><code class="docutils literal notranslate"><span class="pre">guac-keyboard-gap</span></code></dt><dd><p>Assigned to any <code class="docutils literal notranslate"><span class="pre">div</span></code> elements created as a result of <code class="docutils literal notranslate"><span class="pre">&lt;gap&gt;</span></code> tags in the keyboard layout. <code class="docutils literal notranslate"><span class="pre">&lt;gap&gt;</span></code> tags are intended to behave as keys with no visible styling or caps.</p> </dd> <dt><code class="docutils literal notranslate"><span class="pre">guac-keyboard-key-container</span></code></dt><dd><p>Assigned to the <code class="docutils literal notranslate"><span class="pre">div</span></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="docutils literal notranslate"><span class="pre">resize()</span></code> function.</p> </dd> <dt><code class="docutils literal notranslate"><span class="pre">guac-keyboard-key</span></code></dt><dd><p>Assigned to the <code class="docutils literal notranslate"><span class="pre">div</span></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><code class="docutils literal notranslate"><span class="pre">guac-keyboard-cap</span></code></dt><dd><p>Assigned to the <code class="docutils literal notranslate"><span class="pre">div</span></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="docutils literal notranslate"><span class="pre">&lt;cap&gt;</span></code> element in the layout XML.</p> </dd> <dt><code class="samp docutils literal notranslate"><span class="pre">guac-keyboard-requires-</span><em><span class="pre">MODIFIER</span></em></code></dt><dd><p>Added to the cap element when that cap requires a specific modifier.</p> </dd> <dt><code class="samp docutils literal notranslate"><span class="pre">guac-keyboard-uses-</span><em><span class="pre">MODIFIER</span></em></code></dt><dd><p>Added to the key element when any cap contained within it requires a specific modifier.</p> </dd> <dt><code class="samp docutils literal notranslate"><span class="pre">guac-keyboard-modifier-</span><em><span class="pre">MODIFIER</span></em></code></dt><dd><p>Added to and removed from the root keyboard element when a modifier key is activated or deactivated respectively.</p> </dd> <dt><code class="docutils literal notranslate"><span class="pre">guac-keyboard-pressed</span></code></dt><dd><p>Added to and removed from any key element as it is pressed and released respectively.</p> </dd> </dl> <div class="admonition important"> <p class="admonition-title">Important</p> <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> </section> <section id="handling-key-events"> <span id="osk-event-handling"></span><h3>Handling key events<a class="headerlink" href="#handling-key-events" title="Link to this heading"></a></h3> <p>Key events generated by the on-screen keyboard are identical to those of <code class="docutils literal notranslate"><span class="pre">Guacamole.Keyboard</span></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="highlight-javascript notranslate"><div class="highlight"><pre><span></span><span class="c1">// Assuming we have an instance of Guacamole.OnScreenKeyboard already</span> <span class="c1">// called &quot;keyboard&quot;</span> <span class="nx">keyboard</span><span class="p">.</span><span class="nx">onkeydown</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="p">(</span><span class="nx">keysym</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="c1">// Do something ...</span> <span class="p">};</span> <span class="nx">keyboard</span><span class="p">.</span><span class="nx">onkeyup</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kd">function</span><span class="p">(</span><span class="nx">keysym</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> <span class="w"> </span><span class="c1">// Do something ...</span> <span class="p">};</span> </pre></div> </div> </section> </section> </section> </div> </div> <footer><div class="rst-footer-buttons" role="navigation" aria-label="Footer"> <a href="guacamole-common.html" class="btn btn-neutral float-left" title="guacamole-common" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a> <a href="guacamole-ext.html" class="btn btn-neutral float-right" title="guacamole-ext" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a> </div> <hr/> <div role="contentinfo"> <p>Copyright &copy; 2024 <a href="http://www.apache.org/">The Apache Software Foundation</a>, Licensed under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>. Apache Guacamole, Guacamole, Apache, the Apache feather logo, and the Apache Guacamole project logo are trademarks of The Apache Software Foundation.</p> </div> Built with <a href="https://www.sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>. </footer> </div> </div> </section> </div> <script> jQuery(function () { SphinxRtdTheme.Navigation.enable(true); }); </script> </body> </html>