Touch and Hover event propagrated by geometry way.(5) 98/304098/19
authorjoogab.yun <joogab.yun@samsung.com>
Wed, 10 Jan 2024 04:51:24 +0000 (13:51 +0900)
committerjoogab.yun <joogab.yun@samsung.com>
Tue, 6 Feb 2024 01:25:31 +0000 (10:25 +0900)
1. If there is a consumed actor, the intercept is sent only up to the moment before the consumed actor.
2. To propagate the gesture, check whether it has been detected and the NeedGesturePropagation flag.

Change-Id: Icfbec13c000092ae8526e0a269cd180fd7431a9e

26 files changed:
automated-tests/src/dali/utc-Dali-GeoTouchProcessing.cpp
automated-tests/src/dali/utc-Dali-PanGestureDetector.cpp
dali/internal/event/events/gesture-detector-impl.cpp
dali/internal/event/events/gesture-detector-impl.h
dali/internal/event/events/gesture-event-processor.cpp
dali/internal/event/events/gesture-event-processor.h
dali/internal/event/events/gesture-event.h
dali/internal/event/events/gesture-processor.cpp
dali/internal/event/events/gesture-processor.h
dali/internal/event/events/gesture-recognizer.h
dali/internal/event/events/long-press-gesture/long-press-gesture-processor.cpp
dali/internal/event/events/long-press-gesture/long-press-gesture-processor.h
dali/internal/event/events/long-press-gesture/long-press-gesture-recognizer.cpp
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/pinch-gesture/pinch-gesture-processor.cpp
dali/internal/event/events/pinch-gesture/pinch-gesture-processor.h
dali/internal/event/events/pinch-gesture/pinch-gesture-recognizer.cpp
dali/internal/event/events/rotation-gesture/rotation-gesture-processor.cpp
dali/internal/event/events/rotation-gesture/rotation-gesture-processor.h
dali/internal/event/events/rotation-gesture/rotation-gesture-recognizer.cpp
dali/internal/event/events/tap-gesture/tap-gesture-processor.cpp
dali/internal/event/events/tap-gesture/tap-gesture-processor.h
dali/internal/event/events/tap-gesture/tap-gesture-recognizer.cpp
dali/internal/event/events/touch-event-processor.cpp

index 1cb4cfc..0e0793f 100644 (file)
@@ -1741,6 +1741,82 @@ int UtcDaliGeoTouchEventInterruptedDifferentConsumer(void)
   END_TEST;
 }
 
