X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fevent%2Fevents%2Ftouch-event-processor.cpp;h=4ac3034e9a501082dca8d7b07f21029664f8f5ef;hb=4a0533ec46ae7625a339e6f10d704d51b66b85d3;hp=fb024a383ed69d5787ec9740d0b33bb15d7b3d9a;hpb=9d6d686c6dd8d2bad11844a9dd6514b1c52f50a3;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/internal/event/events/touch-event-processor.cpp b/dali/internal/event/events/touch-event-processor.cpp index fb024a3..4ac3034 100644 --- a/dali/internal/event/events/touch-event-processor.cpp +++ b/dali/internal/event/events/touch-event-processor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,9 +23,6 @@ #endif // INTERNAL INCLUDES -#include -#include -#include #include #include #include @@ -33,70 +30,100 @@ #include #include #include -#include +#include #include +#include +#include +#include namespace Dali { - namespace Internal { - namespace { - #if defined(DEBUG_ENABLED) -Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_TOUCH_PROCESSOR" ); +Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_TOUCH_PROCESSOR"); -const char * TOUCH_POINT_STATE[ 6 ] = -{ - "DOWN", - "UP", - "MOTION", - "LEAVE", - "STATIONARY", - "INTERRUPTED", +const char* TOUCH_POINT_STATE[6] = + { + "DOWN", + "UP", + "MOTION", + "LEAVE", + "STATIONARY", + "INTERRUPTED", }; #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 EmitTouchSignals( Dali::Actor actor, const TouchEvent& event, const Dali::TouchData& touchData ) +Dali::Actor EmitTouchSignals(Dali::Actor actor, const Dali::TouchEvent& touchEvent) { Dali::Actor consumedActor; - if ( actor ) + if(actor) { - Dali::Actor oldParent( actor.GetParent() ); + Dali::Actor oldParent(actor.GetParent()); - Actor& actorImpl( GetImplementation(actor) ); + Actor& actorImpl(GetImplementation(actor)); - bool consumed( false ); + bool consumed(false); // Only emit the signal if the actor's touch signal has connections (or derived actor implementation requires touch). - if ( actorImpl.GetTouchRequired() ) + if(actorImpl.GetTouchRequired()) { - consumed = actorImpl.EmitTouchEventSignal( event, touchData ); + consumed = actorImpl.EmitTouchEventSignal(touchEvent); } - if ( consumed ) + if(consumed) { // One of this actor's listeners has consumed the event so set this actor as the consumed actor. - consumedActor = Dali::Actor( &actorImpl ); + consumedActor = Dali::Actor(&actorImpl); } else { // The actor may have been removed/reparented during the signal callbacks. Dali::Actor parent = actor.GetParent(); - if ( parent && - (parent == oldParent) ) + if(parent && + (parent == oldParent)) { // One of the actor's parents may consumed the event and they should be set as the consumed actor. - consumedActor = EmitTouchSignals( parent, event, touchData ); + consumedActor = EmitTouchSignals(parent, touchEvent); } } } @@ -104,246 +131,296 @@ Dali::Actor EmitTouchSignals( Dali::Actor actor, const TouchEvent& event, const return consumedActor; } -Dali::Actor AllocAndEmitTouchSignals( unsigned long time, Dali::Actor actor, const Integration::Point& point ) +Dali::Actor AllocAndEmitTouchSignals(unsigned long time, Dali::Actor actor, const Integration::Point& point) { - TouchEvent touchEvent( time ); - TouchDataPtr touchData( new TouchData( time ) ); - Dali::TouchData touchDataHandle( touchData.Get() ); + TouchEventPtr touchEvent(new TouchEvent(time)); + Dali::TouchEvent touchEventHandle(touchEvent.Get()); - touchEvent.points.push_back( point.GetTouchPoint() ); - touchData->AddPoint( point ); + touchEvent->AddPoint(point); - return EmitTouchSignals( actor, touchEvent, touchDataHandle ); + return EmitTouchSignals(actor, touchEventHandle); } - /** * Changes the state of the primary point to leave and emits the touch signals */ -Dali::Actor EmitTouchSignals( Actor* actor, RenderTask& renderTask, const TouchEvent& originalEvent, const TouchDataPtr& originalTouchData, PointState::Type state ) +Dali::Actor EmitTouchSignals(Actor* actor, RenderTask& renderTask, const TouchEventPtr& originalTouchEvent, PointState::Type state) { Dali::Actor consumingActor; - if( actor ) + if(actor) { - TouchDataPtr touchData = TouchData::Clone( *originalTouchData.Get() ); + TouchEventPtr touchEventImpl = TouchEvent::Clone(*originalTouchEvent.Get()); - Integration::Point& primaryPoint = touchData->GetPoint( 0 ); + Integration::Point& primaryPoint = touchEventImpl->GetPoint(0); const Vector2& screenPosition = primaryPoint.GetScreenPosition(); - Vector2 localPosition; - actor->ScreenToLocal( renderTask, localPosition.x, localPosition.y, screenPosition.x, screenPosition.y ); - - primaryPoint.SetLocalPosition( localPosition ); - primaryPoint.SetHitActor( Dali::Actor( actor ) ); - primaryPoint.SetState( state ); + Vector2 localPosition; + actor->ScreenToLocal(renderTask, localPosition.x, localPosition.y, screenPosition.x, screenPosition.y); - TouchEvent touchEvent( originalEvent ); - touchEvent.points[0] = primaryPoint.GetTouchPoint(); + primaryPoint.SetLocalPosition(localPosition); + primaryPoint.SetHitActor(Dali::Actor(actor)); + primaryPoint.SetState(state); - consumingActor = EmitTouchSignals( Dali::Actor(actor), touchEvent, Dali::TouchData( touchData.Get() ) ); + consumingActor = EmitTouchSignals(Dali::Actor(actor), Dali::TouchEvent(touchEventImpl.Get())); } return consumingActor; } +/** + * @brief Parses the primary touch point by performing a hit-test if necessary + * + * @param[out] hitTestResults The hit test results are put into this variable + * @param[in/out] capturingTouchActorObserver The observer for the capturing touch actor member + * @param[in] lastRenderTask The last render task member + * @param[in] currentPoint The current point information + * @param[in] scene The scene that this touch is related to + */ +void ParsePrimaryTouchPoint( + HitTestAlgorithm::Results& hitTestResults, + ActorObserver& capturingTouchActorObserver, + const RenderTaskPtr& lastRenderTask, + const Integration::Point& currentPoint, + const Internal::Scene& scene) +{ + Actor* capturingTouchActor = capturingTouchActorObserver.GetActor(); + + // We only set the capturing touch actor when the first touch-started actor captures all touch so if it's set, just use it + if(capturingTouchActor && lastRenderTask) + { + hitTestResults.actor = Dali::Actor(capturingTouchActor); + hitTestResults.renderTask = lastRenderTask; + const Vector2& screenPosition = currentPoint.GetScreenPosition(); + capturingTouchActor->ScreenToLocal(*lastRenderTask, hitTestResults.actorCoordinates.x, hitTestResults.actorCoordinates.y, screenPosition.x, screenPosition.y); + } + else + { + HitTestAlgorithm::HitTest(scene.GetSize(), scene.GetRenderTaskList(), scene.GetLayerList(), currentPoint.GetScreenPosition(), hitTestResults); + + if(currentPoint.GetState() == PointState::STARTED && hitTestResults.actor) + { + // If we've just started touch, then check whether the actor has requested to capture all touch events + Actor* hitActor = &GetImplementation(hitTestResults.actor); + if(hitActor->CapturesAllTouchAfterStart()) + { + capturingTouchActorObserver.SetActor(hitActor); + } + } + } +} + } // unnamed namespace -TouchEventProcessor::TouchEventProcessor( Scene& scene ) -: mScene( scene ), - mLastPrimaryHitActor( MakeCallback( this, &TouchEventProcessor::OnObservedActorDisconnected ) ), +TouchEventProcessor::TouchEventProcessor(Scene& scene) +: mScene(scene), + mLastPrimaryHitActor(MakeCallback(this, &TouchEventProcessor::OnObservedActorDisconnected)), mLastConsumedActor(), + mCapturingTouchActor(), mTouchDownConsumedActor(), mLastRenderTask() { - DALI_LOG_TRACE_METHOD( gLogFilter ); + DALI_LOG_TRACE_METHOD(gLogFilter); } TouchEventProcessor::~TouchEventProcessor() { - DALI_LOG_TRACE_METHOD( gLogFilter ); + DALI_LOG_TRACE_METHOD(gLogFilter); } -void TouchEventProcessor::ProcessTouchEvent( const Integration::TouchEvent& event ) +bool TouchEventProcessor::ProcessTouchEvent(const Integration::TouchEvent& event) { - DALI_LOG_TRACE_METHOD( gLogFilter ); - DALI_ASSERT_ALWAYS( !event.points.empty() && "Empty TouchEvent sent from Integration\n" ); + DALI_LOG_TRACE_METHOD(gLogFilter); + DALI_ASSERT_ALWAYS(!event.points.empty() && "Empty TouchEvent sent from Integration\n"); PRINT_HIERARCHY(gLogFilter); // 1) Check if it is an interrupted event - we should inform our last primary hit actor about this // and emit the stage signal as well. - if ( event.points[0].GetState() == PointState::INTERRUPTED ) + if(event.points[0].GetState() == PointState::INTERRUPTED) { - Dali::Actor consumingActor; - Integration::Point currentPoint( event.points[0] ); + Dali::Actor consumingActor; + Integration::Point currentPoint(event.points[0]); - Actor* lastPrimaryHitActor( mLastPrimaryHitActor.GetActor() ); - if ( lastPrimaryHitActor ) + Actor* lastPrimaryHitActor(mLastPrimaryHitActor.GetActor()); + if(lastPrimaryHitActor) { - Dali::Actor lastPrimaryHitActorHandle( lastPrimaryHitActor ); - currentPoint.SetHitActor( lastPrimaryHitActorHandle ); + Dali::Actor lastPrimaryHitActorHandle(lastPrimaryHitActor); + currentPoint.SetHitActor(lastPrimaryHitActorHandle); - consumingActor = AllocAndEmitTouchSignals( event.time, lastPrimaryHitActorHandle, currentPoint ); + consumingActor = AllocAndEmitTouchSignals(event.time, lastPrimaryHitActorHandle, currentPoint); } // If the last consumed actor was different to the primary hit actor then inform it as well (if it has not already been informed). - Actor* lastConsumedActor( mLastConsumedActor.GetActor() ); - if ( lastConsumedActor && - lastConsumedActor != lastPrimaryHitActor && - lastConsumedActor != consumingActor ) + Actor* lastConsumedActor(mLastConsumedActor.GetActor()); + if(lastConsumedActor && + lastConsumedActor != lastPrimaryHitActor && + lastConsumedActor != consumingActor) { - Dali::Actor lastConsumedActorHandle( lastConsumedActor ); - currentPoint.SetHitActor( lastConsumedActorHandle ); - AllocAndEmitTouchSignals( event.time, lastConsumedActorHandle, currentPoint ); + Dali::Actor lastConsumedActorHandle(lastConsumedActor); + currentPoint.SetHitActor(lastConsumedActorHandle); + AllocAndEmitTouchSignals(event.time, lastConsumedActorHandle, currentPoint); } // Tell the touch-down consuming actor as well, if required - Actor* touchDownConsumedActor( mTouchDownConsumedActor.GetActor() ); - if ( touchDownConsumedActor && - touchDownConsumedActor != lastPrimaryHitActor && - touchDownConsumedActor != lastConsumedActor && - touchDownConsumedActor != consumingActor ) + Actor* touchDownConsumedActor(mTouchDownConsumedActor.GetActor()); + if(touchDownConsumedActor && + touchDownConsumedActor != lastPrimaryHitActor && + touchDownConsumedActor != lastConsumedActor && + touchDownConsumedActor != consumingActor) { - Dali::Actor touchDownConsumedActorHandle( touchDownConsumedActor ); + Dali::Actor touchDownConsumedActorHandle(touchDownConsumedActor); - currentPoint.SetHitActor( touchDownConsumedActorHandle ); - AllocAndEmitTouchSignals( event.time, touchDownConsumedActorHandle, currentPoint ); + currentPoint.SetHitActor(touchDownConsumedActorHandle); + AllocAndEmitTouchSignals(event.time, touchDownConsumedActorHandle, currentPoint); } - mLastPrimaryHitActor.SetActor( NULL ); - mLastConsumedActor.SetActor( NULL ); - mTouchDownConsumedActor.SetActor( NULL ); + mLastPrimaryHitActor.SetActor(nullptr); + mLastConsumedActor.SetActor(nullptr); + mCapturingTouchActor.SetActor(nullptr); + mTouchDownConsumedActor.SetActor(nullptr); mLastRenderTask.Reset(); - currentPoint.SetHitActor( Dali::Actor() ); + currentPoint.SetHitActor(Dali::Actor()); - TouchEvent touchEvent( event.time ); - TouchDataPtr touchData( new TouchData( event.time ) ); - Dali::TouchData touchDataHandle( touchData.Get() ); + TouchEventPtr touchEventImpl(new TouchEvent(event.time)); + Dali::TouchEvent touchEventHandle(touchEventImpl.Get()); - touchEvent.points.push_back( currentPoint.GetTouchPoint() ); - touchData->AddPoint( currentPoint ); + touchEventImpl->AddPoint(currentPoint); - mScene.EmitTouchedSignal( touchEvent, touchDataHandle ); - return; // No need for hit testing + mScene.EmitTouchedSignal(touchEventHandle); + return false; // No need for hit testing & already an interrupted event so just return false } // 2) Hit Testing. - TouchEvent touchEvent( event.time ); - TouchDataPtr touchData( new TouchData( event.time ) ); - Dali::TouchData touchDataHandle( touchData.Get() ); + TouchEventPtr touchEventImpl(new TouchEvent(event.time)); + Dali::TouchEvent touchEventHandle(touchEventImpl.Get()); - DALI_LOG_INFO( gLogFilter, Debug::Concise, "\n" ); - DALI_LOG_INFO( gLogFilter, Debug::General, "Point(s): %d\n", event.GetPointCount() ); + DALI_LOG_INFO(gLogFilter, Debug::Concise, "\n"); + DALI_LOG_INFO(gLogFilter, Debug::General, "Point(s): %d\n", event.GetPointCount()); RenderTaskPtr currentRenderTask; + bool firstPointParsed = false; - for ( Integration::PointContainerConstIterator iter = event.points.begin(), beginIter = event.points.begin(), endIter = event.points.end(); iter != endIter; ++iter ) + for(auto&& currentPoint : event.points) { HitTestAlgorithm::Results hitTestResults; - HitTestAlgorithm::HitTest( mScene.GetSize(), mScene.GetRenderTaskList(), mScene.GetLayerList(), iter->GetScreenPosition(), hitTestResults ); + if(!firstPointParsed) + { + firstPointParsed = true; + ParsePrimaryTouchPoint(hitTestResults, mCapturingTouchActor, mLastRenderTask, currentPoint, mScene); - Integration::Point newPoint( *iter ); - newPoint.SetHitActor( hitTestResults.actor ); - newPoint.SetLocalPosition( hitTestResults.actorCoordinates ); + // Only set the currentRenderTask for the primary hit actor. + currentRenderTask = hitTestResults.renderTask; + } + else + { + HitTestAlgorithm::HitTest(mScene.GetSize(), mScene.GetRenderTaskList(), mScene.GetLayerList(), currentPoint.GetScreenPosition(), hitTestResults); + } - touchEvent.points.push_back( newPoint.GetTouchPoint() ); - touchData->AddPoint( newPoint ); + Integration::Point newPoint(currentPoint); + newPoint.SetHitActor(hitTestResults.actor); + newPoint.SetLocalPosition(hitTestResults.actorCoordinates); - DALI_LOG_INFO( gLogFilter, Debug::General, " State(%s), Screen(%.0f, %.0f), HitActor(%p, %s), Local(%.2f, %.2f)\n", - TOUCH_POINT_STATE[iter->GetState()], iter->GetScreenPosition().x, iter->GetScreenPosition().y, - ( hitTestResults.actor ? reinterpret_cast< void* >( &hitTestResults.actor.GetBaseObject() ) : NULL ), - ( hitTestResults.actor ? hitTestResults.actor.GetName().c_str() : "" ), - hitTestResults.actorCoordinates.x, hitTestResults.actorCoordinates.y ); + touchEventImpl->AddPoint(newPoint); - // Only set the currentRenderTask for the primary hit actor. - if ( iter == beginIter && hitTestResults.renderTask ) - { - currentRenderTask = hitTestResults.renderTask; - } + DALI_LOG_INFO(gLogFilter, Debug::General, " State(%s), Screen(%.0f, %.0f), HitActor(%p, %s), Local(%.2f, %.2f)\n", TOUCH_POINT_STATE[currentPoint.GetState()], currentPoint.GetScreenPosition().x, currentPoint.GetScreenPosition().y, (hitTestResults.actor ? reinterpret_cast(&hitTestResults.actor.GetBaseObject()) : NULL), (hitTestResults.actor ? hitTestResults.actor.GetProperty(Dali::Actor::Property::NAME).c_str() : ""), hitTestResults.actorCoordinates.x, hitTestResults.actorCoordinates.y); } // 3) Recursively deliver events to the actor and its parents, until the event is consumed or the stage is reached. + bool consumed = false; + // Emit the touch signal Dali::Actor consumedActor; - if ( currentRenderTask ) + if(currentRenderTask) { - consumedActor = EmitTouchSignals( touchData->GetPoint( 0 ).GetHitActor(), touchEvent, touchDataHandle ); + // 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; } - Integration::Point& primaryPoint = touchData->GetPoint( 0 ); - Dali::Actor primaryHitActor = primaryPoint.GetHitActor(); - PointState::Type primaryPointState = primaryPoint.GetState(); + Integration::Point& primaryPoint = touchEventImpl->GetPoint(0); + Dali::Actor primaryHitActor = primaryPoint.GetHitActor(); + PointState::Type primaryPointState = primaryPoint.GetState(); - DALI_LOG_INFO( gLogFilter, Debug::Concise, "PrimaryHitActor: (%p) %s\n", primaryHitActor ? reinterpret_cast< void* >( &primaryHitActor.GetBaseObject() ) : NULL, primaryHitActor ? primaryHitActor.GetName().c_str() : "" ); - DALI_LOG_INFO( gLogFilter, Debug::Concise, "ConsumedActor: (%p) %s\n", consumedActor ? reinterpret_cast< void* >( &consumedActor.GetBaseObject() ) : NULL, consumedActor ? consumedActor.GetName().c_str() : "" ); + DALI_LOG_INFO(gLogFilter, Debug::Concise, "PrimaryHitActor: (%p) %s\n", primaryHitActor ? reinterpret_cast(&primaryHitActor.GetBaseObject()) : NULL, primaryHitActor ? primaryHitActor.GetProperty(Dali::Actor::Property::NAME).c_str() : ""); + DALI_LOG_INFO(gLogFilter, Debug::Concise, "ConsumedActor: (%p) %s\n", consumedActor ? reinterpret_cast(&consumedActor.GetBaseObject()) : NULL, consumedActor ? consumedActor.GetProperty(Dali::Actor::Property::NAME).c_str() : ""); - if ( ( primaryPointState == PointState::DOWN ) && - ( touchEvent.GetPointCount() == 1 ) && - ( consumedActor && consumedActor.OnStage() ) ) + if((primaryPointState == PointState::DOWN) && + (touchEventImpl->GetPointCount() == 1) && + (consumedActor && consumedActor.GetProperty(Dali::Actor::Property::CONNECTED_TO_SCENE))) { - mTouchDownConsumedActor.SetActor( &GetImplementation( consumedActor ) ); + mTouchDownConsumedActor.SetActor(&GetImplementation(consumedActor)); } // 4) Check if the last primary hit actor requires a leave event and if it was different to the current primary // hit actor. Also process the last consumed actor in the same manner. - Actor* lastPrimaryHitActor( mLastPrimaryHitActor.GetActor() ); - Actor* lastConsumedActor( mLastConsumedActor.GetActor() ); - if( ( primaryPointState == PointState::MOTION ) || ( primaryPointState == PointState::UP ) || ( primaryPointState == PointState::STATIONARY ) ) + Actor* lastPrimaryHitActor(mLastPrimaryHitActor.GetActor()); + Actor* lastConsumedActor(mLastConsumedActor.GetActor()); + if((primaryPointState == PointState::MOTION) || (primaryPointState == PointState::UP) || (primaryPointState == PointState::STATIONARY)) { - if( mLastRenderTask ) + if(mLastRenderTask) { Dali::Actor leaveEventConsumer; RenderTask& lastRenderTaskImpl = *mLastRenderTask.Get(); - if( lastPrimaryHitActor && - lastPrimaryHitActor != primaryHitActor && - lastPrimaryHitActor != consumedActor ) + if(lastPrimaryHitActor && + lastPrimaryHitActor != primaryHitActor && + lastPrimaryHitActor != consumedActor) { - if( lastPrimaryHitActor->IsHittable() && IsActuallySensitive( lastPrimaryHitActor ) ) + if(lastPrimaryHitActor->IsHittable() && IsActuallySensitive(lastPrimaryHitActor)) { - if ( lastPrimaryHitActor->GetLeaveRequired() ) + if(lastPrimaryHitActor->GetLeaveRequired()) { - DALI_LOG_INFO( gLogFilter, Debug::Concise, "LeaveActor(Hit): (%p) %s\n", reinterpret_cast< void* >( lastPrimaryHitActor ), lastPrimaryHitActor->GetName().c_str() ); - leaveEventConsumer = EmitTouchSignals( mLastPrimaryHitActor.GetActor(), lastRenderTaskImpl, touchEvent, touchData, PointState::LEAVE ); + DALI_LOG_INFO(gLogFilter, Debug::Concise, "LeaveActor(Hit): (%p) %s\n", reinterpret_cast(lastPrimaryHitActor), lastPrimaryHitActor->GetName().data()); + leaveEventConsumer = EmitTouchSignals(mLastPrimaryHitActor.GetActor(), lastRenderTaskImpl, touchEventImpl, PointState::LEAVE); } } else { // At this point mLastPrimaryHitActor was touchable and sensitive in the previous touch event process but is not in the current one. // An interrupted event is send to allow some actors to go back to their original state (i.e. Button controls) - DALI_LOG_INFO( gLogFilter, Debug::Concise, "InterruptedActor(Hit): (%p) %s\n", reinterpret_cast< void* >( lastPrimaryHitActor ), lastPrimaryHitActor->GetName().c_str() ); - leaveEventConsumer = EmitTouchSignals( mLastPrimaryHitActor.GetActor(), lastRenderTaskImpl, touchEvent, touchData, PointState::INTERRUPTED ); + DALI_LOG_INFO(gLogFilter, Debug::Concise, "InterruptedActor(Hit): (%p) %s\n", reinterpret_cast(lastPrimaryHitActor), lastPrimaryHitActor->GetName().data()); + leaveEventConsumer = EmitTouchSignals(mLastPrimaryHitActor.GetActor(), lastRenderTaskImpl, touchEventImpl, PointState::INTERRUPTED); } } + consumed |= leaveEventConsumer ? true : false; + // Check if the motion event has been consumed by another actor's listener. In this case, the previously // consumed actor's listeners may need to be informed (through a leave event). // Further checks here to ensure we do not signal the same actor twice for the same event. - if ( lastConsumedActor && - lastConsumedActor != consumedActor && - lastConsumedActor != lastPrimaryHitActor && - lastConsumedActor != primaryHitActor && - lastConsumedActor != leaveEventConsumer ) + if(lastConsumedActor && + lastConsumedActor != consumedActor && + lastConsumedActor != lastPrimaryHitActor && + lastConsumedActor != primaryHitActor && + lastConsumedActor != leaveEventConsumer) { - if( lastConsumedActor->IsHittable() && IsActuallySensitive( lastConsumedActor ) ) + if(lastConsumedActor->IsHittable() && IsActuallySensitive(lastConsumedActor)) { - if( lastConsumedActor->GetLeaveRequired() ) + if(lastConsumedActor->GetLeaveRequired()) { - DALI_LOG_INFO( gLogFilter, Debug::Concise, "LeaveActor(Consume): (%p) %s\n", reinterpret_cast< void* >( lastConsumedActor ), lastConsumedActor->GetName().c_str() ); - EmitTouchSignals( lastConsumedActor, lastRenderTaskImpl, touchEvent, touchData, PointState::LEAVE ); + DALI_LOG_INFO(gLogFilter, Debug::Concise, "LeaveActor(Consume): (%p) %s\n", reinterpret_cast(lastConsumedActor), lastConsumedActor->GetName().data()); + EmitTouchSignals(lastConsumedActor, lastRenderTaskImpl, touchEventImpl, PointState::LEAVE); } } else { // At this point mLastConsumedActor was touchable and sensitive in the previous touch event process but is not in the current one. // An interrupted event is send to allow some actors to go back to their original state (i.e. Button controls) - DALI_LOG_INFO( gLogFilter, Debug::Concise, "InterruptedActor(Consume): (%p) %s\n", reinterpret_cast< void* >( lastConsumedActor ), lastConsumedActor->GetName().c_str() ); - EmitTouchSignals( mLastConsumedActor.GetActor(), lastRenderTaskImpl, touchEvent, touchData, PointState::INTERRUPTED ); + DALI_LOG_INFO(gLogFilter, Debug::Concise, "InterruptedActor(Consume): (%p) %s\n", reinterpret_cast(lastConsumedActor), lastConsumedActor->GetName().data()); + EmitTouchSignals(mLastConsumedActor.GetActor(), lastRenderTaskImpl, touchEventImpl, PointState::INTERRUPTED); } } } @@ -352,35 +429,37 @@ void TouchEventProcessor::ProcessTouchEvent( const Integration::TouchEvent& even // 5) If our primary point is an Up event, then the primary point (in multi-touch) will change next // time so set our last primary actor to NULL. Do the same to the last consumed actor as well. - if ( primaryPointState == PointState::UP ) + if(primaryPointState == PointState::UP) { - mLastPrimaryHitActor.SetActor( NULL ); - mLastConsumedActor.SetActor( NULL ); + mLastPrimaryHitActor.SetActor(nullptr); + mLastConsumedActor.SetActor(nullptr); + mCapturingTouchActor.SetActor(nullptr); mLastRenderTask.Reset(); } else { - // The primaryHitActor may have been removed from the stage so ensure it is still on the stage before setting members. - if ( primaryHitActor && primaryHitActor.OnStage() ) + // The primaryHitActor may have been removed from the scene so ensure it is still on the scene before setting members. + if(primaryHitActor && GetImplementation(primaryHitActor).OnScene()) { - mLastPrimaryHitActor.SetActor( &GetImplementation( primaryHitActor ) ); + mLastPrimaryHitActor.SetActor(&GetImplementation(primaryHitActor)); - // Only observe the consumed actor if we have a primaryHitActor (check if it is still on stage). - if ( consumedActor && consumedActor.OnStage() ) + // Only observe the consumed actor if we have a primaryHitActor (check if it is still on the scene). + if(consumedActor && GetImplementation(consumedActor).OnScene()) { - mLastConsumedActor.SetActor( &GetImplementation( consumedActor ) ); + mLastConsumedActor.SetActor(&GetImplementation(consumedActor)); } else { - mLastConsumedActor.SetActor( NULL ); + mLastConsumedActor.SetActor(nullptr); } mLastRenderTask = currentRenderTask; } else { - mLastPrimaryHitActor.SetActor( NULL ); - mLastConsumedActor.SetActor( NULL ); + mLastPrimaryHitActor.SetActor(nullptr); + mLastConsumedActor.SetActor(nullptr); + mCapturingTouchActor.SetActor(nullptr); mLastRenderTask.Reset(); } } @@ -388,35 +467,35 @@ void TouchEventProcessor::ProcessTouchEvent( const Integration::TouchEvent& even // 6) Emit an interrupted event to the touch-down actor if it hasn't consumed the up and // emit the stage touched event if required. - if ( touchEvent.GetPointCount() == 1 ) // Only want the first touch and the last release + if(touchEventImpl->GetPointCount() == 1) // Only want the first touch and the last release { - switch ( primaryPointState ) + switch(primaryPointState) { case PointState::UP: { - Actor* touchDownConsumedActor( mTouchDownConsumedActor.GetActor() ); - if ( touchDownConsumedActor && - touchDownConsumedActor != consumedActor && - touchDownConsumedActor != lastPrimaryHitActor && - touchDownConsumedActor != lastConsumedActor ) + Actor* touchDownConsumedActor(mTouchDownConsumedActor.GetActor()); + if(touchDownConsumedActor && + touchDownConsumedActor != consumedActor && + touchDownConsumedActor != lastPrimaryHitActor && + touchDownConsumedActor != lastConsumedActor) { - Dali::Actor touchDownConsumedActorHandle( touchDownConsumedActor ); + Dali::Actor touchDownConsumedActorHandle(touchDownConsumedActor); - Integration::Point currentPoint = touchData->GetPoint( 0 ); - currentPoint.SetHitActor( touchDownConsumedActorHandle ); - currentPoint.SetState( PointState::INTERRUPTED ); + Integration::Point currentPoint = touchEventImpl->GetPoint(0); + currentPoint.SetHitActor(touchDownConsumedActorHandle); + currentPoint.SetState(PointState::INTERRUPTED); - AllocAndEmitTouchSignals( event.time, touchDownConsumedActorHandle, currentPoint ); + AllocAndEmitTouchSignals(event.time, touchDownConsumedActorHandle, currentPoint); } - mTouchDownConsumedActor.SetActor( NULL ); + mTouchDownConsumedActor.SetActor(nullptr); DALI_FALLTHROUGH; } case PointState::DOWN: { - mScene.EmitTouchedSignal( touchEvent, touchDataHandle ); + mScene.EmitTouchedSignal(touchEventHandle); break; } @@ -430,35 +509,34 @@ void TouchEventProcessor::ProcessTouchEvent( const Integration::TouchEvent& even } } } + + return consumed; } -void TouchEventProcessor::OnObservedActorDisconnected( Actor* actor ) +void TouchEventProcessor::OnObservedActorDisconnected(Actor* actor) { - if ( actor == mLastPrimaryHitActor.GetActor() ) + if(actor == mLastPrimaryHitActor.GetActor()) { - Dali::Actor handle( actor ); + Dali::Actor actorHandle(actor); Integration::Point point; - point.SetState( PointState::INTERRUPTED ); - point.SetHitActor( handle ); - - TouchDataPtr touchData( new TouchData ); - touchData->AddPoint( point ); - Dali::TouchData touchDataHandle( touchData.Get() ); + point.SetState(PointState::INTERRUPTED); + point.SetHitActor(actorHandle); - TouchEvent touchEvent( 0 ); - touchEvent.points.push_back( point.GetTouchPoint() ); + TouchEventPtr touchEventImpl(new TouchEvent); + touchEventImpl->AddPoint(point); + Dali::TouchEvent touchEventHandle(touchEventImpl.Get()); - Dali::Actor eventConsumer = EmitTouchSignals( handle, touchEvent, touchDataHandle ); + Dali::Actor eventConsumer = EmitTouchSignals(actorHandle, touchEventHandle); - if ( mLastConsumedActor.GetActor() != eventConsumer ) + if(mLastConsumedActor.GetActor() != eventConsumer) { - EmitTouchSignals( Dali::Actor( mLastConsumedActor.GetActor() ), touchEvent, touchDataHandle ); + EmitTouchSignals(Dali::Actor(mLastConsumedActor.GetActor()), touchEventHandle); } // Do not set mLastPrimaryHitActor to NULL we may be iterating through its observers - mLastConsumedActor.SetActor( NULL ); + mLastConsumedActor.SetActor(nullptr); mLastRenderTask.Reset(); } }