The Wheel event calls the WheelEvent callback by going back from the last child actor to the parent via hitTest.
InterceptWheelEvent checks the wheel event in the parent first.
Returning false from InterceptWheelEvent allows child actors to receive WheelEvents.
If it returns true, the actor will receive a WheelEvent.
for example
Actor parent = Actor::New();
Actor actor = Actor::New();
parent.Add(actor);
actor.WheelEventSignal().Connect(&application, functor);
parent.WheelEventSignal().Connect(&application, parentFunctor);
The callbacks are called in the order functor -> parentFunctor.
If you connect InterceptWheelSignal to parentActor.
Dali::DevelActor::InterceptWheelSignal(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 WheelEvent was intercepted.
So the child actor will not be able to receive wheel events.
Only the parentFunctor is called.
Change-Id: I8ec2c70ca148565e6e899cedb9a997b2f851b0b8
*/
#include <dali-test-suite-utils.h>
+#include <dali/devel-api/actors/actor-devel.h>
#include <dali/devel-api/events/wheel-event-devel.h>
#include <dali/integration-api/events/wheel-event-integ.h>
#include <dali/public-api/dali-core.h>
// Functor that sets the data when called
struct WheelEventReceivedFunctor
{
- WheelEventReceivedFunctor(SignalData& data)
- : signalData(data)
+ WheelEventReceivedFunctor(SignalData& data, bool returnValue = true)
+ : signalData(data),
+ returnValue(returnValue)
{
}
signalData.receivedWheelEvent = wheelEvent;
signalData.wheeledActor = actor;
- return true;
+ return returnValue;
}
SignalData& signalData;
+ bool returnValue;
};
} // anonymous namespace
data.Reset();
END_TEST;
}
+
+int UtcDaliWheelEventIntercept(void)
+{
+ TestApplication application; // Reset all test adapter return codes
+
+ Actor actor = Actor::New();
+ actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+ actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+ application.GetScene().Add(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Connect to actor's wheel event signal
+ SignalData data;
+ WheelEventReceivedFunctor functor(data);
+ actor.WheelEventSignal().Connect(&application, functor);
+
+ Vector2 screenCoordinates(10.0f, 10.0f);
+ Integration::WheelEvent event(Integration::WheelEvent::MOUSE_WHEEL, 0, SHIFT_MODIFIER, screenCoordinates, 1, 1000u);
+
+ // Emit a wheel signal
+ application.ProcessEvent(event);
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_CHECK(actor == data.wheeledActor);
+ DALI_TEST_EQUALS(WheelEvent::MOUSE_WHEEL, data.receivedWheelEvent.GetType(), TEST_LOCATION); // check type
+ DALI_TEST_EQUALS(0, data.receivedWheelEvent.GetDirection(), TEST_LOCATION); // check direction
+ DALI_TEST_EQUALS(SHIFT_MODIFIER, data.receivedWheelEvent.GetModifiers(), TEST_LOCATION); // check modifier
+ DALI_TEST_EQUALS(screenCoordinates, data.receivedWheelEvent.GetPoint(), TEST_LOCATION); // check modifier
+ DALI_TEST_EQUALS(1, data.receivedWheelEvent.GetDelta(), TEST_LOCATION); // check modifier
+ DALI_TEST_EQUALS(1000u, data.receivedWheelEvent.GetTime(), TEST_LOCATION); // check modifier
+ data.Reset();
+
+ // Intercept wheel events on the root actor.
+ Actor rootActor(application.GetScene().GetRootLayer());
+
+ // Connect to root actor's intercept wheel event signal
+ SignalData rootData;
+ WheelEventReceivedFunctor rootFunctor(rootData); // Consumes signal
+ Dali::DevelActor::InterceptWheelSignal(rootActor).Connect(&application, rootFunctor);
+
+ Integration::WheelEvent newEvent(Integration::WheelEvent::MOUSE_WHEEL, 0, SHIFT_MODIFIER, screenCoordinates, 1, 1000u);
+ application.ProcessEvent(newEvent);
+
+ // It should be able to receive wheel events to root actor by registering only InterceptWheelEvent.
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
+ DALI_TEST_CHECK(rootActor == rootData.wheeledActor);
+ DALI_TEST_EQUALS(WheelEvent::MOUSE_WHEEL, rootData.receivedWheelEvent.GetType(), TEST_LOCATION); // check type
+ DALI_TEST_EQUALS(0, rootData.receivedWheelEvent.GetDirection(), TEST_LOCATION); // check direction
+ DALI_TEST_EQUALS(SHIFT_MODIFIER, rootData.receivedWheelEvent.GetModifiers(), TEST_LOCATION); // check modifier
+ DALI_TEST_EQUALS(screenCoordinates, rootData.receivedWheelEvent.GetPoint(), TEST_LOCATION); // check modifier
+ DALI_TEST_EQUALS(1, rootData.receivedWheelEvent.GetDelta(), TEST_LOCATION); // check modifier
+ DALI_TEST_EQUALS(1000u, rootData.receivedWheelEvent.GetTime(), TEST_LOCATION); // check modifier
+
+ // Remove actor from the scene
+ application.GetScene().Remove(actor);
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Emit a move at the same point, we should not be signalled.
+ application.ProcessEvent(event);
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+ END_TEST;
+}
return GetImplementation(actor).InterceptTouchedSignal();
}
+Actor::WheelEventSignalType& InterceptWheelSignal(Actor actor)
+{
+ return GetImplementation(actor).InterceptWheelSignal();
+}
+
void SetNeedGesturePropagation(Actor actor, bool propagation)
{
return GetImplementation(actor).SetNeedGesturePropagation(propagation);
DALI_CORE_API Actor::TouchEventSignalType& InterceptTouchedSignal(Actor actor);
/**
+ * @brief This signal is emitted when intercepting the actor's wheel event.
+ *
+ * A callback of the following type may be connected:
+ * @code
+ * void MyCallbackName( Actor actor );
+ * @endcode
+ * actor The actor to intercept
+ *
+ * @note WheelEvent callbacks are called from the last child in the order of the parent's actor.
+ * The InterceptWheelEvent callback is to intercept the wheel event in the parent.
+ * So, if the parent interepts the wheel event, the child cannot receive the Wheel event.
+ *
+ * @note example
+ * Actor parent = Actor::New();
+ * Actor child = Actor::New();
+ * parent.Add(child);
+ * child.WheelEventSignal().Connect(&application, childFunctor);
+ * parent.WheelEventSignal().Connect(&application, parentFunctor);
+ * The wheel event callbacks are called in the order childFunctor -> parentFunctor.
+ *
+ * If you connect InterceptWheelSignal to parentActor.
+ * Dali::DevelActor::InterceptWheelSignal(parent).Connect(&application, interceptFunctor);
+ *
+ * When interceptFunctor returns false, the wheel event callbacks are called in the same order childFunctor -> parentFunctor.
+ * If interceptFunctor returns true, it means that the WheelEvent was intercepted.
+ * So the child actor will not be able to receive wheel events.
+ * Only the parentFunctor is called.
+ *
+ * @return The signal to connect to
+ * @pre The Actor has been initialized
+ */
+DALI_CORE_API Actor::WheelEventSignalType& InterceptWheelSignal(Actor actor);
+
+/**
* @brief This is used when the parent actor wants to listen to gesture events.
*
* @note example The child is overlapped on the parent.
return EmitConsumingSignal(*this, mHoveredSignal, event);
}
+bool Actor::EmitInterceptWheelEventSignal(const Dali::WheelEvent& event)
+{
+ return EmitConsumingSignal(*this, mInterceptWheelSignal, event);
+}
+
bool Actor::EmitWheelEventSignal(const Dali::WheelEvent& event)
{
return EmitConsumingSignal(*this, mWheelEventSignal, event);
mInterceptTouchedSignal(),
mTouchedSignal(),
mHoveredSignal(),
+ mInterceptWheelSignal(),
mWheelEventSignal(),
mOnSceneSignal(),
mOffSceneSignal(),
}
/**
+ * Query whether the application or derived actor type requires intercept wheel events.
+ * @return True if intercept wheel events are required.
+ */
+ bool GetInterceptWheelRequired() const
+ {
+ return !mInterceptWheelSignal.Empty();
+ }
+
+ /**
* Query whether the application or derived actor type requires wheel events.
* @return True if wheel events are required.
*/
bool EmitHoverEventSignal(const Dali::HoverEvent& event);
/**
+ * Used by the EventProcessor to emit intercept wheel event signals.
+ * @param[in] event The wheel event.
+ * @return True if the event was intercepted.
+ */
+ bool EmitInterceptWheelEventSignal(const Dali::WheelEvent& event);
+
+ /**
* Used by the EventProcessor to emit wheel event signals.
* @param[in] event The wheel event.
* @return True if the event was consumed.
}
/**
+ * @copydoc DevelActor::InterceptWheelSignal()
+ */
+ Dali::Actor::WheelEventSignalType& InterceptWheelSignal()
+ {
+ return mInterceptWheelSignal;
+ }
+
+ /**
* @copydoc Dali::Actor::WheelEventSignal()
*/
Dali::Actor::WheelEventSignalType& WheelEventSignal()
Dali::Actor::TouchEventSignalType mInterceptTouchedSignal;
Dali::Actor::TouchEventSignalType mTouchedSignal;
Dali::Actor::HoverSignalType mHoveredSignal;
+ Dali::Actor::WheelEventSignalType mInterceptWheelSignal;
Dali::Actor::WheelEventSignalType mWheelEventSignal;
Dali::Actor::OnSceneSignalType mOnSceneSignal;
Dali::Actor::OffSceneSignalType mOffSceneSignal;
Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_WHEEL_PROCESSOR");
#endif
+Dali::Actor EmitInterceptWheelSignals(Dali::Actor actor, const Dali::WheelEvent& wheelEvent)
+{
+ Dali::Actor interceptedActor;
+
+ if(actor)
+ {
+ Dali::Actor parent = actor.GetParent();
+ if(parent)
+ {
+ // Recursively deliver events to the actor and its parents for intercept wheel event.
+ interceptedActor = EmitInterceptWheelSignals(parent, wheelEvent);
+ }
+
+ if(!interceptedActor)
+ {
+ bool intercepted = false;
+ Actor& actorImpl(GetImplementation(actor));
+ if(actorImpl.GetInterceptWheelRequired())
+ {
+ DALI_TRACE_SCOPE(gTraceFilter, "DALI_EMIT_INTERCEPT_WHEEL_EVENT_SIGNAL");
+ intercepted = actorImpl.EmitInterceptWheelEventSignal(wheelEvent);
+ 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.
*/
if(actorImpl.GetWheelEventRequired())
{
// Emit the signal to the parent
+ DALI_TRACE_SCOPE(gTraceFilter, "DALI_EMIT_WHEEL_EVENT_SIGNAL");
consumed = actorImpl.EmitWheelEventSignal(event);
}
{
case Dali::HitTestAlgorithm::CHECK_ACTOR:
{
- if(GetImplementation(actor).GetWheelEventRequired() && // Does the Application or derived actor type require a wheel event?
+ if((GetImplementation(actor).GetWheelEventRequired() || GetImplementation(actor).GetInterceptWheelRequired()) && // Does the Application or derived actor type require a wheel event?
GetImplementation(actor).IsHittable())
{
hittable = true;
DALI_LOG_INFO(gLogFilter, Debug::General, " Screen(%.0f, %.0f), HitActor(%p, %s), Local(%.2f, %.2f)\n", event.point.x, event.point.y, (hitTestResults.actor ? reinterpret_cast<void*>(&hitTestResults.actor.GetBaseObject()) : NULL), (hitTestResults.actor ? hitTestResults.actor.GetProperty<std::string>(Dali::Actor::Property::NAME).c_str() : ""), hitTestResults.actorCoordinates.x, hitTestResults.actorCoordinates.y);
// Recursively deliver events to the actor and its parents, until the event is consumed or the stage is reached.
- Dali::Actor consumedActor = EmitWheelSignals(hitTestResults.actor, wheelEventHandle);
+ Dali::Actor consumedActor;
+
+ // Emit the intercept wheel event signal
+ Dali::Actor interceptedActor = EmitInterceptWheelSignals(hitTestResults.actor, wheelEventHandle);
+ if(interceptedActor)
+ {
+ consumedActor = EmitWheelSignals(interceptedActor, wheelEventHandle);
+ }
+ else
+ {
+ consumedActor = EmitWheelSignals(hitTestResults.actor, wheelEventHandle);
+ }
DALI_LOG_INFO(gLogFilter, Debug::Concise, "HitActor: (%p) %s\n", hitTestResults.actor ? reinterpret_cast<void*>(&hitTestResults.actor.GetBaseObject()) : NULL, hitTestResults.actor ? hitTestResults.actor.GetProperty<std::string>(Dali::Actor::Property::NAME).c_str() : "");
DALI_LOG_INFO(gLogFilter, Debug::Concise, "ConsumedActor: (%p) %s\n", consumedActor ? reinterpret_cast<void*>(&consumedActor.GetBaseObject()) : NULL, consumedActor ? consumedActor.GetProperty<std::string>(Dali::Actor::Property::NAME).c_str() : "");