Merge remote-tracking branch 'origin/tizen' into new_text
[platform/core/uifw/dali-core.git] / automated-tests / src / dali / utc-Dali-TouchProcessing.cpp
index b0c3709..cb66ac4 100644 (file)
@@ -57,7 +57,7 @@ struct SignalData
     touchEvent.time = 0u;
     touchEvent.points.clear();
 
-    touchedActor = NULL;
+    touchedActor.Reset();
   }
 
   bool functorCalled;
@@ -485,6 +485,8 @@ int UtcDaliTouchInterruptedParentConsumer(void)
 
   // Remove actor from Stage
   Stage::GetCurrent().Remove( actor );
+  data.Reset();
+  rootData.Reset();
 
   // Render and notify
   application.SendNotification();
@@ -712,9 +714,6 @@ int UtcDaliTouchActorBecomesInsensitiveParentConsumer(void)
   data.Reset();
   rootData.Reset();
 
-  // Remove actor from Stage
-  Stage::GetCurrent().Remove( actor );
-
   // Render and notify
   application.SendNotification();
   application.Render();
@@ -724,7 +723,8 @@ int UtcDaliTouchActorBecomesInsensitiveParentConsumer(void)
 
   // Emit a motion signal, signalled with an interrupted (should get interrupted even if within root actor)
   application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2 ( 200.0f, 200.0f )) );
-  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Interrupted, data.touchEvent.points[0].state, TEST_LOCATION );
   DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
   DALI_TEST_EQUALS( TouchPoint::Interrupted, rootData.touchEvent.points[0].state, TEST_LOCATION );
   END_TEST;
@@ -1088,7 +1088,7 @@ int UtcDaliTouchActorRemovedInSignal(void)
   data.Reset();
 
   // Completely delete the actor
-  actor = NULL;
+  actor.Reset();
 
   // Emit event, should not crash and should not receive an event.
   application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2( 210.0f, 210.0f ) ) );
@@ -1145,6 +1145,7 @@ int UtcDaliTouchActorUnStaged(void)
 
   // Remove actor from stage
   Stage::GetCurrent().Remove( actor );
+  data.Reset();
 
   // Render and notify
   application.SendNotification();
@@ -1289,3 +1290,460 @@ int UtcDaliTouchLeaveActorReadded(void)
 
   END_TEST;
 }
