165fbc4310e66f4f85b176f7aa5de3143bc0b556
[platform/core/uifw/dali-core.git] / automated-tests / src / dali / utc-Dali-TapGestureRecognizer.cpp
1 /*
2  * Copyright (c) 2022 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 #include <dali-test-suite-utils.h>
19 #include <dali/integration-api/events/touch-event-integ.h>
20 #include <dali/integration-api/input-options.h>
21 #include <dali/integration-api/render-task-list-integ.h>
22 #include <dali/public-api/dali-core.h>
23 #include <stdlib.h>
24
25 #include <iostream>
26
27 using namespace Dali;
28
29 ///////////////////////////////////////////////////////////////////////////////
30 namespace
31 {
32 struct SignalData
33 {
34   SignalData()
35   : functorCalled(false),
36     voidFunctorCalled(false),
37     receivedGesture()
38   {
39   }
40
41   void Reset()
42   {
43     functorCalled     = false;
44     voidFunctorCalled = false;
45
46     receivedGesture.Reset();
47
48     tappedActor.Reset();
49   }
50
51   bool       functorCalled;
52   bool       voidFunctorCalled;
53   TapGesture receivedGesture;
54   Actor      tappedActor;
55 };
56
57 // Functor that sets the data when called
58 struct GestureReceivedFunctor
59 {
60   GestureReceivedFunctor(SignalData& data)
61   : signalData(data)
62   {
63   }
64
65   void operator()(Actor actor, const TapGesture& tap)
66   {
67     signalData.functorCalled   = true;
68     signalData.receivedGesture = tap;
69     signalData.tappedActor     = actor;
70   }
71
72   void operator()()
73   {
74     signalData.voidFunctorCalled = true;
75   }
76
77   SignalData& signalData;
78 };
79
80 Integration::TouchEvent GenerateSingleTouch(PointState::Type state, const Vector2& screenPosition, uint32_t time)
81 {
82   Integration::TouchEvent touchEvent;
83   Integration::Point      point;
84   point.SetState(state);
85   point.SetScreenPosition(screenPosition);
86   point.SetDeviceClass(Device::Class::TOUCH);
87   point.SetDeviceSubclass(Device::Subclass::NONE);
88   touchEvent.points.push_back(point);
89   touchEvent.time = time;
90   return touchEvent;
91 }
92
93 Integration::TouchEvent GenerateDoubleTouch(PointState::Type state, const Vector2& screenPositionA, const Vector2& screenPositionB, uint32_t time)
94 {
95   Integration::TouchEvent touchEvent;
96   Integration::Point      point;
97   point.SetState(state);
98   point.SetScreenPosition(screenPositionA);
99   point.SetDeviceClass(Device::Class::TOUCH);
100   point.SetDeviceSubclass(Device::Subclass::NONE);
101   touchEvent.points.push_back(point);
102   point.SetScreenPosition(screenPositionB);
103   touchEvent.points.push_back(point);
104   touchEvent.time = time;
105   return touchEvent;
106 }
107
108 } // namespace
109
110 ///////////////////////////////////////////////////////////////////////////////
111
112 int UtcDaliTapGestureRecognizerBasic(void)
113 {
114   TestApplication application;
115
116   TapGestureDetector detector = TapGestureDetector::New();
117
118   Actor actor = Actor::New();
119   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
120   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
121   application.GetScene().Add(actor);
122
123   // Render and notify
124   application.SendNotification();
125   application.Render();
126
127   detector.Attach(actor);
128
129   SignalData             data;
130   GestureReceivedFunctor functor(data);
131   detector.DetectedSignal().Connect(&application, functor);
132
133   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), 150));
134
135   application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(20.0f, 20.0f), 200));
136
137   application.SendNotification();
138
139   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
140
141   END_TEST;
142 }
143
144 int UtcDaliTapGestureRecognizerGapTooLong(void)
145 {
146   TestApplication application;
147
148   TapGestureDetector detector = TapGestureDetector::New();
149
150   Actor actor = Actor::New();
151   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
152   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
153   application.GetScene().Add(actor);
154
155   // Render and notify
156   application.SendNotification();
157   application.Render();
158
159   detector.Attach(actor);
160
161   SignalData             data;
162   GestureReceivedFunctor functor(data);
163   detector.DetectedSignal().Connect(&application, functor);
164
165   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), 150));
166
167   application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(20.0f, 20.0f), 651));
168
169   application.SendNotification();
170
171   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
172
173   END_TEST;
174 }
175
176 int UtcDaliTapGestureRecognizerInterrupted(void)
177 {
178   TestApplication application;
179
180   TapGestureDetector detector = TapGestureDetector::New();
181
182   Actor actor = Actor::New();
183   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
184   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
185   application.GetScene().Add(actor);
186
187   // Render and notify
188   application.SendNotification();
189   application.Render();
190
191   detector.Attach(actor);
192
193   SignalData             data;
194   GestureReceivedFunctor functor(data);
195   detector.DetectedSignal().Connect(&application, functor);
196
197   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), 150));
198
199   application.ProcessEvent(GenerateSingleTouch(PointState::INTERRUPTED, Vector2(20.0f, 20.0f), 175));
200
201   application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(20.0f, 20.0f), 200));
202
203   application.SendNotification();
204
205   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
206
207   END_TEST;
208 }
209
210 int UtcDaliTapGestureRecognizerMoveTooFar(void)
211 {
212   TestApplication application;
213
214   TapGestureDetector detector = TapGestureDetector::New();
215   detector.SetMaximumTapsRequired(2);
216
217   Actor actor = Actor::New();
218   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
219   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
220   application.GetScene().Add(actor);
221
222   // Render and notify
223   application.SendNotification();
224   application.Render();
225
226   detector.Attach(actor);
227
228   SignalData             data;
229   GestureReceivedFunctor functor(data);
230   detector.DetectedSignal().Connect(&application, functor);
231
232   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), 150));
233
234   application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(50.0f, 20.0f), 200));
235
236   application.SendNotification();
237
238   application.GetPlatform().TriggerTimer();
239   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
240
241   END_TEST;
242 }
243
244 int UtcDaliTapGestureRecognizerStartDouble(void)
245 {
246   TestApplication application;
247
248   TapGestureDetector detector = TapGestureDetector::New();
249
250   Actor actor = Actor::New();
251   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
252   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
253   application.GetScene().Add(actor);
254
255   // Render and notify
256   application.SendNotification();
257   application.Render();
258
259   detector.Attach(actor);
260
261   SignalData             data;
262   GestureReceivedFunctor functor(data);
263   detector.DetectedSignal().Connect(&application, functor);
264
265   application.ProcessEvent(GenerateDoubleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), Vector2(25.0f, 25.0f), 150));
266
267   application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(20.0f, 20.0f), 200));
268
269   application.SendNotification();
270
271   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
272
273   END_TEST;
274 }
275
276 int UtcDaliTapGestureRecognizerEndDouble(void)
277 {
278   TestApplication application;
279
280   TapGestureDetector detector = TapGestureDetector::New();
281
282   Actor actor = Actor::New();
283   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
284   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
285   application.GetScene().Add(actor);
286
287   // Render and notify
288   application.SendNotification();
289   application.Render();
290
291   detector.Attach(actor);
292
293   SignalData             data;
294   GestureReceivedFunctor functor(data);
295   detector.DetectedSignal().Connect(&application, functor);
296
297   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), 150));
298
299   application.ProcessEvent(GenerateDoubleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), Vector2(25.0f, 25.0f), 200));
300
301   application.ProcessEvent(GenerateDoubleTouch(PointState::UP, Vector2(20.0f, 20.0f), Vector2(25.0f, 25.0f), 200));
302
303   application.SendNotification();
304
305   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
306
307   END_TEST;
308 }
309
310 int UtcDaliTapGestureRecognizerDoubleTap(void)
311 {
312   TestApplication application;
313
314   TapGestureDetector detector = TapGestureDetector::New(2);
315
316   Actor actor = Actor::New();
317   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
318   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
319   application.GetScene().Add(actor);
320
321   // Render and notify
322   application.SendNotification();
323   application.Render();
324
325   detector.Attach(actor);
326
327   SignalData             data;
328   GestureReceivedFunctor functor(data);
329   detector.DetectedSignal().Connect(&application, functor);
330
331   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), 150));
332
333   application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(20.0f, 20.0f), 200));
334
335   application.SendNotification();
336
337   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
338
339   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), 250));
340
341   application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(20.0f, 20.0f), 300));
342
343   application.SendNotification();
344
345   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
346
347   END_TEST;
348 }
349
350 int UtcDaliTapGestureRecognizerDoubleTapMoveTooFar(void)
351 {
352   TestApplication application;
353
354   TapGestureDetector detector = TapGestureDetector::New(2);
355
356   Actor actor = Actor::New();
357   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
358   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
359   application.GetScene().Add(actor);
360
361   // Render and notify
362   application.SendNotification();
363   application.Render();
364
365   detector.Attach(actor);
366
367   SignalData             data;
368   GestureReceivedFunctor functor(data);
369   detector.DetectedSignal().Connect(&application, functor);
370
371   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), 150));
372
373   application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(20.0f, 20.0f), 200));
374
375   application.SendNotification();
376
377   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
378
379   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 50.0f), 250));
380
381   application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(20.0f, 50.0f), 300));
382
383   application.SendNotification();
384
385   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
386
387   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(50.0f, 50.0f), 450));
388
389   application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(50.0f, 50.0f), 500));
390
391   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(50.0f, 50.0f), 550));
392
393   application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(50.0f, 50.0f), 600));
394
395   application.SendNotification();
396
397   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
398
399   END_TEST;
400 }
401
402 int UtcDaliTapGestureRecognizerDoubleTapWaitTooLong(void)
403 {
404   TestApplication application;
405
406   TapGestureDetector detector = TapGestureDetector::New(2);
407
408   Actor actor = Actor::New();
409   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
410   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
411   application.GetScene().Add(actor);
412
413   // Render and notify
414   application.SendNotification();
415   application.Render();
416
417   detector.Attach(actor);
418
419   SignalData             data;
420   GestureReceivedFunctor functor(data);
421   detector.DetectedSignal().Connect(&application, functor);
422
423   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), 150));
424
425   application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(20.0f, 20.0f), 200));
426
427   application.SendNotification();
428
429   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
430
431   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), 750));
432
433   application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(20.0f, 20.0f), 850));
434
435   application.SendNotification();
436
437   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
438
439   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), 900));
440
441   application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(20.0f, 20.0f), 1450));
442
443   application.SendNotification();
444
445   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
446
447   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(50.0f, 50.0f), 1500));
448
449   application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(50.0f, 50.0f), 1550));
450
451   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(50.0f, 50.0f), 1600));
452
453   application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(50.0f, 50.0f), 1650));
454
455   application.SendNotification();
456
457   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
458
459   END_TEST;
460 }
461
462 int UtcDaliTapGestureRecognizerMultipleDetectors(void)
463 {
464   TestApplication application;
465
466   Actor actor = Actor::New();
467   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
468   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
469   application.GetScene().Add(actor);
470
471   Actor actor2 = Actor::New();
472   actor2.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
473   actor2.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
474   actor2.SetProperty(Actor::Property::POSITION_X, 100.0f);
475   application.GetScene().Add(actor2);
476
477   // Render and notify
478   application.SendNotification();
479   application.Render();
480
481   TapGestureDetector detector = TapGestureDetector::New();
482   detector.Attach(actor);
483
484   TapGestureDetector detector2 = TapGestureDetector::New(2);
485   detector2.Attach(actor2);
486
487   SignalData             data;
488   GestureReceivedFunctor functor(data);
489   detector.DetectedSignal().Connect(&application, functor);
490
491   SignalData             data2;
492   GestureReceivedFunctor functor2(data2);
493   detector2.DetectedSignal().Connect(&application, functor2);
494
495   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), 150));
496
497   application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(20.0f, 20.0f), 200));
498
499   application.SendNotification();
500
501   application.GetPlatform().TriggerTimer();
502   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
503   DALI_TEST_EQUALS(true, actor == data.tappedActor, TEST_LOCATION);
504   data.Reset();
505   DALI_TEST_EQUALS(false, data2.functorCalled, TEST_LOCATION);
506
507   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(120.0f, 20.0f), 250));
508
509   application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(120.0f, 20.0f), 300));
510
511   application.SendNotification();
512
513   DALI_TEST_EQUALS(false, data2.functorCalled, TEST_LOCATION);
514
515   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(120.0f, 20.0f), 350));
516
517   application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(120.0f, 20.0f), 400));
518
519   application.SendNotification();
520
521   application.GetPlatform().TriggerTimer();
522   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
523   DALI_TEST_EQUALS(true, data2.functorCalled, TEST_LOCATION);
524
525   END_TEST;
526 }
527
528 int UtcDaliTapGestureRecognizerTripleTap(void)
529 {
530   TestApplication application;
531
532   TapGestureDetector detector = TapGestureDetector::New(3);
533
534   Actor actor = Actor::New();
535   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
536   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
537   application.GetScene().Add(actor);
538
539   // Render and notify
540   application.SendNotification();
541   application.Render();
542
543   detector.Attach(actor);
544
545   SignalData             data;
546   GestureReceivedFunctor functor(data);
547   detector.DetectedSignal().Connect(&application, functor);
548
549   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), 150));
550
551   application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(20.0f, 20.0f), 200));
552
553   application.SendNotification();
554
555   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
556
557   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), 250));
558
559   application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(20.0f, 20.0f), 300));
560
561   application.SendNotification();
562
563   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
564
565   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), 350));
566
567   application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(20.0f, 20.0f), 400));
568
569   application.SendNotification();
570
571   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
572
573   END_TEST;
574 }
575
576 int UtcDaliTapGestureSetMaximumAllowedTime(void)
577 {
578   TestApplication application;
579
580   TapGestureDetector detector = TapGestureDetector::New(2);
581
582   Actor actor = Actor::New();
583   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
584   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
585   application.GetScene().Add(actor);
586
587   // Render and notify
588   application.SendNotification();
589   application.Render();
590
591   detector.Attach(actor);
592
593   try
594   {
595     Integration::SetTapMaximumAllowedTime(0);
596   }
597   catch(...)
598   {
599     DALI_TEST_CHECK(false); // Should not get here
600   }
601
602   // Reduce the maximum allowable time. 500 -> 100
603   Integration::SetTapMaximumAllowedTime(100);
604
605   SignalData             data;
606   GestureReceivedFunctor functor(data);
607   detector.DetectedSignal().Connect(&application, functor);
608
609   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), 150));
610
611   application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(20.0f, 20.0f), 200));
612
613   application.SendNotification();
614
615   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
616
617   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), 300));
618
619   application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(20.0f, 20.0f), 350));
620
621   application.SendNotification();
622
623   // The double tap fails because the maximum allowed time has been exceeded
624   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
625
626   // reset maximum allowed time
627   Integration::SetTapMaximumAllowedTime(500);
628
629   END_TEST;
630 }