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