+
+int UtcDaliTouchStencil(void)
+{
+  TestApplication application;
+  Stage stage = Stage::GetCurrent();
+
+  ImageActor actor = ImageActor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  stage.Add(actor);
+
+  Actor stencil = Actor::New();
+  stencil.SetSize(50.0f, 50.0f);
+  stencil.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  stencil.SetDrawMode( DrawMode::STENCIL );
+  stage.Add(stencil);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's touched signal
+  SignalData data;
+  TouchEventFunctor functor( data );
+  actor.TouchedSignal().Connect( &application, functor );
+
+  // Emit an event within stencil area
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Emit an event outside the stencil area but within the actor area
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 60.0f, 60.0f ) ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  END_TEST;
+}
+
+int UtcDaliTouchStencilInActorHierarchy(void)
+{
+  TestApplication application;
+  Stage stage = Stage::GetCurrent();
+
+  ImageActor parent = ImageActor::New();
+  parent.SetSize(100.0f, 100.0f);
+  parent.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  stage.Add(parent);
+
+  ImageActor child = ImageActor::New();
+  child.SetSize(25.0f, 25.0f);
+  child.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  parent.Add(child);
+
+  Actor stencil = Actor::New();
+  stencil.SetSize(50.0f, 50.0f);
+  stencil.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  stencil.SetDrawMode( DrawMode::STENCIL );
+  stage.Add(stencil);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to touch signals
+  SignalData parentData;
+  parent.TouchedSignal().Connect( &application, TouchEventFunctor(parentData) );
+  SignalData childData;
+  child.TouchedSignal().Connect( &application, TouchEventFunctor(childData) );
+
+  // Emit an event within stencil area
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( false, parentData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, childData.functorCalled, TEST_LOCATION );
+  parentData.Reset();
+  childData.Reset();
+
+  // Emit an event outside child area and within stencil area
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2( 40.0f, 40.0f ) ) );
+  DALI_TEST_EQUALS( true, parentData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( false, childData.functorCalled, TEST_LOCATION );
+  parentData.Reset();
+  childData.Reset();
+
+  // Emit an event outside stencil are but within parent area
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2( 60.0f, 60.0f ) ) );
+  DALI_TEST_EQUALS( false, parentData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( false, childData.functorCalled, TEST_LOCATION );
+  parentData.Reset();
+  childData.Reset();
+
+  // Readd actor (so that stencil is the first child)
+  stage.Remove(parent);
+  application.SendNotification();
+  application.Render();
+  stage.Add(parent);
+  application.SendNotification();
+  application.Render();
+
+  // Redo hit in same area...
+
+  // Emit an event within stencil area
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( false, parentData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, childData.functorCalled, TEST_LOCATION );
+  parentData.Reset();
+  childData.Reset();
+
+  // Emit an event outside child area and within stencil area
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2( 40.0f, 40.0f ) ) );
+  DALI_TEST_EQUALS( true, parentData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( false, childData.functorCalled, TEST_LOCATION );
+  parentData.Reset();
+  childData.Reset();
+
+  // Emit an event outside stencil are but within parent area
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2( 60.0f, 60.0f ) ) );
+  DALI_TEST_EQUALS( false, parentData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( false, childData.functorCalled, TEST_LOCATION );
+  parentData.Reset();
+  childData.Reset();
+
+  END_TEST;
+}
+
+int UtcDaliTouchMultipleStencils(void)
+{
+  TestApplication application;
+  Stage stage = Stage::GetCurrent();
+
+  ImageActor actor = ImageActor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  stage.Add(actor);
+
+  Actor stencil = Actor::New();
+  stencil.SetSize(50.0f, 50.0f);
+  stencil.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  stencil.SetDrawMode( DrawMode::STENCIL );
+  stage.Add(stencil);
+
+  Actor stencil2 = Actor::New();
+  stencil2.SetSize(50.0f, 50.0f);
+  stencil2.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  stencil2.SetDrawMode( DrawMode::STENCIL );
+  stencil2.SetPosition(50.0f, 50.0f);
+  stage.Add(stencil2);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's touched signal
+  SignalData data;
+  TouchEventFunctor functor( data );
+  actor.TouchedSignal().Connect( &application, functor );
+
+  // Emit an event within stencil area
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Emit an event inside the second stencil area
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 60.0f, 60.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Emit an event outside both stencil areas but within the actor area
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 60.0f ) ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  END_TEST;
+}
+
+int UtcDaliTouchStencilNonRenderableActor(void)
+{
+  TestApplication application;
+  Stage stage = Stage::GetCurrent();
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  stage.Add(actor);
+
+  Actor stencil = Actor::New();
+  stencil.SetSize(50.0f, 50.0f);
+  stencil.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  stencil.SetDrawMode( DrawMode::STENCIL );
+  stage.Add(stencil);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's touched signal
+  SignalData data;
+  TouchEventFunctor functor( data );
+  actor.TouchedSignal().Connect( &application, functor );
+
+  // Emit an event within stencil area
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Emit an event outside the stencil area but within the actor area, we should have a hit!
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 60.0f, 60.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  END_TEST;
+}
+
+int UtcDaliTouchActorUnstaged(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's touched signal
+  SignalData data;
+  TouchEventFunctor functor( data );
+  actor.TouchedSignal().Connect( &application, functor );
+
+  // Emit a down signal
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Down, data.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_CHECK( actor == data.touchEvent.points[0].hitActor );
+  data.Reset();
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Unparent the actor
+  actor.Unparent();
+
+  // Should receive an interrupted event
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Interrupted, data.touchEvent.points[0].state, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliTouchParentUnstaged(void)
+{
+  TestApplication application;
+
+  Actor parent = Actor::New();
+  parent.SetSize(100.0f, 100.0f);
+  parent.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(parent);
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  parent.Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's touched signal
+  SignalData data;
+  TouchEventFunctor functor( data );
+  actor.TouchedSignal().Connect( &application, functor );
+
+  // Emit a down signal
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Down, data.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_CHECK( actor == data.touchEvent.points[0].hitActor );
+  data.Reset();
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Unparent the parent of the touchable actor
+  parent.Unparent();
+
+  // Should receive an interrupted event
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Interrupted, data.touchEvent.points[0].state, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliTouchActorUnstagedDifferentConsumer(void)
+{
+  TestApplication application;
+
+  Actor parent = Actor::New();
+  parent.SetSize(100.0f, 100.0f);
+  parent.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(parent);
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  parent.Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's touched signal
+  SignalData data;
+  TouchEventFunctor functor( data, false /* Do not consume */ );
+  actor.TouchedSignal().Connect( &application, functor );
+
+  // Connect to parent's touched signal
+  SignalData parentData;
+  TouchEventFunctor parentFunctor( parentData );
+  parent.TouchedSignal().Connect( &application, parentFunctor );
+
+  // Emit a down signal
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Down, data.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_CHECK( actor == data.touchEvent.points[0].hitActor );
+  DALI_TEST_CHECK( actor == data.touchedActor );
+  DALI_TEST_EQUALS( true, parentData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Down, parentData.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_CHECK( actor == parentData.touchEvent.points[0].hitActor );
+  DALI_TEST_CHECK( parent == parentData.touchedActor );
+  data.Reset();
+  parentData.Reset();
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Unparent the actor
+  actor.Unparent();
+
+  // Should receive an interrupted event for both actor & parent
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Interrupted, data.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, parentData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Interrupted, parentData.touchEvent.points[0].state, TEST_LOCATION );
+  data.Reset();
+  parentData.Reset();
+
+  // Readd actor to parent
+  parent.Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit a motion signal
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, parentData.functorCalled, TEST_LOCATION );
+  data.Reset();
+  parentData.Reset();
+
+  // Parent is now consumer, connect again to the touched signal of the actor so that it becomes the consumer
+  SignalData secondData;
+  TouchEventFunctor secondFunctor( secondData /* Consume */ );
+  actor.TouchedSignal().Connect( &application, secondFunctor );
+
+  // Unparent the actor
+  actor.Unparent();
+
+  // Should receive an interrupted event for both actor functors & the parent as well as it was last consumer
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Interrupted, data.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, parentData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Interrupted, parentData.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, secondData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Interrupted, secondData.touchEvent.points[0].state, TEST_LOCATION );
+  data.Reset();
+  parentData.Reset();
+  secondData.Reset();
+
+  END_TEST;
+}
+
+int UtcDaliTouchInterruptedDifferentConsumer(void)
+{
+  TestApplication application;
+  Actor rootActor( Stage::GetCurrent().GetRootLayer() );
+
+  Actor parent = Actor::New();
+  parent.SetSize(100.0f, 100.0f);
+  parent.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(parent);
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  parent.Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's touched signal
+  SignalData data;
+  TouchEventFunctor functor( data, false /* Do not consume */ );
+  actor.TouchedSignal().Connect( &application, functor );
+
+  // Connect to parent's touched signal
+  SignalData parentData;
+  TouchEventFunctor parentFunctor( parentData, false /* Do not consume */ );
+  parent.TouchedSignal().Connect( &application, parentFunctor );
+
+  // Connect to root's touched signal and consume
+  SignalData rootData;
+  TouchEventFunctor rootFunctor( rootData );
+  rootActor.TouchedSignal().Connect( &application, rootFunctor );
+
+  // Emit a down signal
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Down, data.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_CHECK( actor == data.touchEvent.points[0].hitActor );
+  DALI_TEST_CHECK( actor == data.touchedActor );
+  DALI_TEST_EQUALS( true, parentData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Down, parentData.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_CHECK( actor == parentData.touchEvent.points[0].hitActor );
+  DALI_TEST_CHECK( parent == parentData.touchedActor );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Down, rootData.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_CHECK( actor == rootData.touchEvent.points[0].hitActor );
+  DALI_TEST_CHECK( rootActor == rootData.touchedActor );
+  data.Reset();
+  parentData.Reset();
+  rootData.Reset();
+
+  // Root is now consumer, connect to the touched signal of the parent so that it becomes the consumer
+  SignalData secondData;
+  TouchEventFunctor secondFunctor( secondData /* Consume */ );
+  parent.TouchedSignal().Connect( &application, secondFunctor );
+
+  // Emit an interrupted signal, all three should STILL be called
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Interrupted, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Interrupted, data.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, parentData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Interrupted, parentData.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Interrupted, rootData.touchEvent.points[0].state, TEST_LOCATION );
+  data.Reset();
+  parentData.Reset();
+  rootData.Reset();
+
+  END_TEST;
+}