Discard some motion during pan gesture 78/276378/7
authorEunki, Hong <eunkiki.hong@samsung.com>
Wed, 15 Jun 2022 12:57:34 +0000 (21:57 +0900)
committerEunki, Hong <eunkiki.hong@samsung.com>
Fri, 17 Jun 2022 09:11:35 +0000 (18:11 +0900)
When event spend so long time, a lot of events are queued.

Ecore cannot skip these event, so we make some heuristic
threshold of discard motion events on pan gesture.

We can setup this value by PanGestuerDetector's member vaule.
The name is "MaximumMotionEventAge".
the time scale is millisecond.

Default age is UINT_MAX ms (~= 49 days)
That mean, we will not discard every motion events.
(Ecore event callback also use uint32_t type in ms.)

Change-Id: Ib721e81d690327dcbc6c6c58383b33c7d5560922
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
automated-tests/src/dali/utc-Dali-PanGestureDetector.cpp
automated-tests/src/dali/utc-Dali-PanGestureRecognizer.cpp
dali/internal/event/events/gesture-requests.h
dali/internal/event/events/pan-gesture/pan-gesture-detector-impl.cpp
dali/internal/event/events/pan-gesture/pan-gesture-detector-impl.h
dali/internal/event/events/pan-gesture/pan-gesture-processor.cpp
dali/internal/event/events/pan-gesture/pan-gesture-processor.h
dali/internal/event/events/pan-gesture/pan-gesture-recognizer.cpp
dali/internal/event/events/pan-gesture/pan-gesture-recognizer.h
dali/public-api/events/pan-gesture-detector.cpp
dali/public-api/events/pan-gesture-detector.h

index 713cffe..b1314ea 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -249,6 +249,7 @@ int UtcDaliPanGestureDetectorNew(void)
 
   DALI_TEST_EQUALS(1u, detector.GetMinimumTouchesRequired(), TEST_LOCATION);
   DALI_TEST_EQUALS(1u, detector.GetMaximumTouchesRequired(), TEST_LOCATION);
+  DALI_TEST_EQUALS(std::numeric_limits<uint32_t>::max(), detector.GetMaximumMotionEventAge(), TEST_LOCATION);
 
   // Attach an actor and emit a touch event on the actor to ensure complete line coverage
   Actor actor = Actor::New();
@@ -376,6 +377,44 @@ int UtcDaliPanGestureSetMaximumTouchesRequired(void)
   END_TEST;
 }
 
+int UtcDaliPanGestureSetMaximumMotionEventAge(void)
+{
+  TestApplication application;
+
+  PanGestureDetector detector = PanGestureDetector::New();
+
+  uint32_t minTime = 20;
+
+  DALI_TEST_CHECK(minTime != detector.GetMaximumMotionEventAge());
+
+  detector.SetMaximumMotionEventAge(minTime);
+
+  DALI_TEST_EQUALS(minTime, detector.GetMaximumMotionEventAge(), TEST_LOCATION);
+
+  // Attach an actor and change the maximum touches
+
+  Actor actor = Actor::New();
+  actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+  actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+  application.GetScene().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData             data;
+  GestureReceivedFunctor functor(data);
+
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  detector.SetMaximumMotionEventAge(minTime / 2);
+
+  DALI_TEST_EQUALS(minTime / 2, detector.GetMaximumMotionEventAge(), TEST_LOCATION);
+
+  END_TEST;
+}
+
 int UtcDaliPanGestureGetMinimumTouchesRequired(void)
 {
   TestApplication application;
@@ -394,6 +433,15 @@ int UtcDaliPanGestureGetMaximumTouchesRequired(void)
   END_TEST;
 }
 
