Bug 608703 - Automatic adjustment of the view to keep in sync with the caret rect can be called when it shouldn't [r=mfinkle,mbrubeck]
authorVivien Nicolas <21@vingtetun.org>
Thu, 04 Nov 2010 11:54:12 +0100
changeset 66956 2b3d860098a9e69e47cfc9422004ce2525587105
parent 66955 7e23ed2f6b1a17078c8ed48794c8daeab4d633d6
child 66957 12519ea0d2d981c39b58b61c91a4d22bcbc72434
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, mbrubeck
bugs608703
Bug 608703 - Automatic adjustment of the view to keep in sync with the caret rect can be called when it shouldn't [r=mfinkle,mbrubeck]
mobile/chrome/content/AnimatedZoom.js
mobile/chrome/content/browser-ui.js
mobile/chrome/content/browser.js
--- a/mobile/chrome/content/AnimatedZoom.js
+++ b/mobile/chrome/content/AnimatedZoom.js
@@ -34,20 +34,16 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-let Cc = Components.classes;
-let Ci = Components.interfaces;
-let Cu = Components.utils;
-
 /**
  * Responsible for zooming in to a given view rectangle
  */
 const AnimatedZoom = {
   /** Starts an animated zoom to zoomRect. */
   animateTo: function(aZoomRect) {
     if (!aZoomRect)
       return;
@@ -67,16 +63,20 @@ const AnimatedZoom = {
     if (this.zoomRect) {
       this.zoomFrom = this.zoomRect;
     } else {
       this.zoomFrom = this.getStartRect();
       this.updateTo(this.zoomFrom);
 
       window.addEventListener("MozBeforePaint", this, false);
       mozRequestAnimationFrame();
+
+      let event = document.createEvent("Events");
+      event.initEvent("AnimatedZoomBegin", true, true);
+      window.dispatchEvent(event);
     }
   },
 
   /** Get the visible rect, in device pixels relative to the content origin. */
   getStartRect: function getStartRect() {
     let browser = getBrowser();
     let bcr = browser.getBoundingClientRect();
     let scroll = browser.getPosition();
@@ -100,16 +100,24 @@ const AnimatedZoom = {
   /** Stop animation, zoom to point, and clean up. */
   finish: function() {
     window.removeEventListener("MozBeforePaint", this, false);
     Browser.setVisibleRect(this.zoomTo || this.zoomRect);
     this.beginTime = null;
     this.zoomTo = null;
     this.zoomFrom = null;
     this.zoomRect = null;
+
+    let event = document.createEvent("Events");
+    event.initEvent("AnimatedZoomEnd", true, true);
+    window.dispatchEvent(event);
+  },
+
+  isZooming: function isZooming() {
+    return this.beginTime != null;
   },
 
   handleEvent: function(aEvent) {
     try {
       let tdiff = aEvent.timeStamp - this.beginTime;
       let counter = tdiff / this.animationDuration;
       if (counter < 1) {
         // update browser to interpolated rectangle
--- a/mobile/chrome/content/browser-ui.js
+++ b/mobile/chrome/content/browser-ui.js
@@ -2027,39 +2027,54 @@ var FormHelperUI = {
   _zoom: function _formHelperZoom(aElementRect, aCaretRect) {
     let zoomRect = this.visibleScreenArea;
     let browser = getBrowser();
 
     // Zoom to a specified Rect
     if (aElementRect && Browser.selectedTab.allowZoom && Services.prefs.getBoolPref("formhelper.autozoom")) {
       this._currentElementRect = aElementRect;
       // Zoom to an element by keeping the caret into view
-      let zoomLevel = this._getZoomLevelForRect(aElementRect);
-      zoomLevel = Math.min(Math.max(kBrowserFormZoomLevelMin, zoomLevel), kBrowserFormZoomLevelMax);
-      zoomLevel = Browser.selectedTab.clampZoomLevel(zoomLevel);
+      let zoomLevel = Browser.selectedTab.clampZoomLevel(this._getZoomLevelForRect(aElementRect));
 
       zoomRect = this._getZoomRectForPoint(aElementRect.center().x, aElementRect.y, zoomLevel);
       Browser.animatedZoomTo(zoomRect);
     }
 
-    // Move the view to show the caret if needed
-    if (aCaretRect) {
-      this._currentCaretRect = aCaretRect;
-      let caretRect = aCaretRect.scale(browser.scale, browser.scale);
-      let scroll = browser.getPosition();
-      zoomRect.x += scroll.x;
-      zoomRect.y += scroll.y;
-
-      if (zoomRect.contains(caretRect))
-        return;
-
-      let [deltaX, deltaY] = this._getOffsetForCaret(caretRect, zoomRect);
-      if (deltaX != 0 || deltaY != 0)
-        browser.scrollBy(deltaX, deltaY);
+    this._ensureCaretVisible(aCaretRect);
+  },
+
+  _ensureCaretVisible: function _ensureCaretVisible(aCaretRect) {
+    if (!aCaretRect)
+      return;
+
+    // the scrollX/scrollY position can change because of the animated zoom so
+    // delay the caret adjustment
+    if (AnimatedZoom.isZooming()) {
+      let self = this;
+      window.addEventListener("AnimatedZoomEnd", function() {
+        window.removeEventListener("AnimatedZoomEnd", arguments.callee, true);
+          self._ensureCaretVisible(aCaretRect);
+      }, true);
+      return;
     }
+
+    let browser = getBrowser();
+    let zoomRect = this.visibleScreenArea;
+
+    this._currentCaretRect = aCaretRect;
+    let caretRect = aCaretRect.scale(browser.scale, browser.scale);
+
+    let scroll = browser.getPosition();
+    zoomRect = new Rect(scroll.x, scroll.y, zoomRect.width, zoomRect.height);
+    if (zoomRect.contains(caretRect))
+      return;
+
+    let [deltaX, deltaY] = this._getOffsetForCaret(caretRect, zoomRect);
+    if (deltaX != 0 || deltaY != 0)
+      browser.scrollBy(deltaX, deltaY);
   },
 
   /* Store the current zoom level, and scroll positions to restore them if needed */
   _zoomStart: function _formHelperZoomStart() {
     if (!Services.prefs.getBoolPref("formhelper.restore"))
       return;
 
     this._restore = {
--- a/mobile/chrome/content/browser.js
+++ b/mobile/chrome/content/browser.js
@@ -52,17 +52,17 @@ let Cc = Components.classes;
 let Ci = Components.interfaces;
 let Cu = Components.utils;
 
 function getBrowser() {
   return Browser.selectedBrowser;
 }
 
 const kDefaultBrowserWidth = 980;
-const kBrowserFormZoomLevelMin = 1.0;
+const kBrowserFormZoomLevelMin = 0.8;
 const kBrowserFormZoomLevelMax = 2.0;
 const kBrowserViewZoomLevelPrecision = 10000;
 
 const kDefaultMetadata = { allowZoom: true };
 
 // Override sizeToContent in the main window. It breaks things (bug 565887)
 window.sizeToContent = function() {
   Components.utils.reportError("window.sizeToContent is not allowed in this window");