// EXTERNAL INCLUDES
#include <cmath>
-#include <dali/public-api/events/touch-point.h>
#include <dali/public-api/math/vector2.h>
#include <dali/integration-api/events/gesture-requests.h>
-#include <dali/integration-api/events/tap-gesture-event.h>
#include <dali/integration-api/events/touch-event-integ.h>
#include <base/core-event-interface.h>
{
// 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)
mTapsRegistered(0),
mTouchPosition(),
mTouchTime(0u),
- mTimerSlot( this )
+ mLastTapTime(0u)
{
- mTimer = Dali::Timer::New(MAXIMUM_TIME_ALLOWED);
- mTimer.TickSignal().Connect( mTimerSlot, &TapGestureDetector::TimerCallback );
}
TapGestureDetector::~TapGestureDetector()
{
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
}
}
-void TapGestureDetector::Update(const Integration::GestureRequest& request)
+void TapGestureDetector::SetupForTouchDown( const Integration::TouchEvent& event, const TouchPoint& point )
{
- const Integration::TapGestureRequest& tap = static_cast<const Integration::TapGestureRequest&>(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<const Integration::TapGestureRequest&>(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
*/
// EXTERNAL INCLUDES
+#include <dali/integration-api/events/tap-gesture-event.h>
#include <dali/public-api/common/vector-wrapper.h>
-#include <timer.h>
+#include <dali/public-api/events/touch-point.h>
// INTERNAL INCLUDES
#include <events/gesture-detector.h>
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:
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