2 * Copyright (c) 2023 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/event/events/tap-gesture/tap-gesture-detector-impl.h>
22 #include <cstring> // for strcmp
25 #include <dali/integration-api/debug.h>
26 #include <dali/integration-api/platform-abstraction.h>
27 #include <dali/internal/event/common/thread-local-storage.h>
28 #include <dali/internal/event/events/gesture-event-processor.h>
29 #include <dali/internal/event/events/tap-gesture/tap-gesture-impl.h>
30 #include <dali/public-api/events/tap-gesture.h>
31 #include <dali/public-api/object/type-registry.h>
39 #if defined(DEBUG_ENABLED)
40 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_TAP_GESTURE_DETECTOR");
41 #endif // defined(DEBUG_ENABLED)
43 constexpr uint32_t DEFAULT_TAPS_REQUIRED = 1u;
44 constexpr uint32_t DEFAULT_TOUCHES_REQUIRED = 1u;
45 constexpr uint32_t DEFAULT_TAP_WAIT_TIME = 330u;
48 const char* const SIGNAL_TAP_DETECTED = "tapDetected";
52 return Dali::TapGestureDetector::New();
55 TypeRegistration mType(typeid(Dali::TapGestureDetector), typeid(Dali::GestureDetector), Create);
57 SignalConnectorType signalConnector1(mType, SIGNAL_TAP_DETECTED, &TapGestureDetector::DoConnectSignal);
61 TapGestureDetectorPtr TapGestureDetector::New()
63 return new TapGestureDetector(DEFAULT_TAPS_REQUIRED);
66 TapGestureDetectorPtr TapGestureDetector::New(uint32_t tapsRequired)
68 return new TapGestureDetector(tapsRequired);
71 TapGestureDetector::TapGestureDetector(uint32_t tapsRequired)
72 : GestureDetector(GestureType::TAP),
73 mMinimumTapsRequired(tapsRequired),
74 mMaximumTapsRequired(tapsRequired),
75 mTouchesRequired(DEFAULT_TOUCHES_REQUIRED),
77 mWaitTime(DEFAULT_TAP_WAIT_TIME),
80 mReceiveAllTapEvents(false)
84 TapGestureDetector::~TapGestureDetector()
86 if(mTimerId != 0 && ThreadLocalStorage::Created())
88 Dali::Integration::PlatformAbstraction& platformAbstraction = ThreadLocalStorage::Get().GetPlatformAbstraction();
89 platformAbstraction.CancelTimer(mTimerId);
93 bool TapGestureDetector::CheckMinMaxTapsRequired()
95 if(mMinimumTapsRequired > mMaximumTapsRequired)
97 DALI_LOG_ERROR("Minimum taps requested is greater than the maximum requested. minimumTapsRequired(%d) maximumTapsRequired(%d)\n", mMinimumTapsRequired, mMaximumTapsRequired);
107 void TapGestureDetector::SetMinimumTapsRequired(uint32_t taps)
109 if(mMinimumTapsRequired != taps)
111 mMinimumTapsRequired = taps;
113 if(!mAttachedActors.empty())
115 CheckMinMaxTapsRequired();
120 void TapGestureDetector::SetMaximumTapsRequired(uint32_t taps)
122 if(mMaximumTapsRequired != taps)
124 mMaximumTapsRequired = taps;
126 if(!mAttachedActors.empty())
128 CheckMinMaxTapsRequired();
133 void TapGestureDetector::SetTouchesRequired(uint32_t touches)
135 if(mTouchesRequired != touches)
137 mTouchesRequired = touches;
139 if(!mAttachedActors.empty())
141 mGestureEventProcessor.GestureDetectorUpdated(this);
146 uint32_t TapGestureDetector::GetMinimumTapsRequired() const
148 return mMinimumTapsRequired;
151 uint32_t TapGestureDetector::GetMaximumTapsRequired() const
153 return mMaximumTapsRequired;
156 uint32_t TapGestureDetector::GetTouchesRequired() const
158 return mTouchesRequired;
161 void TapGestureDetector::ReceiveAllTapEvents(bool receive)
163 mReceiveAllTapEvents = receive;
166 void TapGestureDetector::EmitTapGestureSignal(Dali::Actor tappedActor, const Dali::TapGesture& tap)
168 if(!CheckMinMaxTapsRequired())
173 Dali::Integration::PlatformAbstraction& platformAbstraction = ThreadLocalStorage::Get().GetPlatformAbstraction();
176 platformAbstraction.CancelTimer(mTimerId);
180 uint32_t numberOfTaps = 0u;
181 if(mMaximumTapsRequired > 0u)
183 numberOfTaps = tap.GetNumberOfTaps() % mMaximumTapsRequired;
184 numberOfTaps = numberOfTaps == 0u ? mMaximumTapsRequired : numberOfTaps;
185 if (numberOfTaps >= mMinimumTapsRequired)
187 Internal::TapGesturePtr internalTap(new Internal::TapGesture(tap.GetState()));
188 internalTap->SetTime(tap.GetTime());
189 internalTap->SetNumberOfTouches(tap.GetNumberOfTouches());
190 internalTap->SetScreenPoint(tap.GetScreenPoint());
191 internalTap->SetLocalPoint(tap.GetLocalPoint());
192 internalTap->SetSourceType(tap.GetSourceType());
193 internalTap->SetSourceData(tap.GetSourceData());
194 internalTap->SetNumberOfTaps(numberOfTaps);
195 mTap = Dali::TapGesture(internalTap.Get());
196 if(numberOfTaps == mMaximumTapsRequired || mReceiveAllTapEvents)
198 // Guard against destruction during signal emission
199 Dali::TapGestureDetector handle(this);
200 DALI_LOG_DEBUG_INFO("emitting tap gesture actor id(%d)\n", tappedActor.GetProperty<int32_t>(Dali::Actor::Property::ID));
201 mDetectedSignal.Emit(tappedActor, mTap);
205 mTappedActor = tappedActor;
206 mTimerId = platformAbstraction.StartTimer(mWaitTime, MakeCallback(this, &TapGestureDetector::TimerCallback));
212 bool TapGestureDetector::TimerCallback()
214 // Guard against destruction during signal emission
215 Dali::TapGestureDetector handle(this);
216 DALI_LOG_DEBUG_INFO("emitting tap gesture actor id(%d)\n", mTappedActor.GetProperty<int32_t>(Dali::Actor::Property::ID));
217 mDetectedSignal.Emit(mTappedActor, mTap);
223 bool TapGestureDetector::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
225 bool connected(true);
226 TapGestureDetector* gesture = static_cast<TapGestureDetector*>(object); // TypeRegistry guarantees that this is the correct type.
228 if(0 == strcmp(signalName.c_str(), SIGNAL_TAP_DETECTED))
230 gesture->DetectedSignal().Connect(tracker, functor);
234 // signalName does not match any signal
241 void TapGestureDetector::OnActorAttach(Actor& actor)
243 CheckMinMaxTapsRequired();
244 mWaitTime = mGestureEventProcessor.GetTapGestureProcessor().GetMaximumAllowedTime();
245 DALI_LOG_INFO(gLogFilter, Debug::General, "TapGestureDetector attach actor(%d)\n", actor.GetId());
248 void TapGestureDetector::OnActorDetach(Actor& actor)
250 DALI_LOG_INFO(gLogFilter, Debug::General, "TapGestureDetector detach actor(%d)\n", actor.GetId());
253 void TapGestureDetector::OnActorDestroyed(Object& object)
258 } // namespace Internal