Bug 1073250 - Ignore subsequent touches if an any APZC along the handoff chain of the one targeted by the first touch is overscrolled. r=kats
authorBotond Ballo <botond@mozilla.com>
Fri, 03 Oct 2014 20:33:49 -0400
changeset 209030 a19ccad6a93485444b44e806d95310a40a5a3776
parent 209029 6d73cc06f9fed9512dd0cd2d531ff1445071679c
child 209031 42904535d23a715a3676d366681bbdbf205dd179
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewerskats
bugs1073250
milestone35.0a1
Bug 1073250 - Ignore subsequent touches if an any APZC along the handoff chain of the one targeted by the first touch is overscrolled. r=kats
gfx/layers/apz/src/APZCTreeManager.cpp
gfx/layers/apz/src/OverscrollHandoffState.cpp
gfx/layers/apz/src/OverscrollHandoffState.h
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -620,17 +620,17 @@ nsEventStatus
 APZCTreeManager::ProcessTouchInput(MultiTouchInput& aInput,
                                    ScrollableLayerGuid* aOutTargetGuid)
 {
   if (aInput.mType == MultiTouchInput::MULTITOUCH_START) {
     // If we are in an overscrolled state and a second finger goes down,
     // ignore that second touch point completely. The touch-start for it is
     // dropped completely; subsequent touch events until the touch-end for it
     // will have this touch point filtered out.
-    if (mApzcForInputBlock && mApzcForInputBlock->IsOverscrolled()) {
+    if (mApzcForInputBlock && BuildOverscrollHandoffChain(mApzcForInputBlock)->HasOverscrolledApzc()) {
       if (mRetainedTouchIdentifier == -1) {
         mRetainedTouchIdentifier = mApzcForInputBlock->GetLastTouchIdentifier();
       }
       return nsEventStatus_eConsumeNoDefault;
     }
 
     // NS_TOUCH_START event contains all active touches of the current
     // session thus resetting mTouchCount.
--- a/gfx/layers/apz/src/OverscrollHandoffState.cpp
+++ b/gfx/layers/apz/src/OverscrollHandoffState.cpp
@@ -64,16 +64,28 @@ void
 OverscrollHandoffChain::ForEachApzc(APZCMethod aMethod) const
 {
   MOZ_ASSERT(Length() > 0);
   for (uint32_t i = 0; i < Length(); ++i) {
     (mChain[i]->*aMethod)();
   }
 }
 
+bool
+OverscrollHandoffChain::AnyApzc(APZCPredicate aPredicate) const
+{
+  MOZ_ASSERT(Length() > 0);
+  for (uint32_t i = 0; i < Length(); ++i) {
+    if ((mChain[i]->*aPredicate)()) {
+      return true;
+    }
+  }
+  return false;
+}
+
 void
 OverscrollHandoffChain::FlushRepaints() const
 {
   ForEachApzc(&AsyncPanZoomController::FlushRepaintForOverscrollHandoff);
 }
 
 void
 OverscrollHandoffChain::CancelAnimations() const
@@ -124,10 +136,17 @@ OverscrollHandoffChain::CanBePanned(cons
     if (mChain[j]->IsPannable()) {
       return true;
     }
   }
 
   return false;
 }
 
+bool
+OverscrollHandoffChain::HasOverscrolledApzc() const
+{
+  return AnyApzc(&AsyncPanZoomController::IsOverscrolled);
+}
+
+
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/apz/src/OverscrollHandoffState.h
+++ b/gfx/layers/apz/src/OverscrollHandoffState.h
@@ -100,21 +100,26 @@ public:
 
   // Snap back the APZC that is overscrolled on the subset of the chain from
   // |aStart| onwards, if any.
   void SnapBackOverscrolledApzc(const AsyncPanZoomController* aStart) const;
 
   // Determine whether the given APZC, or any APZC further in the chain,
   // has room to be panned.
   bool CanBePanned(const AsyncPanZoomController* aApzc) const;
+
+  // Determine whether any APZC along this handoff chain is overscrolled.
+  bool HasOverscrolledApzc() const;
 private:
   std::vector<nsRefPtr<AsyncPanZoomController>> mChain;
 
   typedef void (AsyncPanZoomController::*APZCMethod)();
+  typedef bool (AsyncPanZoomController::*APZCPredicate)() const;
   void ForEachApzc(APZCMethod aMethod) const;
+  bool AnyApzc(APZCPredicate aPredicate) const;
 };
 
 /**
  * This class groups the state maintained during overscroll handoff.
  */
 struct OverscrollHandoffState {
   OverscrollHandoffState(const OverscrollHandoffChain& aChain,
                          const ScreenPoint& aPanDistance)