Merge branch 'devel/master' into tizen
[platform/core/uifw/dali-core.git] / automated-tests / src / dali / utc-Dali-LongPressGestureRecognizer.cpp
1 /*
2  * Copyright (c) 2020 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/render-task-list-integ.h>
21 #include <dali/public-api/dali-core.h>
22 #include <stdlib.h>
23
24 #include <chrono>
25 #include <iostream>
26 #include <thread>
27
28 using namespace Dali;
29
30 ///////////////////////////////////////////////////////////////////////////////
31 namespace
32 {
33 struct SignalData
34 {
35   SignalData()
36   : functorCalled(false),
37     voidFunctorCalled(false),
38     receivedGesture()
39   {
40   }
41
42   void Reset()
43   {
44     functorCalled     = false;
45     voidFunctorCalled = false;
46
47     receivedGesture.Reset();
48
49     pressedActor.Reset();
50   }
51
52   bool             functorCalled;
53   bool             voidFunctorCalled;
54   LongPressGesture receivedGesture;
55   Actor            pressedActor;
56 };
57
58 // Functor that sets the data when called
59 struct GestureReceivedFunctor
60 {
61   GestureReceivedFunctor(SignalData& data)
62   : signalData(data)
63   {
64   }
65
66   void operator()(Actor actor, const LongPressGesture& pan)
67   {
68     signalData.functorCalled   = true;
69     signalData.receivedGesture = pan;
70     signalData.pressedActor    = actor;
71   }
72
73   void operator()()
74   {
75     signalData.voidFunctorCalled = true;
76   }
77
78   SignalData& signalData;
79 };
80
81 Integration::TouchEvent GenerateSingleTouch(PointState::Type state, const Vector2& screenPosition, uint32_t time)
82 {
83   Integration::TouchEvent touchEvent;
84   Integration::Point      point;
85   point.SetState(state);
86   point.SetDeviceId(4);
87   point.SetScreenPosition(screenPosition);
88   point.SetDeviceClass(Device::Class::TOUCH);
89   point.SetDeviceSubclass(Device::Subclass::NONE);
90   touchEvent.points.push_back(point);
91   touchEvent.time = time;
92   return touchEvent;
93 }
94
95 Integration::TouchEvent GenerateDoubleTouch(PointState::Type stateA, const Vector2& screenPositionA, PointState::Type stateB, const Vector2& screenPositionB, uint32_t time)
96 {
97   Integration::TouchEvent touchEvent;
98   Integration::Point      point;
99   point.SetState(stateA);
100   point.SetDeviceId(4);
101   point.SetScreenPosition(screenPositionA);
102   point.SetDeviceClass(Device::Class::TOUCH);
103   point.SetDeviceSubclass(Device::Subclass::NONE);
104   touchEvent.points.push_back(point);
105   point.SetScreenPosition(screenPositionB);
106   point.SetState(stateB);
107   point.SetDeviceId(7);
108   touchEvent.points.push_back(point);
109   touchEvent.time = time;
110   return touchEvent;
111 }
112
113 } // namespace
114
115 ///////////////////////////////////////////////////////////////////////////////
116
117 int UtcDaliLongPressGestureRecognizerBasicNoAction(void)
118 {
119   TestApplication application;
120
121   LongPressGestureDetector detector = LongPressGestureDetector::New();
122
123   Actor actor = Actor::New();
124   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
125   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
126   application.GetScene().Add(actor);
127
128   // Render and notify
129   application.SendNotification();
130   application.Render();
131
132   detector.Attach(actor);
133
134   SignalData             data;
135   GestureReceivedFunctor functor(data);
136   detector.DetectedSignal().Connect(&application, functor);
137
138   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), 150));
139
140   application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(20.0f, 20.0f), 200));
141
142   application.SendNotification();
143
144   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
145
146   END_TEST;
147 }
148
149 int UtcDaliLongPressGestureRecognizerBasic(void)
150 {
151   TestApplication application;
152
153   LongPressGestureDetector detector = LongPressGestureDetector::New();
154
155   Actor actor = Actor::New();
156   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
157   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
158   application.GetScene().Add(actor);
159
160   // Render and notify
161   application.SendNotification();
162   application.Render();
163
164   detector.Attach(actor);
165
166   SignalData             data;
167   GestureReceivedFunctor functor(data);
168   detector.DetectedSignal().Connect(&application, functor);
169
170   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), 150));
171
172   application.GetPlatform().TriggerTimer();
173
174   application.SendNotification();
175
176   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
177
178   END_TEST;
179 }
180
181 int UtcDaliLongPressGestureRecognizerTooShortWait(void)
182 {
183   TestApplication application;
184
185   LongPressGestureDetector detector = LongPressGestureDetector::New();
186
187   Actor actor = Actor::New();
188   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
189   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
190   application.GetScene().Add(actor);
191
192   // Render and notify
193   application.SendNotification();
194   application.Render();
195
196   detector.Attach(actor);
197
198   SignalData             data;
199   GestureReceivedFunctor functor(data);
200   detector.DetectedSignal().Connect(&application, functor);
201
202   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), 150));
203
204   application.SendNotification();
205
206   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
207
208   END_TEST;
209 }
210
211 int UtcDaliLongPressGestureRecognizerTooFewPoints(void)
212 {
213   TestApplication application;
214
215   LongPressGestureDetector detector = LongPressGestureDetector::New();
216
217   detector.SetTouchesRequired(2, 2);
218
219   Actor actor = Actor::New();
220   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
221   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
222   application.GetScene().Add(actor);
223
224   // Render and notify
225   application.SendNotification();
226   application.Render();
227
228   detector.Attach(actor);
229
230   SignalData             data;
231   GestureReceivedFunctor functor(data);
232   detector.DetectedSignal().Connect(&application, functor);
233
234   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), 150));
235
236   // There should be no function to call
237   application.GetPlatform().TriggerTimer();
238
239   application.SendNotification();
240
241   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
242
243   END_TEST;
244 }
245
246 int UtcDaliLongPressGestureRecognizerTooManyPoints(void)
247 {
248   TestApplication application;
249
250   LongPressGestureDetector detector = LongPressGestureDetector::New();
251
252   Actor actor = Actor::New();
253   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
254   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
255   application.GetScene().Add(actor);
256
257   // Render and notify
258   application.SendNotification();
259   application.Render();
260
261   detector.Attach(actor);
262
263   SignalData             data;
264   GestureReceivedFunctor functor(data);
265   detector.DetectedSignal().Connect(&application, functor);
266
267   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), 150));
268   application.ProcessEvent(GenerateDoubleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), PointState::DOWN, Vector2(20.0f, 90.0f), 151));
269
270   // There should be no function to call as the double touch should have cancelled it
271   application.GetPlatform().TriggerTimer();
272
273   application.SendNotification();
274
275   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
276
277   END_TEST;
278 }
279
280 int UtcDaliLongPressGestureRecognizerMultiplePointsMoving(void)
281 {
282   TestApplication application;
283
284   LongPressGestureDetector detector = LongPressGestureDetector::New();
285
286   detector.SetTouchesRequired(2, 2);
287
288   Actor actor = Actor::New();
289   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
290   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
291   application.GetScene().Add(actor);
292
293   // Render and notify
294   application.SendNotification();
295   application.Render();
296
297   detector.Attach(actor);
298
299   SignalData             data;
300   GestureReceivedFunctor functor(data);
301   detector.DetectedSignal().Connect(&application, functor);
302
303   application.ProcessEvent(GenerateDoubleTouch(PointState::DOWN, Vector2(20.0f, 0.0f), PointState::DOWN, Vector2(20.0f, 90.0f), 151));
304   application.ProcessEvent(GenerateDoubleTouch(PointState::MOTION, Vector2(20.0f, 10.0f), PointState::MOTION, Vector2(20.0f, 80.0f), 153));
305   application.ProcessEvent(GenerateDoubleTouch(PointState::MOTION, Vector2(20.0f, 20.0f), PointState::MOTION, Vector2(20.0f, 70.0f), 155));
306   application.ProcessEvent(GenerateDoubleTouch(PointState::MOTION, Vector2(20.0f, 30.0f), PointState::MOTION, Vector2(20.0f, 60.0f), 157));
307   application.ProcessEvent(GenerateDoubleTouch(PointState::MOTION, Vector2(20.0f, 40.0f), PointState::MOTION, Vector2(20.0f, 50.0f), 159));
308   application.ProcessEvent(GenerateDoubleTouch(PointState::STATIONARY, Vector2(20.0f, 40.0f), PointState::UP, Vector2(20.0f, 50.0f), 160));
309   application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(20.0f, 40.0f), 161));
310
311   application.GetPlatform().TriggerTimer();
312
313   application.SendNotification();
314
315   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
316
317   END_TEST;
318 }
319
320 int UtcDaliLongPressGestureRecognizerMultiplePointsLongPress(void)
321 {
322   TestApplication application;
323
324   LongPressGestureDetector detector = LongPressGestureDetector::New();
325
326   Actor actor = Actor::New();
327   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
328   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
329   application.GetScene().Add(actor);
330
331   // Render and notify
332   application.SendNotification();
333   application.Render();
334
335   detector.Attach(actor);
336   detector.SetTouchesRequired(2, 2); // Set after we've attached forcing us to change things internally
337
338   SignalData             data;
339   GestureReceivedFunctor functor(data);
340   detector.DetectedSignal().Connect(&application, functor);
341
342   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 40.0f), 140));
343   application.ProcessEvent(GenerateDoubleTouch(PointState::DOWN, Vector2(20.0f, 40.0f), PointState::DOWN, Vector2(20.0f, 90.0f), 150));
344
345   application.GetPlatform().TriggerTimer();
346
347   application.ProcessEvent(GenerateDoubleTouch(PointState::STATIONARY, Vector2(20.0f, 20.0f), PointState::UP, Vector2(20.0f, 90.0f), 760));
348   application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(20.0f, 20.0f), 761));
349
350   application.SendNotification();
351
352   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
353
354   END_TEST;
355 }
356
357 int UtcDaliLongPressGestureRecognizerMultipleDetectors(void)
358 {
359   TestApplication application;
360
361   Actor actor = Actor::New();
362   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
363   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
364   application.GetScene().Add(actor);
365
366   Actor actor2 = Actor::New();
367   actor2.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
368   actor2.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
369   actor2.SetProperty(Actor::Property::POSITION_X, 100.0f);
370   application.GetScene().Add(actor2);
371
372   // Render and notify
373   application.SendNotification();
374   application.Render();
375
376   LongPressGestureDetector detector = LongPressGestureDetector::New();
377   detector.Attach(actor);
378
379   LongPressGestureDetector detector2 = LongPressGestureDetector::New(2);
380   detector2.Attach(actor2);
381
382   SignalData             data;
383   GestureReceivedFunctor functor(data);
384   detector.DetectedSignal().Connect(&application, functor);
385
386   SignalData             data2;
387   GestureReceivedFunctor functor2(data2);
388   detector2.DetectedSignal().Connect(&application, functor2);
389
390   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(20.0f, 20.0f), 150));
391
392   application.GetPlatform().TriggerTimer();
393
394   application.ProcessEvent(GenerateSingleTouch(PointState::UP, Vector2(20.0f, 20.0f), 700));
395
396   application.SendNotification();
397
398   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
399   DALI_TEST_EQUALS(true, actor == data.pressedActor, TEST_LOCATION);
400   data.Reset();
401   DALI_TEST_EQUALS(false, data2.functorCalled, TEST_LOCATION);
402
403   application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(120.0f, 40.0f), 800));
404   application.ProcessEvent(GenerateDoubleTouch(PointState::DOWN, Vector2(120.0f, 40.0f), PointState::DOWN, Vector2(120.0f, 90.0f), 805));
405
406   application.GetPlatform().TriggerTimer();
407
408   application.SendNotification();
409
410   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
411   DALI_TEST_EQUALS(true, data2.functorCalled, TEST_LOCATION);
412
413   END_TEST;
414 }