diff --git a/guacamole/src/main/webapp/client.xhtml b/guacamole/src/main/webapp/client.xhtml index 286753920..40aec7ebe 100644 --- a/guacamole/src/main/webapp/client.xhtml +++ b/guacamole/src/main/webapp/client.xhtml @@ -42,13 +42,6 @@ - -
-
- -
-
-
diff --git a/guacamole/src/main/webapp/scripts/client-ui.js b/guacamole/src/main/webapp/scripts/client-ui.js index 6b7e71bd0..ba523b015 100644 --- a/guacamole/src/main/webapp/scripts/client-ui.js +++ b/guacamole/src/main/webapp/scripts/client-ui.js @@ -57,35 +57,23 @@ GuacUI.Client = { "containers": { "state" : document.getElementById("statusDialog"), - "keyboard" : document.getElementById("keyboardContainer"), - "magnifier" : document.getElementById("magnifier") + "keyboard" : document.getElementById("keyboardContainer") }, "pan_overlay" : document.getElementById("pan-overlay"), - "magnifier_background" : document.getElementById("magnifier-background"), - "magnifier" : document.getElementById("magnifier-display"), "state" : document.getElementById("statusText"), "client" : null, "sessionState" : new GuacamoleSessionState() }; -GuacUI.Client.magnifier_background.onclick = function() { - GuacUI.StateManager.setState(GuacUI.Client.states.INTERACTIVE); -}; - -GuacUI.Client.containers.magnifier.addEventListener("click", function(e) { - GuacUI.StateManager.setState(GuacUI.Client.states.PAN_TYPING); - e.stopPropagation(); -}, true); - /** * Component which displays a magnified (100% zoomed) client display. * * @constructor * @augments GuacUI.DraggableComponent */ -GuacUI.Client.Magnifier = function(magnifier) { +GuacUI.Client.Magnifier = function() { /** * Reference to this magnifier. @@ -93,21 +81,50 @@ GuacUI.Client.Magnifier = function(magnifier) { */ var guac_magnifier = this; + /** + * Large background div which will block touch events from reaching the + * client while also providing a click target to deactivate the + * magnifier. + * @private + */ + var magnifier_background = GuacUI.createElement("div", "magnifier-background"); + + /** + * Container div for the magnifier, providing a clipping rectangle. + * @private + */ + var magnifier = GuacUI.createChildElement(magnifier_background, + "div", "magnifier"); + + /** + * Canvas which will contain the static image copy of the display at time + * of show. + * @private + */ + var magnifier_display = GuacUI.createChildElement(magnifier, "canvas"); + + /** + * Context of magnifier display. + * @private + */ + var magnifier_context = magnifier_display.getContext("2d"); + /* - * Call parent constructor. + * This component is draggable. */ GuacUI.DraggableComponent.apply(this, [magnifier]); // Ensure transformations on display originate at 0,0 - GuacamoleUI.containers.magnifier.style.transformOrigin = - GuacamoleUI.containers.magnifier.style.webkitTransformOrigin = - GuacamoleUI.containers.magnifier.style.MozTransformOrigin = - GuacamoleUI.containers.magnifier.style.OTransformOrigin = - GuacamoleUI.containers.magnifier.style.msTransformOrigin = + magnifier.style.transformOrigin = + magnifier.style.webkitTransformOrigin = + magnifier.style.MozTransformOrigin = + magnifier.style.OTransformOrigin = + magnifier.style.msTransformOrigin = "0 0"; - var magnifier_display = GuacUI.Client.magnifier; - var magnifier_context = magnifier_display.getContext("2d"); + /* + * Reposition magnifier display relative to own position on screen. + */ this.onmove = function(x, y) { @@ -132,6 +149,10 @@ GuacUI.Client.Magnifier = function(magnifier) { }; + /* + * Copy display and add self to body on show. + */ + this.show = function() { // Copy displayed image @@ -140,17 +161,41 @@ GuacUI.Client.Magnifier = function(magnifier) { magnifier_context.drawImage(GuacamoleUI.client.flatten(), 0, 0); // Show magnifier container - GuacUI.Client.magnifier_background.style.display = "block"; + document.body.appendChild(magnifier_background); + + GuacamoleUI.eventTarget.style.width = magnifier.offsetWidth + "px"; + GuacamoleUI.eventTarget.style.height = magnifier.offsetHeight + "px"; }; + /* + * Remove self from body on hide. + */ + this.hide = function() { // Hide magnifier container - GuacUI.Client.magnifier_background.style.display = "none"; + document.body.removeChild(magnifier_background); }; + /* + * If the user clicks on the background, switch to INTERACTIVE mode. + */ + + magnifier_background.addEventListener("click", function() { + GuacUI.StateManager.setState(GuacUI.Client.states.INTERACTIVE); + }, true); + + /* + * If the user clicks on the magnifier, switch to PAN_TYPING mode. + */ + + magnifier.addEventListener("click", function(e) { + GuacUI.StateManager.setState(GuacUI.Client.states.PAN_TYPING); + e.stopPropagation(); + }, true); + }; /* @@ -159,7 +204,7 @@ GuacUI.Client.Magnifier = function(magnifier) { GuacUI.Client.Magnifier.prototype = new GuacUI.DraggableComponent(); GuacUI.StateManager.registerComponent( - new GuacUI.Client.Magnifier(GuacUI.Client.containers.magnifier), + new GuacUI.Client.Magnifier(), GuacUI.Client.states.MAGNIFIER ); @@ -194,22 +239,28 @@ GuacUI.StateManager.registerComponent( * Pan UI */ -GuacUI.Client.PanOverlay = function(client) { +GuacUI.Client.PanOverlay = function(pan_overlay) { this.show = function() { - GuacUI.Client.pan_overlay.style.display = "block"; + pan_overlay.style.display = "block"; }; this.hide = function() { - GuacUI.Client.pan_overlay.style.display = "none"; + pan_overlay.style.display = "none"; }; + pan_overlay.addEventListener("click", function() { + GuacUI.StateManager.setState(GuacUI.Client.PAN_TYPING); + }, false); + }; GuacUI.Client.PanOverlay.prototype = new GuacUI.Component(); GuacUI.StateManager.registerComponent( - new GuacUI.Client.PanOverlay(), + new GuacUI.Client.PanOverlay( + document.getElementById("pan-overlay") + ), GuacUI.Client.states.PAN, GuacUI.Client.states.PAN_TYPING ); @@ -218,27 +269,31 @@ GuacUI.StateManager.registerComponent( * Native Keyboard */ -GuacUI.Client.NativeKeyboard = function() { +GuacUI.Client.NativeKeyboard = function(eventTarget) { this.show = function() { - GuacamoleUI.eventTarget.focus(); + eventTarget.style.display = "block"; + eventTarget.focus(); }; this.hide = function() { - GuacamoleUI.eventTarget.blur(); + eventTarget.blur(); + eventTarget.style.display = "none"; }; + eventTarget.addEventListener("blur", function() { + GuacUI.StateManager.setState(GuacUI.Client.states.INTERACTIVE); + }, false); + }; GuacUI.StateManager.registerComponent( - new GuacUI.Client.NativeKeyboard(), + new GuacUI.Client.NativeKeyboard( + document.getElementById("eventTarget") + ), GuacUI.Client.states.PAN_TYPING ); -GuacUI.Client.eventTarget.onblur = function() { - GuacUI.StateManager.setState(GuacUI.Client.states.INTERACTIVE); -}; - /* * Set initial state */ diff --git a/guacamole/src/main/webapp/scripts/guac-ui.js b/guacamole/src/main/webapp/scripts/guac-ui.js index b657c2fe8..f4a456932 100644 --- a/guacamole/src/main/webapp/scripts/guac-ui.js +++ b/guacamole/src/main/webapp/scripts/guac-ui.js @@ -18,6 +18,21 @@ var GuacUI = GuacUI || {}; +/** + * Creates a new element having the given tagname and CSS class. + */ +GuacUI.createElement = function(tagname, classname) { + var new_element = document.createElement(tagname); + new_element.className = classname; + return new_element; +}; + +GuacUI.createChildElement = function(parent, tagname, classname) { + var element = GuacUI.createElement(tagname, classname); + parent.appendChild(element); + return element; +}; + /** * Central registry of all components for all states. */ diff --git a/guacamole/src/main/webapp/scripts/interface.js b/guacamole/src/main/webapp/scripts/interface.js index 06bfdf89a..bf1800d6c 100644 --- a/guacamole/src/main/webapp/scripts/interface.js +++ b/guacamole/src/main/webapp/scripts/interface.js @@ -50,8 +50,6 @@ var GuacamoleUI = { }; -GuacamoleUI.magnifierContext = GuacamoleUI.magnifier.getContext("2d"); - /** * Array of all supported audio mimetypes, populated when this script is * loaded. @@ -560,7 +558,10 @@ GuacamoleUI.attach = function(guac) { longPressTimeout = window.setTimeout(function() { longPressTimeout = null; - GuacUI.StateManager.setState(GuacUI.Client.states.MAGNIFIER); + if (GuacamoleUI.client.getScale() != 1.0) + GuacUI.StateManager.setState(GuacUI.Client.states.MAGNIFIER); + else + GuacUI.StateManager.setState(GuacUI.Client.states.PAN); }, GuacamoleUI.LONG_PRESS_DETECT_TIMEOUT); } diff --git a/guacamole/src/main/webapp/styles/client.css b/guacamole/src/main/webapp/styles/client.css index 056173069..78f0cc8c8 100644 --- a/guacamole/src/main/webapp/styles/client.css +++ b/guacamole/src/main/webapp/styles/client.css @@ -172,8 +172,7 @@ div#display > * { margin-right: auto; } -div#magnifier-background { - display: none; +div.magnifier-background { position: absolute; left: 0; top: 0; @@ -183,7 +182,7 @@ div#magnifier-background { overflow: hidden; } -div#magnifier { +div.magnifier { position: absolute; left: 0;