diff --git a/guacamole/src/main/webapp/client.xhtml b/guacamole/src/main/webapp/client.xhtml index 58c41af69..46782aff8 100644 --- a/guacamole/src/main/webapp/client.xhtml +++ b/guacamole/src/main/webapp/client.xhtml @@ -54,23 +54,26 @@ + +
+ - - - - -
- - -
+ +
+ + +
+ +
+
diff --git a/guacamole/src/main/webapp/images/menu-icons/tango/edit-paste.png b/guacamole/src/main/webapp/images/menu-icons/tango/edit-paste.png new file mode 100644 index 000000000..28dc0fecf Binary files /dev/null and b/guacamole/src/main/webapp/images/menu-icons/tango/edit-paste.png differ diff --git a/guacamole/src/main/webapp/images/menu-icons/tango/input-keyboard.png b/guacamole/src/main/webapp/images/menu-icons/tango/input-keyboard.png new file mode 100644 index 000000000..e1c28b928 Binary files /dev/null and b/guacamole/src/main/webapp/images/menu-icons/tango/input-keyboard.png differ diff --git a/guacamole/src/main/webapp/images/menu-icons/tango/system-log-out.png b/guacamole/src/main/webapp/images/menu-icons/tango/system-log-out.png new file mode 100644 index 000000000..c2117a363 Binary files /dev/null and b/guacamole/src/main/webapp/images/menu-icons/tango/system-log-out.png differ diff --git a/guacamole/src/main/webapp/scripts/interface.js b/guacamole/src/main/webapp/scripts/interface.js index 1f5e7a5f0..6b6c132fb 100644 --- a/guacamole/src/main/webapp/scripts/interface.js +++ b/guacamole/src/main/webapp/scripts/interface.js @@ -23,7 +23,7 @@ var GuacamoleUI = { /* UI Elements */ - "viewport" : document.getElementById("viewport"), + "viewport" : document.getElementById("viewportClone"), "display" : document.getElementById("display"), "menu" : document.getElementById("menu"), "menuControl" : document.getElementById("menuControl"), @@ -37,7 +37,11 @@ var GuacamoleUI = { "showKeyboard" : document.getElementById("showKeyboard"), "ctrlAltDelete": document.getElementById("ctrlAltDelete"), "reconnect" : document.getElementById("reconnect"), - "logout" : document.getElementById("logout") + "logout" : document.getElementById("logout"), + + "touchShowClipboard" : document.getElementById("touchShowClipboard"), + "touchShowKeyboard" : document.getElementById("touchShowKeyboard"), + "touchLogout" : document.getElementById("touchLogout") }, @@ -133,6 +137,26 @@ var GuacamoleUI = { GuacamoleUI.display.style.opacity = "0.1"; }; + GuacamoleUI.hideTouchMenu = function() { + GuacamoleUI.touchMenu.style.visibility = "hidden"; + }; + + GuacamoleUI.showTouchMenu = function() { + + GuacamoleUI.touchMenu.style.left = + ((GuacamoleUI.viewport.offsetWidth - GuacamoleUI.touchMenu.offsetWidth) / 2 + + window.pageXOffset) + + "px"; + + GuacamoleUI.touchMenu.style.top = + ((GuacamoleUI.viewport.offsetHeight - GuacamoleUI.touchMenu.offsetHeight) / 2 + + window.pageYOffset) + + "px"; + + GuacamoleUI.touchMenu.style.visibility = "visible"; + + }; + GuacamoleUI.shadeMenu = function() { if (!menu_shaded) { @@ -212,8 +236,10 @@ var GuacamoleUI = { }; - // Assume no native OSK by default - GuacamoleUI.oskMode = GuacamoleUI.OSK_MODE_GUAC; + GuacamoleUI.buttons.touchShowClipboard.onclick = function() { + // FIXME: Implement + alert("Not yet implemented... Sorry."); + }; // Show/Hide keyboard var keyboardResizeInterval = null; @@ -228,23 +254,10 @@ var GuacamoleUI = { window.onresize = null; window.clearInterval(keyboardResizeInterval); } - - // If not shown ... action depends on OSK mode. + + // Otherwise, show it else { - // If we think the platform has a native OSK, use the event target to - // cause it to display. - if (GuacamoleUI.oskMode == GuacamoleUI.OSK_MODE_NATIVE) { - - // ...but use the Guac OSK if clicked again - GuacamoleUI.oskMode = GuacamoleUI.OSK_MODE_GUAC; - - // Try to show native OSK by focusing eventTarget. - GuacamoleUI.eventTarget.focus(); - return; - - } - // Ensure event target is NOT focused if we are using the Guac OSK. GuacamoleUI.eventTarget.blur(); @@ -253,18 +266,39 @@ var GuacamoleUI = { // Automatically update size window.onresize = updateKeyboardSize; - keyboardResizeInterval = window.setInterval(updateKeyboardSize, GuacamoleUI.KEYBOARD_AUTO_RESIZE_INTERVAL); + keyboardResizeInterval = window.setInterval(updateKeyboardSize, + GuacamoleUI.KEYBOARD_AUTO_RESIZE_INTERVAL); updateKeyboardSize(); + } - }; + // Touch-specific keyboard show + GuacamoleUI.buttons.touchShowKeyboard.onclick = + function(e) { + + // Center event target in case browser automatically centers + // input fields on focus. + GuacamoleUI.eventTarget.style.left = + (window.pageXOffset + GuacamoleUI.viewport.offsetWidth / 2) + "px"; + + GuacamoleUI.eventTarget.style.top = + (window.pageYOffset + GuacamoleUI.viewport.offsetHeight / 2) + "px"; + + GuacamoleUI.eventTarget.focus(); + GuacamoleUI.hideTouchMenu(); + + }; + // Logout - GuacamoleUI.buttons.logout.onclick = function() { - window.location.href = "logout"; - }; + GuacamoleUI.buttons.logout.onclick = + GuacamoleUI.buttons.touchLogout.onclick = + function() { + window.location.href = "logout"; + GuacamoleUI.hideTouchMenu(); + }; // Timeouts for detecting if users wants menu to open or close var detectMenuOpenTimeout = null; @@ -350,7 +384,7 @@ var GuacamoleUI = { // Assume native OSK if menu shown via long-press GuacamoleUI.oskMode = GuacamoleUI.OSK_MODE_NATIVE; - GuacamoleUI.showMenu(); + GuacamoleUI.showTouchMenu(); }, GuacamoleUI.LONG_PRESS_DETECT_TIMEOUT); @@ -367,6 +401,7 @@ var GuacamoleUI = { // Close menu if shown GuacamoleUI.shadeMenu(); + GuacamoleUI.hideTouchMenu(); // Record touch location if (e.touches.length == 1) { @@ -421,6 +456,12 @@ var GuacamoleUI = { GuacamoleUI.eventTarget.setAttribute("autocorrect", "off"); GuacamoleUI.eventTarget.setAttribute("autocapitalize", "off"); + // Automatically reposition event target on scroll + window.addEventListener("scroll", function() { + GuacamoleUI.eventTarget.style.left = window.pageXOffset + "px"; + GuacamoleUI.eventTarget.style.top = window.pageYOffset + "px"; + }); + })(); // Tie UI events / behavior to a specific Guacamole client @@ -463,39 +504,36 @@ GuacamoleUI.attach = function(guac) { var mouse = new Guacamole.Mouse(guac_display); mouse.onmousedown = mouse.onmouseup = mouse.onmousemove = function(mouseState) { - - // Get current viewport scroll - var scroll_x = GuacamoleUI.viewport.scrollLeft; - var scroll_y = GuacamoleUI.viewport.scrollTop; - + // Determine mouse position within view - var mouse_view_x = mouseState.x + guac_display.offsetLeft - scroll_x; - var mouse_view_y = mouseState.y + guac_display.offsetTop - scroll_y; + var mouse_view_x = mouseState.x + guac_display.offsetLeft - window.pageXOffset; + var mouse_view_y = mouseState.y + guac_display.offsetTop - window.pageYOffset; // Determine viewport dimensioins var view_width = GuacamoleUI.viewport.offsetWidth; var view_height = GuacamoleUI.viewport.offsetHeight; - // Scroll horizontally if necessary - if (mouse_view_x > view_width) { - GuacamoleUI.viewport.scrollLeft += mouse_view_x - view_width; - GuacamoleUI.stopLongPressDetect(); - } - else if (mouse_view_x < 0) { - GuacamoleUI.viewport.scrollLeft += mouse_view_x; - GuacamoleUI.stopLongPressDetect(); - } + // Determine scroll amounts based on mouse position relative to document - // Scroll vertically if necessary - if (mouse_view_y > view_height) { - GuacamoleUI.viewport.scrollTop += mouse_view_y - view_height; - GuacamoleUI.stopLongPressDetect(); - } - else if (mouse_view_y < 0) { - GuacamoleUI.viewport.scrollTop += mouse_view_y; - GuacamoleUI.stopLongPressDetect(); - } + var scroll_amount_x; + if (mouse_view_x > view_width) + scroll_amount_x = mouse_view_x - view_width; + else if (mouse_view_x < 0) + scroll_amount_x = mouse_view_x; + else + scroll_amount_x = 0; + var scroll_amount_y; + if (mouse_view_y > view_height) + scroll_amount_y = mouse_view_y - view_height; + else if (mouse_view_y < 0) + scroll_amount_y = mouse_view_y; + else + scroll_amount_y = 0; + + // Scroll (if necessary) to keep mouse on screen. + window.scrollBy(scroll_amount_x, scroll_amount_y); + // Send mouse event guac.sendMouseState(mouseState); @@ -706,4 +744,4 @@ GuacamoleUI.attach = function(guac) { guac.sendKeyEvent(0, KEYSYM_CTRL); }; -}; \ No newline at end of file +}; diff --git a/guacamole/src/main/webapp/styles/client.css b/guacamole/src/main/webapp/styles/client.css index 6d30bb958..66b3f31f0 100644 --- a/guacamole/src/main/webapp/styles/client.css +++ b/guacamole/src/main/webapp/styles/client.css @@ -47,7 +47,7 @@ div.dialogOuter { display: table; height: 100%; width: 100%; - position: absolute; + position: fixed; left: 0; top: 0; @@ -141,7 +141,7 @@ div.dialog p { /* Menu */ #menu { - position: absolute; + position: fixed; left: 0; top: 0; width: 100%; @@ -218,7 +218,7 @@ div#clipboardDiv textarea { } div#menuControl { - position: absolute; + position: fixed; top: 0; left: 0; @@ -229,15 +229,17 @@ div#menuControl { z-index: 3; } -/* Viewport */ +/* Viewport Clone */ -div#viewport { +div#viewportClone { + display: table; height: 100%; width: 100%; - position: absolute; + position: fixed; left: 0; top: 0; - overflow: auto; + + visibility: hidden; } /* Keyboard event target */ @@ -253,4 +255,20 @@ textarea#eventTarget { opacity: 0; overflow: hidden; +} + +/* Touch-specific menu */ + +div#touchMenu { + + position: absolute; + visibility: hidden; + z-index: 4; + + white-space: pre; + background: black; + border: 1px solid silver; + padding: 1em; + opacity: 0.8; + } \ No newline at end of file