diff --git a/gfx/layers/ipc/GestureEventListener.cpp b/gfx/layers/ipc/GestureEventListener.cpp index e5f1f40ce261..c98be4a487b2 100644 --- a/gfx/layers/ipc/GestureEventListener.cpp +++ b/gfx/layers/ipc/GestureEventListener.cpp @@ -4,26 +4,15 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include "base/basictypes.h" -#include "base/thread.h" - #include "GestureEventListener.h" #include "AsyncPanZoomController.h" namespace mozilla { namespace layers { -/** - * Maximum time for a touch on the screen and corresponding lift of the finger - * to be considered a tap. This also applies to double taps, except that it is - * used twice. - */ -static const int MAX_TAP_TIME = 300; - GestureEventListener::GestureEventListener(AsyncPanZoomController* aAsyncPanZoomController) : mAsyncPanZoomController(aAsyncPanZoomController), - mState(GESTURE_NONE), - mLastTouchInput(MultiTouchInput::MULTITOUCH_START, 0) + mState(NoGesture) { } @@ -60,13 +49,7 @@ nsEventStatus GestureEventListener::HandleInputEvent(const InputData& aEvent) } } - size_t length = mTouches.Length(); - if (length == 1) { - mTapStartTime = event.mTime; - if (mState == GESTURE_NONE) { - mState = GESTURE_WAITING_SINGLE_TAP; - } - } else if (length == 2) { + if (mTouches.Length() == 2) { // Another finger has been added; it can't be a tap anymore. HandleTapCancel(event); } @@ -106,37 +89,18 @@ nsEventStatus GestureEventListener::HandleInputEvent(const InputData& aEvent) NS_WARN_IF_FALSE(foundAlreadyExistingTouch, "Touch ended, but not in list"); - if (event.mTime - mTapStartTime <= MAX_TAP_TIME) { - if (mState == GESTURE_WAITING_DOUBLE_TAP) { - mDoubleTapTimeoutTask->Cancel(); - - // We were waiting for a double tap and it has arrived. - HandleDoubleTap(event); - mState = GESTURE_NONE; - } else if (mState == GESTURE_WAITING_SINGLE_TAP) { - HandleSingleTapUpEvent(event); - - // We were not waiting for anything but a single tap has happened that - // may turn into a double tap. Wait a while and if it doesn't turn into - // a double tap, send a single tap instead. - mState = GESTURE_WAITING_DOUBLE_TAP; - - // Cache the current event since it may become the single tap that we - // send. - mLastTouchInput = event; - - mDoubleTapTimeoutTask = - NewRunnableMethod(this, &GestureEventListener::TimeoutDoubleTap); - - MessageLoop::current()->PostDelayedTask( - FROM_HERE, - mDoubleTapTimeoutTask, - MAX_TAP_TIME); + if (event.mTime - mTouchStartTime <= MAX_TAP_TIME) { + // XXX: Incorrect use of the tap event. In the future, we want to send this + // on NS_TOUCH_END, then have a short timer afterwards which sends + // SingleTapConfirmed. Since we don't have double taps yet, this is fine for + // now. + if (HandleSingleTapUpEvent(event) == nsEventStatus_eConsumeNoDefault) { + return nsEventStatus_eConsumeNoDefault; } - } - if (mState == GESTURE_WAITING_SINGLE_TAP) { - mState = GESTURE_NONE; + if (HandleSingleTapConfirmedEvent(event) == nsEventStatus_eConsumeNoDefault) { + return nsEventStatus_eConsumeNoDefault; + } } break; @@ -166,7 +130,7 @@ nsEventStatus GestureEventListener::HandlePinchGestureEvent(const MultiTouchInpu float(NS_hypot(firstTouch.x - secondTouch.x, firstTouch.y - secondTouch.y)); - if (mState == GESTURE_NONE) { + if (mState == NoGesture) { PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_START, aEvent.mTime, focusPoint, @@ -175,7 +139,7 @@ nsEventStatus GestureEventListener::HandlePinchGestureEvent(const MultiTouchInpu mAsyncPanZoomController->HandleInputEvent(pinchEvent); - mState = GESTURE_PINCH; + mState = InPinchGesture; } else { PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_SCALE, aEvent.mTime, @@ -189,16 +153,16 @@ nsEventStatus GestureEventListener::HandlePinchGestureEvent(const MultiTouchInpu mPreviousSpan = currentSpan; rv = nsEventStatus_eConsumeNoDefault; - } else if (mState == GESTURE_PINCH) { + } else if (mState == InPinchGesture) { PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_END, aEvent.mTime, mTouches[0].mScreenPoint, 1.0f, 1.0f); - + mAsyncPanZoomController->HandleInputEvent(pinchEvent); - mState = GESTURE_NONE; + mState = NoGesture; rv = nsEventStatus_eConsumeNoDefault; } @@ -213,47 +177,27 @@ nsEventStatus GestureEventListener::HandlePinchGestureEvent(const MultiTouchInpu nsEventStatus GestureEventListener::HandleSingleTapUpEvent(const MultiTouchInput& aEvent) { TapGestureInput tapEvent(TapGestureInput::TAPGESTURE_UP, aEvent.mTime, aEvent.mTouches[0].mScreenPoint); - return mAsyncPanZoomController->HandleInputEvent(tapEvent); + mAsyncPanZoomController->HandleInputEvent(tapEvent); + + return nsEventStatus_eConsumeDoDefault; } nsEventStatus GestureEventListener::HandleSingleTapConfirmedEvent(const MultiTouchInput& aEvent) { TapGestureInput tapEvent(TapGestureInput::TAPGESTURE_CONFIRMED, aEvent.mTime, aEvent.mTouches[0].mScreenPoint); - return mAsyncPanZoomController->HandleInputEvent(tapEvent); -} - -nsEventStatus GestureEventListener::HandleTapCancel(const MultiTouchInput& aEvent) -{ - mTapStartTime = 0; - - switch (mState) - { - case GESTURE_WAITING_SINGLE_TAP: - case GESTURE_WAITING_DOUBLE_TAP: - mState = GESTURE_NONE; - break; - default: - break; - } + mAsyncPanZoomController->HandleInputEvent(tapEvent); return nsEventStatus_eConsumeDoDefault; } -nsEventStatus GestureEventListener::HandleDoubleTap(const MultiTouchInput& aEvent) +nsEventStatus GestureEventListener::HandleTapCancel(const MultiTouchInput& aEvent) { - TapGestureInput tapEvent(TapGestureInput::TAPGESTURE_DOUBLE, aEvent.mTime, aEvent.mTouches[0].mScreenPoint); - return mAsyncPanZoomController->HandleInputEvent(tapEvent); -} - -void GestureEventListener::TimeoutDoubleTap() -{ - // If we haven't gotten another tap by now, reset the state and treat it as a - // single tap. It couldn't have been a double tap. - if (mState == GESTURE_WAITING_DOUBLE_TAP) { - mState = GESTURE_NONE; - - HandleSingleTapConfirmedEvent(mLastTouchInput); - } + // XXX: In the future we will have to actually send a cancel notification to + // Gecko, but for now since we're doing both the "SingleUp" and + // "SingleConfirmed" notifications together, there's no need to cancel either + // one. + mTouchStartTime = 0; + return nsEventStatus_eConsumeDoDefault; } AsyncPanZoomController* GestureEventListener::GetAsyncPanZoomController() { diff --git a/gfx/layers/ipc/GestureEventListener.h b/gfx/layers/ipc/GestureEventListener.h index 4a227a4f2768..9e88476f42b0 100644 --- a/gfx/layers/ipc/GestureEventListener.h +++ b/gfx/layers/ipc/GestureEventListener.h @@ -55,18 +55,16 @@ public: protected: enum GestureState { - // There's no gesture going on, and we don't think we're about to enter one. - GESTURE_NONE, - // There's a pinch happening, which occurs when there are two touch inputs. - GESTURE_PINCH, - // A touch start has happened and it may turn into a tap. We use this - // because, if we put down two fingers and then lift them very quickly, this - // may be mistaken for a tap. - GESTURE_WAITING_SINGLE_TAP, - // A single tap has happened for sure, and we're waiting for a second tap. - GESTURE_WAITING_DOUBLE_TAP + NoGesture = 0, + InPinchGesture }; + /** + * Maximum time for a touch on the screen and corresponding lift of the finger + * to be considered a tap. + */ + enum { MAX_TAP_TIME = 500 }; + /** * Attempts to handle the event as a pinch event. If it is not a pinch event, * then we simply tell the next consumer to consume the event instead. @@ -102,24 +100,6 @@ protected: */ nsEventStatus HandleTapCancel(const MultiTouchInput& aEvent); - /** - * Attempts to handle a double tap. This happens when we get two single taps - * within a short time. In general, this will not attempt to block the touch - * event from being passed along to AsyncPanZoomController since APZC needs to - * know about touches ending (and we only know if a touch was a double tap - * once it ends). - */ - nsEventStatus HandleDoubleTap(const MultiTouchInput& aEvent); - - /** - * Times out a single tap we think may be turned into a double tap. This will - * also send a single tap if we're still in the "GESTURE_WAITING_DOUBLE_TAP" - * state when this is called. This should be called a short time after a - * single tap is detected, and the delay on it should be enough that the user - * has time to tap again (to make a double tap). - */ - void TimeoutDoubleTap(); - nsRefPtr mAsyncPanZoomController; /** @@ -127,10 +107,6 @@ protected: * this array, even if we choose not to handle it. When it ends, we remove it. */ nsTArray mTouches; - - /** - * Current gesture we're dealing with. - */ GestureState mState; /** @@ -141,28 +117,9 @@ protected: /** * Stores the time a touch started, used for detecting a tap gesture. Only - * valid when there's exactly one touch in mTouches. This is the time that the - * first touch was inserted into the array. This is a PRUint64 because it is - * initialized from interactions with InputData, which stores its timestamps as - * a PRUint64. + * valid when there's exactly one touch in mTouches. */ - PRUint64 mTapStartTime; - - /** - * Cached copy of the last touch input, only valid when in the - * "GESTURE_WAITING_DOUBLE_TAP" state. This is used to forward along to - * AsyncPanZoomController if a single tap needs to be sent (since it is sent - * shortly after the user actually taps, since we need to wait for a double - * tap). - */ - MultiTouchInput mLastTouchInput; - - /** - * Task used to timeout a double tap. This gets posted to the UI thread such - * that it runs a short time after a single tap happens. We cache it so that - * we can cancel it if a double tap actually comes in. - */ - CancelableTask *mDoubleTapTimeoutTask; + PRUint64 mTouchStartTime; }; }