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