Bug 1260588 - C++ APZ should only allow handoff to ancestor APZC r=botond
authorRandall Barker <rbarker@mozilla.com>
Tue, 29 Mar 2016 16:46:29 -0700
changeset 291415 5620c5785d8e80ce0f50fa557d14a134741e1c02
parent 291414 d82bdcd0b640dc5aefb0c10ea108a2c04c81d98c
child 291416 95e61ede373da7ae3755ca149da42ff873e05a42
push id19656
push usergwagner@mozilla.com
push dateMon, 04 Apr 2016 13:43:23 +0000
treeherderb2g-inbound@e99061fde28a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbotond
bugs1260588
milestone48.0a1
Bug 1260588 - C++ APZ should only allow handoff to ancestor APZC r=botond
gfx/layers/apz/src/AsyncPanZoomController.cpp
gfx/layers/apz/src/InputBlockState.cpp
gfx/layers/apz/src/InputBlockState.h
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -2355,21 +2355,21 @@ bool AsyncPanZoomController::AttemptScro
   ParentLayerPoint displacement = aStartPoint - aEndPoint;
 
   ParentLayerPoint overscroll;  // will be used outside monitor block
 
   // If the direction of panning is reversed within the same input block,
   // a later event in the block could potentially scroll an APZC earlier
   // in the handoff chain, than an earlier event in the block (because
   // the earlier APZC was scrolled to its extent in the original direction).
-  // If immediate handoff is disallowed, we want to disallow this (to
-  // preserve the property that a single input block only scrolls one APZC),
-  // so we skip the earlier APZC.
-  bool scrollThisApzc = gfxPrefs::APZAllowImmediateHandoff() ||
-      (CurrentInputBlock() && (!CurrentInputBlock()->GetScrolledApzc() || this == CurrentInputBlock()->GetScrolledApzc()));
+  // We want to disallow this.
+  bool scrollThisApzc = false;
+  if (InputBlockState* block = CurrentInputBlock()) {
+    scrollThisApzc = !block->GetScrolledApzc() || block->IsDownchainOfScrolledApzc(this);
+  }
 
   if (scrollThisApzc) {
     ReentrantMonitorAutoEnter lock(mMonitor);
 
     ParentLayerPoint adjustedDisplacement;
     bool forceVerticalOverscroll =
       (aOverscrollHandoffState.mScrollSource == ScrollSource::Wheel &&
        !mFrameMetrics.AllowVerticalScrollWithWheel());
@@ -2378,31 +2378,29 @@ bool AsyncPanZoomController::AttemptScro
     bool xChanged = mX.AdjustDisplacement(displacement.x, adjustedDisplacement.x, overscroll.x);
 
     if (xChanged || yChanged) {
       ScheduleComposite();
     }
 
     if (!IsZero(adjustedDisplacement)) {
       ScrollBy(adjustedDisplacement / mFrameMetrics.GetZoom());
-      if (!gfxPrefs::APZAllowImmediateHandoff()) {
-        if (InputBlockState* block = CurrentInputBlock()) {
-          block->SetScrolledApzc(this);
-        }
+      if (InputBlockState* block = CurrentInputBlock()) {
+        block->SetScrolledApzc(this);
       }
       ScheduleCompositeAndMaybeRepaint();
       UpdateSharedCompositorFrameMetrics();
     }
+
+    // Adjust the start point to reflect the consumed portion of the scroll.
+    aStartPoint = aEndPoint + overscroll;
   } else {
     overscroll = displacement;
   }
 
-  // Adjust the start point to reflect the consumed portion of the scroll.
-  aStartPoint = aEndPoint + overscroll;
-
   // If we consumed the entire displacement as a normal scroll, great.
   if (IsZero(overscroll)) {
     return true;
   }
 
   if (AllowScrollHandoffInCurrentBlock()) {
     // If there is overscroll, first try to hand it off to an APZC later
     // in the handoff chain to consume (either as a normal scroll or as
--- a/gfx/layers/apz/src/InputBlockState.cpp
+++ b/gfx/layers/apz/src/InputBlockState.cpp
@@ -83,17 +83,17 @@ InputBlockState::GetBlockId() const
 
 bool
 InputBlockState::IsTargetConfirmed() const
 {
   return mTargetConfirmed;
 }
 
 bool
-InputBlockState::IsAncestorOf(AsyncPanZoomController* aA, AsyncPanZoomController* aB)
+InputBlockState::IsDownchainOf(AsyncPanZoomController* aA, AsyncPanZoomController* aB) const
 {
   if (aA == aB) {
     return true;
   }
 
   bool seenA = false;
   for (size_t i = 0; i < mOverscrollHandoffChain->Length(); ++i) {
     AsyncPanZoomController* apzc = mOverscrollHandoffChain->GetApzcAtIndex(i);
@@ -107,27 +107,35 @@ InputBlockState::IsAncestorOf(AsyncPanZo
   return false;
 }
 
 
 void
 InputBlockState::SetScrolledApzc(AsyncPanZoomController* aApzc)
 {
   // An input block should only have one scrolled APZC.
-  MOZ_ASSERT(!mScrolledApzc || mScrolledApzc == aApzc);
+  MOZ_ASSERT(!mScrolledApzc || (gfxPrefs::APZAllowImmediateHandoff() ? IsDownchainOf(mScrolledApzc, aApzc) : mScrolledApzc == aApzc));
 
   mScrolledApzc = aApzc;
 }
 
 AsyncPanZoomController*
 InputBlockState::GetScrolledApzc() const
 {
   return mScrolledApzc;
 }
 
+bool
+InputBlockState::IsDownchainOfScrolledApzc(AsyncPanZoomController* aApzc) const
+{
+  MOZ_ASSERT(aApzc && mScrolledApzc);
+
+  return IsDownchainOf(mScrolledApzc, aApzc);
+}
+
 CancelableBlockState::CancelableBlockState(const RefPtr<AsyncPanZoomController>& aTargetApzc,
                                            bool aTargetConfirmed)
   : InputBlockState(aTargetApzc, aTargetConfirmed)
   , mPreventDefault(false)
   , mContentResponded(false)
   , mContentResponseTimerExpired(false)
 {
 }
--- a/gfx/layers/apz/src/InputBlockState.h
+++ b/gfx/layers/apz/src/InputBlockState.h
@@ -47,24 +47,25 @@ public:
   const RefPtr<AsyncPanZoomController>& GetTargetApzc() const;
   const RefPtr<const OverscrollHandoffChain>& GetOverscrollHandoffChain() const;
   uint64_t GetBlockId() const;
 
   bool IsTargetConfirmed() const;
 
   void SetScrolledApzc(AsyncPanZoomController* aApzc);
   AsyncPanZoomController* GetScrolledApzc() const;
+  bool IsDownchainOfScrolledApzc(AsyncPanZoomController* aApzc) const;
 
 protected:
   virtual void UpdateTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc);
 
 private:
   // Checks whether |aA| is an ancestor of |aB| (or the same as |aB|) in
   // |mOverscrollHandoffChain|.
-  bool IsAncestorOf(AsyncPanZoomController* aA, AsyncPanZoomController* aB);
+  bool IsDownchainOf(AsyncPanZoomController* aA, AsyncPanZoomController* aB) const;
 
 private:
   RefPtr<AsyncPanZoomController> mTargetApzc;
   bool mTargetConfirmed;
   const uint64_t mBlockId;
 
   // The APZC that was actually scrolled by events in this input block.
   // This is used in configurations where a single input block is only