Bug 944047 - Store the last FrameMetrics for sub-frames in TabChild. r=botond
authorChris Lord <chrislord.net@gmail.com>
Thu, 05 Dec 2013 20:47:21 +0000
changeset 173769 2722412248da07351ad840e2e9deac96feac2c58
parent 173768 1689fa499c1ce39ec6ffd8b21ddd9d1464b4a6c6
child 173770 ec5f9193d1786e68bb1b8ebb846caa93e0eec78a
push id3224
push userlsblakk@mozilla.com
push dateTue, 04 Feb 2014 01:06:49 +0000
treeherdermozilla-beta@60c04d0987f1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbotond
bugs944047
milestone28.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 944047 - Store the last FrameMetrics for sub-frames in TabChild. r=botond As well as the root frame, make sure to store the last received FrameMetrics for sub-frames in TabChild. This prevents us sending scroll events triggered by the APZC back to the APZC.
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -317,31 +317,35 @@ TabChild::HandleEvent(nsIDOMEvent* aEven
       return NS_ERROR_UNEXPECTED;
 
     nsIScrollableFrame* scrollFrame = nsLayoutUtils::FindScrollableFrameFor(viewId);
     if (!scrollFrame)
       return NS_OK;
 
     CSSIntPoint scrollOffset = scrollFrame->GetScrollPositionCSSPixels();
 
-    if (viewId == mLastMetrics.mScrollId) {
-      // For the root frame, we store the last metrics, including the last
-      // scroll offset, sent by APZC. (This is updated in ProcessUpdateFrame()).
+    if (viewId == mLastRootMetrics.mScrollId) {
+      // We store the last metrics that was sent via the TabParent (This is
+      // updated in ProcessUpdateFrame and RecvUpdateFrame).
       // We use this here to avoid sending APZC back a scroll event that
       // originally came from APZC (besides being unnecessary, the event might
       // be slightly out of date by the time it reaches APZC).
-      // We should probably do this for subframes, too.
-      if (RoundedToInt(mLastMetrics.mScrollOffset) == scrollOffset) {
+      if (RoundedToInt(mLastRootMetrics.mScrollOffset) == scrollOffset) {
         return NS_OK;
       }
 
       // Update the last scroll offset now, otherwise RecvUpdateDimensions()
       // might trigger a scroll to the old offset before RecvUpdateFrame()
       // gets a chance to update it.
-      mLastMetrics.mScrollOffset = scrollOffset;
+      mLastRootMetrics.mScrollOffset = scrollOffset;
+    } else if (viewId == mLastSubFrameMetrics.mScrollId) {
+      if (RoundedToInt(mLastSubFrameMetrics.mScrollOffset) == scrollOffset) {
+        return NS_OK;
+      }
+      mLastSubFrameMetrics.mScrollOffset = scrollOffset;
     }
 
     SendUpdateScrollOffset(presShellId, viewId, scrollOffset);
   }
 
   return NS_OK;
 }
 
@@ -379,31 +383,31 @@ TabChild::Observe(nsISupports *aSubject,
         // Reset CSS viewport and zoom to default on new page, then
         // calculate them properly using the actual metadata from the
         // page.
         SetCSSViewport(kDefaultViewportSize);
 
         // Calculate a really simple resolution that we probably won't
         // be keeping, as well as putting the scroll offset back to
         // the top-left of the page.
-        mLastMetrics.mViewport = CSSRect(CSSPoint(), kDefaultViewportSize);
-        mLastMetrics.mCompositionBounds = ScreenIntRect(ScreenIntPoint(), mInnerSize);
-        mLastMetrics.mZoom = mLastMetrics.CalculateIntrinsicScale();
-        mLastMetrics.mDevPixelsPerCSSPixel = mWidget->GetDefaultScale();
+        mLastRootMetrics.mViewport = CSSRect(CSSPoint(), kDefaultViewportSize);
+        mLastRootMetrics.mCompositionBounds = ScreenIntRect(ScreenIntPoint(), mInnerSize);
+        mLastRootMetrics.mZoom = mLastRootMetrics.CalculateIntrinsicScale();
+        mLastRootMetrics.mDevPixelsPerCSSPixel = mWidget->GetDefaultScale();
         // We use ScreenToLayerScale(1) below in order to turn the
         // async zoom amount into the gecko zoom amount.
-        mLastMetrics.mCumulativeResolution =
-          mLastMetrics.mZoom / mLastMetrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1);
+        mLastRootMetrics.mCumulativeResolution =
+          mLastRootMetrics.mZoom / mLastRootMetrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1);
         // This is the root layer, so the cumulative resolution is the same
         // as the resolution.
-        mLastMetrics.mResolution = mLastMetrics.mCumulativeResolution / LayoutDeviceToParentLayerScale(1);
-        mLastMetrics.mScrollOffset = CSSPoint(0, 0);
+        mLastRootMetrics.mResolution = mLastRootMetrics.mCumulativeResolution / LayoutDeviceToParentLayerScale(1);
+        mLastRootMetrics.mScrollOffset = CSSPoint(0, 0);
 
