diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp index 50768cd8ed27..732df2b4159b 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -674,9 +674,15 @@ nsEventStatus AsyncPanZoomController::OnScale(const PinchGestureInput& aEvent) { nsEventStatus AsyncPanZoomController::OnScaleEnd(const PinchGestureInput& aEvent) { APZC_LOG("%p got a scale-end in state %d\n", this, mState); - SetState(PANNING); - mX.StartTouch(aEvent.mFocusPoint.x); - mY.StartTouch(aEvent.mFocusPoint.y); + // When a pinch ends, it might either turn into a pan (if only one finger + // was lifted) or not (if both fingers were lifted). GestureEventListener + // sets mCurrentSpan to a negative value in the latter case, and sets + // mFocusPoint to the remaining touch point in the former case. + if (aEvent.mCurrentSpan >= 0) { + SetState(PANNING); + mX.StartTouch(aEvent.mFocusPoint.x); + mY.StartTouch(aEvent.mFocusPoint.y); + } { ReentrantMonitorAutoEnter lock(mMonitor); ScheduleComposite(); diff --git a/gfx/layers/ipc/GestureEventListener.cpp b/gfx/layers/ipc/GestureEventListener.cpp index 637f90e0d222..0e1a6743d2fa 100644 --- a/gfx/layers/ipc/GestureEventListener.cpp +++ b/gfx/layers/ipc/GestureEventListener.cpp @@ -194,8 +194,7 @@ nsEventStatus GestureEventListener::HandleInputEvent(const InputData& aEvent) // This gets called if there's a touch that has to bail for weird reasons // like pinching and then moving away from the window that the pinch was // started in without letting go of the screen. - HandlePinchGestureEvent(event, true); - break; + return HandlePinchGestureEvent(event, true); } return HandlePinchGestureEvent(event, false); @@ -257,9 +256,19 @@ nsEventStatus GestureEventListener::HandlePinchGestureEvent(const MultiTouchInpu } else if (mState == GESTURE_PINCH) { PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_END, aEvent.mTime, - mTouches[0].mScreenPoint, - 1.0f, - 1.0f); + ScreenPoint(), // may change below + 1.0f, // may change below + 1.0f); // may change below + + if (mTouches.Length() > 0) { + // Pinch is changing to pan. APZC will start a pan at mFocusPoint + // (which isn't really a focus point in this case...). + pinchEvent.mFocusPoint = mTouches[0].mScreenPoint; + } else { + // Pinch is ending, no pan to follow. APZC will check for the spans + // being negative. + pinchEvent.mCurrentSpan = pinchEvent.mPreviousSpan = -1.0f; + } mAsyncPanZoomController->HandleInputEvent(pinchEvent); diff --git a/gfx/tests/gtest/TestAsyncPanZoomController.cpp b/gfx/tests/gtest/TestAsyncPanZoomController.cpp index af141779b42a..af10bbde291b 100644 --- a/gfx/tests/gtest/TestAsyncPanZoomController.cpp +++ b/gfx/tests/gtest/TestAsyncPanZoomController.cpp @@ -128,8 +128,10 @@ ApzcPinch(AsyncPanZoomController* aApzc, int aFocusX, int aFocusY, float aScale) aApzc->HandleInputEvent(PinchGestureInput(PinchGestureInput::PINCHGESTURE_END, 0, ScreenPoint(aFocusX, aFocusY), - 10.0 * aScale, - 10.0 * aScale)); + // note: negative values here tell APZC + // not to turn the pinch into a pan + -1.0, + -1.0)); } TEST(AsyncPanZoomController, Constructor) {