[Tizen] 1. Add Timer at TapGestureDetector 14/267614/1
authorjoogab.yun <joogab.yun@samsung.com>
Thu, 29 Jul 2021 17:09:43 +0000 (02:09 +0900)
committerjoogab.yun <joogab.yun@samsung.com>
Wed, 8 Dec 2021 02:04:25 +0000 (11:04 +0900)
   Currently, when double tap operation is performed,
   single tap and double tap are always transmitted together.

   So, when single and double taps are required, then after one tap, we wait for the timeout,
   if the timeout happens, then we emit the single-tap,
   if we tap again during this time, then we emit a double-tap instead.

2. Add ReceiveAllTapEvents(bool)

If MaximumTaps is greater than MinimumTaps, the event is sent by checking whether it is the correct single tap or multi tap.
However, there are cases when I want to receive all tap events without these checks.

3. Fix SVACE error in tap-gesture-detector-impl.cpp

Change-Id: I835252c863d459039a570bce958a4a72b7734e74

automated-tests/src/dali/utc-Dali-TapGestureDetector.cpp
dali/internal/event/events/tap-gesture/tap-gesture-detector-impl.cpp
dali/internal/event/events/tap-gesture/tap-gesture-detector-impl.h
dali/internal/event/events/tap-gesture/tap-gesture-recognizer.h
dali/public-api/events/tap-gesture-detector.cpp
dali/public-api/events/tap-gesture-detector.h

index a05941a..714c146 100644 (file)
@@ -1081,4 +1081,67 @@ int UtcDaliTapGestureGetSourceType(void)
   DALI_TEST_EQUALS(data.receivedGesture.GetSourceType(), GestureSourceType::TERTIARY, TEST_LOCATION);
 
   END_TEST;
+}
+
+int UtcDaliTapGestureReceiveAllTapEvents(void)
+{
+  TestApplication application;
+
+  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);
+
+  TapGestureDetector detector = TapGestureDetector::New();
+  detector.SetMaximumTapsRequired(2u);
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Emit signals, Because MaximumTapsRequired is 2, a timer that checks whether it is a single tap or a double tap operates internally.
+  application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(50.0f, 50.0f), 0, 100));
+  application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(50.0f, 50.0f), 0, 120));
+  application.SendNotification();
+
+  // So detector don't get the tap event yet.
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // Emit signals, Send the second tab.
+  application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), 0, 130));
+  application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(20.0f, 20.0f), 0, 150));
+  application.SendNotification();
+  application.GetPlatform().TriggerTimer();
+
+  // It find out to be a double tap. Detector receives events.
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // Detector want to receive all tap events.
+  detector.ReceiveAllTapEvents(true);
+
+  // Emit signals, should receive
+  application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(50.0f, 50.0f), 0, 500));
+  application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(50.0f, 50.0f), 0, 520));
+  application.SendNotification();
+
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // Emit signals, should receive
+  application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), 0, 530));
+  application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(20.0f, 20.0f), 0, 550));
+  application.SendNotification();
+
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  END_TEST;
 }
\ No newline at end of file
index a3f13c4..f89d15d 100644 (file)
 #include <cstring> // for strcmp
 
 // INTERNAL INCLUDES
-#include <dali/public-api/events/tap-gesture.h>
-#include <dali/public-api/object/type-registry.h>
 #include <dali/integration-api/debug.h>
+#include <dali/integration-api/platform-abstraction.h>
+#include <dali/internal/event/common/thread-local-storage.h>
 #include <dali/internal/event/events/gesture-event-processor.h>