-        utils->SetResolution(mLastMetrics.mResolution.scale,
-                             mLastMetrics.mResolution.scale);
+        utils->SetResolution(mLastRootMetrics.mResolution.scale,
+                             mLastRootMetrics.mResolution.scale);
 
         HandlePossibleViewportChange();
       }
     }
   }
 
   return NS_OK;
 }
@@ -549,17 +553,17 @@ TabChild::HandlePossibleViewportChange()
 
   // We're not being displayed in any way; don't bother doing anything because
   // that will just confuse future adjustments.
   if (!screenW || !screenH) {
     return;
   }
 
   float oldBrowserWidth = mOldViewportWidth;
-  mLastMetrics.mViewport.SizeTo(viewport);
+  mLastRootMetrics.mViewport.SizeTo(viewport);
   if (!oldBrowserWidth) {
     oldBrowserWidth = kDefaultViewportSize.width;
   }
   SetCSSViewport(viewport);
 
   // If this page has not been painted yet, then this must be getting run
   // because a meta-viewport element was added (via the DOMMetaAdded handler).
   // in this case, we should not do anything that forces a reflow (see bug
@@ -595,22 +599,22 @@ TabChild::HandlePossibleViewportChange()
     // For non-HTML content (e.g. SVG), just assume page size == viewport size.
     pageSize = viewport;
   }
   if (!pageSize.width) {
     // Return early rather than divide by 0.
     return;
   }
 
-  float oldScreenWidth = mLastMetrics.mCompositionBounds.width;
+  float oldScreenWidth = mLastRootMetrics.mCompositionBounds.width;
   if (!oldScreenWidth) {
     oldScreenWidth = mInnerSize.width;
   }
 
-  FrameMetrics metrics(mLastMetrics);
+  FrameMetrics metrics(mLastRootMetrics);
   metrics.mViewport = CSSRect(CSSPoint(), viewport);
   metrics.mScrollableRect = CSSRect(CSSPoint(), pageSize);
   metrics.mCompositionBounds = ScreenIntRect(ScreenIntPoint(), mInnerSize);
 
   // This change to the zoom accounts for all types of changes I can conceive:
   // 1. screen size changes, CSS viewport does not (pages with no meta viewport
   //    or a fixed size viewport)
   // 2. screen size changes, CSS viewport also does (pages with a device-width
@@ -1527,24 +1531,25 @@ TabChild::RecvUpdateFrame(const FrameMet
   } else {
     // aFrameMetrics.mIsRoot is false, so we are trying to update a subframe.
     // This requires special handling.
     nsCOMPtr<nsIContent> content = nsLayoutUtils::FindContentFor(
                                       aFrameMetrics.mScrollId);
     if (content) {
       FrameMetrics newSubFrameMetrics(aFrameMetrics);
       APZCCallbackHelper::UpdateSubFrame(content, newSubFrameMetrics);
+      mLastSubFrameMetrics = newSubFrameMetrics;
       return true;
     }
   }
 
   // We've recieved a message that is out of date and we want to ignore.
   // However we can't reply without painting so we reply by painting the
   // exact same thing as we did before.
-  return ProcessUpdateFrame(mLastMetrics);
+  return ProcessUpdateFrame(mLastRootMetrics);
 }
 
 bool
 TabChild::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics)
   {
     if (!mGlobal || !mTabChildGlobal) {
         return true;
     }
@@ -1598,17 +1603,17 @@ TabChild::ProcessUpdateFrame(const Frame
         data.AppendFloat(cssCompositedRect.width);
         data.AppendLiteral(", \"height\" : ");
         data.AppendFloat(cssCompositedRect.height);
         data.AppendLiteral(" }");
     data.AppendLiteral(" }");
 
     DispatchMessageManagerMessage(NS_LITERAL_STRING("Viewport:Change"), data);
 
-    mLastMetrics = newMetrics;
+    mLastRootMetrics = newMetrics;
 
     return true;
 }
 
 bool
 TabChild::RecvHandleDoubleTap(const CSSIntPoint& aPoint)
 {
     if (!mGlobal || !mTabChildGlobal) {
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -458,17 +458,18 @@ private:
 
     class CachedFileDescriptorInfo;
     class CachedFileDescriptorCallbackRunnable;
 
     TextureFactoryIdentifier mTextureFactoryIdentifier;
     nsCOMPtr<nsIWebNavigation> mWebNav;
     nsCOMPtr<nsIWidget> mWidget;
     nsCOMPtr<nsIURI> mLastURI;
-    FrameMetrics mLastMetrics;
+    FrameMetrics mLastRootMetrics;
+    FrameMetrics mLastSubFrameMetrics;
     RenderFrameChild* mRemoteFrame;
     nsRefPtr<ContentChild> mManager;
     nsRefPtr<TabChildGlobal> mTabChildGlobal;
     uint32_t mChromeFlags;
     nsIntRect mOuterRect;
     ScreenIntSize mInnerSize;
     // When we're tracking a possible tap gesture, this is the "down"
     // point of the touchstart.