Print the number of loop count when we trace iteration
[platform/core/uifw/dali-core.git] / dali / internal / event / events / tap-gesture / tap-gesture-processor.cpp
1 /*
2  * Copyright (c) 2023 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/event/events/tap-gesture/tap-gesture-processor.h>
20
21 // EXTERNAL INCLUDES
22 #include <algorithm>
23
24 // INTERNAL INCLUDES
25 #include <dali/integration-api/debug.h>
26 #include <dali/integration-api/trace.h>
27 #include <dali/internal/event/actors/actor-impl.h>
28 #include <dali/internal/event/common/scene-impl.h>
29 #include <dali/internal/event/events/gesture-requests.h>
30 #include <dali/internal/event/events/tap-gesture/tap-gesture-event.h>
31 #include <dali/internal/event/events/tap-gesture/tap-gesture-impl.h>
32 #include <dali/internal/event/events/tap-gesture/tap-gesture-recognizer.h>
33 #include <dali/internal/event/render-tasks/render-task-impl.h>
34 #include <dali/public-api/actors/actor.h>
35 #include <dali/public-api/common/dali-common.h>
36 #include <dali/public-api/events/tap-gesture.h>
37 #include <dali/public-api/math/vector2.h>
38
39 namespace Dali
40 {
41 namespace Internal
42 {
43 namespace
44 {
45 DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_PERFORMANCE_MARKER, false);
46 constexpr uint32_t DEFAULT_MAXIMUM_ALLOWED_TIME = 330u;
47 constexpr uint32_t DEFAULT_RECOGNIZER_TIME      = 330u;
48
49 /**
50  * Creates a TapGesture and asks the specified detector to emit its detected signal.
51  * @param[in]  actor             The actor on which a tap has occurred.
52  * @param[in]  gestureDetectors  A reference to gesture detectors that should emit the signal.
53  * @param[in]  tapEvent          The tapEvent received from the adaptor.
54  * @param[in]  localPoint        Relative to the actor attached to the detector.
55  */
56 void EmitTapSignal(
57   Actor*                          actor,
58   const GestureDetectorContainer& gestureDetectors,
59   const TapGestureEvent&          tapEvent,
60   Vector2                         localPoint)
61 {
62   Internal::TapGesturePtr tap(new Internal::TapGesture(tapEvent.state));
63   tap->SetTime(tapEvent.time);
64   tap->SetNumberOfTaps(tapEvent.numberOfTaps);
65   tap->SetNumberOfTouches(tapEvent.numberOfTouches);
66   tap->SetScreenPoint(tapEvent.point);
67   tap->SetLocalPoint(localPoint);
68   tap->SetSourceType(tapEvent.sourceType);
69   tap->SetSourceData(tapEvent.sourceData);
70
71 #ifdef TRACE_ENABLED
72   if(gTraceFilter && gTraceFilter->IsTraceEnabled())
73   {
74     std::ostringstream stream;
75     stream << "[" << gestureDetectors.size() << "]";
76     DALI_TRACE_BEGIN_WITH_MESSAGE(gTraceFilter, "DALI_EMIT_TAP_GESTURE_SIGNAL", stream.str().c_str());
77   }
78 #endif
79
80   Dali::Actor                                    actorHandle(actor);
81   const GestureDetectorContainer::const_iterator endIter = gestureDetectors.end();
82   for(GestureDetectorContainer::const_iterator iter = gestureDetectors.begin(); iter != endIter; ++iter)
83   {
84     static_cast<TapGestureDetector*>(*iter)->EmitTapGestureSignal(actorHandle, Dali::TapGesture(tap.Get()));
85   }
86
87 #ifdef TRACE_ENABLED
88   if(gTraceFilter && gTraceFilter->IsTraceEnabled())
89   {
90     std::ostringstream stream;
91     stream << "[" << gestureDetectors.size() << "]";
92     DALI_TRACE_END_WITH_MESSAGE(gTraceFilter, "DALI_EMIT_TAP_GESTURE_SIGNAL", stream.str().c_str());
93   }
94 #endif
95 }
96
97 } // unnamed namespace
98
99 TapGestureProcessor::TapGestureProcessor()
100 : GestureProcessor(GestureType::TAP),
101   mTapGestureDetectors(),
102   mMinTouchesRequired(1),
103   mMaxTouchesRequired(1),
104   mCurrentTapEvent(nullptr),
105   mPossibleProcessed(false),
106   mMaximumAllowedTime(DEFAULT_MAXIMUM_ALLOWED_TIME),
107   mRecognizerTime(DEFAULT_RECOGNIZER_TIME)
108 {
109 }
110
111 TapGestureProcessor::~TapGestureProcessor() = default;
112
113 void TapGestureProcessor::Process(Scene& scene, const TapGestureEvent& tapEvent)
114 {
115   DALI_TRACE_SCOPE(gTraceFilter, "DALI_PROCESS_TAP_GESTURE");
116   switch(tapEvent.state)
117   {
118     case GestureState::POSSIBLE:
119     {
120       // 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 )
121       HitTestAlgorithm::Results hitTestResults;
122       if(HitTest(scene, tapEvent.point, hitTestResults))
123       {
124         SetActor(&GetImplementation(hitTestResults.actor));
125         mCurrentTapActor.SetActor(GetCurrentGesturedActor());
126
127         // Indicate that we've processed a touch down. Bool should be sufficient as a change in actor will result in a cancellation
128         mPossibleProcessed = true;
129       }
130       else
131       {
132         ResetActor();
133       }
134       break;
135     }
136
137     case GestureState::STARTED:
138     {
139       // Ensure that we're processing a hit on the current actor and that we've already processed a touch down
140       HitTestAlgorithm::Results hitTestResults;
141       if(GetCurrentGesturedActor() && HitTest(scene, tapEvent.point, hitTestResults) && mPossibleProcessed)
142       {
143         // Check that this actor is still the one that was used for the last touch down ?
144         if(mCurrentTapActor.GetActor() == &GetImplementation(hitTestResults.actor))
145         {
146           mCurrentTapEvent = &tapEvent;
147           ProcessAndEmit(hitTestResults);
148         }
149         mCurrentTapEvent   = nullptr;
150         mPossibleProcessed = false;
151       }
152       break;
153     }
154
155     case GestureState::CANCELLED:
156     {
157       mPossibleProcessed = false;
158       ResetActor();
159       break;
160     }
161
162     case GestureState::CONTINUING:
163     {
164       DALI_ABORT("Incorrect state received from Integration layer: CONTINUING\n");
165       break;
166     }
167     case GestureState::FINISHED:
168     {
169       DALI_ABORT("Incorrect state received from Integration layer: FINISHED\n");
170       break;
171     }
172     case GestureState::CLEAR:
173     {
174       DALI_ABORT("Incorrect state received from Integration layer: CLEAR\n");
175       break;
176     }
177   }
178 }
179
180 void TapGestureProcessor::AddGestureDetector(TapGestureDetector* gestureDetector, Scene& scene)
181 {
182   bool firstRegistration(mTapGestureDetectors.empty());
183
184   mTapGestureDetectors.push_back(gestureDetector);
185
186   const unsigned int touchesRequired = gestureDetector->GetTouchesRequired();
187
188   if(firstRegistration)
189   {
190     // If this is the first tap gesture detector that has been added, then our minimum and maximum
191     // requirements are the same as each other.
192
193     mMinTouchesRequired = mMaxTouchesRequired = touchesRequired;
194
195     TapGestureRequest request;
196     request.minTouches = mMinTouchesRequired;
197     request.maxTouches = mMaxTouchesRequired;
198
199     Size size          = scene.GetSize();
200     mGestureRecognizer = new TapGestureRecognizer(*this, Vector2(size.width, size.height), static_cast<const TapGestureRequest&>(request), mMaximumAllowedTime, mRecognizerTime);
201   }
202   else
203   {
204     // If we have already registered for tap gesture detection before then we need to check our
205     // minimum and maximums and see if our gesture detection requirements have changed, if they
206     // have, then we should ask the adaptor to update its detection policy.
207
208     // This is quicker than calling UpdateDetection as there is no need to iterate through the container
209
210     unsigned int minTouches = mMinTouchesRequired < touchesRequired ? mMinTouchesRequired : touchesRequired;
211     unsigned int maxTouches = mMaxTouchesRequired > touchesRequired ? mMaxTouchesRequired : touchesRequired;
212
213     if((minTouches != mMinTouchesRequired) || (maxTouches != mMaxTouchesRequired))
214     {
215       TapGestureRequest request;
216       request.minTouches = mMinTouchesRequired = minTouches;
217       request.maxTouches = mMaxTouchesRequired = maxTouches;
218
219       mGestureRecognizer->Update(request);
220     }
221   }
222 }
223
224 void TapGestureProcessor::RemoveGestureDetector(TapGestureDetector* gestureDetector)
225 {
226   // Find detector ...
227   TapGestureDetectorContainer::iterator endIter = std::remove(mTapGestureDetectors.begin(), mTapGestureDetectors.end(), gestureDetector);
228   DALI_ASSERT_DEBUG(endIter != mTapGestureDetectors.end());
229
230   // ... and remove it
231   mTapGestureDetectors.erase(endIter, mTapGestureDetectors.end());
232
233   if(mTapGestureDetectors.empty())
234   {
235     mGestureRecognizer = nullptr;
236
237     ResetActor();
238   }
239   else
240   {
241     UpdateDetection();
242   }
243 }
244
245 void TapGestureProcessor::GestureDetectorUpdated(TapGestureDetector* gestureDetector)
246 {
247   // Nothing to do.
248 }
249
250 void TapGestureProcessor::SetMaximumAllowedTime(uint32_t time)
251 {
252   if(time == 0u)
253   {
254     DALI_LOG_WARNING("MaximumAllowedTime must be greater than zero.");
255     return;
256   }
257   if(mMaximumAllowedTime != time)
258   {
259     mMaximumAllowedTime = time;
260
261     if(mGestureRecognizer)
262     {
263       TapGestureRecognizer* tapRecognizer = dynamic_cast<TapGestureRecognizer*>(mGestureRecognizer.Get());
264       if(tapRecognizer)
265       {
266         tapRecognizer->SetMaximumAllowedTime(time);
267       }
268     }
269   }
270 }
271
272 uint32_t TapGestureProcessor::GetMaximumAllowedTime() const
273 {
274   return mMaximumAllowedTime;
275 }
276
277 void TapGestureProcessor::SetRecognizerTime(uint32_t time)
278 {
279   if(time == 0u)
280   {
281     DALI_LOG_WARNING("RecognizerTime must be greater than zero.");
282     return;
283   }
284   if(mRecognizerTime != time)
285   {
286     mRecognizerTime = time;
287
288     if(mGestureRecognizer)
289     {
290       TapGestureRecognizer* tapRecognizer = dynamic_cast<TapGestureRecognizer*>(mGestureRecognizer.Get());
291       if(tapRecognizer)
292       {
293         tapRecognizer->SetRecognizerTime(time);
294       }
295     }
296   }
297 }
298
299 void TapGestureProcessor::UpdateDetection()
300 {
301   DALI_ASSERT_DEBUG(!mTapGestureDetectors.empty());
302
303   unsigned int minTouches = UINT_MAX;
304   unsigned int maxTouches = 0;
305
306   for(TapGestureDetectorContainer::iterator iter = mTapGestureDetectors.begin(), endIter = mTapGestureDetectors.end(); iter != endIter; ++iter)
307   {
308     TapGestureDetector* detector(*iter);
309
310     if(detector)
311     {
312       const unsigned int touchesRequired = detector->GetTouchesRequired();
313
314       minTouches = touchesRequired < minTouches ? touchesRequired : minTouches;
315       maxTouches = touchesRequired > maxTouches ? touchesRequired : maxTouches;
316     }
317   }
318
319   if((minTouches != mMinTouchesRequired) || (maxTouches != mMaxTouchesRequired))
320   {
321     TapGestureRequest request;
322     request.minTouches = mMinTouchesRequired = minTouches;
323     request.maxTouches = mMaxTouchesRequired = maxTouches;
324
325     mGestureRecognizer->Update(request);
326   }
327 }
328
329 bool TapGestureProcessor::CheckGestureDetector(GestureDetector* detector, Actor* actor)
330 {
331   DALI_ASSERT_DEBUG(mCurrentTapEvent);
332
333   TapGestureDetector* tapDetector(static_cast<TapGestureDetector*>(detector));
334
335   return (tapDetector->GetMinimumTapsRequired() <= mCurrentTapEvent->numberOfTaps) && (tapDetector->GetTouchesRequired() == mCurrentTapEvent->numberOfTouches);
336 }
337
338 void TapGestureProcessor::EmitGestureSignal(Actor* actor, const GestureDetectorContainer& gestureDetectors, Vector2 actorCoordinates)
339 {
340   DALI_ASSERT_DEBUG(mCurrentTapEvent);
341
342   EmitTapSignal(actor, gestureDetectors, *mCurrentTapEvent, actorCoordinates);
343 }
344
345 } // namespace Internal
346
347 } // namespace Dali