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 713cffe016098b50083dd3a6a5160cacdd9e6dca..b1314eaa0d9b1bf5f6392c6265a3e9c783ccad92 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 8fed854f2cdc9330ce15fd01ba3f5a2f502ca4e5..5f6e07517dda7405a0f668c3ce4b2b0c2799edd9 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 fc7e6fc09d66e49c6873a7616cd57112e78b0a92..b47d0b331b25984980a0acf2c2a18a828cb9f6e9 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 c2596491b8c4b08b86a48dacb9fb3c311e575fa8..0c6576ab092d0db8ce5c62fcad7268c1093a8b68 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 2c13b37146dddc3e9b7e131f5f4043af5892a327..a03f681f0895fdd828eff892d1871c7bbcdda7f6 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
@@ -78,6 +83,11 @@ public:
    */
   uint32_t GetMaximumTouchesRequired() const;
 
+  /**
+   * @copydoc Dali::PanGestureDetector::GetMaximumMotionEventAge() const
+   */
+  uint32_t GetMaximumMotionEventAge() const;
+
   /**
    * @copydoc Dali::PanGestureDetector::AddAngle()
    */
@@ -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 b1909dcb8fc8c746596af5d2799697ba9b51ac87..2a2e08e45281bad1d7e0072b1f687e0b88f56066 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 3f40eb9db10c829c203cc7e4f881248e02e9757f..bfeb623d9764d1a7823dc3f1fdf6d278122069f6 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 d59a9b696e8f5968ef955ff139eb75ef321e79ad..39e43ceab1abd2d4bd091962cab05e7b7810d09d 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 8744a417a78f6234d7ee767a19eb89ab273355f0..8bc371506c2d72bc03b3e72d7f2b7a919b61307b 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 a129a81f424910f8741af074c8d29b0a1697493e..0300ad4ce5aa81c53bf0e4c3241fe64026e3bb66 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 c31549d12e1d539359b7962208245047e5b7e362..3467ff543ac26b2f6257ec5a98479aa337f62e26 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.