+int UtcDaliGeoTouchEventInterruptedDifferentConsumer02(void)
+{
+  TestApplication application;
+
+  application.GetScene().SetGeometryHittestEnabled(true);
+
+  Actor rootActor(application.GetScene().GetRootLayer());
+
+  Actor parent = Actor::New();
+  parent.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+  parent.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+  application.GetScene().Add(parent);
+
+  Actor actor = Actor::New();
+  actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+  actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+  parent.Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's touched signal
+  SignalData        data;
+  TouchEventFunctor functor(data, false /* Do not consume */);
+  actor.TouchedSignal().Connect(&application, functor);
+
+  // Connect to parent's touched signal
+  SignalData        parentData;
+  TouchEventFunctor parentFunctor(parentData, false /* Do not consume */);
+  parent.TouchedSignal().Connect(&application, parentFunctor);
+
+  // Connect to root's touched signal
+  SignalData        rootData;
+  TouchEventFunctor rootFunctor(rootData, false /* Do not consume */);
+  rootActor.TouchedSignal().Connect(&application, rootFunctor);
+
+  // Emit a down signal
+  application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(PointState::DOWN, data.receivedTouch.points[0].state, TEST_LOCATION);
+  DALI_TEST_CHECK(actor == data.receivedTouch.points[0].hitActor);
+  DALI_TEST_CHECK(actor == data.touchedActor);
+  DALI_TEST_EQUALS(true, parentData.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(PointState::DOWN, parentData.receivedTouch.points[0].state, TEST_LOCATION);
+  DALI_TEST_CHECK(actor == parentData.receivedTouch.points[0].hitActor);
+  DALI_TEST_CHECK(parent == parentData.touchedActor);
+  DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(PointState::DOWN, rootData.receivedTouch.points[0].state, TEST_LOCATION);
+  DALI_TEST_CHECK(actor == rootData.receivedTouch.points[0].hitActor);
+  DALI_TEST_CHECK(rootActor == rootData.touchedActor);
+  data.Reset();
+  parentData.Reset();
+  rootData.Reset();
+
+  // child is now consumer, connect to the touched signal of the child so that it becomes the consumer
+  SignalData        secondData;
+  TouchEventFunctor secondFunctor(secondData /* Consume */);
+  actor.TouchedSignal().Connect(&application, secondFunctor);
+
+  // Emit an motion signal, Since child has comsume, Actors who were previously touched will get interrupted.
+  application.ProcessEvent(GenerateSingleTouch(PointState::MOTION, Vector2(20.0f, 20.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(PointState::MOTION, data.receivedTouch.points[0].state, TEST_LOCATION);
+  DALI_TEST_EQUALS(true, parentData.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(PointState::INTERRUPTED, parentData.receivedTouch.points[0].state, TEST_LOCATION);
+  DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(PointState::INTERRUPTED, rootData.receivedTouch.points[0].state, TEST_LOCATION);
+  data.Reset();
+  parentData.Reset();
+  rootData.Reset();
+
+  END_TEST;
+}
+
+
 int UtcDaliGeoTouchEventGetRadius(void)
 {
   TestApplication application;
index 3206272..2d31057 100644 (file)
@@ -3124,3 +3124,155 @@ int UtcDaliPanGestureFeedTouch(void)
 
   END_TEST;
 }
+
+int UtcDaliPanGestureFeedTouchWhenGesturePropargation(void)
+{
+  TestApplication application;
+  Integration::Scene scene     = application.GetScene();
+  RenderTaskList   taskList  = scene.GetRenderTaskList();
+  Dali::RenderTask task      = taskList.GetTask(0);
+
+  Actor parentActor = Actor::New();
+  parentActor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+  parentActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+
+  Actor childActor = Actor::New();
+  childActor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+  childActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+
+  parentActor.Add(childActor);
+  application.GetScene().Add(parentActor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData             pData;
+  GestureReceivedFunctor pFunctor(pData);
+
+  PanGestureDetector parentDetector = PanGestureDetector::New();
+  parentDetector.DetectedSignal().Connect(&application, pFunctor);
+
+  SignalData             cData;
+  GestureReceivedFunctor cFunctor(cData);
+
+  PanGestureDetector childDetector = PanGestureDetector::New();
+  childDetector.DetectedSignal().Connect(&application, cFunctor);
+
+  // Start gesture within the actor's area, we receive the gesture not parent actor but child actor.
+  Integration::TouchEvent tp = GenerateSingleTouch(PointState::DOWN, Vector2(50.0f, 50.0f), 100);
+  Internal::TouchEventPtr touchEventImpl(new Internal::TouchEvent(100));
+  touchEventImpl->AddPoint(tp.GetPoint(0));
+  touchEventImpl->SetRenderTask(task);
+  Dali::TouchEvent touchEventHandle(touchEventImpl.Get());
+  if(!childDetector.FeedTouch(childActor, touchEventHandle))
+  {
+    parentDetector.FeedTouch(parentActor, touchEventHandle);
+  }
+
+  tp = GenerateSingleTouch(PointState::MOTION, Vector2(60.0f, 60.0f), 150);
+  touchEventImpl = new Internal::TouchEvent(150);
+  touchEventImpl->AddPoint(tp.GetPoint(0));
+  touchEventImpl->SetRenderTask(task);
+  touchEventHandle = Dali::TouchEvent(touchEventImpl.Get());
+  if(!childDetector.FeedTouch(childActor, touchEventHandle))
+  {
+    parentDetector.FeedTouch(parentActor, touchEventHandle);
+  }
+
+  tp = GenerateSingleTouch(PointState::MOTION, Vector2(70.0f, 70.0f), 200);
+  touchEventImpl = new Internal::TouchEvent(200);
+  touchEventImpl->AddPoint(tp.GetPoint(0));
+  touchEventImpl->SetRenderTask(task);
+  touchEventHandle = Dali::TouchEvent(touchEventImpl.Get());
+  if(!childDetector.FeedTouch(childActor, touchEventHandle))
+  {
+    parentDetector.FeedTouch(parentActor, touchEventHandle);
+  }
+
+  tp = GenerateSingleTouch(PointState::MOTION, Vector2(80.0f, 80.0f), 250);
+  touchEventImpl = new Internal::TouchEvent(200);
+  touchEventImpl->AddPoint(tp.GetPoint(0));
+  touchEventImpl->SetRenderTask(task);
+  touchEventHandle = Dali::TouchEvent(touchEventImpl.Get());
+  if(!childDetector.FeedTouch(childActor, touchEventHandle))
+  {
+    parentDetector.FeedTouch(parentActor, touchEventHandle);
+  }
+
+  tp = GenerateSingleTouch(PointState::UP, Vector2(100.0f, 100.0f), 300);
+  touchEventImpl = new Internal::TouchEvent(250);
+  touchEventImpl->AddPoint(tp.GetPoint(0));
+  touchEventImpl->SetRenderTask(task);
+  touchEventHandle = Dali::TouchEvent(touchEventImpl.Get());
+  if(!childDetector.FeedTouch(childActor, touchEventHandle))
+  {
+    parentDetector.FeedTouch(parentActor, touchEventHandle);
+  }
+
+  DALI_TEST_EQUALS(true, cData.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(false, pData.functorCalled, TEST_LOCATION);
+  cData.Reset();
+  pData.Reset();
+
+  // If GesturePropargation is set, a gesture event is to pass over to the parent.
+  Dali::DevelActor::SetNeedGesturePropagation(childActor, true);
+
+  // So now the parent got the gesture event.
+  tp = GenerateSingleTouch(PointState::DOWN, Vector2(50.0f, 50.0f), 100);
+  touchEventImpl = new Internal::TouchEvent(100);
+  touchEventImpl->AddPoint(tp.GetPoint(0));
+  touchEventImpl->SetRenderTask(task);
+  touchEventHandle = Dali::TouchEvent(touchEventImpl.Get());
+  if(!childDetector.FeedTouch(childActor, touchEventHandle))
+  {
+    parentDetector.FeedTouch(parentActor, touchEventHandle);
+  }
+
+  tp = GenerateSingleTouch(PointState::MOTION, Vector2(60.0f, 60.0f), 150);
+  touchEventImpl = new Internal::TouchEvent(150);
+  touchEventImpl->AddPoint(tp.GetPoint(0));
+  touchEventImpl->SetRenderTask(task);
+  touchEventHandle = Dali::TouchEvent(touchEventImpl.Get());
+  if(!childDetector.FeedTouch(childActor, touchEventHandle))
+  {
+    parentDetector.FeedTouch(parentActor, touchEventHandle);
+  }
+
+  tp = GenerateSingleTouch(PointState::MOTION, Vector2(70.0f, 70.0f), 200);
+  touchEventImpl = new Internal::TouchEvent(200);
+  touchEventImpl->AddPoint(tp.GetPoint(0));
+  touchEventImpl->SetRenderTask(task);
+  touchEventHandle = Dali::TouchEvent(touchEventImpl.Get());
+  if(!childDetector.FeedTouch(childActor, touchEventHandle))
+  {
+    parentDetector.FeedTouch(parentActor, touchEventHandle);
+  }
+
+  tp = GenerateSingleTouch(PointState::MOTION, Vector2(80.0f, 80.0f), 250);
+  touchEventImpl = new Internal::TouchEvent(200);
+  touchEventImpl->AddPoint(tp.GetPoint(0));
+  touchEventImpl->SetRenderTask(task);
+  touchEventHandle = Dali::TouchEvent(touchEventImpl.Get());
+  if(!childDetector.FeedTouch(childActor, touchEventHandle))
+  {
+    parentDetector.FeedTouch(parentActor, touchEventHandle);
+  }
+
+  tp = GenerateSingleTouch(PointState::UP, Vector2(100.0f, 100.0f), 300);
+  touchEventImpl = new Internal::TouchEvent(250);
+  touchEventImpl->AddPoint(tp.GetPoint(0));
+  touchEventImpl->SetRenderTask(task);
+  touchEventHandle = Dali::TouchEvent(touchEventImpl.Get());
+  if(!childDetector.FeedTouch(childActor, touchEventHandle))
+  {
+    parentDetector.FeedTouch(parentActor, touchEventHandle);
+  }
+
+  DALI_TEST_EQUALS(true, cData.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(true, pData.functorCalled, TEST_LOCATION);
+  cData.Reset();
+  pData.Reset();
+
+  END_TEST;
+}
\ No newline at end of file
index dfa343f..12bbbc1 100644 (file)
@@ -37,7 +37,8 @@ namespace Internal
 GestureDetector::GestureDetector(GestureType::Value type, const SceneGraph::PropertyOwner* sceneObject)
 : Object(sceneObject),
   mType(type),
-  mGestureEventProcessor(ThreadLocalStorage::Get().GetGestureEventProcessor())
+  mGestureEventProcessor(ThreadLocalStorage::Get().GetGestureEventProcessor()),
+  mIsDetected(false)
 {
 }
 
@@ -268,7 +269,10 @@ bool GestureDetector::FeedTouch(Dali::Actor& actor, Dali::TouchEvent& touch)
     Dali::Internal::Actor& actorImpl(GetImplementation(actor));
     if(state == PointState::DOWN)
     {
+      //TODO We need to find a better way to add detectors to the processor other than detach and attach.
+      Detach(actorImpl);
       Attach(actorImpl);
+      mIsDetected = false;
     }
 
     Integration::TouchEvent touchEvent(touch.GetTime());
@@ -292,15 +296,30 @@ bool GestureDetector::FeedTouch(Dali::Actor& actor, Dali::TouchEvent& touch)
     Dali::Internal::TouchEvent& touchEventImpl(GetImplementation(touch));
     mGestureEventProcessor.ProcessTouchEvent(this, actorImpl, GetImplementation(touchEventImpl.GetRenderTaskPtr()), actorImpl.GetScene(), touchEvent);
 
+    if(IsDetected())
+    {
+      ret = !actorImpl.NeedGesturePropagation();
+    }
+
     if(state == PointState::FINISHED || state == PointState::INTERRUPTED || state == PointState::LEAVE)
     {
+      //TODO We need to find a better way to remove detectors to the processor other than detach.
       Detach(actorImpl);
     }
-    ret = true;
   }
   return ret;
 }
 
+bool GestureDetector::IsDetected() const
+{
+  return mIsDetected;
+}
+
+void GestureDetector::SetDetected(bool detected)
+{
+  mIsDetected = detected;
+}
+
 bool GestureDetector::IsAttached(Actor& actor) const
 {
   return (find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &actor) != mPendingAttachActors.end()) ||
index 1a4ecaa..b7953ce 100644 (file)
@@ -112,6 +112,18 @@ public:
    */
   bool IsAttached(Actor& actor) const;
 
+  /**
+   * @brief Returns whether the gesture was detected.
+   * @return true, if the gesture was detected, false otherwise.
+   */
+  bool IsDetected() const;
+
+  /**
+   * @brief Sets whether the gesture was detected.
+   * @param detected Whether gesture detected.
+   */
+  void SetDetected(bool detected);
+
 protected: // Creation & Destruction
   /**
    * Construct a new GestureDetector.
@@ -174,6 +186,7 @@ protected:
   GestureDetectorActorContainer mAttachedActors;        ///< Object::Observer is used to provide weak-pointer behaviour
   GestureDetectorActorContainer mPendingAttachActors;   ///< Object::Observer is used to provide weak-pointer behaviour
   GestureEventProcessor&        mGestureEventProcessor; ///< A reference to the gesture event processor.
+  bool mIsDetected : 1;                                 ///< Whether gesture detected.
 };
 
 } // namespace Internal
index a45500a..2664557 100644 (file)
@@ -42,7 +42,8 @@ GestureEventProcessor::GestureEventProcessor(SceneGraph::UpdateManager& updateMa
   mRotationGestureProcessor(),
   mRenderController(renderController),
   envOptionMinimumPanDistance(-1),
-  envOptionMinimumPanEvents(-1)
+  envOptionMinimumPanEvents(-1),
+  mIsProcessingFeedTouch(false)
 {
 }
 
@@ -50,44 +51,49 @@ GestureEventProcessor::~GestureEventProcessor() = default;
 
 void GestureEventProcessor::ProcessTouchEvent(Scene& scene, const Integration::TouchEvent& event)
 {
-  mLongPressGestureProcessor.ProcessTouch(scene, event);
-  mPanGestureProcessor.ProcessTouch(scene, event);
-  mPinchGestureProcessor.ProcessTouch(scene, event);
-  mTapGestureProcessor.ProcessTouch(scene, event);
-  mRotationGestureProcessor.ProcessTouch(scene, event);
+  if(!mIsProcessingFeedTouch)
+  {
+    mLongPressGestureProcessor.ProcessTouch(scene, event);
+    mPanGestureProcessor.ProcessTouch(scene, event);
+    mPinchGestureProcessor.ProcessTouch(scene, event);
+    mTapGestureProcessor.ProcessTouch(scene, event);
+    mRotationGestureProcessor.ProcessTouch(scene, event);
+  }
+  mIsProcessingFeedTouch = false;
 }
 
 void GestureEventProcessor::ProcessTouchEvent(GestureDetector* gestureDetector, Actor& actor, Dali::Internal::RenderTask& renderTask, Scene& scene, const Integration::TouchEvent& event)
 {
+  mIsProcessingFeedTouch = true;
   switch(gestureDetector->GetType())
   {
     case GestureType::LONG_PRESS:
     {
-      mLongPressGestureProcessor.ProcessTouch(actor, renderTask, scene, event);
+      mLongPressGestureProcessor.ProcessTouch(gestureDetector, actor, renderTask, scene, event);
       break;
     }
 
     case GestureType::PAN:
     {
-      mPanGestureProcessor.ProcessTouch(actor, renderTask, scene, event);
+      mPanGestureProcessor.ProcessTouch(gestureDetector, actor, renderTask, scene, event);
       break;
     }
 
     case GestureType::PINCH:
     {
-      mPinchGestureProcessor.ProcessTouch(actor, renderTask, scene, event);
+      mPinchGestureProcessor.ProcessTouch(gestureDetector, actor, renderTask, scene, event);
       break;
     }
 
     case GestureType::TAP:
     {
-      mTapGestureProcessor.ProcessTouch(actor, renderTask, scene, event);
+      mTapGestureProcessor.ProcessTouch(gestureDetector, actor, renderTask, scene, event);
       break;
     }
 
     case GestureType::ROTATION:
     {
-      mRotationGestureProcessor.ProcessTouch(actor, renderTask, scene, event);
+      mRotationGestureProcessor.ProcessTouch(gestureDetector, actor, renderTask, scene, event);
       break;
     }
   }
index 30d7836..f606971 100644 (file)
@@ -336,6 +336,7 @@ private:
 
   int32_t envOptionMinimumPanDistance;
   int32_t envOptionMinimumPanEvents;
+  bool mIsProcessingFeedTouch;  // Whether the gesture is being recognized via FeedTouch in gestureDetector
 };
 
 } // namespace Internal
index 87b4cb4..93923c4 100644 (file)
@@ -67,12 +67,6 @@ struct GestureEvent
    */
   GestureSourceData sourceData;
 
-  /**
-   * The render task used to generate this touch event.
-   */
-  RenderTaskPtr renderTask;
-
-
 protected: // Constructors only to be used by derived structures.
   /**
    * This constructor is only used by derived classes.
index 2a3c538..3169495 100644 (file)
@@ -78,7 +78,10 @@ GestureProcessor::GestureProcessor(GestureType::Value type)
   mCurrentGesturedActor(nullptr),
   mPoint(),
   mEventTime(0u),
-  mGesturedActorDisconnected(false)
+  mGesturedActorDisconnected(false),
+  mFeededActor(nullptr),
+  mRenderTask(),
+  mGestureDetector(nullptr)
 {
 }
 
@@ -96,11 +99,13 @@ void GestureProcessor::ProcessTouch(Scene& scene, const Integration::TouchEvent&
       mPoint     = event.points[0];
       mEventTime = event.time;
     }
+    mFeededActor = nullptr;
+    mGestureDetector = nullptr;
     mGestureRecognizer->SendEvent(scene, event);
   }
 }
 
-void GestureProcessor::ProcessTouch(Actor& actor, Dali::Internal::RenderTask& renderTask, Scene& scene, const Integration::TouchEvent& event)
+void GestureProcessor::ProcessTouch(GestureDetector* gestureDetector, Actor& actor, Dali::Internal::RenderTask& renderTask, Scene& scene, const Integration::TouchEvent& event)
 {
   if(mGestureRecognizer)
   {
@@ -109,10 +114,28 @@ void GestureProcessor::ProcessTouch(Actor& actor, Dali::Internal::RenderTask& re
       mPoint     = event.points[0];
       mEventTime = event.time;
     }
-    mGestureRecognizer->SendEvent(actor, renderTask, scene, event);
+    mGestureDetector = gestureDetector;
+    mFeededActor.SetActor(&actor);
+    mRenderTask = &renderTask;
+    mGestureRecognizer->SendEvent(scene, event);
   }
 }
 
+Actor* GestureProcessor::GetFeededActor()
+{
+  return mFeededActor.GetActor();
+}
+
+GestureDetector* GestureProcessor::GetFeededGestureDetector()
+{
+  return mGestureDetector;
+}
+
+RenderTaskPtr GestureProcessor::GetFeededRenderTask()
+{
+  return mRenderTask;
+}
+
 void GestureProcessor::GetGesturedActor(Actor*& actor, GestureDetectorContainer& gestureDetectors)
 {
   while(actor)
@@ -214,17 +237,17 @@ void GestureProcessor::ProcessAndEmit(HitTestAlgorithm::Results& hitTestResults)
   }
 }
 
-void GestureProcessor::ProcessAndEmitActor(HitTestAlgorithm::Results& hitTestResults)
+void GestureProcessor::ProcessAndEmitActor(HitTestAlgorithm::Results& hitTestResults, GestureDetector* gestureDetector)
 {
-  if(hitTestResults.actor)
+  if(hitTestResults.actor && gestureDetector)
   {
-    Actor*  hitTestActor(&GetImplementation(hitTestResults.actor));
-    Actor*  actor(hitTestActor);
+    Actor*  actor(&GetImplementation(hitTestResults.actor));
     GestureDetectorContainer gestureDetectors;
-    GetGesturedActor(actor, gestureDetectors);
-
-    if(actor && actor->IsVisible() && !gestureDetectors.empty() && actor == hitTestActor)
+    // Check deriving class for whether the current gesture satisfies the gesture detector's parameters.
+    if(actor && actor->IsVisible() && gestureDetector && CheckGestureDetector(gestureDetector, actor))
     {
+      gestureDetectors.push_back(gestureDetector);
+      gestureDetector->SetDetected(true);
       EmitGestureSignal(actor, gestureDetectors, hitTestResults.actorCoordinates);
     }
   }
index 4c8491b..b1874b4 100644 (file)
@@ -45,12 +45,13 @@ public:
 
   /**
    * Process the touch event in the attached recognizer
+   * @param[in] gestureDetector The gesture detector which gesture want to recognize.
    * @param[in] actor The actor which gesture want to recognize.
    * @param[in] renderTask RenderTask.
    * @param[in] scene Scene.
    * @param[in] event Touch event to process
    */
-  void ProcessTouch(Actor& actor, Dali::Internal::RenderTask& renderTask, Scene& scene, const Integration::TouchEvent& event);
+  void ProcessTouch(GestureDetector* gestureDetector, Actor& actor, Dali::Internal::RenderTask& renderTask, Scene& scene, const Integration::TouchEvent& event);
 
   /**
    * Returns whether any GestureDetector requires a Core::Update
@@ -79,6 +80,24 @@ protected:
   // Methods to be used by deriving classes
 
   /**
+   * @brief Gets the Feeded actor
+   * @return The actor which gesture want to recognize.
+   */
+  Actor* GetFeededActor();
+
+  /**
+   * @brief Gets the Feeded Gesture Detector.
+   * @return The gesture detector which gesture want to recognize.
+   */
+  GestureDetector* GetFeededGestureDetector();
+
+  /**
+   * @brief Get the Feeded Render Task object
+   * @return RenderTaskPtr
+   */
+  RenderTaskPtr GetFeededRenderTask();
+
+  /**
    * Given the hit actor, this walks up the actor tree to determine the actor that is connected to one (or several) gesture detectors.
    *
    * @param[in,out]  actor               The gestured actor. When this function returns, this is the actor that has been hit by the gesture.
@@ -109,7 +128,7 @@ protected:
    *       and EmitGestureSignal() to emit the signal.
    * @pre Hit Testing should already be done.
    */
-  void ProcessAndEmitActor(HitTestAlgorithm::Results& hitTestResults);
+  void ProcessAndEmitActor(HitTestAlgorithm::Results& hitTestResults, GestureDetector* gestureDetector);
 
   /**
    * Hit test the screen coordinates, and place the results in hitTestResults.
@@ -209,6 +228,10 @@ private:                                             // Data
   Integration::Point mPoint;                         ///< The point of event touched.
   uint32_t           mEventTime;                     ///< The time the event occurred.
   bool               mGesturedActorDisconnected : 1; ///< Indicates whether the gestured actor has been disconnected from the scene
+  ActorObserver      mFeededActor;                   ///< The actor used to generate this touch event.
+  RenderTaskPtr      mRenderTask;                    ///< The render task used to generate this touch event.
+  GestureDetector*   mGestureDetector;               ///< The gesture detector which gesture want to recognize.
+
 };
 
 } // namespace Internal
index 498879e..d2c5e93 100644 (file)
@@ -27,6 +27,7 @@
 #include <dali/public-api/events/gesture.h>
 #include <dali/public-api/math/vector2.h>
 #include <dali/public-api/object/ref-object.h>
+#include <dali/public-api/events/gesture-detector.h>
 
 namespace Dali
 {
@@ -44,7 +45,7 @@ template<typename T>
 class RecognizerObserver
 {
 public:
-  virtual void Process(Scene& scene, const T& event, Actor* actor = nullptr) = 0;
+  virtual void Process(Scene& scene, const T& event) = 0;
 
   virtual ~RecognizerObserver() = default;
   ;
@@ -132,20 +133,6 @@ public:
     SendEvent(event);
   }
 
-  /**
-   * Called when we get a touch event.
-   * @param[in]  actor  The actor the touch event has occurred on
-   * @param[in]  renderTask  The renderTask the touch event has occurred on
-   * @param[in]  scene  The scene the touch event has occurred on
-   * @param[in]  event  The latest touch event
-   */
-  void SendEvent(Actor& actor, Dali::Internal::RenderTask& renderTask, Scene& scene, const Integration::TouchEvent& event)
-  {
-    mActor.SetActor(&actor);
-    mRenderTask = &renderTask;
-    SendEvent(scene, event);
-  }
-
 protected:
   /**
    * Protected Constructor. Should only be able to create derived class objects.
@@ -157,9 +144,7 @@ protected:
     mType(detectorType),
     mScene(nullptr),
     mSourceType(GestureSourceType::INVALID),
-    mSourceData(GestureSourceData::INVALID),
-    mActor(),
-    mRenderTask()
+    mSourceData(GestureSourceData::INVALID)
   {
   }
 
@@ -185,8 +170,6 @@ protected:
   Scene*                      mScene;
   GestureSourceType           mSourceType; /// < Gesture input source type.
   GestureSourceData           mSourceData; /// < Gesture input source data.
-  ActorObserver               mActor;      /// < The actor used to generate this touch event.
-  RenderTaskPtr               mRenderTask; /// < The render task used to generate this touch event.
 };
 
 using GestureRecognizerPtr = IntrusivePtr<GestureRecognizer>;
index a2cc919..81cead4 100644 (file)
@@ -124,7 +124,7 @@ LongPressGestureProcessor::LongPressGestureProcessor()
 
 LongPressGestureProcessor::~LongPressGestureProcessor() = default;
 
-void LongPressGestureProcessor::Process(Scene& scene, const LongPressGestureEvent& longPressEvent, Actor* actor)
+void LongPressGestureProcessor::Process(Scene& scene, const LongPressGestureEvent& longPressEvent)
 {
   DALI_TRACE_SCOPE(gTraceFilter, "DALI_PROCESS_LONG_PRESS_GESTURE");
   switch(longPressEvent.state)
@@ -135,9 +135,9 @@ void LongPressGestureProcessor::Process(Scene& scene, const LongPressGestureEven
       ResetActor();
 
       HitTestAlgorithm::Results hitTestResults;
-      if(actor)
+      if(GetFeededActor())
       {
-        SetActor(actor);
+        SetActor(GetFeededActor());
       }
       else if(HitTest(scene, longPressEvent.point, hitTestResults))
       {
@@ -152,10 +152,10 @@ void LongPressGestureProcessor::Process(Scene& scene, const LongPressGestureEven
       if(currentGesturedActor)
       {
         HitTestAlgorithm::Results hitTestResults;
-        if(actor)
+        if(GetFeededActor())
         {
-          hitTestResults.actor = Dali::Actor(actor);
-          hitTestResults.renderTask = longPressEvent.renderTask;
+          hitTestResults.actor = Dali::Actor(GetFeededActor());
+          hitTestResults.renderTask = GetFeededRenderTask();
 
           Vector2     actorCoords;
           currentGesturedActor->ScreenToLocal(*hitTestResults.renderTask.Get(), actorCoords.x, actorCoords.y, longPressEvent.point.x, longPressEvent.point.y);
@@ -173,9 +173,9 @@ void LongPressGestureProcessor::Process(Scene& scene, const LongPressGestureEven
 
           // Set mCurrentLongPressEvent to use inside overridden methods called from ProcessAndEmit()
           mCurrentLongPressEvent = &longPressEvent;
-          if(actor)
+          if(GetFeededActor())
           {
-            ProcessAndEmitActor(hitTestResults);
+            ProcessAndEmitActor(hitTestResults, GetFeededGestureDetector());
           }
           else
           {
@@ -199,7 +199,6 @@ void LongPressGestureProcessor::Process(Scene& scene, const LongPressGestureEven
 
       // Only send subsequent long press gesture signals if we processed the gesture when it started.
       // Check if actor is still touchable.
-
       Actor* currentGesturedActor = GetCurrentGesturedActor();
       if(currentGesturedActor)
       {
@@ -208,7 +207,10 @@ void LongPressGestureProcessor::Process(Scene& scene, const LongPressGestureEven
           // Ensure actor is still attached to the emitters, if it is not then remove the emitter.
           GestureDetectorContainer::iterator endIter = std::remove_if(mCurrentEmitters.begin(), mCurrentEmitters.end(), IsNotAttachedFunctor(currentGesturedActor));
           mCurrentEmitters.erase(endIter, mCurrentEmitters.end());
-
+          if(GetFeededGestureDetector())
+          {
+            mCurrentEmitters.push_back(GetFeededGestureDetector());
+          }
           if(!mCurrentEmitters.empty())
           {
             Vector2     actorCoords;
index b3d1437..0543748 100644 (file)
@@ -58,9 +58,8 @@ public: // To be called by GestureEventProcessor
    * This method is called whenever a long press gesture event occurs.
    * @param[in] scene The scene the long press gesture event occurs in.
    * @param[in] longPressEvent The event that has occurred.
-   * @param[in] actor The actor where the event occurred. If this is null, the actor is found through hittest.
    */
-  void Process(Scene& scene, const LongPressGestureEvent& longPressEvent, Actor* actor = nullptr) override;
+  void Process(Scene& scene, const LongPressGestureEvent& longPressEvent) override;
 
   /**
    * Adds a gesture detector to this gesture processor.
index 93aad44..85d10bb 100644 (file)
@@ -66,7 +66,6 @@ void LongPressGestureRecognizer::SendEvent(const Integration::TouchEvent& event)
   unsigned int                            pointCount(event.GetPointCount());
   Dali::Integration::PlatformAbstraction& platformAbstraction = ThreadLocalStorage::Get().GetPlatformAbstraction();
   GestureRecognizerPtr                    ptr(this); // To keep us from being destroyed during the life-time of this method
-
   switch(mState)
   {
     // CLEAR: Wait till one point touches the screen before starting timer.
@@ -241,14 +240,13 @@ void LongPressGestureRecognizer::EmitGesture(GestureState state)
     }
     longPress.sourceType = mSourceType;
     longPress.sourceData = mSourceData;
-    longPress.renderTask = mRenderTask;
 
     if(mScene)
     {
       // Create another handle so the recognizer cannot be destroyed during process function
       GestureRecognizerPtr recognizerHandle = this;
 
-      mObserver.Process(*mScene, longPress, mActor.GetActor());
+      mObserver.Process(*mScene, longPress);
     }
   }
 }
index 3a471d3..8267a2b 100644 (file)
@@ -143,7 +143,7 @@ PanGestureProcessor::~PanGestureProcessor()
   mSceneObject = nullptr; // mSceneObject is owned and destroyed by update manager (there is only one of these for now)
 }
 
-void PanGestureProcessor::Process(Scene& scene, const PanGestureEvent& panEvent, Actor* actor)
+void PanGestureProcessor::Process(Scene& scene, const PanGestureEvent& panEvent)
 {
 #if defined(DEBUG_ENABLED)
   DALI_LOG_TRACE_METHOD(gLogFilter);
@@ -163,9 +163,9 @@ void PanGestureProcessor::Process(Scene& scene, const PanGestureEvent& panEvent,
       ResetActor();
 
       HitTestAlgorithm::Results hitTestResults;
-      if(actor)
+      if(GetFeededActor())
       {
-        SetActor(actor);
+        SetActor(GetFeededActor());
         mPossiblePanPosition = panEvent.currentPosition;
       }
       else if(HitTest(scene, panEvent.currentPosition, hitTestResults))
@@ -185,13 +185,13 @@ void PanGestureProcessor::Process(Scene& scene, const PanGestureEvent& panEvent,
       // it can be told when the gesture ends as well.
 
       HitTestAlgorithm::Results hitTestResults;
-      if(actor)
+      if(GetFeededActor())
       {
-        hitTestResults.actor = Dali::Actor(actor);
-        hitTestResults.renderTask = panEvent.renderTask;
+        hitTestResults.actor = Dali::Actor(GetFeededActor());
+        hitTestResults.renderTask = GetFeededRenderTask();
 
         Vector2 actorCoords;
-        actor->ScreenToLocal(*hitTestResults.renderTask.Get(), actorCoords.x, actorCoords.y, panEvent.currentPosition.x, panEvent.currentPosition.y);
+        GetFeededActor()->ScreenToLocal(*hitTestResults.renderTask.Get(), actorCoords.x, actorCoords.y, panEvent.currentPosition.x, panEvent.currentPosition.y);
         hitTestResults.actorCoordinates = actorCoords;
       }
       else
@@ -213,9 +213,9 @@ void PanGestureProcessor::Process(Scene& scene, const PanGestureEvent& panEvent,
 
         // Set mCurrentPanEvent to use inside overridden methods called in ProcessAndEmit()
         mCurrentPanEvent = &panEvent;
-        if(actor)
+        if(GetFeededActor())
         {
-          ProcessAndEmitActor(hitTestResults);
+          ProcessAndEmitActor(hitTestResults, GetFeededGestureDetector());
         }
         else
         {
@@ -235,7 +235,32 @@ void PanGestureProcessor::Process(Scene& scene, const PanGestureEvent& panEvent,
     {
       // Requires a core update
       mNeedsUpdate = true;
+      Actor* currentGesturedActor = GetCurrentGesturedActor();
+      if(GetFeededActor() && GetFeededActor() != currentGesturedActor && (mCurrentPanEmitters.empty() || (currentGesturedActor && currentGesturedActor->NeedGesturePropagation())) && GetFeededGestureDetector())
+      {
+        if(currentGesturedActor)
+        {
+          currentGesturedActor->SetNeedGesturePropagation(false);
+        }
+        mCurrentPanEvent = &panEvent;
+        if(GetFeededActor()->IsHittable() && CheckGestureDetector(GetFeededGestureDetector(), GetFeededActor()))
+        {
+          mCurrentPanEmitters.clear();
+          ResetActor();
 
+          // Record the current render-task for Screen->Actor coordinate conversions
+          mCurrentRenderTask = GetFeededRenderTask();
+
+          Vector2 actorCoords;
+          GetFeededActor()->ScreenToLocal(*mCurrentRenderTask.Get(), actorCoords.x, actorCoords.y, panEvent.currentPosition.x, panEvent.currentPosition.y);
+
+          mCurrentPanEmitters.push_back(GetFeededGestureDetector());
+          SetActor(GetFeededActor());
+          GetFeededGestureDetector()->SetDetected(true);
+          EmitPanSignal(GetFeededActor(), mCurrentPanEmitters, panEvent, actorCoords, GestureState::STARTED, mCurrentRenderTask);
+        }
+        mCurrentPanEvent = nullptr;
+      }
       DALI_FALLTHROUGH;
     }
 
@@ -244,7 +269,6 @@ void PanGestureProcessor::Process(Scene& scene, const PanGestureEvent& panEvent,
     {
       // Only send subsequent pan gesture signals if we processed the pan gesture when it started.
       // Check if actor is still touchable.
-
       Actor* currentGesturedActor = GetCurrentGesturedActor();
       if(currentGesturedActor)
       {
@@ -252,17 +276,18 @@ void PanGestureProcessor::Process(Scene& scene, const PanGestureEvent& panEvent,
         {
           GestureDetectorContainer outsideTouchesRangeEmitters;
 
-          // Removes emitters that no longer have the actor attached
-          // Also remove emitters whose touches are outside the range of the current pan event and add them to outsideTouchesRangeEmitters
-          GestureDetectorContainer::iterator endIter = std::remove_if(mCurrentPanEmitters.begin(), mCurrentPanEmitters.end(), IsNotAttachedAndOutsideTouchesRangeFunctor(currentGesturedActor, panEvent.numberOfTouches, outsideTouchesRangeEmitters));
-          mCurrentPanEmitters.erase(endIter, mCurrentPanEmitters.end());
+          if(!(GetFeededActor() && GetFeededGestureDetector()))
+          {
+            // Removes emitters that no longer have the actor attached
+            // Also remove emitters whose touches are outside the range of the current pan event and add them to outsideTouchesRangeEmitters
+            GestureDetectorContainer::iterator endIter = std::remove_if(mCurrentPanEmitters.begin(), mCurrentPanEmitters.end(), IsNotAttachedAndOutsideTouchesRangeFunctor(currentGesturedActor, panEvent.numberOfTouches, outsideTouchesRangeEmitters));
+            mCurrentPanEmitters.erase(endIter, mCurrentPanEmitters.end());
+          }
 
           Vector2 actorCoords;
-
           if(!outsideTouchesRangeEmitters.empty() || !mCurrentPanEmitters.empty())
           {
             currentGesturedActor->ScreenToLocal(*mCurrentRenderTask.Get(), actorCoords.x, actorCoords.y, panEvent.currentPosition.x, panEvent.currentPosition.y);
-
             // EmitPanSignal checks whether we have a valid actor and whether the container we are passing in has emitters before it emits the pan.
             EmitPanSignal(currentGesturedActor, outsideTouchesRangeEmitters, panEvent, actorCoords, GestureState::FINISHED, mCurrentRenderTask);
             EmitPanSignal(currentGesturedActor, mCurrentPanEmitters, panEvent, actorCoords, panEvent.state, mCurrentRenderTask);
index 4209c24..bfeb623 100644 (file)
@@ -67,9 +67,8 @@ public: // To be called by GestureEventProcessor
    * This method is called whenever a pan gesture event occurs.
    * @param[in] scene The scene the pan gesture event occurs in.
    * @param[in] panEvent The event that has occurred.
-   * @param[in] actor The actor where the event occurred. If this is null, the actor is found through hittest.
    */
-  void Process(Scene& scene, const PanGestureEvent& panEvent, Actor* actor = nullptr) override;
+  void Process(Scene& scene, const PanGestureEvent& panEvent) override;
 
   /**
    * Adds a gesture detector to this gesture processor.
index 4e7af02..4e6ad9e 100644 (file)
@@ -335,14 +335,13 @@ void PanGestureRecognizer::SendPan(GestureState state, const Integration::TouchE
   gesture.time       = currentEvent.time;
   gesture.sourceType = mSourceType;
   gesture.sourceData = mSourceData;
-  gesture.renderTask = mRenderTask;
 
   if(mScene)
   {
     // Create another handle so the recognizer cannot be destroyed during process function
     GestureRecognizerPtr recognizerHandle = this;
 
-    mObserver.Process(*mScene, gesture, mActor.GetActor());
+    mObserver.Process(*mScene, gesture);
   }
 }
 
index 7f25011..6018eb5 100644 (file)
@@ -175,7 +175,7 @@ void PinchGestureProcessor::SetMinimumTouchEventsAfterStart(uint32_t value)
   }
 }
 
-void PinchGestureProcessor::Process(Scene& scene, const PinchGestureEvent& pinchEvent, Actor* actor)
+void PinchGestureProcessor::Process(Scene& scene, const PinchGestureEvent& pinchEvent)
 {
   DALI_TRACE_SCOPE(gTraceFilter, "DALI_PROCESS_PINCH_GESTURE");
   switch(pinchEvent.state)
@@ -189,21 +189,21 @@ void PinchGestureProcessor::Process(Scene& scene, const PinchGestureEvent& pinch
       ResetActor();
 
       HitTestAlgorithm::Results hitTestResults;
-      if(actor)
+      if(GetFeededActor())
       {
-        hitTestResults.actor = Dali::Actor(actor);
-        hitTestResults.renderTask = pinchEvent.renderTask;
+        hitTestResults.actor = Dali::Actor(GetFeededActor());
+        hitTestResults.renderTask = GetFeededRenderTask();
 
         // Record the current render-task for Screen->Actor coordinate conversions
         mCurrentRenderTask = hitTestResults.renderTask;
 
         Vector2     actorCoords;
-        actor->ScreenToLocal(*mCurrentRenderTask.Get(), actorCoords.x, actorCoords.y, pinchEvent.centerPoint.x, pinchEvent.centerPoint.y);
+        GetFeededActor()->ScreenToLocal(*mCurrentRenderTask.Get(), actorCoords.x, actorCoords.y, pinchEvent.centerPoint.x, pinchEvent.centerPoint.y);
         hitTestResults.actorCoordinates = actorCoords;
 
         // Set mCurrentPinchEvent to use inside overridden methods called from ProcessAndEmit()
         mCurrentPinchEvent = &pinchEvent;
-        ProcessAndEmitActor(hitTestResults);
+        ProcessAndEmitActor(hitTestResults, GetFeededGestureDetector());
         mCurrentPinchEvent = nullptr;
       }
       else if(HitTest(scene, pinchEvent.centerPoint, hitTestResults))
@@ -234,6 +234,10 @@ void PinchGestureProcessor::Process(Scene& scene, const PinchGestureEvent& pinch
           // Ensure actor is still attached to the emitters, if it is not then remove the emitter.
           GestureDetectorContainer::iterator endIter = std::remove_if(mCurrentPinchEmitters.begin(), mCurrentPinchEmitters.end(), IsNotAttachedFunctor(currentGesturedActor));
           mCurrentPinchEmitters.erase(endIter, mCurrentPinchEmitters.end());
+          if(GetFeededActor() && GetFeededGestureDetector())
+          {
+            mCurrentPinchEmitters.push_back(GetFeededGestureDetector());
+          }
 
           if(!mCurrentPinchEmitters.empty())
           {
index e5f71d7..9d7acf0 100644 (file)
@@ -78,9 +78,8 @@ public: // To be called by GestureEventProcessor
    * This method is called whenever a pinch gesture event occurs.
    * @param[in] scene The scene the pinch gesture event occurs in.
    * @param[in] pinchEvent The event that has occurred.
-   * @param[in] actor The actor where the event occurred. If this is null, the actor is found through hittest.
    */
-  void Process(Scene& scene, const PinchGestureEvent& pinchEvent, Actor* actor = nullptr) override;
+  void Process(Scene& scene, const PinchGestureEvent& pinchEvent) override;
 
   /**
    * Adds a gesture detector to this gesture processor.
index 49df4ae..9ab75a2 100644 (file)
@@ -262,14 +262,13 @@ void PinchGestureRecognizer::SendPinch(GestureState state, const Integration::To
   gesture.time       = currentEvent.time;
   gesture.sourceType = mSourceType;
   gesture.sourceData = mSourceData;
-  gesture.renderTask = mRenderTask;
 
   if(mScene)
   {
     // Create another handle so the recognizer cannot be destroyed during process function
     GestureRecognizerPtr recognizerHandle = this;
 
-    mObserver.Process(*mScene, gesture, mActor.GetActor());
+    mObserver.Process(*mScene, gesture);
   }
 }
 
index 111e7c1..7f4eaf1 100644 (file)
@@ -121,7 +121,7 @@ RotationGestureProcessor::RotationGestureProcessor()
 {
 }
 
-void RotationGestureProcessor::Process(Scene& scene, const RotationGestureEvent& rotationEvent, Actor* actor)
+void RotationGestureProcessor::Process(Scene& scene, const RotationGestureEvent& rotationEvent)
 {
   DALI_TRACE_SCOPE(gTraceFilter, "DALI_PROCESS_ROTATION_GESTURE");
   switch(rotationEvent.state)
@@ -135,21 +135,21 @@ void RotationGestureProcessor::Process(Scene& scene, const RotationGestureEvent&
       ResetActor();
 
       HitTestAlgorithm::Results hitTestResults;
-      if(actor)
+      if(GetFeededActor())
       {
-        hitTestResults.actor = Dali::Actor(actor);
-        hitTestResults.renderTask = rotationEvent.renderTask;
+        hitTestResults.actor = Dali::Actor(GetFeededActor());
+        hitTestResults.renderTask = GetFeededRenderTask();
 
         // Record the current render-task for Screen->Actor coordinate conversions
         mCurrentRenderTask = hitTestResults.renderTask;
 
         Vector2     actorCoords;
-        actor->ScreenToLocal(*mCurrentRenderTask.Get(), actorCoords.x, actorCoords.y, rotationEvent.centerPoint.x, rotationEvent.centerPoint.y);
+        GetFeededActor()->ScreenToLocal(*mCurrentRenderTask.Get(), actorCoords.x, actorCoords.y, rotationEvent.centerPoint.x, rotationEvent.centerPoint.y);
         hitTestResults.actorCoordinates = actorCoords;
 
         // Set mCurrentRotationEvent to use inside overridden methods called from ProcessAndEmit()
         mCurrentRotationEvent = &rotationEvent;
-        ProcessAndEmitActor(hitTestResults);
+        ProcessAndEmitActor(hitTestResults, GetFeededGestureDetector());
         mCurrentRotationEvent = nullptr;
 
       }
@@ -182,6 +182,11 @@ void RotationGestureProcessor::Process(Scene& scene, const RotationGestureEvent&
           GestureDetectorContainer::iterator endIter = std::remove_if(mCurrentRotationEmitters.begin(), mCurrentRotationEmitters.end(), IsNotAttachedFunctor(currentGesturedActor));
           mCurrentRotationEmitters.erase(endIter, mCurrentRotationEmitters.end());
 
+          if(GetFeededActor() && GetFeededGestureDetector())
+          {
+            mCurrentRotationEmitters.push_back(GetFeededGestureDetector());
+          }
+
           if(!mCurrentRotationEmitters.empty())
           {
             Vector2     actorCoords;
index b1d1fa7..f1459bc 100644 (file)
@@ -63,9 +63,8 @@ public: // To be called by GestureEventProcessor
    * This method is called whenever a rotation gesture event occurs.
    * @param[in] scene The scene the rotation gesture event occurs in.
    * @param[in] rotationEvent The event that has occurred.
-   * @param[in] actor The actor where the event occurred. If this is null, the actor is found through hittest.
    */
-  void Process(Scene& scene, const RotationGestureEvent& rotationEvent, Actor* actor = nullptr) override;
+  void Process(Scene& scene, const RotationGestureEvent& rotationEvent) override;
 
   /**
    * Adds a gesture detector to this gesture processor.
index 37aa79a..dc10844 100644 (file)
@@ -224,14 +224,13 @@ void RotationGestureRecognizer::SendRotation(GestureState state, const Integrati
   gesture.time       = currentEvent.time;
   gesture.sourceType = mSourceType;
   gesture.sourceData = mSourceData;
-  gesture.renderTask = mRenderTask;
 
   if(mScene)
   {
     // Create another handle so the recognizer cannot be destroyed during process function
     GestureRecognizerPtr recognizerHandle = this;
 
-    mObserver.Process(*mScene, gesture, mActor.GetActor());
+    mObserver.Process(*mScene, gesture);
   }
 }
 
index 0f1418a..89c34d5 100644 (file)
@@ -100,7 +100,7 @@ TapGestureProcessor::TapGestureProcessor()
 
 TapGestureProcessor::~TapGestureProcessor() = default;
 
-void TapGestureProcessor::Process(Scene& scene, const TapGestureEvent& tapEvent, Actor* actor)
+void TapGestureProcessor::Process(Scene& scene, const TapGestureEvent& tapEvent)
 {
   DALI_TRACE_SCOPE(gTraceFilter, "DALI_PROCESS_TAP_GESTURE");
   switch(tapEvent.state)
@@ -109,9 +109,9 @@ void TapGestureProcessor::Process(Scene& scene, const TapGestureEvent& tapEvent,
     {
       // Do a hit test and if an actor has been hit then save to see if tap event is still valid on a tap( same actor being hit )
       HitTestAlgorithm::Results hitTestResults;
-      if(actor)
+      if(GetFeededActor())
       {
-        SetActor(actor);
+        SetActor(GetFeededActor());
         mCurrentTapActor.SetActor(GetCurrentGesturedActor());
 
         // Indicate that we've processed a touch down. Bool should be sufficient as a change in actor will result in a cancellation
@@ -138,15 +138,15 @@ void TapGestureProcessor::Process(Scene& scene, const TapGestureEvent& tapEvent,
       HitTestAlgorithm::Results hitTestResults;
       if(GetCurrentGesturedActor())
       {
-        if(actor)
+        if(GetFeededActor())
         {
-          hitTestResults.actor = Dali::Actor(actor);
-          hitTestResults.renderTask = tapEvent.renderTask;
+          hitTestResults.actor = Dali::Actor(GetFeededActor());
+          hitTestResults.renderTask = GetFeededRenderTask();
           // Check that this actor is still the one that was used for the last touch down ?
           if(mCurrentTapActor.GetActor() == &GetImplementation(hitTestResults.actor))
           {
             mCurrentTapEvent = &tapEvent;
-            ProcessAndEmitActor(hitTestResults);
+            ProcessAndEmitActor(hitTestResults, GetFeededGestureDetector());
           }
           mCurrentTapEvent   = nullptr;
           mPossibleProcessed = false;
index b5f8a27..6b1ab28 100644 (file)
@@ -59,9 +59,8 @@ public: // To be called by GestureEventProcessor
    * This method is called whenever a tap gesture event occurs.
    * @param[in] scene The scene the tap gesture event occurs in.
    * @param[in] tapEvent The event that has occurred.
-   * @param[in] actor The actor where the event occurred. If this is null, the actor is found through hittest.
    */
-  void Process(Scene& scene, const TapGestureEvent& event, Actor* actor = nullptr) override;
+  void Process(Scene& scene, const TapGestureEvent& event) override;
 
   /**
    * Adds a gesture detector to this gesture processor.
index b59ccb2..cfa5d72 100644 (file)
@@ -219,12 +219,11 @@ void TapGestureRecognizer::ProcessEvent(TapGestureEvent& event)
 {
   event.sourceType = mSourceType;
   event.sourceData = mSourceData;
-  event.renderTask = mRenderTask;
   if(mScene)
   {
     // Create another handle so the recognizer cannot be destroyed during process function
     GestureRecognizerPtr recognizerHandle = this;
-    mObserver.Process(*mScene, event, mActor.GetActor());
+    mObserver.Process(*mScene, event);
   }
 }
 
index 5df9c31..5b27902 100644 (file)
@@ -132,11 +132,6 @@ Dali::Actor EmitGeoInterceptTouchSignals(std::list<Dali::Internal::Actor*>& acto
   Dali::Actor interceptedActor;
   for(auto&& actor : actorLists)
   {
-    // If there is a consumed actor, the intercept is sent only up to the moment before the consumed actor.
-    if(lastConsumedActor.GetActor() == actor)
-    {
-      break;
-    }
     interceptActorList.push_back(actor);
     if(ShouldEmitInterceptTouchEvent(*actor, touchEvent))
     {
@@ -147,6 +142,11 @@ Dali::Actor EmitGeoInterceptTouchSignals(std::list<Dali::Internal::Actor*>& acto
         break;
       }
     }
+    // If there is a consumed actor, the intercept is sent only up to the moment before the consumed actor.
+    if(lastConsumedActor.GetActor() == actor)
+    {
+      break;
+    }
   }
   return interceptedActor;
 }
@@ -501,6 +501,17 @@ struct TouchEventProcessor::Impl
           {
             // Let's propagate touch events from the intercepted actor or start propagating touch events from the leaf actor.
             localVars.consumedActor = EmitGeoTouchSignals(interceptedActor ? processor.mInterceptedActorLists : processor.mCandidateActorLists, localVars.touchEventHandle);
+
+            // If consumed, the actors who previously received the touch are interrupted, indicating that the touch has been consumed by another actor.
+            if(localVars.consumedActor && localVars.primaryPointState != PointState::DOWN)
+            {
+              std::list<Dali::Internal::Actor*>::reverse_iterator rIter = std::find(processor.mCandidateActorLists.rbegin(), processor.mCandidateActorLists.rend(), localVars.consumedActor);
+              for(++rIter; rIter != processor.mCandidateActorLists.rend(); ++rIter)
+              {
+                Actor* actorImpl(*rIter);
+                EmitTouchSignals(actorImpl, *processor.mLastRenderTask.Get(), localVars.touchEventImpl, PointState::INTERRUPTED, localVars.isGeometry);
+              }
+            }
           }
         }
       }