The Touch event calls the TouchEvent callback by going back from the last child actor to the parent via hitTest.
InterceptTouchEvent checks the touch event in the parent first.
Returning false from interceptTouchEvent allows child actors to receive TouchEvents.
If it returns true, the actor will receive a TouchEvent.
for example
Actor parent = Actor::New();
Actor actor = Actor::New();
parent.Add(actor);
actor.TouchedSignal().Connect(&application, functor);
parent.TouchedSignal().Connect(&application, parentFunctor);
The callbacks are called in the order functor -> parentFunctor.
If you connect interceptTouchSignal to parentActor.
Dali::DevelActor::InterceptTouchedSignal(parent).Connect(&application, interceptFunctor);
When interceptFunctor returns false, it is called in the same order functor -> parentFunctor.
If it returns true, it means that the TouchEvent was intercepted.
So the child actor will not be able to receive touch events.
Only the parentFunctor is called.
Change-Id: Ib6887adbcee59168a7caf7f36bcc400500c626e8
END_TEST;
}
+
+
+int UtcDaliTouchEventIntercept(void)
+{
+ TestApplication application;
+
+ 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 parent's intercept touched signal
+ SignalData interceptData;
+ TouchEventFunctor interceptFunctor(interceptData, true /* Do intercept */);
+ Dali::DevelActor::InterceptTouchedSignal(parent).Connect(&application, interceptFunctor);
+
+ // Emit a down signal
+ application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+ // The actor touched signal is not called because the touch is intercepted in the parent.
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(true, interceptData.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(PointState::DOWN, interceptData.receivedTouch.points[0].state, TEST_LOCATION);
+ DALI_TEST_CHECK(actor == interceptData.receivedTouch.points[0].hitActor);
+ DALI_TEST_CHECK(parent == interceptData.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);
+ data.Reset();
+ parentData.Reset();
+
+ END_TEST;
+}
+
return GetImplementation(actor).ChildOrderChangedSignal();
}
+Actor::TouchEventSignalType& InterceptTouchedSignal(Actor actor)
+{
+ return GetImplementation(actor).InterceptTouchedSignal();
+}
+
} // namespace DevelActor
} // namespace Dali
*/
DALI_CORE_API ChildOrderChangedSignalType& ChildOrderChangedSignal(Actor actor);
+/**
+ * @brief This signal is emitted when intercepting the actor's touch event.
+ *
+ * A callback of the following type may be connected:
+ * @code
+ * void MyCallbackName( Actor actor );
+ * @endcode
+ * actor The actor to intercept
+ *
+ * @note TouchEvent callbacks are called from the last child in the order of the parent's actor.
+ * The InterceptTouchEvent callback is to intercept the touch event in the parent.
+ * So, if the parent interepts the touch event, the child cannot receive the touch event.
+ *
+ * @note example
+ * Actor parent = Actor::New();
+ * Actor child = Actor::New();
+ * parent.Add(child);
+ * child.TouchedSignal().Connect(&application, childFunctor);
+ * parent.TouchedSignal().Connect(&application, parentFunctor);
+ * The touch event callbacks are called in the order childFunctor -> parentFunctor.
+ *
+ * If you connect interceptTouchSignal to parentActor.
+ * Dali::DevelActor::InterceptTouchedSignal(parent).Connect(&application, interceptFunctor);
+ *
+ * When interceptFunctor returns false, the touch event callbacks are called in the same order childFunctor -> parentFunctor.
+ * If interceptFunctor returns true, it means that the TouchEvent was intercepted.
+ * So the child actor will not be able to receive touch events.
+ * Only the parentFunctor is called.
+ *
+ * @return The signal to connect to
+ * @pre The Actor has been initialized
+ */
+DALI_CORE_API Actor::TouchEventSignalType& InterceptTouchedSignal(Actor actor);
+
} // namespace DevelActor
} // namespace Dali
return mGestureData && mGestureData->IsGestureRequired( type );
}
+bool Actor::EmitInterceptTouchEventSignal( const Dali::TouchEvent& touch )
+{
+ return EmitConsumingSignal( *this, mInterceptTouchedSignal, touch );
+}
+
bool Actor::EmitTouchEventSignal( const Dali::TouchEvent& touch )
{
return EmitConsumingSignal( *this, mTouchedSignal, touch );
mAnchorPoint( nullptr ),
mRelayoutData( nullptr ),
mGestureData( nullptr ),
+ mInterceptTouchedSignal(),
mTouchedSignal(),
mHoveredSignal(),
mWheelEventSignal(),
return mKeyboardFocusable;
}
+
+ /**
+ * Query whether the application or derived actor type requires intercept touch events.
+ * @return True if intercept touch events are required.
+ */
+ bool GetInterceptTouchRequired() const
+ {
+ return !mInterceptTouchedSignal.Empty();
+ }
+
/**
* Query whether the application or derived actor type requires touch events.
* @return True if touch events are required.
// Signals
+ /**
+ * Used by the EventProcessor to emit intercept touch event signals.
+ * @param[in] touch The touch data.
+ * @return True if the event was intercepted.
+ */
+ bool EmitInterceptTouchEventSignal( const Dali::TouchEvent& touch );
+
/**
* Used by the EventProcessor to emit touch event signals.
* @param[in] touch The touch data.
*/
void EmitChildRemovedSignal( Actor& child );
+ /**
+ * @copydoc DevelActor::InterceptTouchedSignal()
+ */
+ Dali::Actor::TouchEventSignalType& InterceptTouchedSignal()
+ {
+ return mInterceptTouchedSignal;
+ }
+
/**
* @copydoc Dali::Actor::TouchedSignal()
*/
ActorGestureData* mGestureData; ///< Optional Gesture data. Only created when actor requires gestures
// Signals
+ Dali::Actor::TouchEventSignalType mInterceptTouchedSignal;
Dali::Actor::TouchEventSignalType mTouchedSignal;
Dali::Actor::HoverSignalType mHoveredSignal;
Dali::Actor::WheelEventSignalType mWheelEventSignal;
#endif // defined(DEBUG_ENABLED)
+Dali::Actor EmitInterceptTouchSignals( Dali::Actor actor, const Dali::TouchEvent& touchEvent )
+{
+ Dali::Actor interceptedActor;
+
+ if( actor )
+ {
+ Dali::Actor parent = actor.GetParent();
+ if( parent )
+ {
+ // Recursively deliver events to the actor and its parents for intercept touch event.
+ interceptedActor = EmitInterceptTouchSignals( parent, touchEvent );
+ }
+
+ if( !interceptedActor )
+ {
+ bool intercepted = false;
+ Actor& actorImpl( GetImplementation(actor) );
+ if( actorImpl.GetInterceptTouchRequired() )
+ {
+ intercepted = actorImpl.EmitInterceptTouchEventSignal( touchEvent );
+ if( intercepted )
+ {
+ interceptedActor = Dali::Actor( &actorImpl );
+ }
+ }
+ }
+ }
+
+ return interceptedActor;
+}
/**
* Recursively deliver events to the actor and its parents, until the event is consumed or the stage is reached.
Dali::Actor consumedActor;
if ( currentRenderTask )
{
- consumedActor = EmitTouchSignals( touchEventImpl->GetPoint( 0 ).GetHitActor(), touchEventHandle );
+ // Emit the intercept touch signal
+ Dali::Actor interceptedActor = EmitInterceptTouchSignals( touchEventImpl->GetPoint( 0 ).GetHitActor(), touchEventHandle );
+ if( interceptedActor )
+ {
+ consumedActor = EmitTouchSignals( interceptedActor, touchEventHandle );
+ }
+ else
+ {
+ consumedActor = EmitTouchSignals( touchEventImpl->GetPoint( 0 ).GetHitActor(), touchEventHandle );
+ }
consumed = consumedActor ? true : false;
}