720f7abea758272068cf8746c690916ae38d2fbd
[platform/core/uifw/dali-core.git] / automated-tests / src / dali / utc-Dali-HoverProcessing.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 #include <dali-test-suite-utils.h>
19 #include <dali/devel-api/actors/actor-devel.h>
20 #include <dali/devel-api/events/hover-event-devel.h>
21 #include <dali/integration-api/events/hover-event-integ.h>
22 #include <dali/integration-api/events/touch-integ.h>
23 #include <dali/integration-api/render-task-list-integ.h>
24 #include <dali/public-api/dali-core.h>
25 #include <stdlib.h>
26
27 #include <iostream>
28
29 using namespace Dali;
30
31 void utc_dali_hover_processing_startup(void)
32 {
33   test_return_value = TET_UNDEF;
34 }
35
36 void utc_dali_hover_processing_cleanup(void)
37 {
38   test_return_value = TET_PASS;
39 }
40
41 ///////////////////////////////////////////////////////////////////////////////
42
43 namespace
44 {
45 // Stores data that is populated in the callback and will be read by the TET cases
46 struct SignalData
47 {
48   SignalData()
49   : functorCalled(false),
50     hoverEvent(),
51     hoveredActor()
52   {
53   }
54
55   void Reset()
56   {
57     functorCalled = false;
58     hoverEvent.Reset();
59     hoveredActor.Reset();
60   }
61
62   bool       functorCalled;
63   HoverEvent hoverEvent;
64   Actor      hoveredActor;
65 };
66
67 // Functor that sets the data when called
68 struct HoverEventFunctor
69 {
70   /**
71    * Constructor.
72    * @param[in]  data         Reference to the data to store callback information.
73    * @param[in]  returnValue  What the functor should return.
74    */
75   HoverEventFunctor(SignalData& data, bool returnValue = true)
76   : signalData(data),
77     returnValue(returnValue)
78   {
79   }
80
81   bool operator()(Actor actor, const HoverEvent& hoverEvent)
82   {
83     signalData.functorCalled = true;
84     signalData.hoveredActor  = actor;
85     signalData.hoverEvent    = hoverEvent;
86
87     return returnValue;
88   }
89
90   SignalData& signalData;
91   bool        returnValue;
92 };
93
94 // Functor that removes the actor when called.
95 struct RemoveActorFunctor : public HoverEventFunctor
96 {
97   /**
98    * Constructor.
99    * @param[in]  data         Reference to the data to store callback information.
100    * @param[in]  returnValue  What the functor should return.
101    */
102   RemoveActorFunctor(SignalData& data, bool returnValue = true)
103   : HoverEventFunctor(data, returnValue)
104   {
105   }
106
107   bool operator()(Actor actor, const HoverEvent& hoverEvent)
108   {
109     Actor parent(actor.GetParent());
110     if(parent)
111     {
112       parent.Remove(actor);
113     }
114
115     return HoverEventFunctor::operator()(actor, hoverEvent);
116   }
117 };
118
119 Integration::HoverEvent GenerateSingleHover(PointState::Type state, const Vector2& screenPosition)
120 {
121   Integration::HoverEvent hoverEvent;
122   Integration::Point      point;
123   point.SetState(state);
124   point.SetScreenPosition(screenPosition);
125   hoverEvent.points.push_back(point);
126   return hoverEvent;
127 }
128
129 } // namespace
130
131 ///////////////////////////////////////////////////////////////////////////////
132
133 int UtcDaliHoverNormalProcessing(void)
134 {
135   TestApplication application;
136
137   Actor actor = Actor::New();
138   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
139   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
140   application.GetScene().Add(actor);
141
142   // Render and notify
143   application.SendNotification();
144   application.Render();
145
146   // Connect to actor's hovered signal
147   SignalData        data;
148   HoverEventFunctor functor(data);
149   actor.HoveredSignal().Connect(&application, functor);
150
151   Vector2 screenCoordinates(10.0f, 10.0f);
152   Vector2 localCoordinates;
153   actor.ScreenToLocal(localCoordinates.x, localCoordinates.y, screenCoordinates.x, screenCoordinates.y);
154
155   // Emit a started signal
156   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, screenCoordinates));
157   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
158   DALI_TEST_EQUALS(1u, data.hoverEvent.GetPointCount(), TEST_LOCATION);
159   DALI_TEST_EQUALS(PointState::STARTED, data.hoverEvent.GetState(0), TEST_LOCATION);
160   DALI_TEST_EQUALS(screenCoordinates, data.hoverEvent.GetScreenPosition(0), TEST_LOCATION);
161   DALI_TEST_EQUALS(localCoordinates, data.hoverEvent.GetLocalPosition(0), 0.1f, TEST_LOCATION);
162   DALI_TEST_EQUALS(0, data.hoverEvent.GetDeviceId(0), TEST_LOCATION);
163   DALI_TEST_EQUALS(0u, data.hoverEvent.GetTime(), TEST_LOCATION);
164   DALI_TEST_EQUALS(actor, data.hoverEvent.GetHitActor(0), TEST_LOCATION);
165   DALI_TEST_EQUALS(-1, data.hoverEvent.GetDeviceId(1), TEST_LOCATION);
166   DALI_TEST_EQUALS(PointState::FINISHED, data.hoverEvent.GetState(1), TEST_LOCATION);
167   DALI_TEST_EQUALS(Vector2::ZERO, data.hoverEvent.GetScreenPosition(1), 0.1f, TEST_LOCATION);
168   DALI_TEST_EQUALS(Vector2::ZERO, data.hoverEvent.GetLocalPosition(1), 0.1f, TEST_LOCATION);
169   DALI_TEST_EQUALS(Dali::Actor(), data.hoverEvent.GetHitActor(1), TEST_LOCATION);
170   data.Reset();
171
172   // Emit a motion signal
173   screenCoordinates.x = screenCoordinates.y = 11.0f;
174   actor.ScreenToLocal(localCoordinates.x, localCoordinates.y, screenCoordinates.x, screenCoordinates.y);
175   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, screenCoordinates));
176   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
177   DALI_TEST_EQUALS(1u, data.hoverEvent.GetPointCount(), TEST_LOCATION);
178   DALI_TEST_EQUALS(PointState::MOTION, data.hoverEvent.GetState(0), TEST_LOCATION);
179   DALI_TEST_EQUALS(screenCoordinates, data.hoverEvent.GetScreenPosition(0), TEST_LOCATION);
180   DALI_TEST_EQUALS(localCoordinates, data.hoverEvent.GetLocalPosition(0), 0.1f, TEST_LOCATION);
181   DALI_TEST_EQUALS(0, data.hoverEvent.GetDeviceId(0), TEST_LOCATION);
182   DALI_TEST_EQUALS(0u, data.hoverEvent.GetTime(), TEST_LOCATION);
183   DALI_TEST_EQUALS(actor, data.hoverEvent.GetHitActor(0), TEST_LOCATION);
184   DALI_TEST_EQUALS(-1, data.hoverEvent.GetDeviceId(1), TEST_LOCATION);
185   DALI_TEST_EQUALS(PointState::FINISHED, data.hoverEvent.GetState(1), TEST_LOCATION);
186   DALI_TEST_EQUALS(Vector2::ZERO, data.hoverEvent.GetScreenPosition(1), 0.1f, TEST_LOCATION);
187   DALI_TEST_EQUALS(Vector2::ZERO, data.hoverEvent.GetLocalPosition(1), 0.1f, TEST_LOCATION);
188   DALI_TEST_EQUALS(Dali::Actor(), data.hoverEvent.GetHitActor(1), TEST_LOCATION);
189   data.Reset();
190
191   // Emit a finished signal
192   screenCoordinates.x = screenCoordinates.y = 12.0f;
193   actor.ScreenToLocal(localCoordinates.x, localCoordinates.y, screenCoordinates.x, screenCoordinates.y);
194   application.ProcessEvent(GenerateSingleHover(PointState::FINISHED, screenCoordinates));
195   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
196   DALI_TEST_EQUALS(1u, data.hoverEvent.GetPointCount(), TEST_LOCATION);
197   DALI_TEST_EQUALS(PointState::FINISHED, data.hoverEvent.GetState(0), TEST_LOCATION);
198   DALI_TEST_EQUALS(screenCoordinates, data.hoverEvent.GetScreenPosition(0), TEST_LOCATION);
199   DALI_TEST_EQUALS(localCoordinates, data.hoverEvent.GetLocalPosition(0), 0.1f, TEST_LOCATION);
200   DALI_TEST_EQUALS(0, data.hoverEvent.GetDeviceId(0), TEST_LOCATION);
201   DALI_TEST_EQUALS(0u, data.hoverEvent.GetTime(), TEST_LOCATION);
202   DALI_TEST_EQUALS(actor, data.hoverEvent.GetHitActor(0), TEST_LOCATION);
203   DALI_TEST_EQUALS(-1, data.hoverEvent.GetDeviceId(1), TEST_LOCATION);
204   DALI_TEST_EQUALS(PointState::FINISHED, data.hoverEvent.GetState(1), TEST_LOCATION);
205   DALI_TEST_EQUALS(Vector2::ZERO, data.hoverEvent.GetScreenPosition(1), 0.1f, TEST_LOCATION);
206   DALI_TEST_EQUALS(Vector2::ZERO, data.hoverEvent.GetLocalPosition(1), 0.1f, TEST_LOCATION);
207   DALI_TEST_EQUALS(Dali::Actor(), data.hoverEvent.GetHitActor(1), TEST_LOCATION);
208   data.Reset();
209
210   // Emit a started signal where the actor is not present
211   screenCoordinates.x = screenCoordinates.y = 200.0f;
212   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, screenCoordinates));
213   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
214   DALI_TEST_CHECK(!data.hoverEvent);
215
216   END_TEST;
217 }
218
219 int UtcDaliHoverOutsideCameraNearFarPlanes(void)
220 {
221   TestApplication application;
222
223   Integration::Scene stage     = application.GetScene();
224   Vector2            stageSize = stage.GetSize();
225
226   Actor actor = Actor::New();
227   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
228   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER);
229   actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
230   stage.Add(actor);
231
232   // Render and notify
233   application.SendNotification();
234   application.Render();
235
236   // Get the camera's near and far planes
237   RenderTaskList   taskList  = stage.GetRenderTaskList();
238   Dali::RenderTask task      = taskList.GetTask(0);
239   CameraActor      camera    = task.GetCameraActor();
240   float            nearPlane = camera.GetNearClippingPlane();
241   float            farPlane  = camera.GetFarClippingPlane();
242
243   // Calculate the current distance of the actor from the camera
244   float tanHalfFov = tanf(camera.GetFieldOfView() * 0.5f);
245   float distance   = (stageSize.y * 0.5f) / tanHalfFov;
246
247   // Connect to actor's hovered signal
248   SignalData        data;
249   HoverEventFunctor functor(data);
250   actor.HoveredSignal().Connect(&application, functor);
251
252   Vector2 screenCoordinates(stageSize.x * 0.5f, stageSize.y * 0.5f);
253
254   // Emit a started signal
255   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, screenCoordinates));
256   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
257   data.Reset();
258
259   // Emit a started signal where actor is just at the camera's near plane
260   actor.SetProperty(Actor::Property::POSITION_Z, distance - nearPlane);
261
262   // Render and notify
263   application.SendNotification();
264   application.Render();
265
266   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, screenCoordinates));
267   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
268   data.Reset();
269
270   // Emit a started signal where actor is closer than the camera's near plane
271   actor.SetProperty(Actor::Property::POSITION_Z, (distance - nearPlane) + 1.0f);
272
273   // Render and notify
274   application.SendNotification();
275   application.Render();
276
277   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, screenCoordinates));
278   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
279   data.Reset();
280
281   // Emit a started signal where actor is just at the camera's far plane
282   actor.SetProperty(Actor::Property::POSITION_Z, distance - farPlane);
283
284   // Render and notify
285   application.SendNotification();
286   application.Render();
287
288   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, screenCoordinates));
289   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
290   data.Reset();
291
292   // Emit a started signal where actor is further than the camera's far plane
293   actor.SetProperty(Actor::Property::POSITION_Z, (distance - farPlane) - 1.0f);
294
295   // Render and notify
296   application.SendNotification();
297   application.Render();
298
299   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, screenCoordinates));
300   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
301   data.Reset();
302   END_TEST;
303 }
304
305 int UtcDaliHoverEmitEmpty(void)
306 {
307   TestApplication application;
308
309   try
310   {
311     // Emit an empty HoverEvent
312     Integration::HoverEvent event;
313     application.ProcessEvent(event);
314     tet_result(TET_FAIL);
315   }
316   catch(Dali::DaliException& e)
317   {
318     DALI_TEST_ASSERT(e, "!event.points.empty()", TEST_LOCATION);
319   }
320   END_TEST;
321 }
322
323 int UtcDaliHoverInterrupted(void)
324 {
325   TestApplication application;
326
327   Actor actor = Actor::New();
328   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
329   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
330   application.GetScene().Add(actor);
331
332   // Render and notify
333   application.SendNotification();
334   application.Render();
335
336   // Connect to actor's hovered signal
337   SignalData        data;
338   HoverEventFunctor functor(data);
339   actor.HoveredSignal().Connect(&application, functor);
340
341   // Emit a started signal
342   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
343   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
344   DALI_TEST_EQUALS(PointState::STARTED, data.hoverEvent.GetState(0), TEST_LOCATION);
345   data.Reset();
346
347   // Emit an interrupted signal, we should be signalled regardless of whether there is a hit or not.
348   application.ProcessEvent(GenerateSingleHover(PointState::INTERRUPTED, Vector2(200.0f, 200.0f /* Outside actor */)));
349   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
350   DALI_TEST_EQUALS(PointState::INTERRUPTED, data.hoverEvent.GetState(0), TEST_LOCATION);
351   data.Reset();
352
353   // Emit another interrupted signal, our signal handler should not be called.
354   application.ProcessEvent(GenerateSingleHover(PointState::INTERRUPTED, Vector2(200.0f, 200.0f)));
355   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
356   END_TEST;
357 }
358
359 int UtcDaliHoverParentConsumer(void)
360 {
361   TestApplication application;
362   Actor           rootActor(application.GetScene().GetRootLayer());
363
364   Actor actor = Actor::New();
365   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
366   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
367   application.GetScene().Add(actor);
368
369   // Render and notify
370   application.SendNotification();
371   application.Render();
372
373   // Connect to actor's hovered signal
374   SignalData        data;
375   HoverEventFunctor functor(data, false);
376   actor.HoveredSignal().Connect(&application, functor);
377
378   // Connect to root actor's hovered signal
379   SignalData        rootData;
380   HoverEventFunctor rootFunctor(rootData); // Consumes signal
381   rootActor.HoveredSignal().Connect(&application, rootFunctor);
382
383   Vector2 screenCoordinates(10.0f, 10.0f);
384   Vector2 actorCoordinates, rootCoordinates;
385   actor.ScreenToLocal(actorCoordinates.x, actorCoordinates.y, screenCoordinates.x, screenCoordinates.y);
386   rootActor.ScreenToLocal(rootCoordinates.x, rootCoordinates.y, screenCoordinates.x, screenCoordinates.y);
387
388   // Emit a started signal
389   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, screenCoordinates));
390   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
391   DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
392   DALI_TEST_EQUALS(1u, data.hoverEvent.GetPointCount(), TEST_LOCATION);
393   DALI_TEST_EQUALS(1u, rootData.hoverEvent.GetPointCount(), TEST_LOCATION);
394   DALI_TEST_EQUALS(PointState::STARTED, data.hoverEvent.GetState(0), TEST_LOCATION);
395   DALI_TEST_EQUALS(PointState::STARTED, rootData.hoverEvent.GetState(0), TEST_LOCATION);
396   DALI_TEST_EQUALS(screenCoordinates, data.hoverEvent.GetScreenPosition(0), TEST_LOCATION);
397   DALI_TEST_EQUALS(screenCoordinates, rootData.hoverEvent.GetScreenPosition(0), TEST_LOCATION);
398   DALI_TEST_EQUALS(actorCoordinates, data.hoverEvent.GetLocalPosition(0), 0.1f, TEST_LOCATION);
399   DALI_TEST_EQUALS(rootCoordinates, rootData.hoverEvent.GetLocalPosition(0), 0.1f, TEST_LOCATION);
400   DALI_TEST_CHECK(actor == data.hoverEvent.GetHitActor(0));
401   DALI_TEST_CHECK(actor == rootData.hoverEvent.GetHitActor(0));
402   data.Reset();
403   rootData.Reset();
404
405   // Emit a motion signal
406   screenCoordinates.x = screenCoordinates.y = 11.0f;
407   actor.ScreenToLocal(actorCoordinates.x, actorCoordinates.y, screenCoordinates.x, screenCoordinates.y);
408   rootActor.ScreenToLocal(rootCoordinates.x, rootCoordinates.y, screenCoordinates.x, screenCoordinates.y);
409   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, screenCoordinates));
410   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
411   DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
412   DALI_TEST_EQUALS(1u, data.hoverEvent.GetPointCount(), TEST_LOCATION);
413   DALI_TEST_EQUALS(1u, rootData.hoverEvent.GetPointCount(), TEST_LOCATION);
414   DALI_TEST_EQUALS(PointState::MOTION, data.hoverEvent.GetState(0), TEST_LOCATION);
415   DALI_TEST_EQUALS(PointState::MOTION, rootData.hoverEvent.GetState(0), TEST_LOCATION);
416   DALI_TEST_EQUALS(screenCoordinates, data.hoverEvent.GetScreenPosition(0), TEST_LOCATION);
417   DALI_TEST_EQUALS(screenCoordinates, rootData.hoverEvent.GetScreenPosition(0), TEST_LOCATION);
418   DALI_TEST_EQUALS(actorCoordinates, data.hoverEvent.GetLocalPosition(0), 0.1f, TEST_LOCATION);
419   DALI_TEST_EQUALS(rootCoordinates, rootData.hoverEvent.GetLocalPosition(0), 0.1f, TEST_LOCATION);
420   DALI_TEST_CHECK(actor == data.hoverEvent.GetHitActor(0));
421   DALI_TEST_CHECK(actor == rootData.hoverEvent.GetHitActor(0));
422   data.Reset();
423   rootData.Reset();
424
425   // Emit a finished signal
426   screenCoordinates.x = screenCoordinates.y = 12.0f;
427   actor.ScreenToLocal(actorCoordinates.x, actorCoordinates.y, screenCoordinates.x, screenCoordinates.y);
428   rootActor.ScreenToLocal(rootCoordinates.x, rootCoordinates.y, screenCoordinates.x, screenCoordinates.y);
429   application.ProcessEvent(GenerateSingleHover(PointState::FINISHED, screenCoordinates));
430   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
431   DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
432   DALI_TEST_EQUALS(1u, data.hoverEvent.GetPointCount(), TEST_LOCATION);
433   DALI_TEST_EQUALS(1u, rootData.hoverEvent.GetPointCount(), TEST_LOCATION);
434   DALI_TEST_EQUALS(PointState::FINISHED, data.hoverEvent.GetState(0), TEST_LOCATION);
435   DALI_TEST_EQUALS(PointState::FINISHED, rootData.hoverEvent.GetState(0), TEST_LOCATION);
436   DALI_TEST_EQUALS(screenCoordinates, data.hoverEvent.GetScreenPosition(0), TEST_LOCATION);
437   DALI_TEST_EQUALS(screenCoordinates, rootData.hoverEvent.GetScreenPosition(0), TEST_LOCATION);
438   DALI_TEST_EQUALS(actorCoordinates, data.hoverEvent.GetLocalPosition(0), 0.1f, TEST_LOCATION);
439   DALI_TEST_EQUALS(rootCoordinates, rootData.hoverEvent.GetLocalPosition(0), 0.1f, TEST_LOCATION);
440   DALI_TEST_CHECK(actor == data.hoverEvent.GetHitActor(0));
441   DALI_TEST_CHECK(actor == rootData.hoverEvent.GetHitActor(0));
442   data.Reset();
443   rootData.Reset();
444
445   // Emit a started signal where the actor is not present, will hit the root actor though
446   screenCoordinates.x = screenCoordinates.y = 200.0f;
447   rootActor.ScreenToLocal(rootCoordinates.x, rootCoordinates.y, screenCoordinates.x, screenCoordinates.y);
448   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, screenCoordinates));
449   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
450   DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
451   DALI_TEST_EQUALS(1u, rootData.hoverEvent.GetPointCount(), TEST_LOCATION);
452   DALI_TEST_EQUALS(PointState::STARTED, rootData.hoverEvent.GetState(0), TEST_LOCATION);
453   DALI_TEST_EQUALS(screenCoordinates, rootData.hoverEvent.GetScreenPosition(0), TEST_LOCATION);
454   DALI_TEST_EQUALS(rootCoordinates, rootData.hoverEvent.GetLocalPosition(0), 0.1f, TEST_LOCATION);
455   DALI_TEST_CHECK(rootActor == rootData.hoverEvent.GetHitActor(0));
456   END_TEST;
457 }
458
459 int UtcDaliHoverInterruptedParentConsumer(void)
460 {
461   TestApplication application;
462   Actor           rootActor(application.GetScene().GetRootLayer());
463
464   Actor actor = Actor::New();
465   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
466   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
467   application.GetScene().Add(actor);
468
469   // Render and notify
470   application.SendNotification();
471   application.Render();
472
473   // Connect to actor's hovered signal
474   SignalData        data;
475   HoverEventFunctor functor(data, false);
476   actor.HoveredSignal().Connect(&application, functor);
477
478   // Connect to root actor's hovered signal
479   SignalData        rootData;
480   HoverEventFunctor rootFunctor(rootData); // Consumes signal
481   rootActor.HoveredSignal().Connect(&application, rootFunctor);
482
483   // Emit a started signal
484   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
485   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
486   DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
487   DALI_TEST_EQUALS(PointState::STARTED, data.hoverEvent.GetState(0), TEST_LOCATION);
488   DALI_TEST_EQUALS(PointState::STARTED, rootData.hoverEvent.GetState(0), TEST_LOCATION);
489   DALI_TEST_CHECK(actor == data.hoverEvent.GetHitActor(0));
490   DALI_TEST_CHECK(actor == rootData.hoverEvent.GetHitActor(0));
491   data.Reset();
492   rootData.Reset();
493
494   // Emit an interrupted signal
495   application.ProcessEvent(GenerateSingleHover(PointState::INTERRUPTED, Vector2(200.0f, 200.0f)));
496   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
497   DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
498   DALI_TEST_EQUALS(PointState::INTERRUPTED, data.hoverEvent.GetState(0), TEST_LOCATION);
499   DALI_TEST_EQUALS(PointState::INTERRUPTED, rootData.hoverEvent.GetState(0), TEST_LOCATION);
500   DALI_TEST_CHECK(actor == data.hoverEvent.GetHitActor(0));
501   DALI_TEST_CHECK(actor == rootData.hoverEvent.GetHitActor(0));
502   data.Reset();
503   rootData.Reset();
504
505   // Emit another started signal
506   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
507   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
508   DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
509   DALI_TEST_EQUALS(PointState::STARTED, data.hoverEvent.GetState(0), TEST_LOCATION);
510   DALI_TEST_EQUALS(PointState::STARTED, rootData.hoverEvent.GetState(0), TEST_LOCATION);
511   data.Reset();
512   rootData.Reset();
513
514   // Remove actor from Stage
515   application.GetScene().Remove(actor);
516   data.Reset();
517   rootData.Reset();
518
519   // Render and notify
520   application.SendNotification();
521   application.Render();
522
523   // Emit an interrupted signal, only root actor's signal should be called.
524   application.ProcessEvent(GenerateSingleHover(PointState::INTERRUPTED, Vector2(200.0f, 200.0f /* Outside actor */)));
525   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
526   DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
527   DALI_TEST_EQUALS(PointState::INTERRUPTED, rootData.hoverEvent.GetState(0), TEST_LOCATION);
528   DALI_TEST_CHECK(rootActor == rootData.hoverEvent.GetHitActor(0));
529   data.Reset();
530   rootData.Reset();
531
532   // Emit another interrupted state, none of the signal's should be called.
533   application.ProcessEvent(GenerateSingleHover(PointState::INTERRUPTED, Vector2(200.0f, 200.0f)));
534   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
535   DALI_TEST_EQUALS(false, rootData.functorCalled, TEST_LOCATION);
536   END_TEST;
537 }
538
539 int UtcDaliHoverLeave(void)
540 {
541   TestApplication application;
542
543   Actor actor = Actor::New();
544   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
545   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
546   application.GetScene().Add(actor);
547
548   // Render and notify
549   application.SendNotification();
550   application.Render();
551
552   // Connect to actor's hovered signal
553   SignalData        data;
554   HoverEventFunctor functor(data);
555   actor.HoveredSignal().Connect(&application, functor);
556
557   // Set actor to require leave events
558   actor.SetProperty(Actor::Property::LEAVE_REQUIRED, true);
559
560   // Emit a started signal
561   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
562   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
563   DALI_TEST_EQUALS(PointState::STARTED, data.hoverEvent.GetState(0), TEST_LOCATION);
564   data.Reset();
565
566   // Emit a motion signal outside of actor, should be signalled with a Leave
567   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(200.0f, 200.0f)));
568   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
569   DALI_TEST_EQUALS(PointState::LEAVE, data.hoverEvent.GetState(0), TEST_LOCATION);
570   data.Reset();
571
572   // Another motion outside of actor, no signalling
573   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(201.0f, 201.0f)));
574   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
575   data.Reset();
576
577   // Another motion event inside actor, signalled with start. This is because a new hover event was started on that actor.
578   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(10.0f, 10.0f)));
579   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
580   DALI_TEST_EQUALS(PointState::STARTED, data.hoverEvent.GetState(0), TEST_LOCATION);
581   data.Reset();
582
583   // We do not want to listen to leave events anymore
584   actor.SetProperty(Actor::Property::LEAVE_REQUIRED, false);
585
586   // Another motion event outside of actor, no signalling
587   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(200.0f, 200.0f)));
588   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
589   data.Reset();
590   END_TEST;
591 }
592
593 int UtcDaliHoverLeaveParentConsumer(void)
594 {
595   TestApplication application;
596   Actor           rootActor(application.GetScene().GetRootLayer());
597
598   Actor actor = Actor::New();
599   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
600   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
601   application.GetScene().Add(actor);
602
603   // Render and notify
604   application.SendNotification();
605   application.Render();
606
607   // Connect to actor's hovered signal
608   SignalData        data;
609   HoverEventFunctor functor(data, false);
610   actor.HoveredSignal().Connect(&application, functor);
611
612   // Connect to root actor's hovered signal
613   SignalData        rootData;
614   HoverEventFunctor rootFunctor(rootData); // Consumes signal
615   rootActor.HoveredSignal().Connect(&application, rootFunctor);
616
617   // Set actor to require leave events
618   actor.SetProperty(Actor::Property::LEAVE_REQUIRED, true);
619   rootActor.SetProperty(Actor::Property::LEAVE_REQUIRED, true);
620
621   // Emit a started signal
622   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
623   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
624   DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
625   DALI_TEST_EQUALS(PointState::STARTED, data.hoverEvent.GetState(0), TEST_LOCATION);
626   DALI_TEST_EQUALS(PointState::STARTED, rootData.hoverEvent.GetState(0), TEST_LOCATION);
627   DALI_TEST_CHECK(actor == data.hoverEvent.GetHitActor(0));
628   DALI_TEST_CHECK(actor == rootData.hoverEvent.GetHitActor(0));
629   data.Reset();
630   rootData.Reset();
631
632   // Emit a motion signal outside of actor, should be signalled with a Leave
633   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(200.0f, 200.0f)));
634   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
635   DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
636   DALI_TEST_EQUALS(PointState::LEAVE, data.hoverEvent.GetState(0), TEST_LOCATION);
637   DALI_TEST_EQUALS(PointState::LEAVE, rootData.hoverEvent.GetState(0), TEST_LOCATION);
638   DALI_TEST_CHECK(actor == data.hoverEvent.GetHitActor(0));
639   DALI_TEST_CHECK(actor == rootData.hoverEvent.GetHitActor(0));
640   data.Reset();
641   rootData.Reset();
642
643   // Another motion outside of actor, only rootActor signalled
644   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(201.0f, 201.0f)));
645   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
646   DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
647   DALI_TEST_EQUALS(PointState::MOTION, rootData.hoverEvent.GetState(0), TEST_LOCATION);
648   DALI_TEST_CHECK(rootActor == rootData.hoverEvent.GetHitActor(0));
649   data.Reset();
650   rootData.Reset();
651
652   // Another motion event inside actor, signalled with start. This is because a new hover event was started on that actor.
653   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(10.0f, 10.0f)));
654   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
655   DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
656   DALI_TEST_EQUALS(PointState::STARTED, data.hoverEvent.GetState(0), TEST_LOCATION);
657   DALI_TEST_EQUALS(PointState::STARTED, rootData.hoverEvent.GetState(0), TEST_LOCATION);
658   DALI_TEST_CHECK(actor == data.hoverEvent.GetHitActor(0));
659   DALI_TEST_CHECK(actor == rootData.hoverEvent.GetHitActor(0));
660   data.Reset();
661   rootData.Reset();
662
663   // We do not want to listen to leave events of actor anymore
664   actor.SetProperty(Actor::Property::LEAVE_REQUIRED, false);
665
666   // Another motion event outside of root actor, only root signalled
667   Vector2 stageSize(application.GetScene().GetSize());
668   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(stageSize.width + 10.0f, stageSize.height + 10.0f)));
669   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
670   DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
671   DALI_TEST_EQUALS(PointState::LEAVE, rootData.hoverEvent.GetState(0), TEST_LOCATION);
672   END_TEST;
673 }
674
675 int UtcDaliHoverActorBecomesInsensitive(void)
676 {
677   TestApplication application;
678
679   Actor actor = Actor::New();
680   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
681   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
682   application.GetScene().Add(actor);
683
684   // Render and notify
685   application.SendNotification();
686   application.Render();
687
688   // Connect to actor's hovered signal
689   SignalData        data;
690   HoverEventFunctor functor(data);
691   actor.HoveredSignal().Connect(&application, functor);
692
693   // Emit a started signal
694   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
695   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
696   DALI_TEST_EQUALS(PointState::STARTED, data.hoverEvent.GetState(0), TEST_LOCATION);
697   data.Reset();
698
699   // Change actor to insensitive
700   actor.SetProperty(Actor::Property::SENSITIVE, false);
701
702   // Emit a motion signal, signalled with an interrupted
703   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(200.0f, 200.0f)));
704   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
705   DALI_TEST_EQUALS(PointState::INTERRUPTED, data.hoverEvent.GetState(0), TEST_LOCATION);
706   data.Reset();
707   END_TEST;
708 }
709
710 int UtcDaliHoverActorBecomesInsensitiveParentConsumer(void)
711 {
712   TestApplication application;
713   Actor           rootActor(application.GetScene().GetRootLayer());
714
715   Actor actor = Actor::New();
716   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
717   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
718   application.GetScene().Add(actor);
719
720   // Render and notify
721   application.SendNotification();
722   application.Render();
723
724   // Connect to actor's hovered signal
725   SignalData        data;
726   HoverEventFunctor functor(data, false);
727   actor.HoveredSignal().Connect(&application, functor);
728
729   // Connect to root actor's hovered signal
730   SignalData        rootData;
731   HoverEventFunctor rootFunctor(rootData); // Consumes signal
732   rootActor.HoveredSignal().Connect(&application, rootFunctor);
733
734   // Emit a started signal
735   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
736   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
737   DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
738   DALI_TEST_EQUALS(PointState::STARTED, data.hoverEvent.GetState(0), TEST_LOCATION);
739   DALI_TEST_EQUALS(PointState::STARTED, rootData.hoverEvent.GetState(0), TEST_LOCATION);
740   DALI_TEST_CHECK(actor == data.hoverEvent.GetHitActor(0));
741   DALI_TEST_CHECK(actor == rootData.hoverEvent.GetHitActor(0));
742   data.Reset();
743   rootData.Reset();
744
745   // Remove actor from Stage
746   application.GetScene().Remove(actor);
747
748   // Because it was removed, it gets interrupted.
749   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
750   DALI_TEST_EQUALS(PointState::INTERRUPTED, data.hoverEvent.GetState(0), TEST_LOCATION);
751   data.Reset();
752   rootData.Reset();
753
754   // Render and notify
755   application.SendNotification();
756   application.Render();
757
758   // Make root actor insensitive
759   rootActor.SetProperty(Actor::Property::SENSITIVE, false);
760
761   // Because it is insensitive, it does not receive the event.
762   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(200.0f, 200.0f)));
763   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
764   DALI_TEST_EQUALS(false, rootData.functorCalled, TEST_LOCATION);
765   data.Reset();
766   rootData.Reset();
767
768   END_TEST;
769 }
770
771 int UtcDaliHoverActorBecomesUserInteractionDisabled(void)
772 {
773   TestApplication application;
774
775   Actor actor = Actor::New();
776   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
777   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
778   application.GetScene().Add(actor);
779
780   // Render and notify
781   application.SendNotification();
782   application.Render();
783
784   // Connect to actor's hovered signal
785   SignalData        data;
786   HoverEventFunctor functor(data);
787   actor.HoveredSignal().Connect(&application, functor);
788
789   // Emit a started signal
790   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
791   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
792   DALI_TEST_EQUALS(PointState::STARTED, data.hoverEvent.GetState(0), TEST_LOCATION);
793   data.Reset();
794
795   // Change actor to disable user interaction.
796   actor.SetProperty(DevelActor::Property::USER_INTERACTION_ENABLED, false);
797
798   // Emit a motion signal, signalled with an interrupted
799   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(200.0f, 200.0f)));
800   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
801   DALI_TEST_EQUALS(PointState::INTERRUPTED, data.hoverEvent.GetState(0), TEST_LOCATION);
802   data.Reset();
803   END_TEST;
804 }
805
806 int UtcDaliHoverMultipleLayers(void)
807 {
808   TestApplication application;
809   Actor           rootActor(application.GetScene().GetRootLayer());
810
811   // Connect to actor's hovered signal
812   SignalData        data;
813   HoverEventFunctor functor(data);
814
815   Layer layer1(Layer::New());
816   layer1.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
817   layer1.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
818   application.GetScene().Add(layer1);
819
820   Actor actor1(Actor::New());
821   actor1.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
822   actor1.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
823   actor1.SetProperty(Actor::Property::POSITION_Z, 1.0f); // Should hit actor1 in this layer
824   layer1.Add(actor1);
825
826   // Render and notify
827   application.SendNotification();
828   application.Render();
829
830   // Connect to layer1 and actor1
831   layer1.HoveredSignal().Connect(&application, functor);
832   actor1.HoveredSignal().Connect(&application, functor);
833
834   // Hit in hittable area, actor1 should be hit
835   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
836   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
837   DALI_TEST_CHECK(data.hoveredActor == actor1);
838   data.Reset();
839
840   // Make layer1 insensitive, nothing should be hit
841   layer1.SetProperty(Actor::Property::SENSITIVE, false);
842   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
843   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
844   data.Reset();
845
846   // Make layer1 sensitive again, again actor1 will be hit
847   layer1.SetProperty(Actor::Property::SENSITIVE, true);
848   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
849   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
850   DALI_TEST_CHECK(data.hoveredActor == actor1);
851   data.Reset();
852
853   // Make rootActor insensitive, nothing should be hit
854   rootActor.SetProperty(Actor::Property::SENSITIVE, false);
855   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
856   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
857   data.Reset();
858
859   // Make rootActor sensitive
860   rootActor.SetProperty(Actor::Property::SENSITIVE, true);
861
862   // Add another layer
863   Layer layer2(Layer::New());
864   layer2.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
865   layer2.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
866   layer2.SetProperty(Actor::Property::POSITION_Z, 10.0f); // Should hit layer2 in this layer rather than actor2
867   application.GetScene().Add(layer2);
868
869   Actor actor2(Actor::New());
870   actor2.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
871   actor2.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
872   layer2.Add(actor2);
873
874   // Render and notify
875   application.SendNotification();
876   application.Render();
877
878   // Connect to layer2 and actor2
879   layer2.HoveredSignal().Connect(&application, functor);
880   actor2.HoveredSignal().Connect(&application, functor);
881
882   // Emit an event, should hit layer2
883   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
884   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
885   //DALI_TEST_CHECK( data.hoveredActor == layer2 ); // TODO: Uncomment this after removing renderable hack!
886   data.Reset();
887
888   // Make layer2 insensitive, should hit actor1
889   layer2.SetProperty(Actor::Property::SENSITIVE, false);
890   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
891   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
892   DALI_TEST_CHECK(data.hoveredActor == actor1);
893   data.Reset();
894
895   // Make layer2 sensitive again, should hit layer2
896   layer2.SetProperty(Actor::Property::SENSITIVE, true);
897   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
898   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
899   //DALI_TEST_CHECK( data.hoveredActor == layer2 ); // TODO: Uncomment this after removing renderable hack!
900   data.Reset();
901
902   // Make layer2 invisible, render and notify
903   layer2.SetProperty(Actor::Property::VISIBLE, false);
904   application.SendNotification();
905   application.Render();
906
907   // Should hit actor1
908   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
909   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
910   DALI_TEST_CHECK(data.hoveredActor == actor1);
911   data.Reset();
912
913   // Make rootActor invisible, render and notify
914   rootActor.SetProperty(Actor::Property::VISIBLE, false);
915
916   // Because visible became false, we receive interrupted
917   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
918   DALI_TEST_EQUALS(PointState::INTERRUPTED, data.hoverEvent.GetState(0), TEST_LOCATION);
919   data.Reset();
920
921   application.SendNotification();
922   application.Render();
923
924   // Should not hit anything
925   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
926   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
927   data.Reset();
928   END_TEST;
929 }
930
931 int UtcDaliHoverMultipleRenderTasks(void)
932 {
933   TestApplication    application;
934   Integration::Scene stage(application.GetScene());
935   Vector2            stageSize(stage.GetSize());
936
937   Actor actor = Actor::New();
938   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
939   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
940   stage.Add(actor);
941
942   // Create render task
943   Viewport   viewport(stageSize.width * 0.5f, stageSize.height * 0.5f, stageSize.width * 0.5f, stageSize.height * 0.5f);
944   RenderTask renderTask(application.GetScene().GetRenderTaskList().CreateTask());
945   renderTask.SetViewport(viewport);
946   renderTask.SetInputEnabled(true);
947
948   // Render and notify
949   application.SendNotification();
950   application.Render();
951
952   // Connect to actor's hovered signal
953   SignalData        data;
954   HoverEventFunctor functor(data);
955   actor.HoveredSignal().Connect(&application, functor);
956
957   // Emit a started signal
958   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
959   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
960   data.Reset();
961
962   // Ensure renderTask actor can be hit too.
963   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(viewport.x + 5.0f, viewport.y + 5.0f)));
964   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
965   data.Reset();
966
967   // Disable input on renderTask, should not be hittable
968   renderTask.SetInputEnabled(false);
969   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(viewport.x + 5.0f, viewport.y + 5.0f)));
970   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
971   data.Reset();
972   END_TEST;
973 }
974
975 int UtcDaliHoverMultipleRenderTasksWithChildLayer(void)
976 {
977   TestApplication    application;
978   Integration::Scene stage(application.GetScene());
979   Vector2            stageSize(stage.GetSize());
980
981   Actor actor = Actor::New();
982   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
983   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
984   stage.Add(actor);
985
986   Layer layer = Layer::New();
987   layer.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
988   layer.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
989   actor.Add(layer);
990
991   // Create render task
992   Viewport   viewport(stageSize.width * 0.5f, stageSize.height * 0.5f, stageSize.width * 0.5f, stageSize.height * 0.5f);
993   RenderTask renderTask(application.GetScene().GetRenderTaskList().CreateTask());
994   renderTask.SetViewport(viewport);
995   renderTask.SetInputEnabled(true);
996   renderTask.SetSourceActor(actor);
997
998   // Render and notify
999   application.SendNotification();
1000   application.Render();
1001
1002   // Connect to layer's hovered signal
1003   SignalData        data;
1004   HoverEventFunctor functor(data);
1005   actor.HoveredSignal().Connect(&application, functor);
1006   layer.HoveredSignal().Connect(&application, functor);
1007
1008   // Emit a started signal
1009   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
1010   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1011   data.Reset();
1012
1013   // Ensure renderTask actor can be hit too.
1014   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(viewport.x + 5.0f, viewport.y + 5.0f)));
1015   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1016   data.Reset();
1017
1018   // Disable input on renderTask, should not be hittable
1019   renderTask.SetInputEnabled(false);
1020   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(viewport.x + 5.0f, viewport.y + 5.0f)));
1021   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
1022   data.Reset();
1023   END_TEST;
1024 }
1025
1026 int UtcDaliHoverOffscreenRenderTasks(void)
1027 {
1028   TestApplication    application;
1029   Integration::Scene stage(application.GetScene());
1030   Vector2            stageSize(stage.GetSize());
1031
1032   // FrameBufferImage for offscreen RenderTask
1033   FrameBuffer frameBuffer = FrameBuffer::New(stageSize.width, stageSize.height);
1034
1035   // Create a renderable actor to display the FrameBufferImage
1036   Actor renderableActor = CreateRenderableActor(frameBuffer.GetColorTexture());
1037   renderableActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
1038   renderableActor.SetProperty(Actor::Property::SIZE, Vector2(stageSize.x, stageSize.y));
1039   renderableActor.ScaleBy(Vector3(1.0f, -1.0f, 1.0f)); // FIXME
1040   stage.Add(renderableActor);
1041
1042   Actor actor = Actor::New();
1043   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
1044   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
1045   stage.Add(actor);
1046   application.GetGlAbstraction().SetCheckFramebufferStatusResult(GL_FRAMEBUFFER_COMPLETE); // Ensure framebuffer connects
1047
1048   stage.GetRenderTaskList().GetTask(0u).SetScreenToFrameBufferFunction(RenderTask::FULLSCREEN_FRAMEBUFFER_FUNCTION);
1049
1050   // Create a RenderTask
1051   RenderTask renderTask = stage.GetRenderTaskList().CreateTask();
1052   renderTask.SetSourceActor(actor);
1053   renderTask.SetFrameBuffer(frameBuffer);
1054   renderTask.SetInputEnabled(true);
1055
1056   // Create another RenderTask
1057   RenderTask renderTask2(stage.GetRenderTaskList().CreateTask());
1058   renderTask2.SetInputEnabled(true);
1059
1060   // Render and notify
1061   application.SendNotification();
1062   application.Render();
1063
1064   // Connect to actor's hovered signal
1065   SignalData        data;
1066   HoverEventFunctor functor(data);
1067   actor.HoveredSignal().Connect(&application, functor);
1068
1069   // Emit a started signal
1070   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
1071   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1072   data.Reset();
1073   END_TEST;
1074 }
1075
1076 int UtcDaliHoverMultipleRenderableActors(void)
1077 {
1078   TestApplication    application;
1079   Integration::Scene stage(application.GetScene());
1080   Vector2            stageSize(stage.GetSize());
1081
1082   Actor parent = CreateRenderableActor();
1083   parent.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
1084   parent.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
1085   stage.Add(parent);
1086
1087   Actor actor = CreateRenderableActor();
1088   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
1089   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
1090   parent.Add(actor);
1091
1092   // Render and notify
1093   application.SendNotification();
1094   application.Render();
1095
1096   // Connect to layer's hovered signal
1097   SignalData        data;
1098   HoverEventFunctor functor(data);
1099   parent.HoveredSignal().Connect(&application, functor);
1100   actor.HoveredSignal().Connect(&application, functor);
1101
1102   // Emit a started signal
1103   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
1104   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1105   DALI_TEST_CHECK(actor == data.hoveredActor);
1106   END_TEST;
1107 }
1108
1109 int UtcDaliHoverActorRemovedInSignal(void)
1110 {
1111   TestApplication application;
1112
1113   Actor actor = Actor::New();
1114   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
1115   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
1116   application.GetScene().Add(actor);
1117
1118   // Render and notify
1119   application.SendNotification();
1120   application.Render();
1121
1122   // Connect to actor's hovered signal
1123   SignalData         data;
1124   RemoveActorFunctor functor(data);
1125   actor.HoveredSignal().Connect(&application, functor);
1126
1127   // Register for leave events
1128   actor.SetProperty(Actor::Property::LEAVE_REQUIRED, true);
1129
1130   // Emit a started signal
1131   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
1132   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1133   data.Reset();
1134
1135   // Re-add, render and notify
1136   application.GetScene().Add(actor);
1137   application.SendNotification();
1138   application.Render();
1139
1140   // Emit another signal outside of actor's area, should not get anything as the scene has changed.
1141   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(210.0f, 210.0f)));
1142   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
1143   data.Reset();
1144
1145   // Emit a started signal
1146   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
1147   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1148   data.Reset();
1149
1150   // Render and notify
1151   application.SendNotification();
1152   application.Render();
1153
1154   // Emit another signal outside of actor's area, should not get anything as the scene has changed.
1155   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(210.0f, 210.0f)));
1156   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
1157   data.Reset();
1158
1159   // Re-add actor back to stage, render and notify
1160   application.GetScene().Add(actor);
1161   application.SendNotification();
1162   application.Render();
1163
1164   // Emit another started event
1165   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
1166   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1167   data.Reset();
1168
1169   // Completely delete the actor
1170   actor.Reset();
1171
1172   // Emit event, should not crash and should not receive an event.
1173   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(210.0f, 210.0f)));
1174   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
1175   END_TEST;
1176 }
1177
1178 int UtcDaliHoverActorSignalNotConsumed(void)
1179 {
1180   TestApplication application;
1181
1182   Actor actor = Actor::New();
1183   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
1184   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
1185   application.GetScene().Add(actor);
1186
1187   // Render and notify
1188   application.SendNotification();
1189   application.Render();
1190
1191   // Connect to actor's hovered signal
1192   SignalData        data;
1193   HoverEventFunctor functor(data, false);
1194   actor.HoveredSignal().Connect(&application, functor);
1195
1196   // Emit a started signal
1197   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
1198   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1199   END_TEST;
1200 }
1201
1202 int UtcDaliHoverActorUnStaged(void)
1203 {
1204   TestApplication application;
1205
1206   Actor actor = Actor::New();
1207   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
1208   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
1209   application.GetScene().Add(actor);
1210
1211   // Render and notify
1212   application.SendNotification();
1213   application.Render();
1214
1215   // Connect to actor's hovered signal
1216   SignalData        data;
1217   HoverEventFunctor functor(data);
1218   actor.HoveredSignal().Connect(&application, functor);
1219
1220   // Emit a started signal
1221   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
1222   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1223   data.Reset();
1224
1225   // Remove actor from stage
1226   application.GetScene().Remove(actor);
1227
1228   // Interrupted is received because the actor receiving the event removed.
1229   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1230   DALI_TEST_EQUALS(PointState::INTERRUPTED, data.hoverEvent.GetState(0), TEST_LOCATION);
1231   data.Reset();
1232
1233   // Render and notify
1234   application.SendNotification();
1235   application.Render();
1236
1237   // Emit a move at the same point, we should not be signalled.
1238   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(10.0f, 10.0f)));
1239   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
1240   data.Reset();
1241   END_TEST;
1242 }
1243
1244 int UtcDaliHoverLeaveActorReadded(void)
1245 {
1246   TestApplication    application;
1247   Integration::Scene stage = application.GetScene();
1248
1249   Actor actor = Actor::New();
1250   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
1251   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
1252   stage.Add(actor);
1253
1254   // Set actor to receive hover-events
1255   actor.SetProperty(Actor::Property::LEAVE_REQUIRED, true);
1256
1257   // Render and notify
1258   application.SendNotification();
1259   application.Render();
1260
1261   // Connect to actor's hovered signal
1262   SignalData        data;
1263   HoverEventFunctor functor(data);
1264   actor.HoveredSignal().Connect(&application, functor);
1265
1266   // Emit a started and motion
1267   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
1268   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(11.0f, 10.0f)));
1269   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1270   data.Reset();
1271
1272   // Remove actor from stage and add again
1273   stage.Remove(actor);
1274   stage.Add(actor);
1275
1276   // Emit a motion within the actor's bounds
1277   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(12.0f, 10.0f)));
1278   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1279   data.Reset();
1280
1281   // Emit a motion outside the actor's bounds
1282   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(200.0f, 200.0f)));
1283   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1284   DALI_TEST_EQUALS(PointState::LEAVE, data.hoverEvent.GetState(0), TEST_LOCATION);
1285   data.Reset();
1286
1287   END_TEST;
1288 }
1289
1290 int UtcDaliHoverClippingActor(void)
1291 {
1292   TestApplication    application;
1293   Integration::Scene stage = application.GetScene();
1294
1295   Actor actor = Actor::New();
1296   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
1297   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
1298   stage.Add(actor);
1299
1300   Actor clippingActor = Actor::New();
1301   clippingActor.SetProperty(Actor::Property::SIZE, Vector2(50.0f, 50.0f));
1302   clippingActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
1303   clippingActor.SetProperty(Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_CHILDREN);
1304   stage.Add(clippingActor);
1305
1306   // Add a child to the clipped region.
1307   Actor clippingChild = Actor::New();
1308   clippingChild.SetProperty(Actor::Property::SIZE, Vector2(50.0f, 50.0f));
1309   clippingChild.SetProperty(Actor::Property::POSITION, Vector2(25.0f, 25.0f));
1310   clippingChild.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
1311   clippingActor.Add(clippingChild);
1312
1313   // Render and notify.
1314   application.SendNotification();
1315   application.Render();
1316
1317   // Connect to actor's hovered signal.
1318   SignalData        data;
1319   HoverEventFunctor functor(data);
1320   actor.HoveredSignal().Connect(&application, functor);
1321
1322   // Emit an event within clipped area - we should have a hit.
1323   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
1324   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1325   data.Reset();
1326
1327   // Emit an event outside the clipped area but within the actor area, we should have a hit.
1328   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(60.0f, 60.0f)));
1329   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1330   data.Reset();
1331
1332   clippingChild.HoveredSignal().Connect(&application, functor);
1333
1334   // Emit an event inside part of the child which is within the clipped area, we should have a hit.
1335   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(30.0f, 30.0f)));
1336   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1337   data.Reset();
1338
1339   END_TEST;
1340 }
1341
1342 int UtcDaliHoverEventCreate(void)
1343 {
1344   TestApplication application;
1345
1346   Dali::HoverEvent hoverEvent = DevelHoverEvent::New(100);
1347   DALI_TEST_CHECK(hoverEvent);
1348
1349   // Emit a started signal
1350   DALI_TEST_EQUALS(100, hoverEvent.GetTime(), TEST_LOCATION);
1351   DALI_TEST_EQUALS(0, hoverEvent.GetPointCount(), TEST_LOCATION);
1352
1353   END_TEST;
1354 }
1355
1356 int UtcDaliHoverEventIntegNewHoverEvent(void)
1357 {
1358   uint32_t         timestamp = 92858u;
1359   TouchPoint       tp(1, PointState::STARTED, 34.4f, 123.89f, 5.0f, 7.0f);
1360   Dali::HoverEvent hoverEvent = Integration::NewHoverEvent(timestamp, tp);
1361
1362   DALI_TEST_EQUALS(hoverEvent.GetPointCount(), 1u, TEST_LOCATION);
1363   DALI_TEST_EQUALS(hoverEvent.GetState(0), PointState::STARTED, TEST_LOCATION);
1364   DALI_TEST_EQUALS(hoverEvent.GetLocalPosition(0), Vector2(5.0f, 7.0f), TEST_LOCATION);
1365   DALI_TEST_EQUALS(hoverEvent.GetScreenPosition(0), Vector2(34.4f, 123.89f), TEST_LOCATION);
1366
1367   END_TEST;
1368 }
1369
1370 int UtcDaliHoverActorHide(void)
1371 {
1372   TestApplication    application;
1373   Integration::Scene stage = application.GetScene();
1374
1375   Actor actor = Actor::New();
1376   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
1377   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
1378   stage.Add(actor);
1379
1380   // Render and notify
1381   application.SendNotification();
1382   application.Render();
1383
1384   // Connect to actor's hovered signal
1385   SignalData        data;
1386   HoverEventFunctor functor(data);
1387   actor.HoveredSignal().Connect(&application, functor);
1388
1389   // Emit a started
1390   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
1391   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1392   data.Reset();
1393
1394   actor.SetProperty(Actor::Property::VISIBLE, false);
1395
1396   // flush the queue and render once
1397   application.SendNotification();
1398   application.Render();
1399
1400   // Interrupted is received because the actor receiving the event hides.
1401   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1402   DALI_TEST_EQUALS(PointState::INTERRUPTED, data.hoverEvent.GetState(0), TEST_LOCATION);
1403   data.Reset();
1404
1405   END_TEST;
1406 }