+int UtcDaliPanGestureGetMaximumMotionEventAge(void)
+{
+  TestApplication application;
+
+  PanGestureDetector detector = PanGestureDetector::New();
+  DALI_TEST_EQUALS(std::numeric_limits<uint32_t>::max(), detector.GetMaximumMotionEventAge(), TEST_LOCATION);
+  END_TEST;
+}
+
 int UtcDaliPanGestureSignalReceptionNegative(void)
 {
   TestApplication application;
index 8fed854..5f6e075 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
 #include <dali/public-api/dali-core.h>
 #include <stdlib.h>
 
+#include <chrono>
 #include <iostream>
 
 using namespace Dali;
@@ -106,6 +107,15 @@ Integration::TouchEvent GenerateDoubleTouch(PointState::Type stateA, const Vecto
   return touchEvent;
 }
 
+uint32_t GetMilliSeconds()
+{
+  // Get the time of a monotonic clock since its epoch.
+  auto epoch = std::chrono::steady_clock::now().time_since_epoch();
+
+  auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(epoch);
+
+  return static_cast<uint32_t>(duration.count());
+}
 } // namespace
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -519,6 +529,67 @@ int UtcDaliPanGestureRecognizerNewParametersSlowRelease(void)
   END_TEST;
 }
 
+int UtcDaliPanGestureRecognizerNewParamsMaxMotionEventAge(void)
+{
+  TestApplication application;
+
+  PanGestureDetector detector = PanGestureDetector::New();
+
+  detector.SetMaximumMotionEventAge(1000);
+
+  Actor actor = Actor::New();
+  actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+  actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+  application.GetScene().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  detector.Attach(actor);
+
+  SignalData             data;
+  GestureReceivedFunctor functor(data);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  uint32_t currentTime = GetMilliSeconds();
+  application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), currentTime));
+  application.ProcessEvent(GenerateSingleTouch(PointState::MOTION, Vector2(20.0f, 40.0f), currentTime));
+  application.ProcessEvent(GenerateSingleTouch(PointState::MOTION, Vector2(20.0f, 60.0f), currentTime));
+  application.ProcessEvent(GenerateSingleTouch(PointState::MOTION, Vector2(20.0f, 70.0f), currentTime));
+  application.ProcessEvent(GenerateSingleTouch(PointState::MOTION, Vector2(20.0f, 80.0f), currentTime));
+  application.ProcessEvent(GenerateSingleTouch(PointState::MOTION, Vector2(20.0f, 90.0f), currentTime));
+
+  application.SendNotification();
+
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+
+  data.Reset();
+
+  // Update current time
+  currentTime = GetMilliSeconds();
+
+  tet_infoline("Test fast enough motion\n");
+  application.ProcessEvent(GenerateSingleTouch(PointState::MOTION, Vector2(20.0f, 80.0f), currentTime - 100));
+
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+
+  data.Reset();
+
+  // Update current time
+  currentTime = GetMilliSeconds();
+
+  tet_infoline("Test super heavy motion\n");
+  application.ProcessEvent(GenerateSingleTouch(PointState::MOTION, Vector2(20.0f, 80.0f), currentTime - 10000));
+  application.ProcessEvent(GenerateSingleTouch(PointState::MOTION, Vector2(20.0f, 70.0f), currentTime - 9000));
+  application.ProcessEvent(GenerateSingleTouch(PointState::MOTION, Vector2(20.0f, 60.0f), currentTime - 8000));
+  application.ProcessEvent(GenerateSingleTouch(PointState::MOTION, Vector2(20.0f, 50.0f), currentTime - 7000));
+
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+  END_TEST;
+}
+
 int UtcDaliPanGestureRecognizerOtherEvent(void)
 {
   TestApplication application;
index fc7e6fc..b47d0b3 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_GESTURE_REQUESTS_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -21,6 +21,9 @@
 // INTERNAL INCLUDES
 #include <dali/public-api/events/gesture.h>
 
+// EXTERNAL INCLUDES
+#include <limits> // for numeric_limits::max();
+
 namespace Dali
 {
 namespace Internal
@@ -64,7 +67,8 @@ struct PanGestureRequest : public GestureRequest
   PanGestureRequest()
   : GestureRequest(GestureType::PAN),
     minTouches(1),
-    maxTouches(1)
+    maxTouches(1),
+    maxMotionEventAge(std::numeric_limits<uint32_t>::max())
   {
   }
 
@@ -75,8 +79,9 @@ struct PanGestureRequest : public GestureRequest
 
   // Data Members
 
-  unsigned int minTouches; ///< The minimum number of touch points required for a pan gesture.
-  unsigned int maxTouches; ///< The maximum number of touch points required for a pan gesture.
+  uint32_t minTouches;        ///< The minimum number of touch points required for a pan gesture.
+  uint32_t maxTouches;        ///< The maximum number of touch points required for a pan gesture.
+  uint32_t maxMotionEventAge; ///< The maximum age of motion events as milliseconds.
 };
 
 /**
index c259649..0c6576a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -95,13 +95,13 @@ PanGestureDetectorPtr PanGestureDetector::New()
   return new PanGestureDetector(sceneObject);
 }
 
-void PanGestureDetector::SetMinimumTouchesRequired(unsigned int minimum)
+void PanGestureDetector::SetMinimumTouchesRequired(uint32_t minimum)
 {
   DALI_ASSERT_ALWAYS(minimum > 0 && "Can only set a positive number of required touches");
 
   if(mMinimumTouches != minimum)
   {
-    DALI_LOG_INFO(gLogFilter, Debug::Concise, "Minimum Touches Set: %d\n", minimum);
+    DALI_LOG_INFO(gLogFilter, Debug::Concise, "Minimum Touches Set: %u\n", minimum);
 
     mMinimumTouches = minimum;
 
@@ -114,13 +114,13 @@ void PanGestureDetector::SetMinimumTouchesRequired(unsigned int minimum)
   }
 }
 
-void PanGestureDetector::SetMaximumTouchesRequired(unsigned int maximum)
+void PanGestureDetector::SetMaximumTouchesRequired(uint32_t maximum)
 {
   DALI_ASSERT_ALWAYS(maximum > 0 && "Can only set a positive number of maximum touches");
 
   if(mMaximumTouches != maximum)
   {
-    DALI_LOG_INFO(gLogFilter, Debug::Concise, "Maximum Touches Set: %d\n", maximum);
+    DALI_LOG_INFO(gLogFilter, Debug::Concise, "Maximum Touches Set: %u\n", maximum);
 
     mMaximumTouches = maximum;
 
@@ -133,6 +133,23 @@ void PanGestureDetector::SetMaximumTouchesRequired(unsigned int maximum)
   }
 }
 
+void PanGestureDetector::SetMaximumMotionEventAge(uint32_t maximumAge)
+{
+  if(mMaximumMotionEventAge != maximumAge)
+  {
+    DALI_LOG_INFO(gLogFilter, Debug::Concise, "Maximum Motion Age Set: %u ms\n", maximumAge);
+
+    mMaximumMotionEventAge = maximumAge;
+
+    if(!mAttachedActors.empty())
+    {
+      DALI_LOG_INFO(gLogFilter, Debug::General, "Updating Gesture Detector\n");
+
+      mGestureEventProcessor.GestureDetectorUpdated(this);
+    }
+  }
+}
+
 uint32_t PanGestureDetector::GetMinimumTouchesRequired() const
 {
   return mMinimumTouches;
@@ -143,6 +160,11 @@ uint32_t PanGestureDetector::GetMaximumTouchesRequired() const
   return mMaximumTouches;
 }
 
+uint32_t PanGestureDetector::GetMaximumMotionEventAge() const
+{
+  return mMaximumMotionEventAge;
+}
+
 void PanGestureDetector::AddAngle(Radian angle, Radian threshold)
 {
   threshold = fabsf(threshold); // Ensure the threshold is positive.
@@ -292,7 +314,8 @@ void PanGestureDetector::SetPanGestureProperties(const Dali::PanGesture& pan)
 PanGestureDetector::PanGestureDetector(const SceneGraph::PanGesture& sceneObject)
 : GestureDetector(GestureType::PAN, &sceneObject),
   mMinimumTouches(1),
-  mMaximumTouches(1)
+  mMaximumTouches(1),
+  mMaximumMotionEventAge(std::numeric_limits<uint32_t>::max())
 {
 }
 
index 2c13b37..a03f681 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_PAN_GESTURE_DETECTOR_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -59,14 +59,19 @@ public: // Creation
 
 public:
   /**
-   * @copydoc Dali::PanGestureDetector::SetMinimumTouchesRequired(unsigned int)
+   * @copydoc Dali::PanGestureDetector::SetMinimumTouchesRequired(uint32_t)
    */
-  void SetMinimumTouchesRequired(unsigned int minimum);
+  void SetMinimumTouchesRequired(uint32_t minimum);
 
   /**
-   * @copydoc Dali::PanGestureDetector::SetMaximumTouchesRequired(unsigned int)
+   * @copydoc Dali::PanGestureDetector::SetMaximumTouchesRequired(uint32_t)
    */
-  void SetMaximumTouchesRequired(unsigned int maximum);
+  void SetMaximumTouchesRequired(uint32_t maximum);
+
+  /**
+   * @copydoc Dali::PanGestureDetector::SetMaximumMotionEventAge(uint32_t)
+   */
+  void SetMaximumMotionEventAge(uint32_t maximumAge);
 
   /**
    * @copydoc Dali::PanGestureDetector::GetMinimumTouchesRequired() const
@@ -79,6 +84,11 @@ public:
   uint32_t GetMaximumTouchesRequired() const;
 
   /**
+   * @copydoc Dali::PanGestureDetector::GetMaximumMotionEventAge() const
+   */
+  uint32_t GetMaximumMotionEventAge() const;
+
+  /**
    * @copydoc Dali::PanGestureDetector::AddAngle()
    */
   void AddAngle(Radian angle, Radian threshold);
@@ -225,8 +235,9 @@ private:
 private:
   Dali::PanGestureDetector::DetectedSignalType mDetectedSignal;
 
-  unsigned int mMinimumTouches; ///< The minimum number of fingers required to be touching for pan.
-  unsigned int mMaximumTouches; ///< The maximum number of fingers required to be touching for pan.
+  uint32_t mMinimumTouches;        ///< The minimum number of fingers required to be touching for pan.
+  uint32_t mMaximumTouches;        ///< The maximum number of fingers required to be touching for pan.
+  uint32_t mMaximumMotionEventAge; ///< The maximum age of motion events as milliseconds.
 
   AngleContainer mAngleContainer; ///< A container of all angles allowed for pan to occur.
 };
