author | Ryan VanderMeulen <ryanvm@gmail.com> |
Fri, 27 Jul 2012 20:46:49 -0400 | |
changeset 100798 | 02d63f48e7526de741d9f02610ec9e8f53d0fa6d |
parent 100797 | 73113b32afacc2fe05e32f9dd17b52c80a96029c |
child 100799 | 4cdd2356937121f0ef2e28c0238981efca4d81b3 |
push id | 23193 |
push user | ryanvm@gmail.com |
push date | Sat, 28 Jul 2012 21:54:39 +0000 |
treeherder | mozilla-central@29bff59d3bbe [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
bugs | 775463 |
milestone | 17.0a1 |
backs out | e0e33c1c7c17aeff411248076b5280011a138d26 |
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
|
gfx/layers/ipc/GestureEventListener.cpp | file | annotate | diff | comparison | revisions | |
gfx/layers/ipc/GestureEventListener.h | file | annotate | diff | comparison | revisions |
--- a/gfx/layers/ipc/GestureEventListener.cpp +++ b/gfx/layers/ipc/GestureEventListener.cpp @@ -1,34 +1,23 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set sw=4 ts=8 et tw=80 : */ /* This Source Code Form is subject to the terms of the Mozilla Public * 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) { } GestureEventListener::~GestureEventListener() { } nsEventStatus GestureEventListener::HandleInputEvent(const InputData& aEvent) @@ -55,23 +44,17 @@ nsEventStatus GestureEventListener::Hand // If we didn't find a touch in our list that matches this, then add it. // If it already existed, we don't want to add it twice because that // messes with our touch move/end code. if (!foundAlreadyExistingTouch) { mTouches.AppendElement(event.mTouches[i]); } } - 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); } break; } case MultiTouchInput::MULTITOUCH_MOVE: { // If we move at all, just bail out of the tap. We need to change this so @@ -101,49 +84,30 @@ nsEventStatus GestureEventListener::Hand foundAlreadyExistingTouch = true; mTouches.RemoveElementAt(j); } } } 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; + 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; + } - // 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 (HandleSingleTapConfirmedEvent(event) == nsEventStatus_eConsumeNoDefault) { + return nsEventStatus_eConsumeNoDefault; } } - if (mState == GESTURE_WAITING_SINGLE_TAP) { - mState = GESTURE_NONE; - } - break; } case MultiTouchInput::MULTITOUCH_CANCEL: // 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; @@ -161,104 +125,84 @@ nsEventStatus GestureEventListener::Hand secondTouch = mTouches[mTouches.Length() - 1].mScreenPoint; nsIntPoint focusPoint = nsIntPoint((firstTouch.x + secondTouch.x)/2, (firstTouch.y + secondTouch.y)/2); float currentSpan = 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, currentSpan, currentSpan); mAsyncPanZoomController->HandleInputEvent(pinchEvent); - mState = GESTURE_PINCH; + mState = InPinchGesture; } else { PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_SCALE, aEvent.mTime, focusPoint, currentSpan, mPreviousSpan); mAsyncPanZoomController->HandleInputEvent(pinchEvent); } 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; } if (aClearTouches) { mTouches.Clear(); } return rv; } 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); + mAsyncPanZoomController->HandleInputEvent(tapEvent); + + return nsEventStatus_eConsumeDoDefault; } 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; - } - + // 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; } -nsEventStatus GestureEventListener::HandleDoubleTap(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); - } -} - AsyncPanZoomController* GestureEventListener::GetAsyncPanZoomController() { return mAsyncPanZoomController; } } }
--- a/gfx/layers/ipc/GestureEventListener.h +++ b/gfx/layers/ipc/GestureEventListener.h @@ -50,29 +50,27 @@ public: /** * Returns the AsyncPanZoomController stored on this class and used for * callbacks. */ AsyncPanZoomController* GetAsyncPanZoomController(); 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. * * |aClearTouches| marks whether or not to terminate any pinch currently * happening. */ nsEventStatus HandlePinchGestureEvent(const MultiTouchInput& aEvent, bool aClearTouches); @@ -97,75 +95,34 @@ protected: * Attempts to handle a tap event cancellation. This happens when we think * something was a tap but it actually wasn't. 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 tap once it ends). */ 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<AsyncPanZoomController> mAsyncPanZoomController; /** * Array containing all active touches. When a touch happens it, gets added to * this array, even if we choose not to handle it. When it ends, we remove it. */ nsTArray<SingleTouchData> mTouches; - - /** - * Current gesture we're dealing with. - */ GestureState mState; /** * Previous span calculated for the purposes of setting inside a * PinchGestureInput. */ float mPreviousSpan; /** * 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; }; } } #endif