This is a method of recognizing gestures by feeding a touch event to a specific actor.
This causes the actor to recognize the gesture without going through a hittest.
So, you can recognize gestures based on touchEvent as shown below.
mTapDetector = TapGestureDetector::New();
mTapDetector.DetectedSignal().Connect(this, &HelloWorldController::OnTap);
control.TouchedSignal().Connect(this, &HelloWorldController::OnTouch);
bool OnTouch(Actor actor, const TouchEvent& touch)
{
mTapDetector.FeedTouch(actor, touch);
return true;
}
This is the beginning of a new gesture recognition method.
Change-Id: Iecf0eab7a82e54a981f69d2e309675afcfa439f1
#include <dali/devel-api/actors/actor-devel.h>
#include <dali/devel-api/events/long-press-gesture-detector-devel.h>
#include <dali/integration-api/events/touch-event-integ.h>
+#include <dali/integration-api/events/touch-integ.h>
#include <dali/integration-api/input-options.h>
#include <dali/integration-api/render-task-list-integ.h>
+#include <dali/internal/event/events/touch-event-impl.h>
+#include <dali/internal/event/render-tasks/render-task-impl.h>
#include <dali/public-api/dali-core.h>
#include <stdlib.h>
#include <test-touch-event-utils.h>
}
};
+Integration::TouchEvent GenerateSingleTouch(PointState::Type state, const Vector2& screenPosition, uint32_t time)
+{
+ Integration::TouchEvent touchEvent;
+ Integration::Point point;
+ point.SetState(state);
+ point.SetDeviceId(4);
+ point.SetScreenPosition(screenPosition);
+ point.SetDeviceClass(Device::Class::TOUCH);
+ point.SetDeviceSubclass(Device::Subclass::NONE);
+ touchEvent.points.push_back(point);
+ touchEvent.time = time;
+ return touchEvent;
+}
} // namespace
///////////////////////////////////////////////////////////////////////////////
END_TEST;
}
+
+int UtcDaliLongPressGestureFeedTouch(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);
+
+ LongPressGestureDetector parentDetector = LongPressGestureDetector::New();
+ parentDetector.DetectedSignal().Connect(&application, pFunctor);
+
+ 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());
+ parentDetector.FeedTouch(parentActor, touchEventHandle);
+
+ TestTriggerLongPress(application);
+
+ tp = GenerateSingleTouch(PointState::UP, Vector2(50.0f, 50.0f), 150);
+ touchEventImpl = new Internal::TouchEvent(150);
+ touchEventImpl->AddPoint(tp.GetPoint(0));
+ touchEventImpl->SetRenderTask(task);
+ touchEventHandle = Dali::TouchEvent(touchEventImpl.Get());
+ parentDetector.FeedTouch(parentActor, touchEventHandle);
+
+ DALI_TEST_EQUALS(true, pData.functorCalled, TEST_LOCATION);
+ pData.Reset();
+
+ END_TEST;
+}
#include <dali/devel-api/actors/actor-devel.h>
#include <dali/devel-api/events/pan-gesture-devel.h>
#include <dali/integration-api/events/touch-event-integ.h>
+#include <dali/integration-api/events/touch-integ.h>
#include <dali/integration-api/input-options.h>
#include <dali/integration-api/profiling.h>
#include <dali/integration-api/render-task-list-integ.h>
+#include <dali/internal/event/events/touch-event-impl.h>
+#include <dali/internal/event/render-tasks/render-task-impl.h>
#include <dali/public-api/dali-core.h>
#include <stdlib.h>
#include <test-touch-event-utils.h>
return pan;
}
+Integration::TouchEvent GenerateSingleTouch(PointState::Type state, const Vector2& screenPosition, uint32_t time)
+{
+ Integration::TouchEvent touchEvent;
+ Integration::Point point;
+ point.SetState(state);
+ point.SetDeviceId(4);
+ point.SetScreenPosition(screenPosition);
+ point.SetDeviceClass(Device::Class::TOUCH);
+ point.SetDeviceSubclass(Device::Subclass::NONE);
+ touchEvent.points.push_back(point);
+ touchEvent.time = time;
+ return touchEvent;
+}
} // namespace
///////////////////////////////////////////////////////////////////////////////
END_TEST;
}
+
+int UtcDaliPanGestureFeedTouch(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);
+
+
+ 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());
+ parentDetector.FeedTouch(parentActor, touchEventHandle);
+
+
+ tp = GenerateSingleTouch(PointState::MOTION, Vector2(70.0f, 70.0f), 150);
+ touchEventImpl = new Internal::TouchEvent(150);
+ touchEventImpl->AddPoint(tp.GetPoint(0));
+ touchEventImpl->SetRenderTask(task);
+ touchEventHandle = Dali::TouchEvent(touchEventImpl.Get());
+ parentDetector.FeedTouch(parentActor, touchEventHandle);
+
+
+ tp = GenerateSingleTouch(PointState::MOTION, Vector2(90.0f, 90.0f), 200);
+ touchEventImpl = new Internal::TouchEvent(200);
+ touchEventImpl->AddPoint(tp.GetPoint(0));
+ touchEventImpl->SetRenderTask(task);
+ touchEventHandle = Dali::TouchEvent(touchEventImpl.Get());
+ parentDetector.FeedTouch(parentActor, touchEventHandle);
+
+ tp = GenerateSingleTouch(PointState::UP, Vector2(100.0f, 100.0f), 250);
+ touchEventImpl = new Internal::TouchEvent(250);
+ touchEventImpl->AddPoint(tp.GetPoint(0));
+ touchEventImpl->SetRenderTask(task);
+ touchEventHandle = Dali::TouchEvent(touchEventImpl.Get());
+ parentDetector.FeedTouch(parentActor, touchEventHandle);
+
+
+ DALI_TEST_EQUALS(true, pData.functorCalled, TEST_LOCATION);
+ pData.Reset();
+
+ END_TEST;
+}
#include <dali-test-suite-utils.h>
#include <dali/devel-api/actors/actor-devel.h>
#include <dali/integration-api/events/touch-event-integ.h>
+#include <dali/integration-api/events/touch-integ.h>
#include <dali/integration-api/render-task-list-integ.h>
+#include <dali/internal/event/events/touch-event-impl.h>
+#include <dali/internal/event/render-tasks/render-task-impl.h>
#include <dali/public-api/dali-core.h>
#include <stdlib.h>
#include <test-touch-event-utils.h>
Integration::Scene scene;
};
+
+Integration::TouchEvent GenerateDoubleTouch(PointState::Type stateA, const Vector2& screenPositionA, PointState::Type stateB, const Vector2& screenPositionB, uint32_t time)
+{
+ Integration::TouchEvent touchEvent;
+ Integration::Point point;
+ point.SetState(stateA);
+ point.SetScreenPosition(screenPositionA);
+ point.SetDeviceClass(Device::Class::TOUCH);
+ point.SetDeviceSubclass(Device::Subclass::NONE);
+ touchEvent.points.push_back(point);
+ point.SetScreenPosition(screenPositionB);
+ point.SetState(stateB);
+ touchEvent.points.push_back(point);
+ touchEvent.time = time;
+ return touchEvent;
+}
+
} // namespace
///////////////////////////////////////////////////////////////////////////////
pData.Reset();
END_TEST;
-}
\ No newline at end of file
+}
+
+int UtcDaliPinchGestureFeedTouch(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);
+
+ PinchGestureDetector parentDetector = PinchGestureDetector::New();
+ parentDetector.DetectedSignal().Connect(&application, pFunctor);
+
+ Integration::TouchEvent tp = GenerateDoubleTouch(PointState::DOWN, Vector2(2.0f, 20.0f), PointState::DOWN, Vector2(38.0f, 20.0f), 100);
+ Internal::TouchEventPtr touchEventImpl(new Internal::TouchEvent(100));
+ touchEventImpl->AddPoint(tp.GetPoint(0));
+ touchEventImpl->AddPoint(tp.GetPoint(1));
+ touchEventImpl->SetRenderTask(task);
+ Dali::TouchEvent touchEventHandle(touchEventImpl.Get());
+ parentDetector.FeedTouch(parentActor, touchEventHandle);
+
+ tp = GenerateDoubleTouch(PointState::MOTION, Vector2(10.0f, 20.0f), PointState::MOTION, Vector2(30.0f, 20.0f), 150);
+ touchEventImpl = new Internal::TouchEvent(150);
+ touchEventImpl->AddPoint(tp.GetPoint(0));
+ touchEventImpl->AddPoint(tp.GetPoint(1));
+ touchEventImpl->SetRenderTask(task);
+ touchEventHandle = Dali::TouchEvent(touchEventImpl.Get());
+ parentDetector.FeedTouch(parentActor, touchEventHandle);
+
+ tp = GenerateDoubleTouch(PointState::MOTION, Vector2(10.0f, 20.0f), PointState::MOTION, Vector2(30.0f, 20.0f), 200);
+ touchEventImpl = new Internal::TouchEvent(200);
+ touchEventImpl->AddPoint(tp.GetPoint(0));
+ touchEventImpl->AddPoint(tp.GetPoint(1));
+ touchEventImpl->SetRenderTask(task);
+ touchEventHandle = Dali::TouchEvent(touchEventImpl.Get());
+ parentDetector.FeedTouch(parentActor, touchEventHandle);
+
+ tp = GenerateDoubleTouch(PointState::MOTION, Vector2(10.0f, 20.0f), PointState::MOTION, Vector2(30.0f, 20.0f), 250);
+ touchEventImpl = new Internal::TouchEvent(250);
+ touchEventImpl->AddPoint(tp.GetPoint(0));
+ touchEventImpl->AddPoint(tp.GetPoint(1));
+ touchEventImpl->SetRenderTask(task);
+ touchEventHandle = Dali::TouchEvent(touchEventImpl.Get());
+ parentDetector.FeedTouch(parentActor, touchEventHandle);
+
+ tp = GenerateDoubleTouch(PointState::MOTION, Vector2(10.0f, 20.0f), PointState::MOTION, Vector2(30.0f, 20.0f), 300);
+ touchEventImpl = new Internal::TouchEvent(300);
+ touchEventImpl->AddPoint(tp.GetPoint(0));
+ touchEventImpl->AddPoint(tp.GetPoint(1));
+ touchEventImpl->SetRenderTask(task);
+ touchEventHandle = Dali::TouchEvent(touchEventImpl.Get());
+ parentDetector.FeedTouch(parentActor, touchEventHandle);
+
+ tp = GenerateDoubleTouch(PointState::UP, Vector2(10.0f, 20.0f), PointState::UP, Vector2(30.0f, 20.0f), 350);
+ touchEventImpl = new Internal::TouchEvent(350);
+ touchEventImpl->AddPoint(tp.GetPoint(0));
+ touchEventImpl->AddPoint(tp.GetPoint(1));
+ touchEventImpl->SetRenderTask(task);
+ touchEventHandle = Dali::TouchEvent(touchEventImpl.Get());
+ parentDetector.FeedTouch(parentActor, touchEventHandle);
+
+
+ DALI_TEST_EQUALS(true, pData.functorCalled, TEST_LOCATION);
+ pData.Reset();
+
+ END_TEST;
+}
#include <dali-test-suite-utils.h>
#include <dali/devel-api/actors/actor-devel.h>
#include <dali/integration-api/events/touch-event-integ.h>
+#include <dali/integration-api/events/touch-integ.h>
#include <dali/integration-api/render-task-list-integ.h>
+#include <dali/internal/event/events/touch-event-impl.h>
+#include <dali/internal/event/render-tasks/render-task-impl.h>
#include <dali/public-api/dali-core.h>
#include <stdlib.h>
#include <test-touch-event-utils.h>
Integration::Scene scene;
};
+Integration::TouchEvent GenerateDoubleTouch(PointState::Type stateA, const Vector2& screenPositionA, PointState::Type stateB, const Vector2& screenPositionB, uint32_t time)
+{
+ Integration::TouchEvent touchEvent;
+ Integration::Point point;
+ point.SetState(stateA);
+ point.SetScreenPosition(screenPositionA);
+ point.SetDeviceClass(Device::Class::TOUCH);
+ point.SetDeviceSubclass(Device::Subclass::NONE);
+ touchEvent.points.push_back(point);
+ point.SetScreenPosition(screenPositionB);
+ point.SetState(stateB);
+ touchEvent.points.push_back(point);
+ touchEvent.time = time;
+ return touchEvent;
+}
} // namespace
///////////////////////////////////////////////////////////////////////////////
pData.Reset();
END_TEST;
-}
\ No newline at end of file
+}
+
+
+int UtcDaliRotationGestureFeedTouch(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);
+
+ RotationGestureDetector parentDetector = RotationGestureDetector::New();
+ parentDetector.DetectedSignal().Connect(&application, pFunctor);
+
+ Integration::TouchEvent tp = GenerateDoubleTouch(PointState::DOWN, Vector2(2.0f, 20.0f), PointState::DOWN, Vector2(38.0f, 20.0f), 100);
+ Internal::TouchEventPtr touchEventImpl(new Internal::TouchEvent(100));
+ touchEventImpl->AddPoint(tp.GetPoint(0));
+ touchEventImpl->AddPoint(tp.GetPoint(1));
+ touchEventImpl->SetRenderTask(task);
+ Dali::TouchEvent touchEventHandle(touchEventImpl.Get());
+ parentDetector.FeedTouch(parentActor, touchEventHandle);
+
+ tp = GenerateDoubleTouch(PointState::MOTION, Vector2(10.0f, 20.0f), PointState::MOTION, Vector2(30.0f, 20.0f), 150);
+ touchEventImpl = new Internal::TouchEvent(150);
+ touchEventImpl->AddPoint(tp.GetPoint(0));
+ touchEventImpl->AddPoint(tp.GetPoint(1));
+ touchEventImpl->SetRenderTask(task);
+ touchEventHandle = Dali::TouchEvent(touchEventImpl.Get());
+ parentDetector.FeedTouch(parentActor, touchEventHandle);
+
+ tp = GenerateDoubleTouch(PointState::MOTION, Vector2(10.0f, 20.0f), PointState::MOTION, Vector2(30.0f, 20.0f), 200);
+ touchEventImpl = new Internal::TouchEvent(200);
+ touchEventImpl->AddPoint(tp.GetPoint(0));
+ touchEventImpl->AddPoint(tp.GetPoint(1));
+ touchEventImpl->SetRenderTask(task);
+ touchEventHandle = Dali::TouchEvent(touchEventImpl.Get());
+ parentDetector.FeedTouch(parentActor, touchEventHandle);
+
+ tp = GenerateDoubleTouch(PointState::MOTION, Vector2(10.0f, 20.0f), PointState::MOTION, Vector2(30.0f, 20.0f), 250);
+ touchEventImpl = new Internal::TouchEvent(250);
+ touchEventImpl->AddPoint(tp.GetPoint(0));
+ touchEventImpl->AddPoint(tp.GetPoint(1));
+ touchEventImpl->SetRenderTask(task);
+ touchEventHandle = Dali::TouchEvent(touchEventImpl.Get());
+ parentDetector.FeedTouch(parentActor, touchEventHandle);
+
+ tp = GenerateDoubleTouch(PointState::MOTION, Vector2(6.0f, 6.0f), PointState::MOTION, Vector2(18.0f, 18.0f), 300);
+ touchEventImpl = new Internal::TouchEvent(300);
+ touchEventImpl->AddPoint(tp.GetPoint(0));
+ touchEventImpl->AddPoint(tp.GetPoint(1));
+ touchEventImpl->SetRenderTask(task);
+ touchEventHandle = Dali::TouchEvent(touchEventImpl.Get());
+ parentDetector.FeedTouch(parentActor, touchEventHandle);
+
+ tp = GenerateDoubleTouch(PointState::UP, Vector2(10.0f, 8.0f), PointState::UP, Vector2(14.0f, 16.0f), 350);
+ touchEventImpl = new Internal::TouchEvent(350);
+ touchEventImpl->AddPoint(tp.GetPoint(0));
+ touchEventImpl->AddPoint(tp.GetPoint(1));
+ touchEventImpl->SetRenderTask(task);
+ touchEventHandle = Dali::TouchEvent(touchEventImpl.Get());
+ parentDetector.FeedTouch(parentActor, touchEventHandle);
+
+
+ DALI_TEST_EQUALS(true, pData.functorCalled, TEST_LOCATION);
+ pData.Reset();
+
+ END_TEST;
+}
#include <dali-test-suite-utils.h>
#include <dali/devel-api/actors/actor-devel.h>
#include <dali/integration-api/events/touch-event-integ.h>
+#include <dali/integration-api/events/touch-integ.h>
#include <dali/integration-api/render-task-list-integ.h>
+#include <dali/internal/event/events/touch-event-impl.h>
+#include <dali/internal/event/render-tasks/render-task-impl.h>
#include <dali/public-api/dali-core.h>
#include <stdlib.h>
#include <test-touch-event-utils.h>
END_TEST;
}
+
+int UtcDaliTapGestureFeedTouch(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);
+
+ TapGestureDetector parentDetector = TapGestureDetector::New();
+ parentDetector.DetectedSignal().Connect(&application, pFunctor);
+
+ Integration::TouchEvent tp = GenerateSingleTouch(PointState::DOWN, Vector2(50.0f, 50.0f), 1, 100);
+ Internal::TouchEventPtr touchEventImpl(new Internal::TouchEvent(100));
+ touchEventImpl->AddPoint(tp.GetPoint(0));
+ touchEventImpl->SetRenderTask(task);
+ Dali::TouchEvent touchEventHandle(touchEventImpl.Get());
+ parentDetector.FeedTouch(parentActor, touchEventHandle);
+
+ tp = GenerateSingleTouch(PointState::UP, Vector2(50.0f, 50.0f), 1, 150);
+ touchEventImpl = new Internal::TouchEvent(150);
+ touchEventImpl->AddPoint(tp.GetPoint(0));
+ touchEventImpl->SetRenderTask(task);
+ touchEventHandle = Dali::TouchEvent(touchEventImpl.Get());
+ parentDetector.FeedTouch(parentActor, touchEventHandle);
+
+ DALI_TEST_EQUALS(true, pData.functorCalled, TEST_LOCATION);
+ pData.Reset();
+
+ END_TEST;
+}
#include <dali/internal/event/common/thread-local-storage.h>
#include <dali/internal/event/events/actor-gesture-data.h>
#include <dali/internal/event/events/gesture-event-processor.h>
+#include <dali/internal/event/events/touch-event-impl.h>
+#include <dali/internal/event/render-tasks/render-task-impl.h>
namespace Dali
{
return actor;
}
+bool GestureDetector::FeedTouch(Dali::Actor& actor, Dali::TouchEvent& touch)
+{
+ bool ret = false;
+ if(touch.GetPointCount() > 0)
+ {
+ const PointState::Type state = touch.GetState(0);
+ Dali::Internal::Actor& actorImpl(GetImplementation(actor));
+ if(state == PointState::DOWN)
+ {
+ Attach(actorImpl);
+ }
+
+ Integration::TouchEvent touchEvent(touch.GetTime());
+ for(std::size_t i = 0; i< touch.GetPointCount(); i++)
+ {
+ Integration::Point point;
+ point.SetState(touch.GetState(i));
+ point.SetDeviceId(touch.GetDeviceId(i));
+ point.SetScreenPosition(touch.GetScreenPosition(i));
+ point.SetRadius(touch.GetRadius(i));
+ point.SetPressure(touch.GetPressure(i));
+ point.SetAngle(touch.GetAngle(i));
+ point.SetDeviceClass(touch.GetDeviceClass(i));
+ point.SetDeviceSubclass(touch.GetDeviceSubclass(i));
+ point.SetMouseButton(touch.GetMouseButton(i));
+ point.SetHitActor(touch.GetHitActor(i));
+ point.SetLocalPosition(touch.GetLocalPosition(i));
+ touchEvent.points.push_back(point);
+ }
+
+ Dali::Internal::TouchEvent& touchEventImpl(GetImplementation(touch));
+ mGestureEventProcessor.ProcessTouchEvent(this, actorImpl, GetImplementation(touchEventImpl.GetRenderTaskPtr()), actorImpl.GetScene(), touchEvent);
+
+ if(state == PointState::FINISHED || state == PointState::INTERRUPTED || state == PointState::LEAVE)
+ {
+ Detach(actorImpl);
+ }
+ ret = true;
+ }
+ return ret;
+}
+
bool GestureDetector::IsAttached(Actor& actor) const
{
return (find(mPendingAttachActors.begin(), mPendingAttachActors.end(), &actor) != mPendingAttachActors.end()) ||
Dali::Actor GetAttachedActor(size_t index) const;
/**
+ * @copydoc Dali::GestureDetector::FeedTouch()
+ */
+ bool FeedTouch(Dali::Actor& actor, Dali::TouchEvent& touch);
+
+ /**
* Returns a const reference to the container of attached actor pointers.
* @return A const reference to the attached internal actors.
*/
mRotationGestureProcessor.ProcessTouch(scene, event);
}
+void GestureEventProcessor::ProcessTouchEvent(GestureDetector* gestureDetector, Actor& actor, Dali::Internal::RenderTask& renderTask, Scene& scene, const Integration::TouchEvent& event)
+{
+ switch(gestureDetector->GetType())
+ {
+ case GestureType::LONG_PRESS:
+ {
+ mLongPressGestureProcessor.ProcessTouch(actor, renderTask, scene, event);
+ break;
+ }
+
+ case GestureType::PAN:
+ {
+ mPanGestureProcessor.ProcessTouch(actor, renderTask, scene, event);
+ break;
+ }
+
+ case GestureType::PINCH:
+ {
+ mPinchGestureProcessor.ProcessTouch(actor, renderTask, scene, event);
+ break;
+ }
+
+ case GestureType::TAP:
+ {
+ mTapGestureProcessor.ProcessTouch(actor, renderTask, scene, event);
+ break;
+ }
+
+ case GestureType::ROTATION:
+ {
+ mRotationGestureProcessor.ProcessTouch(actor, renderTask, scene, event);
+ break;
+ }
+ }
+}
+
void GestureEventProcessor::AddGestureDetector(GestureDetector* gestureDetector, Scene& scene)
{
switch(gestureDetector->GetType())
*/
void ProcessTouchEvent(Scene& scene, const Integration::TouchEvent& event);
+ /**
+ * This function is called by gesture detector whenever a touch event occurs
+ * @param[in] gestureDetector The gesture detector
+ * @param[in] actor The actor
+ * @param[in] renderTask The renderTask
+ * @param[in] scene The scene
+ * @param[in] event The event that has occurred
+ */
+ void ProcessTouchEvent(GestureDetector* gestureDetector, Actor& actor, Dali::Internal::RenderTask& renderTask, Scene& scene, const Integration::TouchEvent& event);
+
public: // To be called by gesture detectors
/**
* This method adds the specified gesture detector to the relevant gesture processor.
// INTERNAL INCLUDES
#include <dali/integration-api/events/event.h>
#include <dali/internal/event/events/gesture-impl.h>
+#include <dali/internal/event/render-tasks/render-task-impl.h>
namespace Dali
{
*/
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.
}
}
+void GestureProcessor::ProcessTouch(Actor& actor, Dali::Internal::RenderTask& renderTask, Scene& scene, const Integration::TouchEvent& event)
+{
+ if(mGestureRecognizer)
+ {
+ if(!event.points.empty())
+ {
+ mPoint = event.points[0];
+ mEventTime = event.time;
+ }
+ mGestureRecognizer->SendEvent(actor, renderTask, scene, event);
+ }
+}
+
void GestureProcessor::GetGesturedActor(Actor*& actor, GestureDetectorContainer& gestureDetectors)
{
while(actor)
}
}
+void GestureProcessor::ProcessAndEmitActor(HitTestAlgorithm::Results& hitTestResults)
+{
+ if(hitTestResults.actor)
+ {
+ Actor* hitTestActor(&GetImplementation(hitTestResults.actor));
+ Actor* actor(hitTestActor);
+ GestureDetectorContainer gestureDetectors;
+ GetGesturedActor(actor, gestureDetectors);
+
+ if(actor && actor->IsVisible() && !gestureDetectors.empty() && actor == hitTestActor)
+ {
+ EmitGestureSignal(actor, gestureDetectors, hitTestResults.actorCoordinates);
+ }
+ }
+}
+
bool GestureProcessor::HitTest(Scene& scene, Vector2 screenCoordinates, HitTestAlgorithm::Results& hitTestResults)
{
GestureHitTestCheck hitCheck(mType);
void ProcessTouch(Scene& scene, const Integration::TouchEvent& event);
/**
+ * Process the touch event in the attached recognizer
+ * @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);
+
+ /**
* Returns whether any GestureDetector requires a Core::Update
* @return true if update required
*/
void ProcessAndEmit(HitTestAlgorithm::Results& hitTestResults);
/**
+ * Calls the emission method in the deriving class for actor
+ *
+ * @param[in] hitTestResults The Hit Test Results.
+ *
+ * @note Uses the CheckGestureDetector() to check if the gesture matches the criteria of the given gesture detector
+ * and EmitGestureSignal() to emit the signal.
+ * @pre Hit Testing should already be done.
+ */
+ void ProcessAndEmitActor(HitTestAlgorithm::Results& hitTestResults);
+
+ /**
* Hit test the screen coordinates, and place the results in hitTestResults.
* @param[in] scene Scene.
* @param[in] screenCoordinates The screen coordinates to test.
// EXTERNAL INCLUDES
#include <dali/integration-api/events/touch-event-integ.h>
+#include <dali/internal/event/events/actor-observer.h>
#include <dali/internal/event/events/gesture-event.h>
+#include <dali/internal/event/render-tasks/render-task-impl.h>
#include <dali/public-api/common/vector-wrapper.h>
#include <dali/public-api/events/gesture.h>
#include <dali/public-api/math/vector2.h>
class RecognizerObserver
{
public:
- virtual void Process(Scene& scene, const T& event) = 0;
+ virtual void Process(Scene& scene, const T& event, Actor* actor = nullptr) = 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)
+ mSourceData(GestureSourceData::INVALID),
+ mActor(),
+ mRenderTask()
{
}
~GestureRecognizer() override = default;
protected:
- Vector2 mScreenSize;
- GestureType::Value mType;
- Scene* mScene;
- GestureSourceType mSourceType; /// < Gesture input source type.
- GestureSourceData mSourceData; /// < Gesture input source data.
+ Vector2 mScreenSize;
+ GestureType::Value mType;
+ 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)
+void LongPressGestureProcessor::Process(Scene& scene, const LongPressGestureEvent& longPressEvent, Actor* actor)
{
DALI_TRACE_SCOPE(gTraceFilter, "DALI_PROCESS_LONG_PRESS_GESTURE");
switch(longPressEvent.state)
ResetActor();
HitTestAlgorithm::Results hitTestResults;
- if(HitTest(scene, longPressEvent.point, hitTestResults))
+ if(actor)
+ {
+ SetActor(actor);
+ }
+ else if(HitTest(scene, longPressEvent.point, hitTestResults))
{
SetActor(&GetImplementation(hitTestResults.actor));
}
if(currentGesturedActor)
{
HitTestAlgorithm::Results hitTestResults;
- HitTest(scene, longPressEvent.point, hitTestResults);
+ if(actor)
+ {
+ hitTestResults.actor = Dali::Actor(actor);
+ hitTestResults.renderTask = longPressEvent.renderTask;
+
+ Vector2 actorCoords;
+ currentGesturedActor->ScreenToLocal(*hitTestResults.renderTask.Get(), actorCoords.x, actorCoords.y, longPressEvent.point.x, longPressEvent.point.y);
+ hitTestResults.actorCoordinates = actorCoords;
+ }
+ else
+ {
+ HitTest(scene, longPressEvent.point, hitTestResults);
+ }
if(hitTestResults.actor && (currentGesturedActor == &GetImplementation(hitTestResults.actor)))
{
// Set mCurrentLongPressEvent to use inside overridden methods called from ProcessAndEmit()
mCurrentLongPressEvent = &longPressEvent;
- ProcessAndEmit(hitTestResults);
+ if(actor)
+ {
+ ProcessAndEmitActor(hitTestResults);
+ }
+ else
+ {
+ ProcessAndEmit(hitTestResults);
+ }
mCurrentLongPressEvent = nullptr;
}
else
* 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) override;
+ void Process(Scene& scene, const LongPressGestureEvent& longPressEvent, Actor* actor = nullptr) override;
/**
* Adds a gesture detector to this gesture processor.
}
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);
+ mObserver.Process(*mScene, longPress, mActor.GetActor());
}
}
}
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)
+void PanGestureProcessor::Process(Scene& scene, const PanGestureEvent& panEvent, Actor* actor)
{
#if defined(DEBUG_ENABLED)
DALI_LOG_TRACE_METHOD(gLogFilter);
ResetActor();
HitTestAlgorithm::Results hitTestResults;
- if(HitTest(scene, panEvent.currentPosition, hitTestResults))
+ if(actor)
+ {
+ SetActor(actor);
+ mPossiblePanPosition = panEvent.currentPosition;
+ }
+ else if(HitTest(scene, panEvent.currentPosition, hitTestResults))
{
SetActor(&GetImplementation(hitTestResults.actor));
mPossiblePanPosition = panEvent.currentPosition;
// it can be told when the gesture ends as well.
HitTestAlgorithm::Results hitTestResults;
- HitTest(scene, panEvent.previousPosition, hitTestResults); // Hit Test previous position
+ if(actor)
+ {
+ hitTestResults.actor = Dali::Actor(actor);
+ hitTestResults.renderTask = panEvent.renderTask;
+
+ Vector2 actorCoords;
+ actor->ScreenToLocal(*hitTestResults.renderTask.Get(), actorCoords.x, actorCoords.y, panEvent.currentPosition.x, panEvent.currentPosition.y);
+ hitTestResults.actorCoordinates = actorCoords;
+ }
+ else
+ {
+ HitTest(scene, panEvent.previousPosition, hitTestResults); // Hit Test previous position
+ }
if(hitTestResults.actor)
{
// Set mCurrentPanEvent to use inside overridden methods called in ProcessAndEmit()
mCurrentPanEvent = &panEvent;
- ProcessAndEmit(hitTestResults);
+ if(actor)
+ {
+ ProcessAndEmitActor(hitTestResults);
+ }
+ else
+ {
+ ProcessAndEmit(hitTestResults);
+ }
mCurrentPanEvent = nullptr;
}
else
* 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) override;
+ void Process(Scene& scene, const PanGestureEvent& panEvent, Actor* actor = nullptr) 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);
+ mObserver.Process(*mScene, gesture, mActor.GetActor());
}
}
}
}
-void PinchGestureProcessor::Process(Scene& scene, const PinchGestureEvent& pinchEvent)
+void PinchGestureProcessor::Process(Scene& scene, const PinchGestureEvent& pinchEvent, Actor* actor)
{
DALI_TRACE_SCOPE(gTraceFilter, "DALI_PROCESS_PINCH_GESTURE");
switch(pinchEvent.state)
ResetActor();
HitTestAlgorithm::Results hitTestResults;
- if(HitTest(scene, pinchEvent.centerPoint, hitTestResults))
+ if(actor)
+ {
+ hitTestResults.actor = Dali::Actor(actor);
+ hitTestResults.renderTask = pinchEvent.renderTask;
+
+ // 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);
+ hitTestResults.actorCoordinates = actorCoords;
+
+ // Set mCurrentPinchEvent to use inside overridden methods called from ProcessAndEmit()
+ mCurrentPinchEvent = &pinchEvent;
+ ProcessAndEmitActor(hitTestResults);
+ mCurrentPinchEvent = nullptr;
+ }
+ else if(HitTest(scene, pinchEvent.centerPoint, hitTestResults))
{
// Record the current render-task for Screen->Actor coordinate conversions
mCurrentRenderTask = hitTestResults.renderTask;
* 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) override;
+ void Process(Scene& scene, const PinchGestureEvent& pinchEvent, Actor* actor = nullptr) 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);
+ mObserver.Process(*mScene, gesture, mActor.GetActor());
}
}
{
}
-void RotationGestureProcessor::Process(Scene& scene, const RotationGestureEvent& rotationEvent)
+void RotationGestureProcessor::Process(Scene& scene, const RotationGestureEvent& rotationEvent, Actor* actor)
{
DALI_TRACE_SCOPE(gTraceFilter, "DALI_PROCESS_ROTATION_GESTURE");
switch(rotationEvent.state)
ResetActor();
HitTestAlgorithm::Results hitTestResults;
- if(HitTest(scene, rotationEvent.centerPoint, hitTestResults))
+ if(actor)
+ {
+ hitTestResults.actor = Dali::Actor(actor);
+ hitTestResults.renderTask = rotationEvent.renderTask;
+
+ // 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);
+ hitTestResults.actorCoordinates = actorCoords;
+
+ // Set mCurrentRotationEvent to use inside overridden methods called from ProcessAndEmit()
+ mCurrentRotationEvent = &rotationEvent;
+ ProcessAndEmitActor(hitTestResults);
+ mCurrentRotationEvent = nullptr;
+
+ }
+ else if(HitTest(scene, rotationEvent.centerPoint, hitTestResults))
{
// Record the current render-task for Screen->Actor coordinate conversions
mCurrentRenderTask = hitTestResults.renderTask;
* 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) override;
+ void Process(Scene& scene, const RotationGestureEvent& rotationEvent, Actor* actor = nullptr) 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);
+ mObserver.Process(*mScene, gesture, mActor.GetActor());
}
}
TapGestureProcessor::~TapGestureProcessor() = default;
-void TapGestureProcessor::Process(Scene& scene, const TapGestureEvent& tapEvent)
+void TapGestureProcessor::Process(Scene& scene, const TapGestureEvent& tapEvent, Actor* actor)
{
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(HitTest(scene, tapEvent.point, hitTestResults))
+ if(actor)
+ {
+ SetActor(actor);
+ 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
+ mPossibleProcessed = true;
+ }
+ else if(HitTest(scene, tapEvent.point, hitTestResults))
{
SetActor(&GetImplementation(hitTestResults.actor));
mCurrentTapActor.SetActor(GetCurrentGesturedActor());
{
// Ensure that we're processing a hit on the current actor and that we've already processed a touch down
HitTestAlgorithm::Results hitTestResults;
- if(GetCurrentGesturedActor() && HitTest(scene, tapEvent.point, hitTestResults) && mPossibleProcessed)
+ if(GetCurrentGesturedActor())
{
- // Check that this actor is still the one that was used for the last touch down ?
- if(mCurrentTapActor.GetActor() == &GetImplementation(hitTestResults.actor))
+ if(actor)
+ {
+ hitTestResults.actor = Dali::Actor(actor);
+ hitTestResults.renderTask = tapEvent.renderTask;
+ // 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);
+ }
+ mCurrentTapEvent = nullptr;
+ mPossibleProcessed = false;
+ }
+ else if(HitTest(scene, tapEvent.point, hitTestResults) && mPossibleProcessed)
{
- mCurrentTapEvent = &tapEvent;
- ProcessAndEmit(hitTestResults);
+ // Check that this actor is still the one that was used for the last touch down ?
+ if(mCurrentTapActor.GetActor() == &GetImplementation(hitTestResults.actor))
+ {
+ mCurrentTapEvent = &tapEvent;
+ ProcessAndEmit(hitTestResults);
+ }
+ mCurrentTapEvent = nullptr;
+ mPossibleProcessed = false;
}
- mCurrentTapEvent = nullptr;
- mPossibleProcessed = false;
}
break;
}
* 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) override;
+ void Process(Scene& scene, const TapGestureEvent& event, Actor* actor = nullptr) 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);
+ mObserver.Process(*mScene, event, mActor.GetActor());
}
}
return mRenderTask;
}
+ Dali::RenderTask& GetRenderTaskPtr()
+ {
+ return mRenderTask;
+ }
+
// Setters
/**
return GetImplementation(*this).GetAttachedActor(index);
}
+bool GestureDetector::FeedTouch(Dali::Actor& actor, Dali::TouchEvent& touch)
+{
+ return GetImplementation(*this).FeedTouch(actor, touch);
+}
+
} // namespace Dali
// INTERNAL INCLUDES
#include <dali/public-api/object/handle.h>
+#include <dali/public-api/events/touch-event.h>
namespace Dali
{
*/
Actor GetAttachedActor(size_t index) const;
+ /**
+ * @brief The gesture is recognized by sending a Touch event to the actor.
+ *
+ * @param actor The actor receiving touch events
+ * @param touch The thouch event
+ * @return If true , the gesture is being recognized.
+ */
+ bool FeedTouch(Dali::Actor& actor, Dali::TouchEvent& touch);
+
protected:
/// @cond internal
/**