+#include <dali/internal/event/events/tap-gesture/tap-gesture-impl.h>
+#include <dali/public-api/events/tap-gesture.h>
+#include <dali/public-api/object/type-registry.h>
 
 namespace Dali
 {
@@ -35,9 +38,9 @@ namespace Internal
 
 namespace
 {
-
-const unsigned int DEFAULT_TAPS_REQUIRED = 1u;
-const unsigned int DEFAULT_TOUCHES_REQUIRED = 1u;
+constexpr uint32_t DEFAULT_TAPS_REQUIRED    = 1u;
+constexpr uint32_t DEFAULT_TOUCHES_REQUIRED = 1u;
+constexpr uint32_t DEFAULT_TAP_WAIT_TIME    = 330u;
 
 // Signals
 const char* const SIGNAL_TAP_DETECTED = "tapDetected";
@@ -64,22 +67,37 @@ TapGestureDetectorPtr TapGestureDetector::New( unsigned int tapsRequired )
 }
 
 TapGestureDetector::TapGestureDetector()
-: GestureDetector( GestureType::TAP ),
-  mMinimumTapsRequired( DEFAULT_TAPS_REQUIRED ),
-  mMaximumTapsRequired( DEFAULT_TAPS_REQUIRED ),
-  mTouchesRequired( DEFAULT_TOUCHES_REQUIRED )
+: GestureDetector(GestureType::TAP),
+  mMinimumTapsRequired(DEFAULT_TAPS_REQUIRED),
+  mMaximumTapsRequired(DEFAULT_TAPS_REQUIRED),
+  mTouchesRequired(DEFAULT_TOUCHES_REQUIRED),
+  mTimerId(0),
+  mTappedActor(),
+  mTap(),
+  mReceiveAllTapEvents(false)
 {
 }
 
-TapGestureDetector::TapGestureDetector( unsigned int tapsRequired )
-: GestureDetector( GestureType::TAP ),
-  mMinimumTapsRequired( tapsRequired ),
-  mMaximumTapsRequired( tapsRequired ),
-  mTouchesRequired( DEFAULT_TOUCHES_REQUIRED )
+TapGestureDetector::TapGestureDetector(unsigned int tapsRequired)
+: GestureDetector(GestureType::TAP),
+  mMinimumTapsRequired(tapsRequired),
+  mMaximumTapsRequired(tapsRequired),
+  mTouchesRequired(DEFAULT_TOUCHES_REQUIRED),
+  mTimerId(0),
+  mTappedActor(),
+  mTap(),
+  mReceiveAllTapEvents(false)
 {
 }
 
-TapGestureDetector::~TapGestureDetector() = default;
+TapGestureDetector::~TapGestureDetector()
+{
+  if(mTimerId != 0 && ThreadLocalStorage::Created())
+  {
+    Dali::Integration::PlatformAbstraction& platformAbstraction = ThreadLocalStorage::Get().GetPlatformAbstraction();
+    platformAbstraction.CancelTimer(mTimerId);
+  }
+}
 
 void TapGestureDetector::SetMinimumTapsRequired(unsigned int taps)
 {
@@ -135,12 +153,52 @@ unsigned int TapGestureDetector::GetTouchesRequired() const
   return mTouchesRequired;
 }
 
+void TapGestureDetector::ReceiveAllTapEvents(bool receive)
+{
+  mReceiveAllTapEvents = receive;
+}
+
 void TapGestureDetector::EmitTapGestureSignal(Dali::Actor tappedActor, const Dali::TapGesture& tap)
 {
+  Dali::Integration::PlatformAbstraction& platformAbstraction = ThreadLocalStorage::Get().GetPlatformAbstraction();
+  if(mTimerId != 0)
+  {
+    platformAbstraction.CancelTimer(mTimerId);
+    mTimerId = 0;
+  }
+  if(mMaximumTapsRequired > tap.GetNumberOfTaps() && !mReceiveAllTapEvents)
+  {
+    mTappedActor = tappedActor;
+
+    Internal::TapGesturePtr internalTap(new Internal::TapGesture(tap.GetState()));
+    internalTap->SetTime(tap.GetTime());
+    internalTap->SetNumberOfTaps(tap.GetNumberOfTaps());
+    internalTap->SetNumberOfTouches(tap.GetNumberOfTouches());
+    internalTap->SetScreenPoint(tap.GetScreenPoint());
+    internalTap->SetLocalPoint(tap.GetLocalPoint());
+    internalTap->SetGestureSourceType(tap.GetSourceType());
+    mTap = Dali::TapGesture(internalTap.Get());
+
+    mTimerId = platformAbstraction.StartTimer(DEFAULT_TAP_WAIT_TIME, MakeCallback(this, &TapGestureDetector::TimerCallback));
+  }
+  else
+  {
+    // Guard against destruction during signal emission
+    Dali::TapGestureDetector handle(this);
+
+    mDetectedSignal.Emit(tappedActor, tap);
+  }
+}
+
+bool TapGestureDetector::TimerCallback()
+{
   // Guard against destruction during signal emission
   Dali::TapGestureDetector handle( this );
 
-  mDetectedSignal.Emit( tappedActor, tap );
+  mDetectedSignal.Emit(mTappedActor, mTap);
+
+  mTimerId = 0;
+  return false;
 }
 
 bool TapGestureDetector::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
index b6b5bc8..8de6319 100644 (file)
@@ -97,6 +97,11 @@ public:
    */
   unsigned int GetTouchesRequired() const;
 
+  /**
+   * @copydoc Dali::TapGestureDetector::ReceiveAllTapEvents()
+   */
+  void ReceiveAllTapEvents(bool receive);
+
 public:
 
   /**
@@ -141,6 +146,12 @@ private:
   TapGestureDetector(const TapGestureDetector&);
   TapGestureDetector& operator=(const TapGestureDetector& rhs);
 
+  /**
+   * Timer Callback
+   * @return will return false; one-shot timer.
+   */
+  bool TimerCallback();
+
 private: // GestureDetector overrides
 
   /**
@@ -162,9 +173,13 @@ private:
 
   Dali::TapGestureDetector::DetectedSignalType mDetectedSignal;
 
-  unsigned int mMinimumTapsRequired;
-  unsigned int mMaximumTapsRequired;
-  unsigned int mTouchesRequired;
+  unsigned int     mMinimumTapsRequired;
+  unsigned int     mMaximumTapsRequired;
+  unsigned int     mTouchesRequired;
+  uint32_t         mTimerId;
+  Dali::Actor      mTappedActor;
+  Dali::TapGesture mTap;
+  bool             mReceiveAllTapEvents;
 };
 
 } // namespace Internal
@@ -191,4 +206,4 @@ inline const Internal::TapGestureDetector& GetImplementation(const Dali::TapGest
 
 } // namespace Dali
 
-#endif // DALI_INTERNAL_TAP_GESTURE_DETECTOR_H
+#endif // DALI_INTERNAL_TAP_GESTURE_DETECTOR_H
\ No newline at end of file
index 66276fc..78020c5 100644 (file)
@@ -120,7 +120,7 @@ private:
    *
    * @param[in] tap event for processing
    */
-  void ProcessEvent( TapGestureEvent& event );
+  void ProcessEvent(TapGestureEvent& event);
 
 private:
 
index fa9376d..e491ef0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
@@ -79,6 +79,11 @@ uint32_t TapGestureDetector::GetMaximumTapsRequired() const
   return GetImplementation(*this).GetMaximumTapsRequired();
 }
 
