Bug 530887 Some web pages do not zoom to fit page on window resize [r=mfinkle] [r=vingtetun]
authorBenjamin Stover <bstover@mozilla.com>
Wed, 25 Nov 2009 11:07:00 -0800
changeset 65850 4571c90f320b820f3e190ecdf5180a2b19f2064d
parent 65849 fdd9badc85e64d25c0d552dbd3230d564aeb1a93
child 65851 17e6d85e44034c410dd0a031573828e1051811c6
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmfinkle, vingtetun
bugs530887
Bug 530887 Some web pages do not zoom to fit page on window resize [r=mfinkle] [r=vingtetun]
mobile/chrome/content/BrowserView.js
mobile/chrome/content/browser.js
--- a/mobile/chrome/content/BrowserView.js
+++ b/mobile/chrome/content/BrowserView.js
@@ -261,28 +261,27 @@ BrowserView.prototype = {
         default:
           // Use a minimum number of tiles sice we don't know the device
           cacheSize = 6;
       }
     }
     
     this._tileManager = new TileManager(this._appendTile, this._removeTile, this, cacheSize);
     this._visibleRectFactory = visibleRectFactory;
-    this._suppressZoomToPage = false;
 
     this._idleServiceObserver = new BrowserView.IdleServiceObserver(this);
     this._idleService = Cc["@mozilla.org/widget/idleservice;1"].getService(Ci.nsIIdleService);
     this._idleService.addIdleObserver(this._idleServiceObserver, kBrowserViewPrefetchBeginIdleWait);
 
     let browsers = document.getElementById("browsers");
     browsers.addEventListener("MozScrolledAreaChanged", this.handleMozScrolledAreaChanged, false);
   },
   
   uninit: function uninit() {
-    this.setBrowser(null, null, false);
+    this.setBrowser(null, null);
     this._idleService.removeIdleObserver(this._idleServiceObserver, kBrowserViewPrefetchBeginIdleWait);
   },
 
   getVisibleRect: function getVisibleRect() {
     return this._visibleRectFactory();
   },
 
   /**
@@ -449,17 +448,17 @@ BrowserView.prototype = {
     let cr = BrowserView.Util.visibleRectToCriticalRect(vr, vs);
 
     this._tileManager.endCriticalMove(cr, this.isRendering());
   },
 
   /**
    * Swap out the current browser and browser viewport state with a new pair.
    */