index b1909dc..2a2e08e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -279,10 +279,12 @@ void PanGestureProcessor::AddGestureDetector(PanGestureDetector* gestureDetector
   {
     mMinTouchesRequired = gestureDetector->GetMinimumTouchesRequired();
     mMaxTouchesRequired = gestureDetector->GetMaximumTouchesRequired();
+    mMaxMotionEventAge  = gestureDetector->GetMaximumMotionEventAge();
 
     PanGestureRequest request;
-    request.minTouches = mMinTouchesRequired;
-    request.maxTouches = mMaxTouchesRequired;
+    request.minTouches        = mMinTouchesRequired;
+    request.maxTouches        = mMaxTouchesRequired;
+    request.maxMotionEventAge = mMaxMotionEventAge;
 
     Size size          = scene.GetSize();
     mGestureRecognizer = new PanGestureRecognizer(*this, Vector2(size.width, size.height), static_cast<const PanGestureRequest&>(request), minDistance, minPanEvents);
@@ -451,8 +453,9 @@ void PanGestureProcessor::UpdateDetection()
 {
   DALI_ASSERT_DEBUG(!mPanGestureDetectors.empty());
 
-  unsigned int minimumRequired = UINT_MAX;
-  unsigned int maximumRequired = 0;
+  uint32_t minimumRequired       = std::numeric_limits<uint32_t>::max();
+  uint32_t maximumRequired       = 0;
+  uint32_t maximumMotionEventAge = std::numeric_limits<uint32_t>::max();
 
   for(PanGestureDetectorContainer::iterator iter = mPanGestureDetectors.begin(), endIter = mPanGestureDetectors.end(); iter != endIter; ++iter)
   {
@@ -460,28 +463,36 @@ void PanGestureProcessor::UpdateDetection()
 
     if(detector)
     {
-      unsigned int minimum = detector->GetMinimumTouchesRequired();
+      uint32_t minimum = detector->GetMinimumTouchesRequired();
       if(minimum < minimumRequired)
       {
         minimumRequired = minimum;
       }
 
-      unsigned int maximum = detector->GetMaximumTouchesRequired();
+      uint32_t maximum = detector->GetMaximumTouchesRequired();
       if(maximum > maximumRequired)
       {
         maximumRequired = maximum;
       }
+
+      uint32_t maximumAge = detector->GetMaximumMotionEventAge();
+      if(maximumAge > maximumMotionEventAge)
+      {
+        maximumMotionEventAge = maximumAge;
+      }
     }
   }
 
-  if((minimumRequired != mMinTouchesRequired) || (maximumRequired != mMaxTouchesRequired))
+  if((minimumRequired != mMinTouchesRequired) || (maximumRequired != mMaxTouchesRequired) || (maximumMotionEventAge != mMaxMotionEventAge))
   {
     mMinTouchesRequired = minimumRequired;
     mMaxTouchesRequired = maximumRequired;
+    mMaxMotionEventAge  = maximumMotionEventAge;
 
     PanGestureRequest request;
-    request.minTouches = mMinTouchesRequired;
-    request.maxTouches = mMaxTouchesRequired;
+    request.minTouches        = mMinTouchesRequired;
+    request.maxTouches        = mMaxTouchesRequired;
+    request.maxMotionEventAge = mMaxMotionEventAge;
     mGestureRecognizer->Update(request);
   }
 }
index 3f40eb9..bfeb623 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_EVENT_PAN_GESTURE_EVENT_PROCESSOR_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -74,7 +74,10 @@ public: // To be called by GestureEventProcessor
    * Adds a gesture detector to this gesture processor.
    * If this is the first gesture detector being added, then this method registers the required
    * gesture with the adaptor.
-   * @param[in]  gestureDetector  The gesture detector being added.
+   * @param[in] gestureDetector The gesture detector being added.
+   * @param[in] scene           The scene the pan gesture event occurs in.
+   * @param[in] minDistance     The minimum required motion distance to start pan gesture. If this value is less than 0, we use default setuped distance.
+   * @param[in] minPanEvents    The minimum required motion event number to start pan gesture. If this value is less than 1, we use default setuped number.
    */
   void AddGestureDetector(PanGestureDetector* gestureDetector, Scene& scene, int32_t minDistance, int32_t minPanEvents);
 
@@ -276,6 +279,7 @@ private:
 
   uint32_t mMinTouchesRequired;
   uint32_t mMaxTouchesRequired;
+  uint32_t mMaxMotionEventAge;
 
   Vector2 mLastVelocity;       ///< The last recorded velocity in local actor coordinates.
   Vector2 mLastScreenVelocity; ///< The last recorded velocity in screen coordinates.
index d59a9b6..39e43ce 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
 #include <dali/internal/event/events/pan-gesture/pan-gesture-recognizer.h>
 
 // EXTERNAL INCLUDES
+#include <chrono>
 #include <cmath>
 
 #include <dali/devel-api/events/touch-point.h>
@@ -35,11 +36,21 @@ namespace Internal
 {
 namespace
 {
-const float         MINIMUM_MOTION_DISTANCE_BEFORE_PAN(15.0f);
-const float         MINIMUM_MOTION_DISTANCE_BEFORE_PAN_SQUARED(MINIMUM_MOTION_DISTANCE_BEFORE_PAN* MINIMUM_MOTION_DISTANCE_BEFORE_PAN);
-const float         MINIMUM_MOTION_DISTANCE_TO_THRESHOLD_ADJUSTMENTS_RATIO(2.0f / 3.0f);
-const unsigned long MINIMUM_TIME_BEFORE_THRESHOLD_ADJUSTMENTS(100);
-const unsigned int  MINIMUM_MOTION_EVENTS_BEFORE_PAN(2);
+constexpr float         MINIMUM_MOTION_DISTANCE_BEFORE_PAN(15.0f);
+constexpr float         MINIMUM_MOTION_DISTANCE_BEFORE_PAN_SQUARED(MINIMUM_MOTION_DISTANCE_BEFORE_PAN* MINIMUM_MOTION_DISTANCE_BEFORE_PAN);
+constexpr float         MINIMUM_MOTION_DISTANCE_TO_THRESHOLD_ADJUSTMENTS_RATIO(2.0f / 3.0f);
+constexpr unsigned long MINIMUM_TIME_BEFORE_THRESHOLD_ADJUSTMENTS(100);
+constexpr unsigned int  MINIMUM_MOTION_EVENTS_BEFORE_PAN(2);
+
+uint32_t GetMilliSeconds()
+{
+  // Get the time of a monotonic clock since its epoch.
+  auto epoch = std::chrono::steady_clock::now().time_since_epoch();
+
+  auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(epoch);
+
+  return static_cast<uint32_t>(duration.count());
+}
 } // unnamed namespace
 
 PanGestureRecognizer::PanGestureRecognizer(Observer& observer, Vector2 screenSize, const PanGestureRequest& request, int32_t minimumDistance, int32_t minimumPanEvents)
@@ -53,7 +64,8 @@ PanGestureRecognizer::PanGestureRecognizer(Observer& observer, Vector2 screenSiz
   mMaximumTouchesRequired(request.maxTouches),
   mMinimumDistanceSquared(static_cast<unsigned int>(MINIMUM_MOTION_DISTANCE_BEFORE_PAN_SQUARED)),
   mMinimumMotionEvents(MINIMUM_MOTION_EVENTS_BEFORE_PAN),
-  mMotionEvents(0)
+  mMotionEvents(0),
+  mMaximumMotionEventAge(request.maxMotionEventAge)
 {
   if(minimumDistance >= 0)
   {
@@ -180,9 +192,21 @@ void PanGestureRecognizer::SendEvent(const Integration::TouchEvent& event)
           switch(primaryPointState)
           {
             case PointState::MOTION:
-              // Pan is continuing, tell Core.
-              SendPan(GestureState::CONTINUING, event);
+            {
+              // Check whether this motion event is acceptable or not.
+              // If event time is too old, we should skip this event.
+              if(GetMilliSeconds() - event.time > mMaximumMotionEventAge)
+              {
+                // Too old event. Skip it.
+                mTouchEvents.pop_back();
+              }
+              else
+              {
+                // Pan is continuing, tell Core.
+                SendPan(GestureState::CONTINUING, event);
+              }
               break;
+            }
 
             case PointState::UP:
               // Pan is finally finished when our primary point is lifted, tell Core and change our state to CLEAR.
@@ -253,6 +277,7 @@ void PanGestureRecognizer::Update(const GestureRequest& request)
 
   mMinimumTouchesRequired = pan.minTouches;
   mMaximumTouchesRequired = pan.maxTouches;
+  mMaximumMotionEventAge  = pan.maxMotionEventAge;
 }
 
 void PanGestureRecognizer::SendPan(GestureState state, const Integration::TouchEvent& currentEvent)
index 8744a41..8bc3715 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_EVENT_PAN_GESTURE_RECOGNIZER_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -49,8 +49,10 @@ public:
 
   /**
    * Constructor
-   * @param[in]  screenSize  The size of the screen.
-   * @param[in]  request     The details of the request.
+   * @param[in] screenSize       The size of the screen.
+   * @param[in] request          The details of the request.
+   * @param[in] minimumDistance  The minimum required motion distance to start pan gesture. If this value is less than 0, we use default setuped distance.
+   * @param[in] minimumPanEvents The minimum required motion event number to start pan gesture. If this value is less than 1, we use default setuped number.
    */
   PanGestureRecognizer(Observer& observer, Vector2 screenSize, const PanGestureRequest& request, int32_t minimumDistance, int32_t minimumPanEvents);
 
@@ -101,16 +103,18 @@ private:
   Vector2 mThresholdAdjustmentPerFrame; ///< The adjustment per frame at the start of a slow pan.
   Vector2 mPreviousPosition;            ///< The previous position.
 
-  unsigned int mThresholdAdjustmentsRemaining; ///< No. of threshold adjustments still to apply (for a slow-pan).
-  unsigned int mThresholdTotalAdjustments;     ///< The total number of adjustments required.
+  uint32_t mThresholdAdjustmentsRemaining; ///< No. of threshold adjustments still to apply (for a slow-pan).
+  uint32_t mThresholdTotalAdjustments;     ///< The total number of adjustments required.
 
-  uint32_t     mPrimaryTouchDownTime;   ///< The initial touch down time.
-  unsigned int mMinimumTouchesRequired; ///< The minimum touches required before a pan should be emitted.
-  unsigned int mMaximumTouchesRequired; ///< The maximum touches after which a pan should not be emitted.
+  uint32_t mPrimaryTouchDownTime;   ///< The initial touch down time.
+  uint32_t mMinimumTouchesRequired; ///< The minimum touches required before a pan should be emitted.
+  uint32_t mMaximumTouchesRequired; ///< The maximum touches after which a pan should not be emitted.
 
-  unsigned int mMinimumDistanceSquared; ///< The minimum distance squared before pan should start.
-  unsigned int mMinimumMotionEvents;    ///< The minimum motion events before pan should start.
-  unsigned int mMotionEvents;           ///< The motion events received so far (before pan is emitted).
+  uint32_t mMinimumDistanceSquared; ///< The minimum distance squared before pan should start.
+  uint32_t mMinimumMotionEvents;    ///< The minimum motion events before pan should start.
+  uint32_t mMotionEvents;           ///< The motion events received so far (before pan is emitted).
+
+  uint32_t mMaximumMotionEventAge; ///< The maximum acceptable motion event age as Milliseconds.
 };
 
 } // namespace Internal
index a129a81..0300ad4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -70,6 +70,11 @@ void PanGestureDetector::SetMaximumTouchesRequired(uint32_t maximum)
   GetImplementation(*this).SetMaximumTouchesRequired(maximum);
 }
 
+void PanGestureDetector::SetMaximumMotionEventAge(uint32_t maximumAge)
+{
+  GetImplementation(*this).SetMaximumMotionEventAge(maximumAge);
+}
+
 uint32_t PanGestureDetector::GetMinimumTouchesRequired() const
 {
   return GetImplementation(*this).GetMinimumTouchesRequired();
@@ -80,6 +85,11 @@ uint32_t PanGestureDetector::GetMaximumTouchesRequired() const
   return GetImplementation(*this).GetMaximumTouchesRequired();
 }
 
+uint32_t PanGestureDetector::GetMaximumMotionEventAge() const
+{
+  return GetImplementation(*this).GetMaximumMotionEventAge();
+}
+
 void PanGestureDetector::AddAngle(Radian angle, Radian threshold)
 {
   GetImplementation(*this).AddAngle(angle, threshold);
index c31549d..3467ff5 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_PAN_GESTURE_DETECTOR_H
 
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -178,6 +178,17 @@ public: // Setters
    */
   void SetMaximumTouchesRequired(uint32_t maximum);
 
+  /**
+   * @brief This value is a maximum duration of motion can live on the pan gesture event queue.
+   * If duration exceed it, the motion event is discarded.
+   *
+   * @SINCE_2_1.28
+   * @param[in] maximumAge Maximum age of motion events as milliseconds
+   * @pre The gesture detector has been initialized.
+   * @note The default maximumAge is 'std::numeric_limits<uint32_t>::max()'.
+   */
+  void SetMaximumMotionEventAge(uint32_t maximumAge);
+
 public: // Getters
   /**
    * @brief Retrieves the minimum number of touches required for the pan gesture to be detected.
@@ -197,6 +208,15 @@ public: // Getters
    */
   uint32_t GetMaximumTouchesRequired() const;
 
+  /**
+   * @brief Retrieves the maximum age for the pan gesture motion as milliseconds.
+   *
+   * @SINCE_2_1.28
+   * @return The maximum age of motion events as milliseconds
+   * @pre The gesture detector has been initialized.
+   */
+  uint32_t GetMaximumMotionEventAge() const;
+
 public: // Directional Panning
   /**
    * @brief The pan gesture is only emitted if the pan occurs in the direction specified by this method with a +/- threshold allowance.