Bug 532442 - unable to zoom [r=mfinkle]
authorBenjamin Stover <bstover@mozilla.com>
Tue, 08 Dec 2009 09:28:01 -0800
changeset 65893 a16cb0d98835d40b799c66001ace44bc2c31b653
parent 65892 cac0a1837012714dcc1f444f571d0a5efb1307e3
child 65894 67626ed8a1f26428c32073c4b2ee76d2b62c655c
push idunknown
push userunknown
push dateunknown
reviewersmfinkle
bugs532442
Bug 532442 - unable to zoom [r=mfinkle]
mobile/chrome/content/browser.js
--- a/mobile/chrome/content/browser.js
+++ b/mobile/chrome/content/browser.js
@@ -1012,37 +1012,56 @@ var Browser = {
 
     let bv = this._browserView;
     let elRect = bv.browserToViewportRect(Browser.getBoundingContentRect(element));
 
     let vis = bv.getVisibleRect();
     return BrowserView.Util.clampZoomLevel(bv.getZoomLevel() * vis.width / (elRect.width + margin * 2));
   },
 
+  /** Find an appropriate zoom rect for an element, if it exists. */
+  _getZoomRectForElement: function _getZoomRectForElement(element, elementY) {
+    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 = (bv.isDefaultZoom()) ? .9 : .6666;
+    if (zoomRatio >= zoomTolerance) {
+      return null;
+    } else {
+      let elRect = this.getBoundingContentRect(element);
+      return this._getZoomRectForPoint(elRect.center().x, elementY, zoomLevel);
+    }
+  },
+
   /**
    * Find a good zoom rectangle for point specified in browser coordinates.
    * @return Point in viewport coordinates
    */
   _getZoomRectForPoint: function _getZoomRectForPoint(x, y, zoomLevel) {
-    let bv = Browser._browserView;
+    let bv = this._browserView;
     let vis = bv.getVisibleRect();
     x = bv.browserToViewport(x);
     y = bv.browserToViewport(y);
 
     zoomLevel = Math.min(kBrowserViewZoomLevelMax, zoomLevel);
     let zoomRatio = zoomLevel / bv.getZoomLevel();
     let newVisW = vis.width / zoomRatio, newVisH = vis.height / zoomRatio;
     let result = new Rect(x - newVisW / 2, y - newVisH / 2, newVisW, newVisH);
 
     // Make sure rectangle doesn't poke out of viewport
     return result.translateInside(bv._browserViewportState.viewportRect);
   },
 
   setVisibleRect: function setVisibleRect(rect) {
-    let bv = Browser._browserView;
+    let bv = this._browserView;
     let vis = bv.getVisibleRect();
     let zoomRatio = vis.width / rect.width;
     let zoomLevel = bv.getZoomLevel() * zoomRatio;
     let scrollX = rect.left * zoomRatio;
     let scrollY = rect.top * zoomRatio;
 
     // The order of operations below is important for artifacting and for performance. Important
     // side effects of functions are noted below.
@@ -1050,58 +1069,50 @@ var Browser = {
     // Hardware scrolling happens immediately when scrollTo is called.  Hide to prevent artifacts.
     bv.beginOffscreenOperation();
 
     // We must scroll to the correct area before TileManager is informed of the change
     // so that only one render is done. Ensures setZoomLevel puts it off.
     bv.beginBatchOperation();
 
     // Critical rect changes when controls are hidden. Must hide before tilemanager viewport.
-    Browser.hideSidebars();
-    Browser.hideTitlebar();
+    this.hideSidebars();
+    this.hideTitlebar();
     bv.setZoomLevel(zoomLevel);
 
     // Ensure container is big enough for scroll values.
     bv.forceContainerResize();
-    Browser.forceChromeReflow();
-    Browser.contentScrollboxScroller.scrollTo(scrollX, scrollY);
+    this.forceChromeReflow();
+    this.contentScrollboxScroller.scrollTo(scrollX, scrollY);
     bv.onAfterVisibleMove();
 
     // Inform tile manager, which happens to render new tiles too. Must call in case a batch
     // operation was in progress before zoom.
     bv.forceViewportChange();
 
     bv.commitBatchOperation();
     bv.commitOffscreenOperation();
   },
 
   zoomToPoint: function zoomToPoint(cX, cY) {
-    let [elementX, elementY] = Browser.transformClientToBrowser(cX, cY);
-
-    let element = Browser.elementFromPoint(elementX, elementY);
-    if (!element)
-      return false;
-
+    let [elementX, elementY] = this.transformClientToBrowser(cX, cY);
+    let zoomRect = null;
+    let element = this.elementFromPoint(elementX, elementY);
     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 = (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;
+    if (element)
+      zoomRect = this._getZoomRectForElement(element, elementY);
+    if (!zoomRect && bv.isDefaultZoom())
+      zoomRect = this._getZoomRectForPoint(elementX, elementY, bv.getZoomLevel() * 2);
+
+    if (zoomRect) {
+      this.setVisibleRect(zoomRect);
+      return true;
+    } else {
+      return false;
+    }
   },
 
   zoomFromPoint: function zoomFromPoint(cX, cY) {
     let bv = this._browserView;
     
     let zoomLevel = bv.getZoomForPage();
     if (!bv.isDefaultZoom()) {
       let [elementX, elementY] = this.transformClientToBrowser(cX, cY);