Merge "Add input source type to TapGesture. This is similar to MouseButton in TouchEv...
[platform/core/uifw/dali-core.git] / automated-tests / src / dali / utc-Dali-TapGestureDetector.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 #include <dali-test-suite-utils.h>
19 #include <dali/devel-api/actors/actor-devel.h>
20 #include <dali/integration-api/events/touch-event-integ.h>
21 #include <dali/integration-api/render-task-list-integ.h>
22 #include <dali/public-api/dali-core.h>
23 #include <stdlib.h>
24 #include <test-touch-event-utils.h>
25
26 #include <iostream>
27
28 using namespace Dali;
29
30 void utc_dali_tap_gesture_detector_startup(void)
31 {
32   test_return_value = TET_UNDEF;
33 }
34
35 void utc_dali_tap_gesture_detector_cleanup(void)
36 {
37   test_return_value = TET_PASS;
38 }
39
40 ///////////////////////////////////////////////////////////////////////////////
41 namespace
42 {
43 // Stores data that is populated in the callback and will be read by the TET cases
44 struct SignalData
45 {
46   SignalData()
47   : functorCalled(false),
48     voidFunctorCalled(false)
49   {
50   }
51
52   void Reset()
53   {
54     functorCalled     = false;
55     voidFunctorCalled = false;
56
57     receivedGesture.Reset();
58
59     tappedActor.Reset();
60   }
61
62   bool       functorCalled;
63   bool       voidFunctorCalled;
64   TapGesture receivedGesture;
65   Actor      tappedActor;
66 };
67
68 // Functor that sets the data when called
69 struct GestureReceivedFunctor
70 {
71   GestureReceivedFunctor(SignalData& data)
72   : signalData(data)
73   {
74   }
75
76   void operator()(Actor actor, const TapGesture& tap)
77   {
78     signalData.functorCalled   = true;
79     signalData.receivedGesture = tap;
80     signalData.tappedActor     = actor;
81   }
82
83   void operator()()
84   {
85     signalData.voidFunctorCalled = true;
86   }
87
88   SignalData& signalData;
89 };
90
91 // Functor that removes the gestured actor from stage
92 struct UnstageActorFunctor : public GestureReceivedFunctor
93 {
94   UnstageActorFunctor(SignalData& data, Integration::Scene scene)
95   : GestureReceivedFunctor(data),
96     scene(scene)
97   {
98   }
99
100   void operator()(Actor actor, const TapGesture& tap)
101   {
102     GestureReceivedFunctor::operator()(actor, tap);
103     scene.Remove(actor);
104   }
105
106   Integration::Scene scene;
107 };
108
109 // Functor for receiving a touch event
110 struct TouchEventFunctor
111 {
112   bool operator()(Actor actor, const TouchEvent& touch)
113   {
114     //For line coverage
115     unsigned int points = touch.GetPointCount();
116     if(points > 0)
117     {
118       tet_printf("Touch Point state = %d\n", touch.GetState(0));
119     }
120     return false;
121   }
122 };
123
124 Integration::TouchEvent GenerateSingleTouch(PointState::Type state, const Vector2& screenPosition, int source, uint32_t time)
125 {
126   Integration::TouchEvent touchEvent;
127   Integration::Point      point;
128   point.SetState(state);
129   point.SetDeviceId(4);
130   point.SetScreenPosition(screenPosition);
131   point.SetDeviceClass(Device::Class::TOUCH);
132   point.SetDeviceSubclass(Device::Subclass::NONE);
133   point.SetMouseButton(static_cast<MouseButton::Type>(source));
134   touchEvent.points.push_back(point);
135   touchEvent.time = time;
136   return touchEvent;
137 }
138
139 } // namespace
140
141 ///////////////////////////////////////////////////////////////////////////////
142
143 // Positive test case for a method
144 int UtcDaliTapGestureDetectorConstructor(void)
145 {
146   TestApplication application;
147
148   TapGestureDetector detector;
149   DALI_TEST_CHECK(!detector);
150   END_TEST;
151 }
152
153 int UtcDaliTapGestureDetectorCopyConstructorP(void)
154 {
155   TestApplication application;
156
157   TapGestureDetector detector = TapGestureDetector::New();
158
159   TapGestureDetector copy(detector);
160   DALI_TEST_CHECK(detector);
161   END_TEST;
162 }
163
164 int UtcDaliTapGestureDetectorAssignmentOperatorP(void)
165 {
166   TestApplication application;
167
168   TapGestureDetector detector = TapGestureDetector::New();
169   ;
170
171   TapGestureDetector assign;
172   assign = detector;
173   DALI_TEST_CHECK(detector);
174
175   DALI_TEST_CHECK(detector == assign);
176   END_TEST;
177 }
178
179 int UtcDaliTapGestureDetectorNew(void)
180 {
181   TestApplication application;
182
183   TapGestureDetector detector = TapGestureDetector::New();
184   DALI_TEST_CHECK(detector);
185   DALI_TEST_EQUALS(1u, detector.GetMinimumTapsRequired(), TEST_LOCATION);
186   DALI_TEST_EQUALS(1u, detector.GetMaximumTapsRequired(), TEST_LOCATION);
187
188   TapGestureDetector detector2 = TapGestureDetector::New(5u);
189   DALI_TEST_CHECK(detector2);
190   DALI_TEST_EQUALS(5u, detector2.GetMinimumTapsRequired(), TEST_LOCATION);
191   DALI_TEST_EQUALS(5u, detector2.GetMaximumTapsRequired(), TEST_LOCATION);
192
193   //Scoped test to test destructor
194   {
195     TapGestureDetector detector3 = TapGestureDetector::New();
196     DALI_TEST_CHECK(detector3);
197   }
198
199   // Attach an actor and emit a touch event on the actor to ensure complete line coverage
200   Actor actor = Actor::New();
201   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
202   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
203   application.GetScene().Add(actor);
204
205   // Render and notify
206   application.SendNotification();
207   application.Render();
208
209   detector.Attach(actor);
210
211   TouchEventFunctor touchFunctor;
212   actor.TouchedSignal().Connect(&application, touchFunctor);
213
214   Integration::TouchEvent touchEvent(1);
215   Integration::Point      point;
216   point.SetDeviceId(1);
217   point.SetState(PointState::DOWN);
218   point.SetScreenPosition(Vector2(20.0f, 20.0f));
219   touchEvent.AddPoint(point);
220   application.ProcessEvent(touchEvent);
221
222   // Render and notify
223   application.SendNotification();
224   application.Render();
225
226   END_TEST;
227 }
228
229 int UtcDaliTapGestureDetectorDownCast(void)
230 {
231   TestApplication application;
232   tet_infoline("Testing Dali::TapGestureDetector::DownCast()");
233
234   TapGestureDetector detector = TapGestureDetector::New();
235
236   BaseHandle object(detector);
237
238   TapGestureDetector detector2 = TapGestureDetector::DownCast(object);
239   DALI_TEST_CHECK(detector2);
240
241   TapGestureDetector detector3 = DownCast<TapGestureDetector>(object);
242   DALI_TEST_CHECK(detector3);
243
244   BaseHandle         unInitializedObject;
245   TapGestureDetector detector4 = TapGestureDetector::DownCast(unInitializedObject);
246   DALI_TEST_CHECK(!detector4);
247
248   TapGestureDetector detector5 = DownCast<TapGestureDetector>(unInitializedObject);
249   DALI_TEST_CHECK(!detector5);
250
251   GestureDetector    detector6 = TapGestureDetector::New();
252   TapGestureDetector detector7 = TapGestureDetector::DownCast(detector6);
253   DALI_TEST_CHECK(detector7);
254   END_TEST;
255 }
256
257 int UtcDaliTapGestureSetTapsRequiredMinMaxCheck(void)
258 {
259   TestApplication application;
260
261   // Attach an actor and change the required touches
262
263   Actor actor = Actor::New();
264   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
265   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
266   application.GetScene().Add(actor);
267
268   // Render and notify
269   application.SendNotification();
270   application.Render();
271
272   // Set the minimum to be greater than the maximum, should Assert
273
274   try
275   {
276     TapGestureDetector detector = TapGestureDetector::New();
277     detector.SetMinimumTapsRequired(7u);
278     detector.SetMaximumTapsRequired(3u);
279     detector.Attach(actor);
280     DALI_TEST_CHECK(false); // Should not get here
281   }
282   catch(DaliException& e)
283   {
284     DALI_TEST_CHECK(true);
285   }
286
287   END_TEST;
288 }
289
290 int UtcDaliTapGestureGetTapsRequired(void)
291 {
292   TestApplication application;
293
294   TapGestureDetector detector = TapGestureDetector::New();
295   DALI_TEST_EQUALS(1u, detector.GetMinimumTapsRequired(), TEST_LOCATION);
296   DALI_TEST_EQUALS(1u, detector.GetMaximumTapsRequired(), TEST_LOCATION);
297   END_TEST;
298 }
299
300 int UtcDaliTapGestureSignalReceptionNegative(void)
301 {
302   TestApplication application;
303
304   Actor actor = Actor::New();
305   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
306   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
307   application.GetScene().Add(actor);
308
309   // Render and notify
310   application.SendNotification();
311   application.Render();
312
313   SignalData             data;
314   GestureReceivedFunctor functor(data);
315
316   TapGestureDetector detector = TapGestureDetector::New();
317   detector.Attach(actor);
318   detector.DetectedSignal().Connect(&application, functor);
319
320   // Do a tap outside actor's area
321   TestGenerateTap(application, 112.0f, 112.0f, 100);
322   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
323   END_TEST;
324 }
325
326 int UtcDaliTapGestureSignalReceptionPositive(void)
327 {
328   TestApplication application;
329
330   Actor actor = Actor::New();
331   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
332   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
333   application.GetScene().Add(actor);
334
335   // Render and notify
336   application.SendNotification();
337   application.Render();
338
339   SignalData             data;
340   GestureReceivedFunctor functor(data);
341
342   TapGestureDetector detector = TapGestureDetector::New();
343   detector.Attach(actor);
344   detector.DetectedSignal().Connect(&application, functor);
345
346   // Do a tap inside actor's area
347   TestGenerateTap(application, 50.0f, 50.0f, 100);
348   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
349   DALI_TEST_EQUALS(1u, data.receivedGesture.GetNumberOfTaps(), TEST_LOCATION);
350   DALI_TEST_EQUALS(1u, data.receivedGesture.GetNumberOfTouches(), TEST_LOCATION);
351   DALI_TEST_EQUALS(Vector2(50.0f, 50.0f), data.receivedGesture.GetLocalPoint(), 0.1, TEST_LOCATION);
352   END_TEST;
353 }
354
355 int UtcDaliTapGestureSignalReceptionDetach(void)
356 {
357   TestApplication application;
358
359   Actor actor = Actor::New();
360   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
361   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
362   application.GetScene().Add(actor);
363
364   // Render and notify
365   application.SendNotification();
366   application.Render();
367
368   SignalData             data;
369   GestureReceivedFunctor functor(data);
370
371   TapGestureDetector detector = TapGestureDetector::New();
372   detector.Attach(actor);
373   detector.DetectedSignal().Connect(&application, functor);
374
375   // Start tap within the actor's area
376   TestGenerateTap(application, 20.0f, 20.0f, 100);
377   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
378   DALI_TEST_EQUALS(1u, data.receivedGesture.GetNumberOfTaps(), TEST_LOCATION);
379   DALI_TEST_EQUALS(1u, data.receivedGesture.GetNumberOfTouches(), TEST_LOCATION);
380   DALI_TEST_EQUALS(Vector2(20.0f, 20.0f), data.receivedGesture.GetLocalPoint(), 0.1, TEST_LOCATION);
381
382   // repeat the tap within the actor's area - we should still receive the signal
383   data.Reset();
384   TestGenerateTap(application, 50.0f, 50.0f, 700);
385   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
386   DALI_TEST_EQUALS(1u, data.receivedGesture.GetNumberOfTaps(), TEST_LOCATION);
387   DALI_TEST_EQUALS(1u, data.receivedGesture.GetNumberOfTouches(), TEST_LOCATION);
388   DALI_TEST_EQUALS(Vector2(50.0f, 50.0f), data.receivedGesture.GetLocalPoint(), 0.1, TEST_LOCATION);
389
390   // Detach actor
391   detector.DetachAll();
392
393   // Ensure we are no longer signalled
394   data.Reset();
395   TestGenerateTap(application, 20.0f, 20.0f, 1300);
396   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
397   TestGenerateTap(application, 50.0f, 50.0f, 1900);
398   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
399   END_TEST;
400 }
401
402 int UtcDaliTapGestureSignalReceptionActorDestroyedWhileTapping(void)
403 {
404   TestApplication application;
405
406   SignalData             data;
407   GestureReceivedFunctor functor(data);
408
409   TapGestureDetector detector = TapGestureDetector::New();
410   detector.DetectedSignal().Connect(&application, functor);
411
412   // Actor lifetime is scoped
413   {
414     Actor actor = Actor::New();
415     actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
416     actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
417     application.GetScene().Add(actor);
418
419     // Render and notify
420     application.SendNotification();
421     application.Render();
422
423     detector.Attach(actor);
424
425     // Start tap within the actor's area
426     TestGenerateTap(application, 20.0f, 20.0f, 100);
427     DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
428
429     // Remove the actor from stage and reset the data
430     application.GetScene().Remove(actor);
431
432     // Render and notify
433     application.SendNotification();
434     application.Render();
435   }
436
437   // Actor should now have been destroyed
438
439   data.Reset();
440   TestGenerateTap(application, 20.0f, 20.0f, 700);
441   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
442   END_TEST;
443 }
444
445 int UtcDaliTapGestureSignalReceptionRotatedActor(void)
446 {
447   TestApplication application;
448
449   Actor actor = Actor::New();
450   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
451   actor.SetProperty(Actor::Property::ORIENTATION, Quaternion(Dali::Degree(90.0f), Vector3::ZAXIS));
452   application.GetScene().Add(actor);
453
454   // Render and notify
455   application.SendNotification();
456   application.Render();
457
458   SignalData             data;
459   GestureReceivedFunctor functor(data);
460
461   TapGestureDetector detector = TapGestureDetector::New();
462   detector.Attach(actor);
463   detector.DetectedSignal().Connect(&application, functor);
464
465   // Do tap, only check finished value
466   TestGenerateTap(application, 5.0f, 5.0f, 100);
467   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
468   DALI_TEST_EQUALS(1u, data.receivedGesture.GetNumberOfTaps(), TEST_LOCATION);
469   DALI_TEST_EQUALS(1u, data.receivedGesture.GetNumberOfTouches(), TEST_LOCATION);
470   DALI_TEST_EQUALS(Vector2(5.0f, 5.0f), data.receivedGesture.GetScreenPoint(), 0.1, TEST_LOCATION);
471
472   // Rotate actor again and render
473   actor.SetProperty(Actor::Property::ORIENTATION, Quaternion(Dali::Degree(180.0f), Vector3::ZAXIS));
474   application.SendNotification();
475   application.Render();
476
477   // Do tap, should still receive event
478   data.Reset();
479   TestGenerateTap(application, 5.0f, 5.0f, 700);
480   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
481   DALI_TEST_EQUALS(1u, data.receivedGesture.GetNumberOfTaps(), TEST_LOCATION);
482   DALI_TEST_EQUALS(1u, data.receivedGesture.GetNumberOfTouches(), TEST_LOCATION);
483   DALI_TEST_EQUALS(Vector2(5.0f, 5.0f), data.receivedGesture.GetScreenPoint(), 0.1, TEST_LOCATION);
484
485   // Rotate actor again and render
486   actor.SetProperty(Actor::Property::ORIENTATION, Quaternion(Dali::Degree(90.0f), Vector3::YAXIS));
487   application.SendNotification();
488   application.Render();
489
490   // Do tap, inside the actor's area (area if it is not rotated), Should not receive the event
491   data.Reset();
492   TestGenerateTap(application, 70.0f, 70.0f, 1300);
493   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
494   END_TEST;
495 }
496
497 int UtcDaliTapGestureSignalReceptionChildHit(void)
498 {
499   TestApplication application;
500
501   Actor parent = Actor::New();
502   parent.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
503   parent.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
504   application.GetScene().Add(parent);
505
506   // Set child to completely cover parent.
507   // Change rotation of child to be different from parent so that we can check if our local coordinate
508   // conversion of the parent actor is correct.
509   Actor child = Actor::New();
510   child.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
511   child.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
512   child.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
513   child.SetProperty(Actor::Property::ORIENTATION, Quaternion(Dali::Degree(90.0f), Vector3::ZAXIS));
514   parent.Add(child);
515
516   TouchEventFunctor touchFunctor;
517   child.TouchedSignal().Connect(&application, touchFunctor);
518
519   // Render and notify
520   application.SendNotification();
521   application.Render();
522
523   SignalData             data;
524   GestureReceivedFunctor functor(data);
525
526   TapGestureDetector detector = TapGestureDetector::New();
527   detector.Attach(parent);
528   detector.DetectedSignal().Connect(&application, functor);
529
530   // Do tap - hits child area but parent should still receive it
531   TestGenerateTap(application, 50.0f, 50.0f, 100);
532   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
533   DALI_TEST_EQUALS(true, parent == data.tappedActor, TEST_LOCATION);
534   DALI_TEST_EQUALS(Vector2(50.0f, 50.0f), data.receivedGesture.GetScreenPoint(), 0.01f, TEST_LOCATION);
535
536   // Attach child and generate same touch points
537   // (Also proves that you can detach and then re-attach another actor)
538   detector.Attach(child);
539   detector.Detach(parent);
540
541   // Do an entire tap, only check finished value
542   data.Reset();
543   TestGenerateTap(application, 51.0f, 51.0f, 700);
544   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
545   DALI_TEST_EQUALS(true, child == data.tappedActor, TEST_LOCATION);
546   DALI_TEST_EQUALS(Vector2(51.0f, 51.0f), data.receivedGesture.GetScreenPoint(), 0.01f, TEST_LOCATION);
547   END_TEST;
548 }
549
550 int UtcDaliTapGestureSignalReceptionAttachDetachMany(void)
551 {
552   TestApplication application;
553
554   Actor first = Actor::New();
555   first.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
556   first.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
557   application.GetScene().Add(first);
558
559   Actor second = Actor::New();
560   second.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
561   second.SetProperty(Actor::Property::POSITION_X, 100.0f);
562   second.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
563   application.GetScene().Add(second);
564
565   // Render and notify
566   application.SendNotification();
567   application.Render();
568
569   SignalData             data;
570   GestureReceivedFunctor functor(data);
571
572   TapGestureDetector detector = TapGestureDetector::New();
573   detector.Attach(first);
574   detector.Attach(second);
575   detector.DetectedSignal().Connect(&application, functor);
576
577   // Tap within second actor's area
578   TestGenerateTap(application, 120.0f, 10.0f, 100);
579   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
580   DALI_TEST_EQUALS(true, second == data.tappedActor, TEST_LOCATION);
581
582   // Tap within first actor's area
583   data.Reset();
584   TestGenerateTap(application, 20.0f, 10.0f, 700);
585   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
586   DALI_TEST_EQUALS(true, first == data.tappedActor, TEST_LOCATION);
587
588   // Detach the second actor
589   detector.Detach(second);
590
591   // second actor shouldn't receive event
592   data.Reset();
593   TestGenerateTap(application, 120.0f, 10.0f, 1300);
594   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
595
596   // first actor should continue receiving event
597   data.Reset();
598   TestGenerateTap(application, 20.0f, 10.0f, 1900);
599   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
600   END_TEST;
601 }
602
603 int UtcDaliTapGestureSignalReceptionActorBecomesUntouchable(void)
604 {
605   TestApplication application;
606
607   Actor actor = Actor::New();
608   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
609   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
610   application.GetScene().Add(actor);
611
612   // Render and notify
613   application.SendNotification();
614   application.Render();
615
616   SignalData             data;
617   GestureReceivedFunctor functor(data);
618
619   TapGestureDetector detector = TapGestureDetector::New();
620   detector.Attach(actor);
621   detector.DetectedSignal().Connect(&application, functor);
622
623   // Tap in actor's area
624   TestGenerateTap(application, 50.0f, 10.0f, 100);
625   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
626
627   // Actor become invisible - actor should not receive the next pan
628   actor.SetProperty(Actor::Property::VISIBLE, false);
629
630   // Render and notify
631   application.SendNotification();
632   application.Render();
633
634   // Tap in the same area, shouldn't receive event
635   data.Reset();
636   TestGenerateTap(application, 50.0f, 10.0f, 700);
637   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
638   END_TEST;
639 }
640
641 int UtcDaliTapGestureSignalReceptionMultipleGestureDetectors(void)
642 {
643   TestApplication application;
644
645   Actor first = Actor::New();
646   first.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
647   first.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
648   application.GetScene().Add(first);
649
650   Actor second = Actor::New();
651   second.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
652   second.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
653   second.SetProperty(Actor::Property::POSITION_X, 100.0f);
654   first.Add(second);
655
656   // Render and notify
657   application.SendNotification();
658   application.Render();
659
660   SignalData             data;
661   GestureReceivedFunctor functor(data);
662
663   TapGestureDetector firstDetector = TapGestureDetector::New();
664   firstDetector.Attach(first);
665   firstDetector.DetectedSignal().Connect(&application, functor);
666
667   // secondDetector is scoped
668   {
669     TapGestureDetector secondDetector = TapGestureDetector::New(2);
670     secondDetector.Attach(second);
671     secondDetector.DetectedSignal().Connect(&application, functor);
672
673     // Tap within second actor's area
674     TestGenerateTap(application, 150.0f, 10.0f, 100);
675     TestGenerateTap(application, 150.0f, 10.0f, 200);
676
677     DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
678     DALI_TEST_EQUALS(true, second == data.tappedActor, TEST_LOCATION);
679
680     // Tap continues as single touch gesture - we should not receive any gesture
681     data.Reset();
682     TestGenerateTap(application, 150.0f, 10.0f, 800);
683     DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
684
685     // Single touch tap starts - first actor should be panned
686     data.Reset();
687     TestGenerateTap(application, 50.0f, 10.0f, 1400);
688     DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
689     DALI_TEST_EQUALS(true, first == data.tappedActor, TEST_LOCATION);
690
691     // Tap changes to double-touch - we shouldn't receive event
692     data.Reset();
693
694     TestGenerateTwoPointTap(application, 50.0f, 10.0f, 60.0f, 20.0f, 2000);
695
696     DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
697   }
698
699   END_TEST;
700 }
701
702 int UtcDaliTapGestureSignalReceptionMultipleDetectorsOnActor(void)
703 {
704   TestApplication application;
705
706   Actor actor = Actor::New();
707   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
708   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
709   application.GetScene().Add(actor);
710
711   // Render and notify
712   application.SendNotification();
713   application.Render();
714
715   // Attach actor to one detector
716   SignalData             firstData;
717   GestureReceivedFunctor firstFunctor(firstData);
718   TapGestureDetector     firstDetector = TapGestureDetector::New();
719   firstDetector.Attach(actor);
720   firstDetector.DetectedSignal().Connect(&application, firstFunctor);
721
722   // Attach actor to another detector
723   SignalData             secondData;
724   GestureReceivedFunctor secondFunctor(secondData);
725   TapGestureDetector     secondDetector = TapGestureDetector::New();
726   secondDetector.Attach(actor);
727   secondDetector.DetectedSignal().Connect(&application, secondFunctor);
728
729   // Tap in actor's area - both detector's functors should be called
730   TestGenerateTap(application, 50.0f, 10.0f, 100);
731   DALI_TEST_EQUALS(true, firstData.functorCalled, TEST_LOCATION);
732   DALI_TEST_EQUALS(true, secondData.functorCalled, TEST_LOCATION);
733   END_TEST;
734 }
735
736 int UtcDaliTapGestureSignalReceptionDifferentPossible(void)
737 {
738   TestApplication application;
739
740   Actor actor = Actor::New();
741   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
742   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
743   application.GetScene().Add(actor);
744
745   // Render and notify
746   application.SendNotification();
747   application.Render();
748
749   // Attach actor to detector
750   SignalData             data;
751   GestureReceivedFunctor functor(data);
752   TapGestureDetector     detector = TapGestureDetector::New();
753   detector.Attach(actor);
754   detector.DetectedSignal().Connect(&application, functor);
755
756   // Gesture possible in actor's area.
757   TestStartLongPress(application, 50.0f, 10.0f, 100);
758   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
759
760   // Move actor somewhere else
761   actor.SetProperty(Actor::Property::POSITION, Vector2(100.0f, 100.0f));
762
763   // Render and notify
764   application.SendNotification();
765   application.Render();
766
767   // Emit STARTED event, we should not receive the tap.
768   TestEndPan(application, Vector2(50.0f, 10.0f), 120);
769   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
770
771   // Tap possible in empty area.
772   TestStartLongPress(application, 50.0f, 10.0f, 700);
773   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
774
775   // Move actor in to the tap position.
776   actor.SetProperty(Actor::Property::POSITION, Vector2(0.0f, 0.0f));
777
778   // Render and notify
779   application.SendNotification();
780   application.Render();
781
782   // Emit STARTED event, we should not receive the tap.
783   TestEndPan(application, Vector2(50.0f, 10.0f), 720);
784   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
785
786   // Normal tap in actor's area for completeness.
787   TestGenerateTap(application, 50.0f, 10.0f, 1300);
788   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
789   END_TEST;
790 }
791
792 int UtcDaliTapGestureActorUnstaged(void)
793 {
794   TestApplication application;
795
796   Actor actor = Actor::New();
797   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
798   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
799   application.GetScene().Add(actor);
800
801   // Render and notify
802   application.SendNotification();
803   application.Render();
804
805   // Attach actor to detector
806   SignalData          data;
807   UnstageActorFunctor functor(data, application.GetScene());
808   TapGestureDetector  detector = TapGestureDetector::New();
809   detector.Attach(actor);
810   detector.DetectedSignal().Connect(&application, functor);
811
812   TestGenerateTap(application, 50.0f, 10.0f, 100);
813   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
814   tet_result(TET_PASS); // If we get here, then the actor removal on signal handler was handled gracefully.
815   END_TEST;
816 }
817
818 int UtcDaliTapGestureDetectorRemovedWhilePossible(void)
819 {
820   TestApplication application;
821
822   Actor actor = Actor::New();
823   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
824   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
825   application.GetScene().Add(actor);
826
827   // Render and notify
828   application.SendNotification();
829   application.Render();
830
831   // Attach actor to detector
832   SignalData             data;
833   GestureReceivedFunctor functor(data);
834   TapGestureDetector     detector = TapGestureDetector::New();
835   detector.Attach(actor);
836   detector.DetectedSignal().Connect(&application, functor);
837
838   // Emit a possible - Down press, as emitted by long press function
839   TestStartLongPress(application, 50.0f, 10.0f, 100);
840
841   // Detach actor and send a STARTED state, no signal.
842   detector.DetachAll();
843   TestEndPan(application, Vector2(50.0f, 10.0f), 120);
844   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
845   END_TEST;
846 }
847
848 int UtcDaliTapGestureActorRemovedWhilePossible(void)
849 {
850   TestApplication application;
851
852   Actor actor = Actor::New();
853   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
854   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
855   application.GetScene().Add(actor);
856
857   // Render and notify
858   application.SendNotification();
859   application.Render();
860
861   // Attach actor to detector
862   SignalData             data;
863   GestureReceivedFunctor functor(data);
864   TapGestureDetector     detector = TapGestureDetector::New();
865   detector.Attach(actor);
866   detector.DetectedSignal().Connect(&application, functor);
867
868   // Emit a possible - Down press, as emitted by long press function
869   TestStartLongPress(application, 50.0f, 10.0f, 100);
870
871   // Remove, render and delete actor
872   application.GetScene().Remove(actor);
873   application.SendNotification();
874   application.Render();
875   actor.Reset();
876
877   // Send a STARTED state, no signal - Up motion as provided by end pan function
878   TestEndPan(application, Vector2(50.0f, 10.0f), 120);
879   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
880   END_TEST;
881 }
882
883 int UtcDaliTapGestureLayerConsumesTouch(void)
884 {
885   TestApplication application;
886
887   Actor actor = Actor::New();
888   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
889   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
890   application.GetScene().Add(actor);
891
892   // Add a detector
893   SignalData             data;
894   GestureReceivedFunctor functor(data);
895   TapGestureDetector     detector = TapGestureDetector::New();
896   detector.Attach(actor);
897   detector.DetectedSignal().Connect(&application, functor);
898
899   // Add a layer to overlap the actor
900   Layer layer = Layer::New();
901   layer.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
902   layer.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
903   application.GetScene().Add(layer);
904   layer.RaiseToTop();
905
906   // Render and notify
907   application.SendNotification();
908   application.Render();
909
910   // Emit signals, should receive
911   TestGenerateTap(application, 50.0f, 50.0f, 100);
912   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
913   data.Reset();
914
915   // Set layer to consume all touch
916   layer.SetProperty(Layer::Property::CONSUMES_TOUCH, true);
917
918   // Render and notify
919   application.SendNotification();
920   application.Render();
921
922   // Emit the same signals again, should not receive
923   TestGenerateTap(application, 50.0f, 50.0f, 700);
924   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
925   data.Reset();
926
927   END_TEST;
928 }
929
930 int UtcDaliTapGestureInterruptedWhenTouchConsumed(void)
931 {
932   TestApplication application;
933
934   Actor actor = Actor::New();
935   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
936   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
937   application.GetScene().Add(actor);
938
939   bool                           consume = false;
940   TouchEventFunctorConsumeSetter touchFunctor(consume);
941   actor.TouchedSignal().Connect(&application, touchFunctor);
942
943   // Render and notify
944   application.SendNotification();
945   application.Render();
946
947   SignalData             data;
948   GestureReceivedFunctor functor(data);
949
950   TapGestureDetector detector = TapGestureDetector::New();
951   detector.Attach(actor);
952   detector.DetectedSignal().Connect(&application, functor);
953
954   // Start gesture within the actor's area, we should receive the gesture as the touch is NOT being consumed
955   TestGenerateTap(application, 50.0f, 50.0f);
956   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
957   data.Reset();
958
959   // Another gesture in the same location, this time we will not receive it as touch is being consumed
960   consume = true;
961   TestGenerateTap(application, 50.0f, 50.0f);
962   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
963   data.Reset();
964
965   END_TEST;
966 }
967
968 int UtcDaliTapGestureDisableDetectionDuringTapN(void)
969 {
970   // Crash sometimes occurred when gesture-recognizer was deleted internally during a signal when the attached actor was detached
971
972   TestApplication application;
973
974   Actor actor = Actor::New();
975   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
976   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
977   application.GetScene().Add(actor);
978
979   // Add a detector
980   TapGestureDetector detector      = TapGestureDetector::New();
981   bool               functorCalled = false;
982   detector.Attach(actor);
983   detector.DetectedSignal().Connect(
984     &application,
985     [&detector, &functorCalled](Actor actor, const TapGesture& gesture) {
986       detector.Detach(actor);
987       functorCalled = true;
988     });
989
990   // Render and notify
991   application.SendNotification();
992   application.Render();
993
994   // Try the gesture, should not crash
995   try
996   {
997     TestGenerateTap(application, 50.0f, 10.0f);
998
999     DALI_TEST_CHECK(true); // No crash, test has passed
1000     DALI_TEST_EQUALS(functorCalled, true, TEST_LOCATION);
1001   }
1002   catch(...)
1003   {
1004     DALI_TEST_CHECK(false); // If we crash, the test has failed
1005   }
1006
1007   END_TEST;
1008 }
1009
1010 int UtcDaliTapGestureWhenGesturePropargation(void)
1011 {
1012   TestApplication application;
1013
1014   Actor parentActor = Actor::New();
1015   parentActor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
1016   parentActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
1017
1018   Actor childActor = Actor::New();
1019   childActor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
1020   childActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
1021
1022   parentActor.Add(childActor);
1023   application.GetScene().Add(parentActor);
1024
1025   // Render and notify
1026   application.SendNotification();
1027   application.Render();
1028
1029   SignalData             pData;
1030   GestureReceivedFunctor pFunctor(pData);
1031
1032   TapGestureDetector parentDetector = TapGestureDetector::New();
1033   parentDetector.Attach(parentActor);
1034   parentDetector.DetectedSignal().Connect(&application, pFunctor);
1035
1036   SignalData             cData;
1037   GestureReceivedFunctor cFunctor(cData);
1038
1039   TapGestureDetector childDetector = TapGestureDetector::New();
1040   childDetector.Attach(childActor);
1041   childDetector.DetectedSignal().Connect(&application, cFunctor);
1042
1043   // Start gesture within the actor's area, we receive the gesture not parent actor but child actor.
1044   TestGenerateTap(application, 50.0f, 50.0f, 100);
1045   DALI_TEST_EQUALS(true, cData.functorCalled, TEST_LOCATION);
1046   DALI_TEST_EQUALS(false, pData.functorCalled, TEST_LOCATION);
1047   cData.Reset();
1048   pData.Reset();
1049
1050   // If GesturePropargation is set, a gesture event is delivered to the parent.
1051   Dali::DevelActor::SetNeedGesturePropagation(childActor, true);
1052
1053   // So now the parent got the gesture event.
1054   TestGenerateTap(application, 50.0f, 50.0f, 700);
1055   DALI_TEST_EQUALS(true, cData.functorCalled, TEST_LOCATION);
1056   DALI_TEST_EQUALS(true, pData.functorCalled, TEST_LOCATION);
1057   cData.Reset();
1058   pData.Reset();
1059
1060   END_TEST;
1061 }
1062
1063 int UtcDaliTapGestureGetSourceType(void)
1064 {
1065   TestApplication application;
1066
1067   Actor actor = Actor::New();
1068   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
1069   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
1070   application.GetScene().Add(actor);
1071
1072   // Render and notify
1073   application.SendNotification();
1074   application.Render();
1075
1076   SignalData             data;
1077   GestureReceivedFunctor functor(data);
1078
1079   TapGestureDetector detector = TapGestureDetector::New();
1080   detector.Attach(actor);
1081   detector.DetectedSignal().Connect(&application, functor);
1082
1083   // Emit a down signal with MouseButton
1084   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), 0, 100));
1085   application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(20.0f, 20.0f), 0, 120));
1086   application.SendNotification();
1087
1088   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1089   DALI_TEST_EQUALS(data.receivedGesture.GetSourceType(), GestureSourceType::INVALID, TEST_LOCATION);
1090
1091   data.Reset();
1092
1093   // Emit a down signal with MouseButton
1094   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), 1, 700));
1095   application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(20.0f, 20.0f), 1, 720));
1096   application.SendNotification();
1097
1098   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1099   DALI_TEST_EQUALS(data.receivedGesture.GetSourceType(), GestureSourceType::PRIMARY, TEST_LOCATION);
1100
1101   data.Reset();
1102
1103   // Emit a down signal with MouseButton
1104   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), 3, 1300));
1105   application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(20.0f, 20.0f), 3, 1320));
1106   application.SendNotification();
1107
1108   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1109   DALI_TEST_EQUALS(data.receivedGesture.GetSourceType(), GestureSourceType::SECONDARY, TEST_LOCATION);
1110
1111   data.Reset();
1112
1113   // Emit a down signal with MouseButton
1114   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), 2, 1900));
1115   application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(20.0f, 20.0f), 2, 1920));
1116   application.SendNotification();
1117
1118   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1119   DALI_TEST_EQUALS(data.receivedGesture.GetSourceType(), GestureSourceType::TERTIARY, TEST_LOCATION);
1120
1121   END_TEST;
1122 }