-  setBrowser: function setBrowser(browser, browserViewportState, doZoom) {
+  setBrowser: function setBrowser(browser, browserViewportState) {
     if (browser && !browserViewportState) {
       throw "Cannot set non-null browser with null BrowserViewportState";
     }
 
     let oldBrowser = this._browser;
     let browserChanged = (oldBrowser !== browser);
 
     if (oldBrowser) {
@@ -477,18 +476,16 @@ BrowserView.prototype = {
       browser.setAttribute("type", "content-primary");
 
       this.beginBatchOperation();
 
       browser.addEventListener("MozAfterPaint", this.handleMozAfterPaint, false);
       browser.addEventListener("scroll", this.handlePageScroll, false);
 
       browser.docShell.isOffScreenBrowser = true;
-      if (doZoom)
-        this.zoomToPage();
 
       if (browserChanged)
         this._viewportChanged(true, true);
 
       this.commitBatchOperation();
     }
   },
 
@@ -560,26 +557,46 @@ BrowserView.prototype = {
     let oldRight = viewport.right;
     let oldBottom = viewport.bottom;
     viewport.right  = bvs.zoomLevel * w;
     viewport.bottom = bvs.zoomLevel * h;
 
     if (browser == this._browser) {
       // Page has now loaded enough to allow zooming.
       let sizeChanged = oldRight != viewport.right || oldBottom != viewport.bottom;
-      this._suppressZoomToPage = false;
       this._viewportChanged(sizeChanged, false);
+      this.updateDefaultZoom();
     }
   },
 
+  /** Call when default zoomToPage value may change. */
+  updateDefaultZoom: function updateDefaultZoom() {
+    let bvs = this._browserViewportState;
+    if (!bvs)
+      return false;
+
+    let isDefault = (bvs.zoomLevel == bvs.defaultZoomLevel);
+    bvs.defaultZoomLevel = this.getZoomForPage();
+    if (isDefault)
+      this.setZoomLevel(bvs.defaultZoomLevel);
+    return isDefault;
+  },
+
+  isDefaultZoom: function isDefaultZoom() {
+    let bvs = this._browserViewportState;
+    if (!bvs)
+      return true;
+    return bvs.zoomLevel == bvs.defaultZoomLevel;
+  },
+
   zoomToPage: function zoomToPage() {
-    // See invalidateEntireView() for why we might be suppressing this zoom.
-    if (!this._suppressZoomToPage) {
-      this._browserViewportState.defaultZoomLevel = this.getZoomForPage();
+    let bvs = this._browserViewportState;
+    if (bvs) {
       this.setZoomLevel(this.getZoomForPage());
+      bvs.defaultZoomLevel = bvs.zoomLevel;  // make sure default zl is up to date
     }
   },
 
   getZoomForPage: function getZoomForPage() {
     let browser = this._browser;
     if (!browser)
       return 0;
 
@@ -630,35 +647,27 @@ BrowserView.prototype = {
   // cases, but should be done for correctness.  Most of the time, one
   // of the following two conditions is satisfied.  Either
   //
   //   (1) Pages have different widths so the Browser calls a
   //       zoomToPage() which forces a dirtyAll, or
   //   (2) MozAfterPaint does indeed inform us of dirtyRects covering
   //       the entire page (everything that could possibly become
   //       visible).
-  //
-  // Since calling this method means "everything is wrong and the
-  // <browser> is about to start giving you new data via MozAfterPaint
-  // and MozScrolledAreaChanged", we also supress any zoomToPage()
-  // that might be called until the next time a MozScrolledAreaChanged
-  // event.
-  //
   /**
    * Invalidates the entire page by throwing away any cached graphical
    * portions of the view and refusing to allow a zoomToPage() until
    * the next explicit update of the viewport dimensions.
    *
    * This method should be called when the <browser> last set by
    * setBrowser() is about to navigate to a new page.
    */
   invalidateEntireView: function invalidateEntireView() {
     if (this._browserViewportState) {
       this._viewportChanged(false, true);
-      this._suppressZoomToPage = true;
     }
   },
 
   /**
    * Render a rectangle within the browser viewport to the destination canvas
    * under the given scale.
    *
    * @param destCanvas The destination canvas into which the image is rendered.
--- a/mobile/chrome/content/browser.js
+++ b/mobile/chrome/content/browser.js
@@ -402,22 +402,21 @@ var Browser = {
       Browser.styles["browser"].width = kDefaultBrowserWidth + "px";
       Browser.styles["browser"].height = scaledDefaultH + "px";
       Browser.styles["browser-handheld"].width = window.screen.width + "px";
       Browser.styles["browser-handheld"].height = scaledScreenH + "px";
 
       // Tell the UI to resize the browser controls before calling  updateSize
       BrowserUI.sizeControls(w, h);
       
-      let bvs = Browser.selectedTab.browserViewportState;
-      if (bvs.zoomLevel == bvs.defaultZoomLevel) {
-        bv.zoomToPage();
+      bv.updateDefaultZoom();
+      if (bv.isDefaultZoom())
+        // XXX this should really only happen on browser startup, not every resize
         Browser.hideSidebars();
-        bv.onAfterVisibleMove();
-      }
+      bv.onAfterVisibleMove();
 
       bv.commitBatchOperation();
     }
     window.addEventListener("resize", resizeHandler, false);
 
     function fullscreenHandler() {
       if (!window.fullScreen)
         document.getElementById("toolbar-main").setAttribute("fullscreen", "true");
@@ -739,17 +738,17 @@ var Browser = {
     let isFirstTab = this._selectedTab == null;
     let lastTab = this._selectedTab;
     this._selectedTab = tab;
 
     tab.ensureBrowserExists();
 
     bv.beginBatchOperation();
 
-    bv.setBrowser(tab.browser, tab.browserViewportState, false);
+    bv.setBrowser(tab.browser, tab.browserViewportState);
     bv.forceContainerResize();
 
     document.getElementById("tabs").selectedTab = tab.chromeTab;
 
     if (!isFirstTab) {
       // Update all of our UI to reflect the new tab's location
       BrowserUI.updateURI();
       getIdentityHandler().checkIdentity();
@@ -1083,40 +1082,40 @@ var Browser = {
 
   zoomToPoint: function zoomToPoint(cX, cY) {
     let [elementX, elementY] = Browser.transformClientToBrowser(cX, cY);
 
     let element = Browser.elementFromPoint(elementX, elementY);
     if (!element)
       return false;
 
-    let defaultZoomLevel = this._browserView.getZoomForPage();
-    let oldZoomLevel = this._browserView.getZoomLevel();
+    let bv = this._browserView;
+    let oldZoomLevel = bv.getZoomLevel();
     let zoomLevel = this._getZoomLevelForElement(element);
     let zoomRatio = oldZoomLevel / zoomLevel;
 
     // Don't zoom in a marginal amount, but be more lenient for the first zoom.
     // > 2/3 means operation increases the zoom level by less than 1.5
     // > 9/10 means operation increases the zoom level by less than 1.1
-    let zoomTolerance = (oldZoomLevel == defaultZoomLevel) ? .9 : .6666;
+    let zoomTolerance = (bv.isDefaultZoom()) ? .9 : .6666;
     if (zoomRatio >= zoomTolerance)
        return false;
 
     let elRect = Browser.getBoundingContentRect(element);
     let zoomRect = this._getZoomRectForPoint(elRect.center().x, elementY, zoomLevel);
 
     this.setVisibleRect(zoomRect);
     return true;
   },
 
   zoomFromPoint: function zoomFromPoint(cX, cY) {
     let bv = this._browserView;
     
     let zoomLevel = bv.getZoomForPage();
-    if (bv.getZoomLevel() != zoomLevel) {
+    if (!bv.isDefaultZoom()) {
       let [elementX, elementY] = this.transformClientToBrowser(cX, cY);
       let zoomRect = this._getZoomRectForPoint(elementX, elementY, zoomLevel);
       this.setVisibleRect(zoomRect);
     }
   },
 
   getBoundingContentRect: function getBoundingContentRect(contentElem) {
     let tab = Browser.getTabForDocument(contentElem.ownerDocument);
@@ -2499,46 +2498,35 @@ Tab.prototype = {
   },
 
   /**
    * Throttles redraws to once every 2 seconds while loading the page, zooming to fit page if
    * user hasn't started zooming.
    */
   _resizeAndPaint: function() {
     let bv = Browser._browserView;
-
-    if (this == Browser.selectedTab) {
-      let restoringPage = (this._state != null);
-
-      if (this._browserViewportState.zoomLevel == this._browserViewportState.defaultZoomLevel && !restoringPage) {
-        // Only fit page if user hasn't started zooming around and this is a page that
-        // isn't being restored.
-        bv.zoomToPage();
-      }
-
-    }
     bv.commitBatchOperation();
-
     if (this._loading) {
       // kick ourselves off 2s later while we're still loading
       bv.beginBatchOperation();
       this._loadingTimeout = setTimeout(Util.bind(this._resizeAndPaint, this), 2000);
     } else {
       delete this._loadingTimeout;
     }
   },
 
   /** Returns tab's identity state for updating security UI. */
   getIdentityState: function() {
     return this._listener.state;
   },
 
   startLoading: function() {
     this._loading = true;
-    this._browserViewportState.defaultZoomLevel = this._browserViewportState.zoomLevel;
+    let bvs = this._browserViewportState;
+    bvs.defaultZoomLevel = bvs.zoomLevel; // ensures zoom level is reset on new pages
 
     if (!this._loadingTimeout) {
       Browser._browserView.beginBatchOperation();
       Browser._browserView.invalidateEntireView();
       this._loadingTimeout = setTimeout(Util.bind(this._resizeAndPaint, this), 2000);
     }
   },