author | Dennis Ek <contact@dennisek.se> |
Tue, 23 May 2017 19:53:06 +0200 | |
changeset 408438 | f5a0a69abe4b17622c5e804db3dc0e564e48c622 |
parent 408399 | bb439487185f4ce5cdc0183db4b6776beb75b954 |
child 408439 | cbae2c2731e49a6ce8458e07da2ccaa1ae34ceeb |
push id | 7391 |
push user | mtabara@mozilla.com |
push date | Mon, 12 Jun 2017 13:08:53 +0000 |
treeherder | mozilla-beta@2191d7f87e2e [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | kats |
bugs | 1111333 |
milestone | 55.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
|
--- a/AUTHORS +++ b/AUTHORS @@ -285,16 +285,17 @@ David Rajchenbach-Teller <dteller@mozill David Savage David S. Miller <davem@redhat.com> David Woodhouse <dwmw2@infradead.org> David Zbarsky <dzbarsky@gmail.com> Dean Tessman <dean_tessman@hotmail.com> <deneen@alum.bucknell.edu> Denis Antrushin <adu@sparc.spb.su> Denis Issoupov <denis@macadamian.com> +Dennis Ek <contact@dennisek.se> Dennis Handly Derrick Rice <derrick.rice@gmail.com> <desale@netscape.com> diablohn Diane Trout <diane@ghic.org> Dietrich Ayala <dietrich@mozilla.com> Digital Creations 2, Inc Disruptive Innovations
--- a/gfx/layers/apz/src/GestureEventListener.cpp +++ b/gfx/layers/apz/src/GestureEventListener.cpp @@ -32,16 +32,22 @@ static const uint32_t MAX_TAP_TIME = 300 /** * Amount of span or focus change needed to take us from the GESTURE_WAITING_PINCH * state to the GESTURE_PINCH state. This is measured as either a change in distance * between the fingers used to compute the span ratio, or the a change in * position of the focus point between the two fingers. */ static const float PINCH_START_THRESHOLD = 35.0f; +/** + * Determines how fast a one touch pinch zooms in and out. The greater the + * value, the faster it zooms. + */ +static const float ONE_TOUCH_PINCH_SPEED = 0.005f; + static bool sLongTapEnabled = true; ParentLayerPoint GetCurrentFocus(const MultiTouchInput& aEvent) { const ParentLayerPoint& firstTouch = aEvent.mTouches[0].mLocalScreenPoint; const ParentLayerPoint& secondTouch = aEvent.mTouches[1].mLocalScreenPoint; return (firstTouch + secondTouch) / 2; } @@ -49,16 +55,23 @@ ParentLayerPoint GetCurrentFocus(const M ParentLayerCoord GetCurrentSpan(const MultiTouchInput& aEvent) { const ParentLayerPoint& firstTouch = aEvent.mTouches[0].mLocalScreenPoint; const ParentLayerPoint& secondTouch = aEvent.mTouches[1].mLocalScreenPoint; ParentLayerPoint delta = secondTouch - firstTouch; return delta.Length(); } +ParentLayerCoord GestureEventListener::GetYSpanFromStartPoint() +{ + const ParentLayerPoint start = mTouchStartPosition; + const ParentLayerPoint& current = mTouches[0].mLocalScreenPoint; + return current.y - start.y; +} + TapGestureInput CreateTapEvent(const MultiTouchInput& aTouch, TapGestureInput::TapGestureType aType) { return TapGestureInput(aType, aTouch.mTime, aTouch.mTimeStamp, aTouch.mTouches[0].mScreenPoint, aTouch.modifiers); } @@ -88,38 +101,41 @@ nsEventStatus GestureEventListener::Hand // Cache the current event since it may become the single or long tap that we // send. mLastTouchInput = aEvent; switch (aEvent.mType) { case MultiTouchInput::MULTITOUCH_START: mTouches.Clear(); + // Cache every touch. for (size_t i = 0; i < aEvent.mTouches.Length(); i++) { mTouches.AppendElement(aEvent.mTouches[i]); } if (aEvent.mTouches.Length() == 1) { rv = HandleInputTouchSingleStart(); } else { rv = HandleInputTouchMultiStart(); } break; case MultiTouchInput::MULTITOUCH_MOVE: + // Update the screen points of the cached touches. for (size_t i = 0; i < aEvent.mTouches.Length(); i++) { for (size_t j = 0; j < mTouches.Length(); j++) { if (aEvent.mTouches[i].mIdentifier == mTouches[j].mIdentifier) { mTouches[j].mScreenPoint = aEvent.mTouches[i].mScreenPoint; mTouches[j].mLocalScreenPoint = aEvent.mTouches[i].mLocalScreenPoint; } } } rv = HandleInputTouchMove(); break; case MultiTouchInput::MULTITOUCH_END: + // Remove the cache of the touch that ended. for (size_t i = 0; i < aEvent.mTouches.Length(); i++) { for (size_t j = 0; j < mTouches.Length(); j++) { if (aEvent.mTouches[i].mIdentifier == mTouches[j].mIdentifier) { mTouches.RemoveElementAt(j); break; } } } @@ -249,28 +265,55 @@ nsEventStatus GestureEventListener::Hand if (MoveDistanceIsLarge()) { // So that we don't fire a long-tap-up if the user moves around after a // long-tap SetState(GESTURE_NONE); } break; case GESTURE_FIRST_SINGLE_TOUCH_DOWN: - case GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN: - case GESTURE_SECOND_SINGLE_TOUCH_DOWN: { + case GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN: { // If we move too much, bail out of the tap. if (MoveDistanceIsLarge()) { CancelLongTapTimeoutTask(); CancelMaxTapTimeoutTask(); mSingleTapSent = Nothing(); SetState(GESTURE_NONE); } break; } + // The user has performed a double tap, but not lifted her finger. + case GESTURE_SECOND_SINGLE_TOUCH_DOWN: { + // If touch has moved noticeably (within MAX_TAP_TIME), change state. + if (MoveDistanceIsLarge()) { + CancelLongTapTimeoutTask(); + CancelMaxTapTimeoutTask(); + mSingleTapSent = Nothing(); + SetState(GESTURE_ONE_TOUCH_PINCH); + + ParentLayerCoord currentSpan = 1.0f; + ParentLayerPoint currentFocus = mTouchStartPosition; + + PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_START, + mLastTouchInput.mTime, + mLastTouchInput.mTimeStamp, + currentFocus, + currentSpan, + currentSpan, + mLastTouchInput.modifiers); + + rv = mAsyncPanZoomController->HandleGestureEvent(pinchEvent); + + mPreviousSpan = currentSpan; + mPreviousFocus = currentFocus; + } + break; + } + case GESTURE_MULTI_TOUCH_DOWN: { if (mLastTouchInput.mTouches.Length() < 2) { NS_WARNING("Wrong input: less than 2 moving points in GESTURE_MULTI_TOUCH_DOWN state"); break; } ParentLayerCoord currentSpan = GetCurrentSpan(mLastTouchInput); ParentLayerPoint currentFocus = GetCurrentFocus(mLastTouchInput); @@ -319,16 +362,40 @@ nsEventStatus GestureEventListener::Hand mLastTouchInput.modifiers); rv = mAsyncPanZoomController->HandleGestureEvent(pinchEvent); mPreviousSpan = currentSpan; break; } + case GESTURE_ONE_TOUCH_PINCH: { + ParentLayerCoord currentSpan = GetYSpanFromStartPoint(); + float effectiveSpan = 1.0f + (fabsf(currentSpan.value) * ONE_TOUCH_PINCH_SPEED); + ParentLayerPoint currentFocus = mTouchStartPosition; + + // Invert zoom. + if (currentSpan.value < 0) { + effectiveSpan = 1.0f / effectiveSpan; + } + + PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_SCALE, + mLastTouchInput.mTime, + mLastTouchInput.mTimeStamp, + currentFocus, + effectiveSpan, + mPreviousSpan, + mLastTouchInput.modifiers); + + rv = mAsyncPanZoomController->HandleGestureEvent(pinchEvent); + mPreviousSpan = effectiveSpan; + + break; + } + default: NS_WARNING("Unhandled state upon touch move"); SetState(GESTURE_NONE); break; } return rv; } @@ -406,16 +473,33 @@ nsEventStatus GestureEventListener::Hand mLastTouchInput.modifiers); mAsyncPanZoomController->HandleGestureEvent(pinchEvent); } rv = nsEventStatus_eConsumeNoDefault; break; + case GESTURE_ONE_TOUCH_PINCH: { + SetState(GESTURE_NONE); + ParentLayerPoint point(-1, -1); + PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_END, + mLastTouchInput.mTime, + mLastTouchInput.mTimeStamp, + point, + 1.0f, + 1.0f, + mLastTouchInput.modifiers); + mAsyncPanZoomController->HandleGestureEvent(pinchEvent); + + rv = nsEventStatus_eConsumeNoDefault; + + break; + } + default: NS_WARNING("Unhandled state upon touch end"); SetState(GESTURE_NONE); break; } return rv; }
--- a/gfx/layers/apz/src/GestureEventListener.h +++ b/gfx/layers/apz/src/GestureEventListener.h @@ -100,34 +100,40 @@ private: // After having gotten into this state we clear the timer for MAX_TAP_TIME. // Allowed next states: GESTURE_SECOND_SINGLE_TOUCH_DOWN, GESTURE_NONE, // GESTURE_MULTI_TOUCH_DOWN. GESTURE_FIRST_SINGLE_TOUCH_UP, // A user put down her finger again right after a single tap thus the // gesture can't be a single tap, but rather a double tap. But we're // still not sure about that until the user lifts her finger again. - // Allowed next states: GESTURE_MULTI_TOUCH_DOWN, GESTURE_NONE. + // Allowed next states: GESTURE_MULTI_TOUCH_DOWN, GESTURE_ONE_TOUCH_PINCH, + // GESTURE_NONE. GESTURE_SECOND_SINGLE_TOUCH_DOWN, // A long touch has happened, but the user still keeps her finger down. // We'll trigger a "long tap up" event when the finger is up. // Allowed next states: GESTURE_NONE, GESTURE_MULTI_TOUCH_DOWN. GESTURE_LONG_TOUCH_DOWN, // We have detected that two or more fingers are on the screen, but there // hasn't been enough movement yet to make us start actually zooming the // screen. // Allowed next states: GESTURE_PINCH, GESTURE_NONE GESTURE_MULTI_TOUCH_DOWN, // There are two or more fingers on the screen, and the user has already // pinched enough for us to start zooming the screen. // Allowed next states: GESTURE_NONE - GESTURE_PINCH + GESTURE_PINCH, + + // The user has double tapped, but not lifted her finger, and moved her + // finger more than PINCH_START_THRESHOLD. + // Allowed next states: GESTURE_NONE. + GESTURE_ONE_TOUCH_PINCH }; /** * These HandleInput* functions comprise input alphabet of the GEL * finite-state machine triggering state transitions. */ nsEventStatus HandleInputTouchSingleStart(); nsEventStatus HandleInputTouchMultiStart(); @@ -137,16 +143,22 @@ private: void HandleInputTimeoutLongTap(); void HandleInputTimeoutMaxTap(bool aDuringFastFling); void TriggerSingleTapConfirmedEvent(); bool MoveDistanceIsLarge(); /** + * Returns current vertical span, counting from the where the user first put + * her finger down. + */ + ParentLayerCoord GetYSpanFromStartPoint(); + + /** * Do actual state transition and reset substates. */ void SetState(GestureState aState); RefPtr<AsyncPanZoomController> mAsyncPanZoomController; /** * Array containing all active touches. When a touch happens it, gets added to