/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
#include <algorithm>
// INTERNAL INCLUDES
-#include <dali/public-api/actors/actor.h>
-#include <dali/public-api/common/dali-common.h>
-#include <dali/public-api/events/tap-gesture.h>
-#include <dali/public-api/math/vector2.h>
#include <dali/integration-api/debug.h>
+#include <dali/integration-api/trace.h>
#include <dali/internal/event/actors/actor-impl.h>
-#include <dali/internal/event/render-tasks/render-task-impl.h>
#include <dali/internal/event/common/scene-impl.h>
-#include <dali/internal/event/events/tap-gesture/tap-gesture-recognizer.h>
-#include <dali/internal/event/events/tap-gesture/tap-gesture-impl.h>
#include <dali/internal/event/events/gesture-requests.h>
#include <dali/internal/event/events/tap-gesture/tap-gesture-event.h>
+#include <dali/internal/event/events/tap-gesture/tap-gesture-impl.h>
+#include <dali/internal/event/events/tap-gesture/tap-gesture-recognizer.h>
+#include <dali/internal/event/render-tasks/render-task-impl.h>
+#include <dali/public-api/actors/actor.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/events/tap-gesture.h>
+#include <dali/public-api/math/vector2.h>
namespace Dali
{
-
namespace Internal
{
-
namespace
{
+DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_PERFORMANCE_MARKER, false);
+constexpr uint32_t DEFAULT_MAXIMUM_ALLOWED_TIME = 330u;
+constexpr uint32_t DEFAULT_RECOGNIZER_TIME = 330u;
/**
* Creates a TapGesture and asks the specified detector to emit its detected signal.
* @param[in] localPoint Relative to the actor attached to the detector.
*/
void EmitTapSignal(
- Actor* actor,
+ Actor* actor,
const GestureDetectorContainer& gestureDetectors,
- const TapGestureEvent& tapEvent,
- Vector2 localPoint)
+ const TapGestureEvent& tapEvent,
+ Vector2 localPoint)
{
- Internal::TapGesturePtr tap( new Internal::TapGesture(tapEvent.state) );
- tap->SetTime( tapEvent.time );
+ Internal::TapGesturePtr tap(new Internal::TapGesture(tapEvent.state));
+ tap->SetTime(tapEvent.time);
tap->SetNumberOfTaps(tapEvent.numberOfTaps);
tap->SetNumberOfTouches(tapEvent.numberOfTouches);
tap->SetScreenPoint(tapEvent.point);
tap->SetLocalPoint(localPoint);
+ tap->SetSourceType(tapEvent.sourceType);
+ tap->SetSourceData(tapEvent.sourceData);
- Dali::Actor actorHandle( actor );
+ DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_EMIT_TAP_GESTURE_SIGNAL", [&](std::ostringstream& oss) {
+ oss << "[" << gestureDetectors.size() << "]";
+ });
+
+ Dali::Actor actorHandle(actor);
const GestureDetectorContainer::const_iterator endIter = gestureDetectors.end();
- for ( GestureDetectorContainer::const_iterator iter = gestureDetectors.begin(); iter != endIter; ++iter )
+ for(GestureDetectorContainer::const_iterator iter = gestureDetectors.begin(); iter != endIter; ++iter)
{
- static_cast< TapGestureDetector* >( *iter )->EmitTapGestureSignal( actorHandle, Dali::TapGesture( tap.Get() ) );
+ static_cast<TapGestureDetector*>(*iter)->EmitTapGestureSignal(actorHandle, Dali::TapGesture(tap.Get()));
}
+
+ DALI_TRACE_END_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_EMIT_TAP_GESTURE_SIGNAL", [&](std::ostringstream& oss) {
+ oss << "[" << gestureDetectors.size() << "]";
+ });
}
} // unnamed namespace
TapGestureProcessor::TapGestureProcessor()
-: GestureProcessor( GestureType::TAP ),
+: GestureProcessor(GestureType::TAP),
mTapGestureDetectors(),
- mMinTapsRequired( 1 ),
- mMaxTapsRequired( 1 ),
- mMinTouchesRequired( 1 ),
- mMaxTouchesRequired( 1 ),
- mCurrentTapEvent( nullptr ),
- mPossibleProcessed( false )
+ mMinTouchesRequired(1),
+ mMaxTouchesRequired(1),
+ mCurrentTapEvent(nullptr),
+ mPossibleProcessed(false),
+ mMaximumAllowedTime(DEFAULT_MAXIMUM_ALLOWED_TIME),
+ mRecognizerTime(DEFAULT_RECOGNIZER_TIME)
{
}
TapGestureProcessor::~TapGestureProcessor() = default;
-void TapGestureProcessor::Process( Scene& scene, const TapGestureEvent& tapEvent )
+void TapGestureProcessor::Process(Scene& scene, const TapGestureEvent& tapEvent)
{
- switch ( tapEvent.state )
+ DALI_TRACE_SCOPE(gTraceFilter, "DALI_PROCESS_TAP_GESTURE");
+ switch(tapEvent.state)
{
case GestureState::POSSIBLE:
{
// 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(GetFeededActor())
+ {
+ 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
+ mPossibleProcessed = true;
+ }
+ else if(HitTest(scene, tapEvent.point, hitTestResults))
{
- SetActor( &GetImplementation( hitTestResults.actor ) );
- mCurrentTapActor.SetActor( GetCurrentGesturedActor() );
+ SetActor(&GetImplementation(hitTestResults.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;
{
// 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(GetFeededActor())
+ {
+ 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, GetFeededGestureDetector());
+ }
+ 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;
}
case GestureState::CONTINUING:
{
- DALI_ABORT( "Incorrect state received from Integration layer: CONTINUING\n" );
+ DALI_ABORT("Incorrect state received from Integration layer: CONTINUING\n");
break;
}
case GestureState::FINISHED:
{
- DALI_ABORT( "Incorrect state received from Integration layer: FINISHED\n" );
+ DALI_ABORT("Incorrect state received from Integration layer: FINISHED\n");
break;
}
case GestureState::CLEAR:
{
- DALI_ABORT( "Incorrect state received from Integration layer: CLEAR\n" );
+ DALI_ABORT("Incorrect state received from Integration layer: CLEAR\n");
break;
}
}
}
-void TapGestureProcessor::AddGestureDetector( TapGestureDetector* gestureDetector, Scene& scene )
+void TapGestureProcessor::AddGestureDetector(TapGestureDetector* gestureDetector, Scene& scene)
{
bool firstRegistration(mTapGestureDetectors.empty());
mTapGestureDetectors.push_back(gestureDetector);
- const unsigned int minTapsRequired = gestureDetector->GetMinimumTapsRequired();
- const unsigned int maxTapsRequired = gestureDetector->GetMaximumTapsRequired();
const unsigned int touchesRequired = gestureDetector->GetTouchesRequired();
- DALI_ASSERT_ALWAYS( minTapsRequired <= maxTapsRequired && "Minimum taps requested is greater than the maximum requested" );
-
- if (firstRegistration)
+ if(firstRegistration)
{
// If this is the first tap gesture detector that has been added, then our minimum and maximum
// requirements are the same as each other.
- mMinTapsRequired = minTapsRequired;
- mMaxTapsRequired = maxTapsRequired;
mMinTouchesRequired = mMaxTouchesRequired = touchesRequired;
TapGestureRequest request;
- request.minTaps = mMinTapsRequired;
- request.maxTaps = mMaxTapsRequired;
request.minTouches = mMinTouchesRequired;
request.maxTouches = mMaxTouchesRequired;
- Size size = scene.GetSize();
- mGestureRecognizer = new TapGestureRecognizer(*this, Vector2(size.width, size.height), static_cast<const TapGestureRequest&>(request));
+ Size size = scene.GetSize();
+ mGestureRecognizer = new TapGestureRecognizer(*this, Vector2(size.width, size.height), static_cast<const TapGestureRequest&>(request), mMaximumAllowedTime, mRecognizerTime);
}
else
{
// This is quicker than calling UpdateDetection as there is no need to iterate through the container
- unsigned int minTaps = mMinTapsRequired < minTapsRequired ? mMinTapsRequired : minTapsRequired;
- unsigned int maxTaps = mMaxTapsRequired > maxTapsRequired ? mMaxTapsRequired : maxTapsRequired;
unsigned int minTouches = mMinTouchesRequired < touchesRequired ? mMinTouchesRequired : touchesRequired;
unsigned int maxTouches = mMaxTouchesRequired > touchesRequired ? mMaxTouchesRequired : touchesRequired;
- if ( (minTaps != mMinTapsRequired)||(maxTaps != mMaxTapsRequired) ||
- (minTouches != mMinTouchesRequired)||(maxTouches != mMaxTouchesRequired) )
+ if((minTouches != mMinTouchesRequired) || (maxTouches != mMaxTouchesRequired))
{
TapGestureRequest request;
- request.minTaps = mMinTapsRequired = minTaps;
- request.maxTaps = mMaxTapsRequired = maxTaps;
request.minTouches = mMinTouchesRequired = minTouches;
request.maxTouches = mMaxTouchesRequired = maxTouches;
}
}
-void TapGestureProcessor::RemoveGestureDetector( TapGestureDetector* gestureDetector )
+void TapGestureProcessor::RemoveGestureDetector(TapGestureDetector* gestureDetector)
{
// Find detector ...
- TapGestureDetectorContainer::iterator endIter = std::remove( mTapGestureDetectors.begin(), mTapGestureDetectors.end(), gestureDetector );
- DALI_ASSERT_DEBUG( endIter != mTapGestureDetectors.end() );
+ TapGestureDetectorContainer::iterator endIter = std::remove(mTapGestureDetectors.begin(), mTapGestureDetectors.end(), gestureDetector);
+ DALI_ASSERT_DEBUG(endIter != mTapGestureDetectors.end());
// ... and remove it
- mTapGestureDetectors.erase( endIter, mTapGestureDetectors.end() );
+ mTapGestureDetectors.erase(endIter, mTapGestureDetectors.end());
- if ( mTapGestureDetectors.empty() )
+ if(mTapGestureDetectors.empty())
{
mGestureRecognizer = nullptr;
}
}
-void TapGestureProcessor::GestureDetectorUpdated( TapGestureDetector* gestureDetector )
+void TapGestureProcessor::GestureDetectorUpdated(TapGestureDetector* gestureDetector)
{
- DALI_ASSERT_DEBUG(find(mTapGestureDetectors.begin(), mTapGestureDetectors.end(), gestureDetector) != mTapGestureDetectors.end());
+ // Nothing to do.
+}
- const unsigned int minTapsRequired = gestureDetector->GetMinimumTapsRequired();
- const unsigned int maxTapsRequired = gestureDetector->GetMaximumTapsRequired();
+void TapGestureProcessor::SetMaximumAllowedTime(uint32_t time)
+{
+ if(time == 0u)
+ {
+ DALI_LOG_WARNING("MaximumAllowedTime must be greater than zero.");
+ return;
+ }
+ if(mMaximumAllowedTime != time)
+ {
+ mMaximumAllowedTime = time;
- DALI_ASSERT_ALWAYS( minTapsRequired <= maxTapsRequired && "Minimum taps requested is greater than the maximum requested" );
+ if(mGestureRecognizer)
+ {
+ TapGestureRecognizer* tapRecognizer = dynamic_cast<TapGestureRecognizer*>(mGestureRecognizer.Get());
+ if(tapRecognizer)
+ {
+ tapRecognizer->SetMaximumAllowedTime(time);
+ }
+ }
+ }
+}
- UpdateDetection();
+uint32_t TapGestureProcessor::GetMaximumAllowedTime() const
+{
+ return mMaximumAllowedTime;
+}
+
+void TapGestureProcessor::SetRecognizerTime(uint32_t time)
+{
+ if(time == 0u)
+ {
+ DALI_LOG_WARNING("RecognizerTime must be greater than zero.");
+ return;
+ }
+ if(mRecognizerTime != time)
+ {
+ mRecognizerTime = time;
+
+ if(mGestureRecognizer)
+ {
+ TapGestureRecognizer* tapRecognizer = dynamic_cast<TapGestureRecognizer*>(mGestureRecognizer.Get());
+ if(tapRecognizer)
+ {
+ tapRecognizer->SetRecognizerTime(time);
+ }
+ }
+ }
}
void TapGestureProcessor::UpdateDetection()
{
DALI_ASSERT_DEBUG(!mTapGestureDetectors.empty());
- unsigned int minTaps = UINT_MAX;
- unsigned int maxTaps = 0;
unsigned int minTouches = UINT_MAX;
unsigned int maxTouches = 0;
- for ( TapGestureDetectorContainer::iterator iter = mTapGestureDetectors.begin(), endIter = mTapGestureDetectors.end(); iter != endIter; ++iter )
+ for(TapGestureDetectorContainer::iterator iter = mTapGestureDetectors.begin(), endIter = mTapGestureDetectors.end(); iter != endIter; ++iter)
{
TapGestureDetector* detector(*iter);
- if( detector )
+ if(detector)
{
- const unsigned int minTapsRequired = detector->GetMinimumTapsRequired();
- const unsigned int maxTapsRequired = detector->GetMaximumTapsRequired();
const unsigned int touchesRequired = detector->GetTouchesRequired();
- minTaps = minTapsRequired < minTaps ? minTapsRequired : minTaps;
- maxTaps = maxTapsRequired > maxTaps ? maxTapsRequired : maxTaps;
minTouches = touchesRequired < minTouches ? touchesRequired : minTouches;
maxTouches = touchesRequired > maxTouches ? touchesRequired : maxTouches;
}
}
- if ( (minTaps != mMinTapsRequired)||(maxTaps != mMaxTapsRequired) ||
- (minTouches != mMinTouchesRequired)||(maxTouches != mMaxTouchesRequired) )
+ if((minTouches != mMinTouchesRequired) || (maxTouches != mMaxTouchesRequired))
{
TapGestureRequest request;
- request.minTaps = mMinTapsRequired = minTaps;
- request.maxTaps = mMaxTapsRequired = maxTaps;
request.minTouches = mMinTouchesRequired = minTouches;
request.maxTouches = mMaxTouchesRequired = maxTouches;
}
}
-bool TapGestureProcessor::CheckGestureDetector( GestureDetector* detector, Actor* actor )
+bool TapGestureProcessor::CheckGestureDetector(GestureDetector* detector, Actor* actor)
{
- DALI_ASSERT_DEBUG( mCurrentTapEvent );
+ DALI_ASSERT_DEBUG(mCurrentTapEvent);
- TapGestureDetector* tapDetector ( static_cast< TapGestureDetector* >( detector ) );
+ TapGestureDetector* tapDetector(static_cast<TapGestureDetector*>(detector));
- return ( ( tapDetector->GetMinimumTapsRequired() <= mCurrentTapEvent->numberOfTaps ) && ( tapDetector->GetMaximumTapsRequired() >= mCurrentTapEvent->numberOfTaps ) ) &&
- ( tapDetector->GetTouchesRequired() == mCurrentTapEvent->numberOfTouches );
+ return (tapDetector->GetMinimumTapsRequired() <= mCurrentTapEvent->numberOfTaps) && (tapDetector->GetTouchesRequired() == mCurrentTapEvent->numberOfTouches);
}
-void TapGestureProcessor::EmitGestureSignal( Actor* actor, const GestureDetectorContainer& gestureDetectors, Vector2 actorCoordinates )
+void TapGestureProcessor::EmitGestureSignal(Actor* actor, const GestureDetectorContainer& gestureDetectors, Vector2 actorCoordinates)
{
- DALI_ASSERT_DEBUG( mCurrentTapEvent );
+ DALI_ASSERT_DEBUG(mCurrentTapEvent);
- EmitTapSignal( actor, gestureDetectors, *mCurrentTapEvent, actorCoordinates );
+ EmitTapSignal(actor, gestureDetectors, *mCurrentTapEvent, actorCoordinates);
}
} // namespace Internal