Single tap results on text-input controls was very slow 06/31306/6
authorRichard Underhill <r.underhill@partner.samsung.com>
Wed, 3 Dec 2014 16:20:01 +0000 (16:20 +0000)
committerRichard Underhill <r.underhill@partner.samsung.com>
Mon, 19 Jan 2015 14:54:25 +0000 (06:54 -0800)
Needs https://review.tizen.org/gerrit/#/c/31308/

Change-Id: Ia2008fe14439bd050a498c0c64bf44ea3a28a8a8
Signed-off-by: Richard Underhill <r.underhill@partner.samsung.com>
adaptors/common/events/tap-gesture-detector.cpp
adaptors/common/events/tap-gesture-detector.h

index 5c3f651..465271c 100644 (file)
 // 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>
 
@@ -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<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
index cb1cad2..8182784 100644 (file)
@@ -19,8 +19,9 @@
  */
 
 // 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>
@@ -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