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
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;
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
GestureDetector::GestureDetector(GestureType::Value type, const SceneGraph::PropertyOwner* sceneObject)
: Object(sceneObject),
mType(type),
- mGestureEventProcessor(ThreadLocalStorage::Get().GetGestureEventProcessor())
+ mGestureEventProcessor(ThreadLocalStorage::Get().GetGestureEventProcessor()),
+ mIsDetected(false)
{
}
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());
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()) ||
*/
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.
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
mRotationGestureProcessor(),
mRenderController(renderController),
envOptionMinimumPanDistance(-1),
- envOptionMinimumPanEvents(-1)
+ envOptionMinimumPanEvents(-1),
+ mIsProcessingFeedTouch(false)
{
}
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;
}
}
int32_t envOptionMinimumPanDistance;
int32_t envOptionMinimumPanEvents;
+ bool mIsProcessingFeedTouch; // Whether the gesture is being recognized via FeedTouch in gestureDetector
};
} // namespace Internal
*/
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.
mCurrentGesturedActor(nullptr),
mPoint(),
mEventTime(0u),
- mGesturedActorDisconnected(false)
+ mGesturedActorDisconnected(false),
+ mFeededActor(nullptr),
+ mRenderTask(),
+ mGestureDetector(nullptr)
{
}
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)
{
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)
}
}
-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);
}
}
/**
* 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
// 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.
* 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.
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
#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
{
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;
;
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.
mType(detectorType),
mScene(nullptr),
mSourceType(GestureSourceType::INVALID),
- mSourceData(GestureSourceData::INVALID),
- mActor(),
- mRenderTask()
+ mSourceData(GestureSourceData::INVALID)
{
}
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>;
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)
ResetActor();
HitTestAlgorithm::Results hitTestResults;
- if(actor)
+ if(GetFeededActor())
{
- SetActor(actor);
+ SetActor(GetFeededActor());
}
else if(HitTest(scene, longPressEvent.point, hitTestResults))
{
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);
// Set mCurrentLongPressEvent to use inside overridden methods called from ProcessAndEmit()
mCurrentLongPressEvent = &longPressEvent;
- if(actor)
+ if(GetFeededActor())
{
- ProcessAndEmitActor(hitTestResults);
+ ProcessAndEmitActor(hitTestResults, GetFeededGestureDetector());
}
else
{
// 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)
{
// 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;
* 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.
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.
}
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);
}
}
}
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);
ResetActor();
HitTestAlgorithm::Results hitTestResults;
- if(actor)
+ if(GetFeededActor())
{
- SetActor(actor);
+ SetActor(GetFeededActor());
mPossiblePanPosition = panEvent.currentPosition;
}
else if(HitTest(scene, panEvent.currentPosition, hitTestResults))
// 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
// Set mCurrentPanEvent to use inside overridden methods called in ProcessAndEmit()
mCurrentPanEvent = &panEvent;
- if(actor)
+ if(GetFeededActor())
{
- ProcessAndEmitActor(hitTestResults);
+ ProcessAndEmitActor(hitTestResults, GetFeededGestureDetector());
}
else
{
{
// 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;
}
{
// 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)
{
{
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);
* 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.
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);
}
}
}
}
-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)
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))
// 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())
{
* 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.
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);
}
}
{
}
-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)
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;
}
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;
* 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.
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);
}
}
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)
{
// 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
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;
* 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.
{
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);
}
}
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))
{
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;
}
{
// 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);
+ }
+ }
}
}
}