+void TapGestureDetector::ReceiveAllTapEvents(bool receive)
+{
+  return GetImplementation(*this).ReceiveAllTapEvents(receive);
+}
+
 TapGestureDetector::DetectedSignalType& TapGestureDetector::DetectedSignal()
 {
   return GetImplementation(*this).DetectedSignal();
index 7432c83..7782231 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TAP_GESTURE_DETECTOR_H
 
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
@@ -148,6 +148,7 @@ public: // Setters
    * @param[in] minimumTaps The minimum taps required
    * @pre The gesture detector has been initialized.
    * @note The default is '1', the maximum is 2.
+   * @see ReceiveAllTapEvents
    */
   void SetMinimumTapsRequired(uint32_t minimumTaps);
 
@@ -159,9 +160,19 @@ public: // Setters
    * @param[in] maximumTaps The maximum taps required
    * @pre The gesture detector has been initialized.
    * @note The default is '1', the maximum is 2.
+   * @see ReceiveAllTapEvents
    */
   void SetMaximumTapsRequired(uint32_t maximumTaps);
 
+  /**
+   * @brief When set to true, all tap gestures will be received when multiple taps are supported by the gesture detector.
+   *
+   * @param[in] receive The receiving all tap events flag
+   * @pre The gesture detector has been initialized.
+   * @note The default is false.
+   */
+  void ReceiveAllTapEvents(bool receive);
+
 public: // Getters
   /**
    * @brief Retrieves the minimum number of taps required.