Bug 810981 - Part 3 - Recalculate zoom level before restoring to a different screen orientation. r=kats draft
authorJan Henning <jh+bugzilla@buttercookie.de>
Wed, 18 May 2016 22:53:34 +0200
changeset 372951 38465ee3f16dded1d1e953fd3cdbf31b821d4777
parent 372950 a6737e5c047ab2327e3a0e52c2a1176e9248a361
child 372952 eb39f09fd93d8a50d4e36c1f92667b025cf5e32d
push id19649
push usermozilla@buttercookie.de
push dateMon, 30 May 2016 18:24:45 +0000
reviewerskats
bugs810981
milestone49.0a1
Bug 810981 - Part 3 - Recalculate zoom level before restoring to a different screen orientation. r=kats On pages that aren't "width=device-width" or similar, Gecko adjusts the resolution when the display dimensions change, e.g. because the device has been rotated. The session store needs to do something similar when restoring a page if the device orientation has changed since the moment the tab state was captured. Therefore, we now include the width of the browser window in the saved zoom data and use it to scale the zoom level as necessary when restoring a tab. MozReview-Commit-ID: LBbEquO1bZ9
mobile/android/components/SessionStore.js
--- a/mobile/android/components/SessionStore.js
+++ b/mobile/android/components/SessionStore.js
@@ -699,22 +699,49 @@ SessionStore.prototype = {
     // Save the current document resolution.
     let zoom = { value: 1 };
     content.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(
       Ci.nsIDOMWindowUtils).getResolution(zoom);
     scrolldata.zoom = {};
     scrolldata.zoom.resolution = zoom.value;
     log("onTabScroll() zoom level: " + zoom.value);
 
+    // Save some data that'll help in adjusting the zoom level
+    // when restoring in a different screen orientation.
+    let viewportInfo = this._getViewportInfo(aWindow.outerWidth, aWindow.outerHeight, content);
+    scrolldata.zoom.autoSize = viewportInfo.autoSize;
+    log("onTabScroll() autoSize: " + scrolldata.zoom.autoSize);
+    scrolldata.zoom.windowWidth = aWindow.outerWidth;
+    log("onTabScroll() windowWidth: " + scrolldata.zoom.windowWidth);
+
     // Save zoom and scroll data.
     data.scrolldata = scrolldata;
     log("onTabScroll() ran for tab " + aWindow.BrowserApp.getTabForBrowser(aBrowser).id);
     this.saveStateDelayed();
   },
 
+  _getViewportInfo: function ss_getViewportInfo(aDisplayWidth, aDisplayHeight, aWindow) {
+    let viewportInfo = {};
+    let defaultZoom = {}, allowZoom = {}, minZoom = {}, maxZoom ={},
+        width = {}, height = {}, autoSize = {};
+    aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(
+      Ci.nsIDOMWindowUtils).getViewportInfo(aDisplayWidth, aDisplayHeight,
+        defaultZoom, allowZoom, minZoom, maxZoom, width, height, autoSize);
+
+    viewportInfo.defaultZoom = defaultZoom.value;
+    viewportInfo.allowZoom = allowZoom.value;
+    viewportInfo.minZoom = maxZoom.value;
+    viewportInfo.maxZoom = maxZoom.value;
+    viewportInfo.width = width.value;
+    viewportInfo.height = height.value;
+    viewportInfo.autoSize = autoSize.value;
+
+    return viewportInfo;
+  },
+
   saveStateDelayed: function ss_saveStateDelayed() {
     if (!this._saveTimer) {
       // Interval until the next disk operation is allowed
       let minimalDelay = this._lastSaveTime + this._interval - Date.now();
 
       // If we have to wait, set a timer, otherwise saveState directly
       let delay = Math.max(minimalDelay, 2000);
       if (delay > 0) {
@@ -1309,25 +1336,46 @@ SessionStore.prototype = {
   },
 
   /**
   * Restores the zoom level of the window. This needs to be called before
   * first paint/load (whichever comes first) to take any effect.
   */
   _restoreZoom: function ss_restoreZoom(aScrollData, aBrowser) {
     if (aScrollData && aScrollData.zoom) {
-      log("_restoreZoom(), resolution: " + aScrollData.zoom.resolution);
+      let recalculatedZoom = this._recalculateZoom(aScrollData.zoom);
+      log("_restoreZoom(), resolution: " + recalculatedZoom);
+
       let utils = aBrowser.contentWindow.QueryInterface(
         Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
       // Restore zoom level.
-      utils.setRestoreResolution(aScrollData.zoom.resolution);
+      utils.setRestoreResolution(recalculatedZoom);
     }
   },
 
   /**
+  * Recalculates the zoom level to account for a changed display width,
+  * e.g. because the device was rotated.
+  */
+  _recalculateZoom: function ss_recalculateZoom(aZoomData) {
+    let browserWin = Services.wm.getMostRecentWindow("navigator:browser");
+
+    // Pages with "width=device-width" won't need any zoom level scaling.
+    if (!aZoomData.autoSize) {
+      let oldWidth = aZoomData.windowWidth;
+      let newWidth = browserWin.outerWidth;
+      if (oldWidth != newWidth && oldWidth > 0 && newWidth > 0) {
+        log("_recalculateZoom(), old resolution: " + aZoomData.resolution);
+        return newWidth / oldWidth * aZoomData.resolution;
+      }
+    }
+    return aZoomData.resolution;
+  },
+
+  /**
   * Takes serialized scroll positions and restores them into the given browser.
   */
   _restoreScrollPosition: function ss_restoreScrollPosition(aScrollData, aBrowser) {
     if (aScrollData) {
       log("_restoreScrollPosition()");
       ScrollPosition.restoreTree(aBrowser.contentWindow, aScrollData);
     }
   },