From f2769ebefa6626e375677852270ba85640f533c5 Mon Sep 17 00:00:00 2001 From: Richard Underhill Date: Wed, 3 Dec 2014 16:20:01 +0000 Subject: [PATCH] Single tap results on text-input controls was very slow Needs https://review.tizen.org/gerrit/#/c/31308/ Change-Id: Ia2008fe14439bd050a498c0c64bf44ea3a28a8a8 Signed-off-by: Richard Underhill --- adaptors/common/events/tap-gesture-detector.cpp | 155 ++++++++++++------------ adaptors/common/events/tap-gesture-detector.h | 44 +++++-- 2 files changed, 115 insertions(+), 84 deletions(-) diff --git a/adaptors/common/events/tap-gesture-detector.cpp b/adaptors/common/events/tap-gesture-detector.cpp index 5c3f651..465271c 100644 --- a/adaptors/common/events/tap-gesture-detector.cpp +++ b/adaptors/common/events/tap-gesture-detector.cpp @@ -21,11 +21,9 @@ // EXTERNAL INCLUDES #include -#include #include #include -#include #include #include @@ -44,7 +42,7 @@ namespace { // TODO: Set these according to DPI const float MAXIMUM_MOTION_ALLOWED = 20.0f; -const unsigned long MAXIMUM_TIME_ALLOWED = 300u; +const unsigned long MAXIMUM_TIME_ALLOWED = 500u; } // unnamed namespace TapGestureDetector::TapGestureDetector(CoreEventInterface& coreEventInterface, Vector2 screenSize, const Integration::TapGestureRequest& request) @@ -56,10 +54,8 @@ TapGestureDetector::TapGestureDetector(CoreEventInterface& coreEventInterface, V mTapsRegistered(0), mTouchPosition(), mTouchTime(0u), - mTimerSlot( this ) + mLastTapTime(0u) { - mTimer = Dali::Timer::New(MAXIMUM_TIME_ALLOWED); - mTimer.TickSignal().Connect( mTimerSlot, &TapGestureDetector::TimerCallback ); } TapGestureDetector::~TapGestureDetector() @@ -79,91 +75,71 @@ void TapGestureDetector::SendEvent(const Integration::TouchEvent& event) { if (pointState == TouchPoint::Down) { - mTouchPosition.x = point.screen.x; - mTouchPosition.y = point.screen.y; - mTouchTime = event.time; - mTapsRegistered = 0; - mState = Touched; - EmitGesture( Gesture::Possible, mTouchTime ); + SetupForTouchDown( event, point ); } break; } case Touched: { - Vector2 distanceDelta(abs(mTouchPosition.x - point.screen.x), - abs(mTouchPosition.y - point.screen.y)); - - unsigned long timeDelta = abs(event.time - mTouchTime); - - if (distanceDelta.x > MAXIMUM_MOTION_ALLOWED || - distanceDelta.y > MAXIMUM_MOTION_ALLOWED || - timeDelta > MAXIMUM_TIME_ALLOWED) + // Only progress from a touch up event + if ( pointState == TouchPoint::Up ) { - // We may have already registered some taps so try emitting the gesture - EmitGesture( mTapsRegistered ? Gesture::Started : Gesture::Cancelled, event.time ); - mState = (pointState == TouchPoint::Motion) ? Failed : Clear; - mTimer.Stop(); + mLastTapTime = mTouchTime; + EmitSingleTap( event.time, point ); + mState = Registered; } + break; + } - if (mState == Touched && pointState == TouchPoint::Up) + case Registered: + { + if ( pointState == TouchPoint::Up ) { - ++mTapsRegistered; - - if (mTapsRegistered < mMaximumTapsRequired) + // This is a possible multiple tap, so has it been quick enough ? + unsigned long timeDelta = abs( event.time - mLastTapTime ); + if ( timeDelta > MAXIMUM_TIME_ALLOWED ) { - // Only emit gesture after timer expires if asked for multiple taps. - mState = Registered; - mTimer.Start(); + mLastTapTime = event.time; + EmitSingleTap( event.time, point ); + mState = Clear; + break; } else { - EmitGesture(Gesture::Started, event.time); + ++mTapsRegistered; + EmitGesture( Gesture::Started, event.time ); mState = Clear; - mTimer.Stop(); } + break; } - break; - } - - case Registered: - { if (pointState == TouchPoint::Down) { - mTimer.Stop(); - Vector2 distanceDelta(abs(mTouchPosition.x - point.screen.x), abs(mTouchPosition.y - point.screen.y)); - // Check if subsequent tap is in a different position, if not then emit the previous tap - // count gesture (if required), + unsigned long timeDelta = abs( mTouchTime - mLastTapTime ); + if (distanceDelta.x > MAXIMUM_MOTION_ALLOWED || - distanceDelta.y > MAXIMUM_MOTION_ALLOWED) + distanceDelta.y > MAXIMUM_MOTION_ALLOWED || + timeDelta > MAXIMUM_TIME_ALLOWED ) { - EmitGesture(Gesture::Started, event.time); - mTouchPosition.x = point.screen.x; - mTouchPosition.y = point.screen.y; + SetupForTouchDown( event, point ); + } + else + { + EmitPossibleState( event ); } - - mTouchTime = event.time; - mState = Touched; - mTimer.Start(); } break; } case Failed: - { - if (pointState == TouchPoint::Up) - { - mState = Clear; - } - break; - } - default: + { mState = Clear; break; + } } } else @@ -175,39 +151,66 @@ void TapGestureDetector::SendEvent(const Integration::TouchEvent& event) } } -void TapGestureDetector::Update(const Integration::GestureRequest& request) +void TapGestureDetector::SetupForTouchDown( const Integration::TouchEvent& event, const TouchPoint& point ) { - const Integration::TapGestureRequest& tap = static_cast(request); - - mMinimumTapsRequired = tap.minTaps; - mMaximumTapsRequired = tap.maxTaps; + mTouchPosition.x = point.screen.x; + mTouchPosition.y = point.screen.y; + mTouchTime = event.time; + mLastTapTime = 0u; + mTapsRegistered = 0; + mState = Touched; + EmitPossibleState( event ); } -bool TapGestureDetector::TimerCallback() +void TapGestureDetector::EmitPossibleState( const Integration::TouchEvent& event ) { - EmitGesture( ( mTapsRegistered >= mMinimumTapsRequired ? Gesture::Started : Gesture::Cancelled ), mTouchTime + MAXIMUM_TIME_ALLOWED); - mState = Clear; + Integration::TapGestureEvent tapEvent( Gesture::Possible ); + tapEvent.point = mTouchPosition; + tapEvent.time = event.time; + mCoreEventInterface.QueueCoreEvent(tapEvent); +} + - // There is no touch event at this time, so ProcessEvents must be called directly - mCoreEventInterface.ProcessCoreEvents(); +void TapGestureDetector::Update(const Integration::GestureRequest& request) +{ + const Integration::TapGestureRequest& tap = static_cast(request); - return false; + mMinimumTapsRequired = tap.minTaps; + mMaximumTapsRequired = tap.maxTaps; } void TapGestureDetector::EmitGesture( Gesture::State state, unsigned int time ) { - if ( (state == Gesture::Possible) || - (state == Gesture::Cancelled) || + if ( (state == Gesture::Cancelled) || (mTapsRegistered >= mMinimumTapsRequired && mTapsRegistered <= mMaximumTapsRequired) ) + { Integration::TapGestureEvent event( state ); - event.numberOfTaps = mTapsRegistered; - event.point = mTouchPosition; - event.time = time; + EmitTap( time, event ); + } +} + +void TapGestureDetector::EmitSingleTap( unsigned int time, const TouchPoint& point ) +{ + Integration::TapGestureEvent event( Gesture::Started ); + Vector2 distanceDelta(abs(mTouchPosition.x - point.screen.x), + abs(mTouchPosition.y - point.screen.y)); - mCoreEventInterface.QueueCoreEvent(event); + if (distanceDelta.x > MAXIMUM_MOTION_ALLOWED || + distanceDelta.y > MAXIMUM_MOTION_ALLOWED ) + { + event.state = Gesture::Cancelled; } - mTapsRegistered = 0; + mTapsRegistered = 1u; + EmitTap( time, event ); +} + +void TapGestureDetector::EmitTap( unsigned int time, Integration::TapGestureEvent& event ) +{ + event.numberOfTaps = mTapsRegistered; + event.point = mTouchPosition; + event.time = time; + mCoreEventInterface.QueueCoreEvent(event); } } // namespace Adaptor diff --git a/adaptors/common/events/tap-gesture-detector.h b/adaptors/common/events/tap-gesture-detector.h index cb1cad2..8182784 100644 --- a/adaptors/common/events/tap-gesture-detector.h +++ b/adaptors/common/events/tap-gesture-detector.h @@ -19,8 +19,9 @@ */ // EXTERNAL INCLUDES +#include #include -#include +#include // INTERNAL INCLUDES #include @@ -77,15 +78,43 @@ public: private: /** - * Timer Callback - * @return will return false; one-shot timer. + * Checks if registered taps are within required bounds and emits tap gesture if they are. + * + * @param[in] state current state of incomplete gesture + * @param[in] time time of this latest touch event */ - bool TimerCallback(); + void EmitGesture( Gesture::State state, unsigned int time ); /** - * Checks if registered taps are within required bounds and emits tap gesture if they are. + * Initialises tap gesture detector for next tap sequence + * + * @param[in] event registered touch event + * @param[in] point position touch event occurred */ - void EmitGesture( Gesture::State state, unsigned int time ); + void SetupForTouchDown( const Integration::TouchEvent& event, const TouchPoint& point ); + + /** + * Emit a touch down event for hit testing + * + * @param[in] event registered touch event + */ + void EmitPossibleState( const Integration::TouchEvent& event ); + + /** + * Force a touch event sequence to be treated as a single tap + * + * @param[in] time time of this latest touch event + * @param[in] point position touch event occurred + */ + void EmitSingleTap( unsigned int time, const TouchPoint& point ); + + /** + * Emit a tap event + * + * @param[in] time time of this latest touch event + * @param[in] event registered touch event + */ + void EmitTap( unsigned int time, Integration::TapGestureEvent& event ); private: @@ -109,9 +138,8 @@ private: Vector2 mTouchPosition; ///< The initial touch down position. unsigned long mTouchTime; ///< The initial touch down time. + unsigned long mLastTapTime; ///< Time last tap gesture was registered - Dali::Timer mTimer; ///< The timer to start when we have registered the tap. We have to register all taps within a certain time frame. - SlotDelegate< TapGestureDetector > mTimerSlot; }; } // namespace Adaptor -- 2.7.4