From afce3a363d186cab20b82eacd09a95d36dea73a0 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 16 May 2014 15:36:07 -0700 Subject: [PATCH] GUAC-694: Do not trust fixed positioning for main display and text input UI. --- .../src/main/webapp/scripts/client-ui.js | 72 +++++++++++++++---- guacamole/src/main/webapp/styles/client.css | 12 +--- 2 files changed, 61 insertions(+), 23 deletions(-) diff --git a/guacamole/src/main/webapp/scripts/client-ui.js b/guacamole/src/main/webapp/scripts/client-ui.js index d30038965..2bf730b96 100644 --- a/guacamole/src/main/webapp/scripts/client-ui.js +++ b/guacamole/src/main/webapp/scripts/client-ui.js @@ -810,8 +810,8 @@ GuacUI.Client.updateDisplayScale = function() { // Calculate scale to fit screen GuacUI.Client.min_zoom = Math.min( - window.innerWidth / Math.max(guac.getDisplay().getWidth(), 1), - window.innerHeight / Math.max(guac.getDisplay().getHeight(), 1) + GuacUI.Client.main.offsetWidth / Math.max(guac.getDisplay().getWidth(), 1), + GuacUI.Client.main.offsetHeight / Math.max(guac.getDisplay().getHeight(), 1) ); // Calculate appropriate maximum zoom level @@ -1569,26 +1569,70 @@ GuacUI.Client.attach = function(guac) { }; /* - * Send size events on resize + * Reflow layout and send size events on resize/scroll */ - window.onresize = function() { + var last_scroll_top = 0; + var last_scroll_left = 0; + var last_width = 0; + var last_height = 0; - // Remove scrollbars during resize - GuacUI.Client.main.style.overflow = "hidden"; + function __update_layout() { - var pixel_density = window.devicePixelRatio || 1; - var width = window.innerWidth * pixel_density; - var height = window.innerHeight * pixel_density; + // Only reflow if size or scroll have changed + if (document.body.scrollTop != last_scroll_top + || document.body.scrollLeft != last_scroll_left + || window.innerWidth != last_width + || window.innerHeight != last_height) { - GuacUI.Client.main.style.overflow = "auto"; + // Reposition document such that it's back on-screen + window.scrollTo(document.body.scrollWidth, document.body.scrollHeight); - if (GuacUI.Client.attachedClient) - GuacUI.Client.attachedClient.sendSize(width, height); + // Determine height of bottom section (currently only text input) + var bottom = GuacUI.Client.text_input.container; + var bottom_height = (bottom && bottom.offsetHeight) | 0; - GuacUI.Client.updateDisplayScale(); + // Calculate correct height of main section (display) + var main_width = window.innerWidth; + var main_height = window.innerHeight - bottom_height; - }; + // Anchor main to top-left of viewport, sized to fit above bottom + var main = GuacUI.Client.main; + main.style.top = document.body.scrollTop + "px"; + main.style.left = document.body.scrollLeft + "px"; + main.style.width = main_width + "px"; + main.style.height = main_height + "px"; + + // Anchor bottom to bottom of viewport + if (bottom) { + bottom.style.top = (document.body.scrollTop + main_height) + "px"; + bottom.style.left = document.body.scrollLeft + "px"; + bottom.style.width = window.innerWidth + "px"; + } + + // Send new size + if (GuacUI.Client.attachedClient) { + var pixel_density = window.devicePixelRatio || 1; + var width = main_width * pixel_density; + var height = main_height * pixel_density; + GuacUI.Client.attachedClient.sendSize(width, height); + } + + // Rescale display appropriately + GuacUI.Client.updateDisplayScale(); + + last_scroll_top = document.body.scrollTop; + last_scroll_left = document.body.scrollLeft; + last_width = window.innerWidth; + last_height = window.innerHeight; + + } + + } + + window.onresize = __update_layout; + window.onscroll = __update_layout; + window.setInterval(__update_layout, 10); GuacamoleSessionStorage.addChangeListener(function(name, value) { if (name === "clipboard") { diff --git a/guacamole/src/main/webapp/styles/client.css b/guacamole/src/main/webapp/styles/client.css index 4c0e00385..b894f7a87 100644 --- a/guacamole/src/main/webapp/styles/client.css +++ b/guacamole/src/main/webapp/styles/client.css @@ -25,6 +25,7 @@ body { font-family: FreeSans, Helvetica, Arial, sans-serif; padding: 0; margin: 0; + overflow: hidden; } img { @@ -115,11 +116,7 @@ div.dialog p { div#main { overflow: auto; - position: fixed; - top: 0; - left: 0; - bottom: 0; - right: 0; + position: absolute; } div.displayOuter { @@ -681,10 +678,7 @@ p.hint { #text-input { display: none; - position: fixed; - left: 0; - bottom: 0; - width: 100%; + position: absolute; border-top: 1px solid rgba(0, 0, 0, 0.5); background: #CDA;