Bug 1027309 - When switching to a new APZC for a touch input block, cancel state in the old APZC. r=drs, a=2.0+
authorKartikaya Gupta <kgupta@mozilla.com>
Wed, 25 Jun 2014 19:13:59 -0400
changeset 207372 58bb80d1fe9d8bfa167dc387abcdeb3de939b5b8
parent 207371 ad16ee0c251bd99869e808c5d97d0d9e6f99edff
child 207373 6d261c1cbe2571887794f21fcdf17dddb1d94134
push id3741
push userasasaki@mozilla.com
push dateMon, 21 Jul 2014 20:25:18 +0000
treeherdermozilla-beta@4d6f46f5af68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdrs, 2
bugs1027309
milestone32.0a2
Bug 1027309 - When switching to a new APZC for a touch input block, cancel state in the old APZC. r=drs, a=2.0+
gfx/layers/apz/src/APZCTreeManager.cpp
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -389,28 +389,38 @@ APZCTreeManager::ReceiveInputEvent(const
             mRetainedTouchIdentifier = mApzcForInputBlock->GetLastTouchIdentifier();
           }
           return nsEventStatus_eConsumeNoDefault;
         }
         // MULTITOUCH_START input contains all active touches of the current
         // session thus resetting mTouchCount.
         mTouchCount = multiTouchInput.mTouches.Length();
         mInOverscrolledApzc = false;
-        mApzcForInputBlock = GetTargetAPZC(ScreenPoint(multiTouchInput.mTouches[0].mScreenPoint),
-                                           &mInOverscrolledApzc);
+        nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(ScreenPoint(multiTouchInput.mTouches[0].mScreenPoint),
+                                                                          &mInOverscrolledApzc);
         for (size_t i = 1; i < multiTouchInput.mTouches.Length(); i++) {
           nsRefPtr<AsyncPanZoomController> apzc2 = GetTargetAPZC(ScreenPoint(multiTouchInput.mTouches[i].mScreenPoint),
                                                                  &mInOverscrolledApzc);
-          mApzcForInputBlock = CommonAncestor(mApzcForInputBlock.get(), apzc2.get());
+          apzc = CommonAncestor(mApzcForInputBlock.get(), apzc2.get());
           APZCTM_LOG("Using APZC %p as the common ancestor\n", mApzcForInputBlock.get());
           // For now, we only ever want to do pinching on the root APZC for a given layers id. So
           // when we find the common ancestor of multiple points, also walk up to the root APZC.
-          mApzcForInputBlock = RootAPZCForLayersId(mApzcForInputBlock);
+          apzc = RootAPZCForLayersId(mApzcForInputBlock);
           APZCTM_LOG("Using APZC %p as the root APZC for multi-touch\n", mApzcForInputBlock.get());
         }
+        if (apzc != mApzcForInputBlock) {
+          // If we're moving to a different APZC as our input target, then send a cancel event
+          // to the old one so that it clears its internal state. Otherwise it could get left
+          // in the middle of a panning touch block (for example) and not clean up properly.
+          if (mApzcForInputBlock) {
+            MultiTouchInput cancel(MultiTouchInput::MULTITOUCH_CANCEL, 0, TimeStamp::Now(), 0);
+            mApzcForInputBlock->ReceiveInputEvent(cancel);
+          }
+          mApzcForInputBlock = apzc;
+        }
 
         // Prepare for possible overscroll handoff.
         BuildOverscrollHandoffChain(mApzcForInputBlock);
 
         if (mApzcForInputBlock) {
           // Cache transformToApzc so it can be used for future events in this block.
           GetInputTransforms(mApzcForInputBlock, transformToApzc, transformToGecko);
           mCachedTransformToApzcForInputBlock = transformToApzc;
@@ -584,17 +594,29 @@ APZCTreeManager::ProcessTouchEvent(Widge
         mRetainedTouchIdentifier = mApzcForInputBlock->GetLastTouchIdentifier();
       }
       return nsEventStatus_eConsumeNoDefault;
     }
     // NS_TOUCH_START event contains all active touches of the current
     // session thus resetting mTouchCount.
     mTouchCount = aEvent.touches.Length();
     mInOverscrolledApzc = false;
-    mApzcForInputBlock = GetTouchInputBlockAPZC(aEvent, &mInOverscrolledApzc);
+
+    nsRefPtr<AsyncPanZoomController> apzc = GetTouchInputBlockAPZC(aEvent, &mInOverscrolledApzc);
+    if (apzc != mApzcForInputBlock) {
+      // If we're moving to a different APZC as our input target, then send a cancel event
+      // to the old one so that it clears its internal state. Otherwise it could get left
+      // in the middle of a panning touch block (for example) and not clean up properly.
+      if (mApzcForInputBlock) {
+        MultiTouchInput cancel(MultiTouchInput::MULTITOUCH_CANCEL, 0, TimeStamp::Now(), 0);
+        mApzcForInputBlock->ReceiveInputEvent(cancel);
+      }
+      mApzcForInputBlock = apzc;
+    }
+
     if (mApzcForInputBlock) {
       // Cache apz transform so it can be used for future events in this block.
       gfx3DMatrix transformToGecko;
       GetInputTransforms(mApzcForInputBlock, mCachedTransformToApzcForInputBlock, transformToGecko);
     } else {
       // Reset the cached apz transform
       mCachedTransformToApzcForInputBlock = gfx3DMatrix();
     }