When a hover event enters a new actor, events are delivered in the order of start...
[platform/core/uifw/dali-core.git] / automated-tests / src / dali / utc-Dali-HoverProcessing.cpp
1 /*
2  * Copyright (c) 2024 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   // rootActor receives "started" state because a new hover event entered in rootActor area.
638   DALI_TEST_EQUALS(PointState::STARTED, rootData.hoverEvent.GetState(0), TEST_LOCATION);
639   DALI_TEST_CHECK(actor == data.hoverEvent.GetHitActor(0));
640   DALI_TEST_CHECK(rootActor == rootData.hoverEvent.GetHitActor(0));
641   data.Reset();
642   rootData.Reset();
643
644   // Another motion outside of actor, only rootActor signalled
645   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(201.0f, 201.0f)));
646   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
647   DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
648   DALI_TEST_EQUALS(PointState::MOTION, rootData.hoverEvent.GetState(0), TEST_LOCATION);
649   DALI_TEST_CHECK(rootActor == rootData.hoverEvent.GetHitActor(0));
650   data.Reset();
651   rootData.Reset();
652
653   // Another motion event inside actor, signalled with start. This is because a new hover event was started on that actor.
654   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(10.0f, 10.0f)));
655   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
656   DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
657   DALI_TEST_EQUALS(PointState::STARTED, data.hoverEvent.GetState(0), TEST_LOCATION);
658   DALI_TEST_EQUALS(PointState::STARTED, rootData.hoverEvent.GetState(0), TEST_LOCATION);
659   DALI_TEST_CHECK(actor == data.hoverEvent.GetHitActor(0));
660   DALI_TEST_CHECK(actor == rootData.hoverEvent.GetHitActor(0));
661   data.Reset();
662   rootData.Reset();
663
664   // We do not want to listen to leave events of actor anymore
665   actor.SetProperty(Actor::Property::LEAVE_REQUIRED, false);
666
667   // Another motion event outside of root actor, only root signalled
668   Vector2 stageSize(application.GetScene().GetSize());
669   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(stageSize.width + 10.0f, stageSize.height + 10.0f)));
670   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
671   DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
672   DALI_TEST_EQUALS(PointState::LEAVE, rootData.hoverEvent.GetState(0), TEST_LOCATION);
673   END_TEST;
674 }
675
676 int UtcDaliHoverActorBecomesInsensitive(void)
677 {
678   TestApplication application;
679
680   Actor actor = Actor::New();
681   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
682   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
683   application.GetScene().Add(actor);
684
685   // Render and notify
686   application.SendNotification();
687   application.Render();
688
689   // Connect to actor's hovered signal
690   SignalData        data;
691   HoverEventFunctor functor(data);
692   actor.HoveredSignal().Connect(&application, functor);
693
694   // Emit a started signal
695   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
696   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
697   DALI_TEST_EQUALS(PointState::STARTED, data.hoverEvent.GetState(0), TEST_LOCATION);
698   data.Reset();
699
700   // Change actor to insensitive
701   actor.SetProperty(Actor::Property::SENSITIVE, false);
702
703   // Emit a motion signal, signalled with an interrupted
704   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(200.0f, 200.0f)));
705   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
706   DALI_TEST_EQUALS(PointState::INTERRUPTED, data.hoverEvent.GetState(0), TEST_LOCATION);
707   data.Reset();
708   END_TEST;
709 }
710
711 int UtcDaliHoverActorBecomesInsensitiveParentConsumer(void)
712 {
713   TestApplication application;
714   Actor           rootActor(application.GetScene().GetRootLayer());
715
716   Actor actor = Actor::New();
717   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
718   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
719   application.GetScene().Add(actor);
720
721   // Render and notify
722   application.SendNotification();
723   application.Render();
724
725   // Connect to actor's hovered signal
726   SignalData        data;
727   HoverEventFunctor functor(data, false);
728   actor.HoveredSignal().Connect(&application, functor);
729
730   // Connect to root actor's hovered signal
731   SignalData        rootData;
732   HoverEventFunctor rootFunctor(rootData); // Consumes signal
733   rootActor.HoveredSignal().Connect(&application, rootFunctor);
734
735   // Emit a started signal
736   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
737   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
738   DALI_TEST_EQUALS(true, rootData.functorCalled, TEST_LOCATION);
739   DALI_TEST_EQUALS(PointState::STARTED, data.hoverEvent.GetState(0), TEST_LOCATION);
740   DALI_TEST_EQUALS(PointState::STARTED, rootData.hoverEvent.GetState(0), TEST_LOCATION);
741   DALI_TEST_CHECK(actor == data.hoverEvent.GetHitActor(0));
742   DALI_TEST_CHECK(actor == rootData.hoverEvent.GetHitActor(0));
743   data.Reset();
744   rootData.Reset();
745
746   // Remove actor from Stage
747   application.GetScene().Remove(actor);
748
749   // Because it was removed, it gets interrupted.
750   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
751   DALI_TEST_EQUALS(PointState::INTERRUPTED, data.hoverEvent.GetState(0), TEST_LOCATION);
752   data.Reset();
753   rootData.Reset();
754
755   // Render and notify
756   application.SendNotification();
757   application.Render();
758
759   // Make root actor insensitive
760   rootActor.SetProperty(Actor::Property::SENSITIVE, false);
761
762   // Because it is insensitive, it does not receive the event.
763   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(200.0f, 200.0f)));
764   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
765   DALI_TEST_EQUALS(false, rootData.functorCalled, TEST_LOCATION);
766   data.Reset();
767   rootData.Reset();
768
769   END_TEST;
770 }
771
772 int UtcDaliHoverActorBecomesUserInteractionDisabled(void)
773 {
774   TestApplication application;
775
776   Actor actor = Actor::New();
777   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
778   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
779   application.GetScene().Add(actor);
780
781   // Render and notify
782   application.SendNotification();
783   application.Render();
784
785   // Connect to actor's hovered signal
786   SignalData        data;
787   HoverEventFunctor functor(data);
788   actor.HoveredSignal().Connect(&application, functor);
789
790   // Emit a started signal
791   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
792   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
793   DALI_TEST_EQUALS(PointState::STARTED, data.hoverEvent.GetState(0), TEST_LOCATION);
794   data.Reset();
795
796   // Change actor to disable user interaction.
797   actor.SetProperty(DevelActor::Property::USER_INTERACTION_ENABLED, false);
798
799   // Emit a motion signal, signalled with an interrupted
800   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(200.0f, 200.0f)));
801   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
802   DALI_TEST_EQUALS(PointState::INTERRUPTED, data.hoverEvent.GetState(0), TEST_LOCATION);
803   data.Reset();
804   END_TEST;
805 }
806
807 int UtcDaliHoverMultipleLayers(void)
808 {
809   TestApplication application;
810   Actor           rootActor(application.GetScene().GetRootLayer());
811
812   // Connect to actor's hovered signal
813   SignalData        data;
814   HoverEventFunctor functor(data);
815
816   Layer layer1(Layer::New());
817   layer1.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
818   layer1.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
819   application.GetScene().Add(layer1);
820
821   Actor actor1(Actor::New());
822   actor1.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
823   actor1.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
824   actor1.SetProperty(Actor::Property::POSITION_Z, 1.0f); // Should hit actor1 in this layer
825   layer1.Add(actor1);
826
827   // Render and notify
828   application.SendNotification();
829   application.Render();
830
831   // Connect to layer1 and actor1
832   layer1.HoveredSignal().Connect(&application, functor);
833   actor1.HoveredSignal().Connect(&application, functor);
834
835   // Hit in hittable area, actor1 should be hit
836   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
837   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
838   DALI_TEST_CHECK(data.hoveredActor == actor1);
839   data.Reset();
840
841   // Make layer1 insensitive, nothing should be hit
842   layer1.SetProperty(Actor::Property::SENSITIVE, false);
843   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
844   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
845   data.Reset();
846
847   // Make layer1 sensitive again, again actor1 will be hit
848   layer1.SetProperty(Actor::Property::SENSITIVE, true);
849   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
850   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
851   DALI_TEST_CHECK(data.hoveredActor == actor1);
852   data.Reset();
853
854   // Make rootActor insensitive, nothing should be hit
855   rootActor.SetProperty(Actor::Property::SENSITIVE, false);
856   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
857   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
858   data.Reset();
859
860   // Make rootActor sensitive
861   rootActor.SetProperty(Actor::Property::SENSITIVE, true);
862
863   // Add another layer
864   Layer layer2(Layer::New());
865   layer2.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
866   layer2.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
867   layer2.SetProperty(Actor::Property::POSITION_Z, 10.0f); // Should hit layer2 in this layer rather than actor2
868   application.GetScene().Add(layer2);
869
870   Actor actor2(Actor::New());
871   actor2.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
872   actor2.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
873   layer2.Add(actor2);
874
875   // Render and notify
876   application.SendNotification();
877   application.Render();
878
879   // Connect to layer2 and actor2
880   layer2.HoveredSignal().Connect(&application, functor);
881   actor2.HoveredSignal().Connect(&application, functor);
882
883   // Emit an event, should hit layer2
884   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
885   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
886   //DALI_TEST_CHECK( data.hoveredActor == layer2 ); // TODO: Uncomment this after removing renderable hack!
887   data.Reset();
888
889   // Make layer2 insensitive, should hit actor1
890   layer2.SetProperty(Actor::Property::SENSITIVE, false);
891   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
892   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
893   DALI_TEST_CHECK(data.hoveredActor == actor1);
894   data.Reset();
895
896   // Make layer2 sensitive again, should hit layer2
897   layer2.SetProperty(Actor::Property::SENSITIVE, true);
898   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
899   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
900   //DALI_TEST_CHECK( data.hoveredActor == layer2 ); // TODO: Uncomment this after removing renderable hack!
901   data.Reset();
902
903   // Make layer2 invisible, render and notify
904   layer2.SetProperty(Actor::Property::VISIBLE, false);
905   application.SendNotification();
906   application.Render();
907
908   // Should hit actor1
909   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
910   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
911   DALI_TEST_CHECK(data.hoveredActor == actor1);
912   data.Reset();
913
914   // Make rootActor invisible, render and notify
915   rootActor.SetProperty(Actor::Property::VISIBLE, false);
916
917   // Because visible became false, we receive interrupted
918   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
919   DALI_TEST_EQUALS(PointState::INTERRUPTED, data.hoverEvent.GetState(0), TEST_LOCATION);
920   data.Reset();
921
922   application.SendNotification();
923   application.Render();
924
925   // Should not hit anything
926   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
927   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
928   data.Reset();
929   END_TEST;
930 }
931
932 int UtcDaliHoverMultipleRenderTasks(void)
933 {
934   TestApplication    application;
935   Integration::Scene stage(application.GetScene());
936   Vector2            stageSize(stage.GetSize());
937
938   Actor actor = Actor::New();
939   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
940   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
941   stage.Add(actor);
942
943   // Create render task
944   Viewport   viewport(stageSize.width * 0.5f, stageSize.height * 0.5f, stageSize.width * 0.5f, stageSize.height * 0.5f);
945   RenderTask renderTask(application.GetScene().GetRenderTaskList().CreateTask());
946   renderTask.SetViewport(viewport);
947   renderTask.SetInputEnabled(true);
948
949   // Render and notify
950   application.SendNotification();
951   application.Render();
952
953   // Connect to actor's hovered signal
954   SignalData        data;
955   HoverEventFunctor functor(data);
956   actor.HoveredSignal().Connect(&application, functor);
957
958   // Emit a started signal
959   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
960   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
961   data.Reset();
962
963   // Ensure renderTask actor can be hit too.
964   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(viewport.x + 5.0f, viewport.y + 5.0f)));
965   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
966   data.Reset();
967
968   // Disable input on renderTask, should not be hittable
969   renderTask.SetInputEnabled(false);
970   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(viewport.x + 5.0f, viewport.y + 5.0f)));
971   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
972   data.Reset();
973   END_TEST;
974 }
975
976 int UtcDaliHoverMultipleRenderTasksWithChildLayer(void)
977 {
978   TestApplication    application;
979   Integration::Scene stage(application.GetScene());
980   Vector2            stageSize(stage.GetSize());
981
982   Actor actor = Actor::New();
983   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
984   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
985   stage.Add(actor);
986
987   Layer layer = Layer::New();
988   layer.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
989   layer.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
990   actor.Add(layer);
991
992   // Create render task
993   Viewport   viewport(stageSize.width * 0.5f, stageSize.height * 0.5f, stageSize.width * 0.5f, stageSize.height * 0.5f);
994   RenderTask renderTask(application.GetScene().GetRenderTaskList().CreateTask());
995   renderTask.SetViewport(viewport);
996   renderTask.SetInputEnabled(true);
997   renderTask.SetSourceActor(actor);
998
999   // Render and notify
1000   application.SendNotification();
1001   application.Render();
1002
1003   // Connect to layer's hovered signal
1004   SignalData        data;
1005   HoverEventFunctor functor(data);
1006   actor.HoveredSignal().Connect(&application, functor);
1007   layer.HoveredSignal().Connect(&application, functor);
1008
1009   // Emit a started signal
1010   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
1011   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1012   data.Reset();
1013
1014   // Ensure renderTask actor can be hit too.
1015   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(viewport.x + 5.0f, viewport.y + 5.0f)));
1016   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1017   data.Reset();
1018
1019   // Disable input on renderTask, should not be hittable
1020   renderTask.SetInputEnabled(false);
1021   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(viewport.x + 5.0f, viewport.y + 5.0f)));
1022   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
1023   data.Reset();
1024   END_TEST;
1025 }
1026
1027 int UtcDaliHoverOffscreenRenderTasks(void)
1028 {
1029   TestApplication    application;
1030   Integration::Scene stage(application.GetScene());
1031   Vector2            stageSize(stage.GetSize());
1032
1033   // FrameBufferImage for offscreen RenderTask
1034   FrameBuffer frameBuffer = FrameBuffer::New(stageSize.width, stageSize.height);
1035
1036   // Create a renderable actor to display the FrameBufferImage
1037   Actor renderableActor = CreateRenderableActor(frameBuffer.GetColorTexture());
1038   renderableActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
1039   renderableActor.SetProperty(Actor::Property::SIZE, Vector2(stageSize.x, stageSize.y));
1040   renderableActor.ScaleBy(Vector3(1.0f, -1.0f, 1.0f)); // FIXME
1041   stage.Add(renderableActor);
1042
1043   Actor actor = Actor::New();
1044   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
1045   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
1046   stage.Add(actor);
1047   application.GetGlAbstraction().SetCheckFramebufferStatusResult(GL_FRAMEBUFFER_COMPLETE); // Ensure framebuffer connects
1048
1049   stage.GetRenderTaskList().GetTask(0u).SetScreenToFrameBufferFunction(RenderTask::FULLSCREEN_FRAMEBUFFER_FUNCTION);
1050
1051   // Create a RenderTask
1052   RenderTask renderTask = stage.GetRenderTaskList().CreateTask();
1053   renderTask.SetSourceActor(actor);
1054   renderTask.SetFrameBuffer(frameBuffer);
1055   renderTask.SetInputEnabled(true);
1056
1057   // Create another RenderTask
1058   RenderTask renderTask2(stage.GetRenderTaskList().CreateTask());
1059   renderTask2.SetInputEnabled(true);
1060
1061   // Render and notify
1062   application.SendNotification();
1063   application.Render();
1064
1065   // Connect to actor's hovered signal
1066   SignalData        data;
1067   HoverEventFunctor functor(data);
1068   actor.HoveredSignal().Connect(&application, functor);
1069
1070   // Emit a started signal
1071   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
1072   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1073   data.Reset();
1074   END_TEST;
1075 }
1076
1077 int UtcDaliHoverMultipleRenderableActors(void)
1078 {
1079   TestApplication    application;
1080   Integration::Scene stage(application.GetScene());
1081   Vector2            stageSize(stage.GetSize());
1082
1083   Actor parent = CreateRenderableActor();
1084   parent.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
1085   parent.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
1086   stage.Add(parent);
1087
1088   Actor actor = CreateRenderableActor();
1089   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
1090   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
1091   parent.Add(actor);
1092
1093   // Render and notify
1094   application.SendNotification();
1095   application.Render();
1096
1097   // Connect to layer's hovered signal
1098   SignalData        data;
1099   HoverEventFunctor functor(data);
1100   parent.HoveredSignal().Connect(&application, functor);
1101   actor.HoveredSignal().Connect(&application, functor);
1102
1103   // Emit a started signal
1104   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
1105   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1106   DALI_TEST_CHECK(actor == data.hoveredActor);
1107   END_TEST;
1108 }
1109
1110 int UtcDaliHoverActorRemovedInSignal(void)
1111 {
1112   TestApplication application;
1113
1114   Actor actor = Actor::New();
1115   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
1116   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
1117   application.GetScene().Add(actor);
1118
1119   // Render and notify
1120   application.SendNotification();
1121   application.Render();
1122
1123   // Connect to actor's hovered signal
1124   SignalData         data;
1125   RemoveActorFunctor functor(data);
1126   actor.HoveredSignal().Connect(&application, functor);
1127
1128   // Register for leave events
1129   actor.SetProperty(Actor::Property::LEAVE_REQUIRED, true);
1130
1131   // Emit a started signal
1132   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
1133   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1134   data.Reset();
1135
1136   // Re-add, render and notify
1137   application.GetScene().Add(actor);
1138   application.SendNotification();
1139   application.Render();
1140
1141   // Emit another signal outside of actor's area, should not get anything as the scene has changed.
1142   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(210.0f, 210.0f)));
1143   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
1144   data.Reset();
1145
1146   // Emit a started signal
1147   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
1148   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1149   data.Reset();
1150
1151   // Render and notify
1152   application.SendNotification();
1153   application.Render();
1154
1155   // Emit another signal outside of actor's area, should not get anything as the scene has changed.
1156   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(210.0f, 210.0f)));
1157   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
1158   data.Reset();
1159
1160   // Re-add actor back to stage, render and notify
1161   application.GetScene().Add(actor);
1162   application.SendNotification();
1163   application.Render();
1164
1165   // Emit another started event
1166   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
1167   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1168   data.Reset();
1169
1170   // Completely delete the actor
1171   actor.Reset();
1172
1173   // Emit event, should not crash and should not receive an event.
1174   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(210.0f, 210.0f)));
1175   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
1176   END_TEST;
1177 }
1178
1179 int UtcDaliHoverActorSignalNotConsumed(void)
1180 {
1181   TestApplication application;
1182
1183   Actor actor = Actor::New();
1184   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
1185   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
1186   application.GetScene().Add(actor);
1187
1188   // Render and notify
1189   application.SendNotification();
1190   application.Render();
1191
1192   // Connect to actor's hovered signal
1193   SignalData        data;
1194   HoverEventFunctor functor(data, false);
1195   actor.HoveredSignal().Connect(&application, functor);
1196
1197   // Emit a started signal
1198   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
1199   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1200   END_TEST;
1201 }
1202
1203 int UtcDaliHoverActorUnStaged(void)
1204 {
1205   TestApplication application;
1206
1207   Actor actor = Actor::New();
1208   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
1209   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
1210   application.GetScene().Add(actor);
1211
1212   // Render and notify
1213   application.SendNotification();
1214   application.Render();
1215
1216   // Connect to actor's hovered signal
1217   SignalData        data;
1218   HoverEventFunctor functor(data);
1219   actor.HoveredSignal().Connect(&application, functor);
1220
1221   // Emit a started signal
1222   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
1223   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1224   data.Reset();
1225
1226   // Remove actor from stage
1227   application.GetScene().Remove(actor);
1228
1229   // Interrupted is received because the actor receiving the event removed.
1230   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1231   DALI_TEST_EQUALS(PointState::INTERRUPTED, data.hoverEvent.GetState(0), TEST_LOCATION);
1232   data.Reset();
1233
1234   // Render and notify
1235   application.SendNotification();
1236   application.Render();
1237
1238   // Emit a move at the same point, we should not be signalled.
1239   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(10.0f, 10.0f)));
1240   DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
1241   data.Reset();
1242   END_TEST;
1243 }
1244
1245 int UtcDaliHoverLeaveActorReadded(void)
1246 {
1247   TestApplication    application;
1248   Integration::Scene stage = application.GetScene();
1249
1250   Actor actor = Actor::New();
1251   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
1252   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
1253   stage.Add(actor);
1254
1255   // Set actor to receive hover-events
1256   actor.SetProperty(Actor::Property::LEAVE_REQUIRED, true);
1257
1258   // Render and notify
1259   application.SendNotification();
1260   application.Render();
1261
1262   // Connect to actor's hovered signal
1263   SignalData        data;
1264   HoverEventFunctor functor(data);
1265   actor.HoveredSignal().Connect(&application, functor);
1266
1267   // Emit a started and motion
1268   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
1269   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(11.0f, 10.0f)));
1270   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1271   data.Reset();
1272
1273   // Remove actor from stage and add again
1274   stage.Remove(actor);
1275   stage.Add(actor);
1276
1277   // Emit a motion within the actor's bounds
1278   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(12.0f, 10.0f)));
1279   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1280   data.Reset();
1281
1282   // Emit a motion outside the actor's bounds
1283   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(200.0f, 200.0f)));
1284   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1285   DALI_TEST_EQUALS(PointState::LEAVE, data.hoverEvent.GetState(0), TEST_LOCATION);
1286   data.Reset();
1287
1288   END_TEST;
1289 }
1290
1291 int UtcDaliHoverClippingActor(void)
1292 {
1293   TestApplication    application;
1294   Integration::Scene stage = application.GetScene();
1295
1296   Actor actor = Actor::New();
1297   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
1298   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
1299   stage.Add(actor);
1300
1301   Actor clippingActor = Actor::New();
1302   clippingActor.SetProperty(Actor::Property::SIZE, Vector2(50.0f, 50.0f));
1303   clippingActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
1304   clippingActor.SetProperty(Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_CHILDREN);
1305   stage.Add(clippingActor);
1306
1307   // Add a child to the clipped region.
1308   Actor clippingChild = Actor::New();
1309   clippingChild.SetProperty(Actor::Property::SIZE, Vector2(50.0f, 50.0f));
1310   clippingChild.SetProperty(Actor::Property::POSITION, Vector2(25.0f, 25.0f));
1311   clippingChild.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
1312   clippingActor.Add(clippingChild);
1313
1314   // Render and notify.
1315   application.SendNotification();
1316   application.Render();
1317
1318   // Connect to actor's hovered signal.
1319   SignalData        data;
1320   HoverEventFunctor functor(data);
1321   actor.HoveredSignal().Connect(&application, functor);
1322
1323   // Emit an event within clipped area - we should have a hit.
1324   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
1325   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1326   data.Reset();
1327
1328   // Emit an event outside the clipped area but within the actor area, we should have a hit.
1329   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(60.0f, 60.0f)));
1330   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1331   data.Reset();
1332
1333   clippingChild.HoveredSignal().Connect(&application, functor);
1334
1335   // Emit an event inside part of the child which is within the clipped area, we should have a hit.
1336   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(30.0f, 30.0f)));
1337   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1338   data.Reset();
1339
1340   END_TEST;
1341 }
1342
1343 int UtcDaliHoverEventCreate(void)
1344 {
1345   TestApplication application;
1346
1347   Dali::HoverEvent hoverEvent = DevelHoverEvent::New(100);
1348   DALI_TEST_CHECK(hoverEvent);
1349
1350   // Emit a started signal
1351   DALI_TEST_EQUALS(100, hoverEvent.GetTime(), TEST_LOCATION);
1352   DALI_TEST_EQUALS(0, hoverEvent.GetPointCount(), TEST_LOCATION);
1353
1354   END_TEST;
1355 }
1356
1357 int UtcDaliHoverEventIntegNewHoverEvent(void)
1358 {
1359   uint32_t         timestamp = 92858u;
1360   TouchPoint       tp(1, PointState::STARTED, 34.4f, 123.89f, 5.0f, 7.0f);
1361   Dali::HoverEvent hoverEvent = Integration::NewHoverEvent(timestamp, tp);
1362
1363   DALI_TEST_EQUALS(hoverEvent.GetPointCount(), 1u, TEST_LOCATION);
1364   DALI_TEST_EQUALS(hoverEvent.GetState(0), PointState::STARTED, TEST_LOCATION);
1365   DALI_TEST_EQUALS(hoverEvent.GetLocalPosition(0), Vector2(5.0f, 7.0f), TEST_LOCATION);
1366   DALI_TEST_EQUALS(hoverEvent.GetScreenPosition(0), Vector2(34.4f, 123.89f), TEST_LOCATION);
1367
1368   END_TEST;
1369 }
1370
1371 int UtcDaliHoverActorHide(void)
1372 {
1373   TestApplication    application;
1374   Integration::Scene stage = application.GetScene();
1375
1376   Actor actor = Actor::New();
1377   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
1378   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
1379   stage.Add(actor);
1380
1381   // Render and notify
1382   application.SendNotification();
1383   application.Render();
1384
1385   // Connect to actor's hovered signal
1386   SignalData        data;
1387   HoverEventFunctor functor(data);
1388   actor.HoveredSignal().Connect(&application, functor);
1389
1390   // Emit a started
1391   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
1392   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1393   data.Reset();
1394
1395   actor.SetProperty(Actor::Property::VISIBLE, false);
1396
1397   // flush the queue and render once
1398   application.SendNotification();
1399   application.Render();
1400
1401   // Interrupted is received because the actor receiving the event hides.
1402   DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
1403   DALI_TEST_EQUALS(PointState::INTERRUPTED, data.hoverEvent.GetState(0), TEST_LOCATION);
1404   data.Reset();
1405
1406   END_TEST;
1407 }
1408
1409 int UtcDaliHoverStartConsumerDifferentAtEnd(void)
1410 {
1411   // Start a hover in one actor, continue it in another actor
1412   // End hover in the second actor
1413   // First actor should still get a hover finished call
1414   TestApplication    application;
1415   Integration::Scene scene = application.GetScene();
1416
1417   Actor actor = Actor::New();
1418   actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
1419   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
1420   scene.Add(actor);
1421
1422   Actor actor2 = Actor::New();
1423   actor2.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
1424   actor2.SetProperty(Actor::Property::POSITION, Vector2(100.0f, 100.0f));
1425   actor2.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
1426   scene.Add(actor2);
1427
1428   // Render and notify
1429   application.SendNotification();
1430   application.Render();
1431
1432   // Connect to hover start actor's hovered signal
1433   SignalData        dataStartActor;
1434   HoverEventFunctor functorStartActor(dataStartActor);
1435   actor.HoveredSignal().Connect(&application, functorStartActor);
1436
1437   // Connect to second actor's hovered signal
1438   SignalData        dataSecondActor;
1439   HoverEventFunctor functorSecondActor(dataSecondActor);
1440   actor2.HoveredSignal().Connect(&application, functorSecondActor);
1441
1442   auto resetData = [&]() { dataStartActor.Reset(); dataSecondActor.Reset(); };
1443
1444   // Emit a started
1445   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
1446   DALI_TEST_EQUALS(true, dataStartActor.functorCalled, TEST_LOCATION);
1447   DALI_TEST_EQUALS(false, dataSecondActor.functorCalled, TEST_LOCATION);
1448   resetData();
1449
1450   // Emit a hover somewhere else
1451   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(110.0f, 110.0f)));
1452   DALI_TEST_EQUALS(false, dataStartActor.functorCalled, TEST_LOCATION);
1453   DALI_TEST_EQUALS(true, dataSecondActor.functorCalled, TEST_LOCATION);
1454   resetData();
1455
1456   // Emit a hover end in the same point, the hover start actor should still be informed
1457   application.ProcessEvent(GenerateSingleHover(PointState::FINISHED, Vector2(110.0f, 110.0f)));
1458   DALI_TEST_EQUALS(true, dataStartActor.functorCalled, TEST_LOCATION);
1459   DALI_TEST_EQUALS(true, dataSecondActor.functorCalled, TEST_LOCATION);
1460   resetData();
1461
1462   // Do it again with the geometry on
1463   // Emit a started
1464   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
1465   DALI_TEST_EQUALS(true, dataStartActor.functorCalled, TEST_LOCATION);
1466   DALI_TEST_EQUALS(false, dataSecondActor.functorCalled, TEST_LOCATION);
1467   resetData();
1468
1469   // Emit a hover somewhere else
1470   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(110.0f, 110.0f)));
1471   DALI_TEST_EQUALS(false, dataStartActor.functorCalled, TEST_LOCATION);
1472   DALI_TEST_EQUALS(true, dataSecondActor.functorCalled, TEST_LOCATION);
1473   resetData();
1474
1475   scene.SetGeometryHittestEnabled(true);
1476
1477   // Emit a hover end in the same point, the hover start actor should still be informed
1478   application.ProcessEvent(GenerateSingleHover(PointState::FINISHED, Vector2(110.0f, 110.0f)));
1479   DALI_TEST_EQUALS(true, dataStartActor.functorCalled, TEST_LOCATION);
1480   DALI_TEST_EQUALS(true, dataSecondActor.functorCalled, TEST_LOCATION);
1481   resetData();
1482
1483   END_TEST;
1484 }
1485
1486 int UtcDaliHoverEnsureDifferentConsumerReceivesInterrupted(void)
1487 {
1488   // Interrupted event with a different consumer to previous event
1489
1490   TestApplication    application;
1491   Integration::Scene scene = application.GetScene();
1492
1493   Actor parent = Actor::New();
1494   parent.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
1495   parent.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
1496   scene.Add(parent);
1497
1498   Actor child = Actor::New();
1499   child.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
1500   child.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
1501   parent.Add(child);
1502
1503   // Render and notify
1504   application.SendNotification();
1505   application.Render();
1506
1507   // Connect to parent's hover signal
1508   SignalData        dataParent;
1509   HoverEventFunctor functorParent(dataParent);
1510   parent.HoveredSignal().Connect(&application, functorParent);
1511
1512   // Connect to child's hovered signal but do not consume
1513   SignalData        dataChildNoConsume;
1514   HoverEventFunctor functorChildNoConsume(dataChildNoConsume, false);
1515   child.HoveredSignal().Connect(&application, functorChildNoConsume);
1516
1517   // Create a functor to consume the event of the child, but don't connect just yet
1518   SignalData        dataChildConsume;
1519   HoverEventFunctor functorChildConsume(dataChildConsume);
1520
1521   auto resetData = [&]() { dataParent.Reset(); dataChildNoConsume.Reset(); dataChildConsume.Reset(); };
1522
1523   // Emit a started
1524   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
1525   DALI_TEST_EQUALS(true, dataParent.functorCalled, TEST_LOCATION);
1526   DALI_TEST_EQUALS(true, dataChildNoConsume.functorCalled, TEST_LOCATION);
1527   DALI_TEST_EQUALS(false, dataChildConsume.functorCalled, TEST_LOCATION);
1528   resetData();
1529
1530   // Connect to child's hover event and consume so it's a different consumer on interrupted
1531   child.HoveredSignal().Connect(&application, functorChildConsume);
1532
1533   // Emit interrupted, all three methods should be called
1534   application.ProcessEvent(GenerateSingleHover(PointState::INTERRUPTED, Vector2(10.0f, 10.0f)));
1535   DALI_TEST_EQUALS(true, dataParent.functorCalled, TEST_LOCATION);
1536   DALI_TEST_EQUALS(true, dataChildNoConsume.functorCalled, TEST_LOCATION);
1537   DALI_TEST_EQUALS(true, dataChildConsume.functorCalled, TEST_LOCATION);
1538   resetData();
1539
1540   END_TEST;
1541 }
1542
1543 int UtcDaliHoverEnsureDifferentConsumerReceivesLeave(void)
1544 {
1545   // Motion event outside previous hit actor
1546   // This event is consumed by a different actor
1547   // The previous consumer's listener should still get called
1548
1549   TestApplication    application;
1550   Integration::Scene scene = application.GetScene();
1551
1552   Actor parent = Actor::New();
1553   parent.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
1554   parent.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
1555   scene.Add(parent);
1556
1557   Actor child = Actor::New();
1558   child.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
1559   child.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
1560   parent.Add(child);
1561
1562   // Render and notify
1563   application.SendNotification();
1564   application.Render();
1565
1566   // Connect to parent's hover signal
1567   SignalData        dataParent;
1568   HoverEventFunctor functorParent(dataParent);
1569   parent.HoveredSignal().Connect(&application, functorParent);
1570
1571   // Connect to child's hovered signal but do not consume
1572   SignalData        dataChildNoConsume;
1573   HoverEventFunctor functorChildNoConsume(dataChildNoConsume, false);
1574   child.HoveredSignal().Connect(&application, functorChildNoConsume);
1575
1576   // Create a functor to consume the event of the child, but don't connect just yet
1577   SignalData        dataChildConsume;
1578   HoverEventFunctor functorChildConsume(dataChildConsume);
1579
1580   auto resetData = [&]() { dataParent.Reset(); dataChildNoConsume.Reset(); dataChildConsume.Reset(); };
1581
1582   // Emit a started
1583   application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
1584   DALI_TEST_EQUALS(true, dataParent.functorCalled, TEST_LOCATION);
1585   DALI_TEST_EQUALS(true, dataChildNoConsume.functorCalled, TEST_LOCATION);
1586   DALI_TEST_EQUALS(false, dataChildConsume.functorCalled, TEST_LOCATION);
1587   resetData();
1588
1589   // Connect to child's hover event and consume so it's a different consumer on interrupted
1590   child.HoveredSignal().Connect(&application, functorChildConsume);
1591
1592   // Also make last consumer insensitive
1593   parent.SetProperty(Actor::Property::SENSITIVE, false);
1594
1595   // Emit interrupted, all three methods should be called
1596   application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(110.0f, 110.0f)));
1597   DALI_TEST_EQUALS(true, dataParent.functorCalled, TEST_LOCATION);
1598   DALI_TEST_EQUALS(true, dataChildNoConsume.functorCalled, TEST_LOCATION);
1599   DALI_TEST_EQUALS(true, dataChildConsume.functorCalled, TEST_LOCATION);
1600   resetData();
1601
1602   END_TEST;
1603 }