Add ALLOW_ONLY_OWN_TOUCH property. 32/276632/12
authorjoogab.yun <joogab.yun@samsung.com>
Wed, 22 Jun 2022 07:52:58 +0000 (16:52 +0900)
committerjoogab.yun <joogab.yun@samsung.com>
Fri, 8 Jul 2022 10:19:44 +0000 (19:19 +0900)
It only receive for touch events that started from itself.
So if it's not a touch started  by myself, actor doesn't receive a touch event.

Change-Id: I58151d7072a4f1dbae1a015e6b3fc0b298745773

automated-tests/src/dali/utc-Dali-Actor.cpp
automated-tests/src/dali/utc-Dali-TouchProcessing.cpp
dali/devel-api/actors/actor-devel.h
dali/internal/event/actors/actor-impl.cpp
dali/internal/event/actors/actor-impl.h
dali/internal/event/actors/actor-property-handler.cpp
dali/internal/event/events/hit-test-algorithm-impl.cpp
dali/internal/event/events/hit-test-algorithm-impl.h
dali/internal/event/events/touch-event-processor.cpp
dali/internal/event/events/touch-event-processor.h

index 5ea0d2235a0052791508bebb9c469d87687f92a5..32ff0fbcbebd87520c2a7991767fc883b655b8c8 100644 (file)
@@ -10460,3 +10460,43 @@ int UtcDaliActorDoesWantedHitTest(void)
   }
   END_TEST;
 }
+
+int UtcDaliActorAllowOnlyOwnTouchPropertyP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  DALI_TEST_EQUALS(actor.GetProperty(DevelActor::Property::ALLOW_ONLY_OWN_TOUCH).Get<bool>(), false, TEST_LOCATION);
+  actor.SetProperty(DevelActor::Property::ALLOW_ONLY_OWN_TOUCH, true);
+  DALI_TEST_EQUALS(actor.GetProperty(DevelActor::Property::ALLOW_ONLY_OWN_TOUCH).Get<bool>(), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(actor.GetPropertyType(DevelActor::Property::ALLOW_ONLY_OWN_TOUCH), Property::BOOLEAN, TEST_LOCATION);
+  DALI_TEST_EQUALS(actor.IsPropertyWritable(DevelActor::Property::ALLOW_ONLY_OWN_TOUCH), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(actor.IsPropertyAnimatable(DevelActor::Property::ALLOW_ONLY_OWN_TOUCH), false, TEST_LOCATION);
+  DALI_TEST_EQUALS(actor.IsPropertyAConstraintInput(DevelActor::Property::ALLOW_ONLY_OWN_TOUCH), false, TEST_LOCATION);
+  DALI_TEST_EQUALS(actor.GetPropertyName(DevelActor::Property::ALLOW_ONLY_OWN_TOUCH), "allowOnlyOwnTouch", TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliActorAllowOnlyOwnTouchPropertyN(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Make sure setting invalid types does not cause a crash
+  try
+  {
+    actor.SetProperty(DevelActor::Property::ALLOW_ONLY_OWN_TOUCH, 1.0f);
+    actor.SetProperty(DevelActor::Property::ALLOW_ONLY_OWN_TOUCH, Vector2::ONE);
+    actor.SetProperty(DevelActor::Property::ALLOW_ONLY_OWN_TOUCH, Vector3::ONE);
+    actor.SetProperty(DevelActor::Property::ALLOW_ONLY_OWN_TOUCH, Vector4::ONE);
+    actor.SetProperty(DevelActor::Property::ALLOW_ONLY_OWN_TOUCH, Property::Map());
+    actor.SetProperty(DevelActor::Property::ALLOW_ONLY_OWN_TOUCH, Property::Array());
+    tet_result(TET_PASS);
+  }
+  catch(...)
+  {
+    tet_result(TET_FAIL);
+  }
+  END_TEST;
+}
\ No newline at end of file
index d39266a98d07d376e95f4b0f95cd0cd8ba82ab49..33653e10d84c41b450212097f4bfda173377c09a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -2292,3 +2292,78 @@ int UtcDaliTouchAreaOffset(void)
 
   END_TEST;
 }
+
+int UtcDaliTouchEventAllowOnlyOwnTouchPropertySet(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetProperty(Actor::Property::SIZE, Vector2(100.0f, 100.0f));
+  actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
+  application.GetScene().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 outside of actor, we should not receive the event
+  application.ProcessEvent(GenerateSingleTouch(PointState::STARTED, Vector2(110.0f, 110.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // Now motion inside of actor, we should receive the event
+  application.ProcessEvent(GenerateSingleTouch(PointState::MOTION, Vector2(80.0f, 80.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // Up event, should not receive the event
+  application.ProcessEvent(GenerateSingleTouch(PointState::FINISHED, Vector2(110.0f, 110.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // Now set the only allow own touch property
+  actor.SetProperty(DevelActor::Property::ALLOW_ONLY_OWN_TOUCH, true);
+
+  // Emit a down signal outside of actor, we should not receive the event
+  application.ProcessEvent(GenerateSingleTouch(PointState::STARTED, Vector2(110.0f, 110.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // Now motion inside of actor, we should NOT receive the event
+  application.ProcessEvent(GenerateSingleTouch(PointState::MOTION, Vector2(80.0f, 80.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // Up event, should not receive the event
+  application.ProcessEvent(GenerateSingleTouch(PointState::FINISHED, Vector2(110.0f, 110.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // Emit a down signal inside of actor, we should receive the event
+  application.ProcessEvent(GenerateSingleTouch(PointState::STARTED, Vector2(10.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // Now motion inside of actor, we should receive the event
+  application.ProcessEvent(GenerateSingleTouch(PointState::MOTION, Vector2(80.0f, 80.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // Now motion outsize of actor, we should receive the event
+  application.ProcessEvent(GenerateSingleTouch(PointState::MOTION, Vector2(110.0f, 110.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // Up event, should receive an interrupted
+  application.ProcessEvent(GenerateSingleTouch(PointState::FINISHED, Vector2(110.0f, 110.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(data.receivedTouch.GetPoint(0).state, PointState::INTERRUPTED, TEST_LOCATION);
+  data.Reset();
+
+  END_TEST;
+}
\ No newline at end of file
index 9d4f0ae42960c0d03e0894605604ca0049d45b16..25b6cef0e80e5ff8e336daae7d8ccff7fbe4d232 100644 (file)
@@ -185,6 +185,13 @@ enum Type
   * @note Default value is true.
   */
   USER_INTERACTION_ENABLED,
+
+  /**
+  * @brief It only receive for touch events that started from itself.
+  * @details Name "allowOnlyOwnTouch", type Property::BOOLEAN
+  * @note Default is false.
+  */
+  ALLOW_ONLY_OWN_TOUCH,
 };
 
 } // namespace Property
index 6dc060a2393429209ff3dc686c611412545c2173..f9de7945d2d88e86918be5efa42b9b9d35a29c9a 100644 (file)
@@ -149,6 +149,7 @@ DALI_PROPERTY("blendEquation", INTEGER, true, false, false, Dali::DevelActor::Pr
 DALI_PROPERTY("touchFocusable", BOOLEAN, true, false, false, Dali::DevelActor::Property::TOUCH_FOCUSABLE)
 DALI_PROPERTY("keyboardFocusableChildren", BOOLEAN, true, false, false, Dali::DevelActor::Property::KEYBOARD_FOCUSABLE_CHILDREN)
 DALI_PROPERTY("userInteractionEnabled", BOOLEAN, true, false, false, Dali::DevelActor::Property::USER_INTERACTION_ENABLED)
+DALI_PROPERTY("allowOnlyOwnTouch", BOOLEAN, true, false, false, Dali::DevelActor::Property::ALLOW_ONLY_OWN_TOUCH)
 DALI_PROPERTY_TABLE_END(DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperties)
 
 // Signals
@@ -1094,6 +1095,7 @@ Actor::Actor(DerivedType derivedType, const SceneGraph::Node& node)
   mIsBlendEquationSet(false),
   mNeedGesturePropagation(false),
   mUserInteractionEnabled(true),
+  mAllowOnlyOwnTouch(false),
   mLayoutDirection(LayoutDirection::LEFT_TO_RIGHT),
   mDrawMode(DrawMode::NORMAL),
   mColorMode(Node::DEFAULT_COLOR_MODE),
index 3392d0dbd32c91ac4bb1a20a5b5e313180c052fc..51fb710c7fb8741b2d7558943f90efe5da8ccd2c 100644 (file)
@@ -1323,6 +1323,15 @@ public:
     return mTouchAreaOffset;
   }
 
+  /**
+   * Query whether the actor will only receive own touch.
+   * @return true, if it only receives touches that started from itself.
+   */
+  bool IsAllowedOnlyOwnTouch() const
+  {
+    return mAllowOnlyOwnTouch;
+  }
+
   // Gestures
 
   /**
@@ -1924,6 +1933,7 @@ protected:
   bool                     mIsBlendEquationSet : 1;        ///< Flag to identify whether the Blend equation is set
   bool                     mNeedGesturePropagation : 1;    ///< Whether the parent listens for gesture events or not
   bool                     mUserInteractionEnabled : 1;    ///< Whether the actor should be enabled user interaction.
+  bool                     mAllowOnlyOwnTouch : 1;         ///< whether the actor will only receive own touch. it only receives touches that started from itself.
   LayoutDirection::Type    mLayoutDirection : 2;           ///< Layout direction, Left to Right or Right to Left.
   DrawMode::Type           mDrawMode : 3;                  ///< Cached: How the actor and its children should be drawn
   ColorMode                mColorMode : 3;                 ///< Cached: Determines whether mWorldColor is inherited
index 4a7daccdaf16c31c2032c0495df2b9db608ae18d..8e3aeaa770235a2f0e612bb85c80f9306241f25b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -629,6 +629,16 @@ void Actor::PropertyHandler::SetDefaultProperty(Internal::Actor& actor, Property
       break;
     }
 
+    case Dali::DevelActor::Property::ALLOW_ONLY_OWN_TOUCH:
+    {
+      bool boolValue = false;
+      if(property.Get(boolValue))
+      {
+        actor.mAllowOnlyOwnTouch = boolValue;
+      }
+      break;
+    }
+
     default:
     {
       // this can happen in the case of a non-animatable default property so just do nothing
@@ -1672,6 +1682,12 @@ bool Actor::PropertyHandler::GetCachedPropertyValue(const Internal::Actor& actor
       break;
     }
 
+    case Dali::DevelActor::Property::ALLOW_ONLY_OWN_TOUCH:
+    {
+      value = actor.mAllowOnlyOwnTouch;
+      break;
+    }
+
     default:
     {
       // Must be a scene-graph only property
index 0ed24bec7432edefc6704f6aeddfdecf9bf3a8ac..e632717554d26918a67a1955d6a925d6b32f4b96 100644 (file)
@@ -122,8 +122,18 @@ struct ActorTouchableCheck : public HitTestInterface
 
   bool ActorRequiresHitResultCheck(Actor* actor, Integration::Point point, Vector2 hitPointLocal, uint32_t timeStamp) override
   {
+    if(point.GetState() != PointState::STARTED && actor->IsAllowedOnlyOwnTouch() && ownActor != actor)
+    {
+      return false;
+    }
     return actor->EmitHitTestResultSignal(point, hitPointLocal, timeStamp);
   }
+
+  void SetOwnActor(const Actor* actor)
+  {
+    ownActor = actor;
+  }
+  const Actor* ownActor;
 };
 
 /**
@@ -625,9 +635,10 @@ bool HitTest(const Vector2& sceneSize, RenderTaskList& renderTaskList, LayerList
   return wasHit;
 }
 
-bool HitTest(const Vector2& sceneSize, RenderTaskList& renderTaskList, LayerList& layerList, const Vector2& screenCoordinates, Results& results)
+bool HitTest(const Vector2& sceneSize, RenderTaskList& renderTaskList, LayerList& layerList, const Vector2& screenCoordinates, Results& results, const Actor* ownActor)
 {
   ActorTouchableCheck actorTouchableCheck;
+  actorTouchableCheck.SetOwnActor(ownActor);
   return HitTest(sceneSize, renderTaskList, layerList, screenCoordinates, results, actorTouchableCheck);
 }
 
index fa22507c864a28e2845977c27af31fc493477910..5a4c2fc69aae3290bc52dd417770704eb78330dc 100644 (file)
@@ -155,11 +155,12 @@ bool HitTest(const Vector2& sceneSize, RenderTaskList& renderTaskList, LayerList
  * @param[in] layerList The layer list of the scene.
  * @param[in] screenCoordinates The screen coordinates.
  * @param[out] results The results of the hit-test.
+ * @param[in] ownActor The actor from which the touch down was started.
  * @return true if something was hit
  *
  * @see HitTest(Stage&, const Vector2&, Results&, HitTestInterface&)
  */
-bool HitTest(const Vector2& sceneSize, RenderTaskList& renderTaskList, LayerList& layerList, const Vector2& screenCoordinates, Results& results);
+bool HitTest(const Vector2& sceneSize, RenderTaskList& renderTaskList, LayerList& layerList, const Vector2& screenCoordinates, Results& results, const Actor* ownActor = nullptr);
 
 } // namespace HitTestAlgorithm
 
index e8673eda3db734f22491ac0c279d1d0bbf05f368..2eca85a005fa2f4924fd291addadf03949f635c1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -180,6 +180,7 @@ Dali::Actor EmitTouchSignals(Actor* actor, RenderTask& renderTask, const TouchEv
 void ParsePrimaryTouchPoint(
   HitTestAlgorithm::Results& hitTestResults,
   ActorObserver&             capturingTouchActorObserver,
+  ActorObserver&             ownTouchActorObserver,
   const RenderTaskPtr&       lastRenderTask,
   const Integration::Point&  currentPoint,
   const Internal::Scene&     scene)
@@ -196,7 +197,8 @@ void ParsePrimaryTouchPoint(
   }
   else
   {
-    HitTestAlgorithm::HitTest(scene.GetSize(), scene.GetRenderTaskList(), scene.GetLayerList(), currentPoint.GetScreenPosition(), hitTestResults);
+    Actor* ownTouchActor = ownTouchActorObserver.GetActor();
+    HitTestAlgorithm::HitTest(scene.GetSize(), scene.GetRenderTaskList(), scene.GetLayerList(), currentPoint.GetScreenPosition(), hitTestResults, ownTouchActor);
 
     if(currentPoint.GetState() == PointState::STARTED && hitTestResults.actor)
     {
@@ -206,6 +208,10 @@ void ParsePrimaryTouchPoint(
       {
         capturingTouchActorObserver.SetActor(hitActor);
       }
+      if(hitActor->IsAllowedOnlyOwnTouch())
+      {
+        ownTouchActorObserver.SetActor(hitActor);
+      }
     }
   }
 }
@@ -217,6 +223,7 @@ TouchEventProcessor::TouchEventProcessor(Scene& scene)
   mLastPrimaryHitActor(MakeCallback(this, &TouchEventProcessor::OnObservedActorDisconnected)),
   mLastConsumedActor(),
   mCapturingTouchActor(),
+  mOwnTouchActor(),
   mTouchDownConsumedActor(),
   mLastRenderTask(),
   mLastPrimaryPointState(PointState::FINISHED)
@@ -229,6 +236,16 @@ TouchEventProcessor::~TouchEventProcessor()
   DALI_LOG_TRACE_METHOD(gLogFilter);
 }
 
+void TouchEventProcessor::Clear()
+{
+  mLastPrimaryHitActor.SetActor(nullptr);
+  mLastConsumedActor.SetActor(nullptr);
+  mCapturingTouchActor.SetActor(nullptr);
+  mOwnTouchActor.SetActor(nullptr);
+  mLastRenderTask.Reset();
+  mLastPrimaryPointState = PointState::FINISHED;
+}
+
 bool TouchEventProcessor::ProcessTouchEvent(const Integration::TouchEvent& event)
 {
   DALI_LOG_TRACE_METHOD(gLogFilter);
@@ -277,12 +294,8 @@ bool TouchEventProcessor::ProcessTouchEvent(const Integration::TouchEvent& event
       AllocAndEmitTouchSignals(event.time, touchDownConsumedActorHandle, currentPoint);
     }
 
-    mLastPrimaryHitActor.SetActor(nullptr);
-    mLastConsumedActor.SetActor(nullptr);
-    mCapturingTouchActor.SetActor(nullptr);
+    Clear();
     mTouchDownConsumedActor.SetActor(nullptr);
-    mLastRenderTask.Reset();
-    mLastPrimaryPointState = PointState::FINISHED;
 
     currentPoint.SetHitActor(Dali::Actor());
 
@@ -308,12 +321,12 @@ bool TouchEventProcessor::ProcessTouchEvent(const Integration::TouchEvent& event
   for(auto&& currentPoint : event.points)
   {
     HitTestAlgorithm::Results hitTestResults;
-    hitTestResults.point = currentPoint;
+    hitTestResults.point     = currentPoint;
     hitTestResults.eventTime = event.time;
     if(!firstPointParsed)
     {
       firstPointParsed = true;
-      ParsePrimaryTouchPoint(hitTestResults, mCapturingTouchActor, mLastRenderTask, currentPoint, mScene);
+      ParsePrimaryTouchPoint(hitTestResults, mCapturingTouchActor, mOwnTouchActor, mLastRenderTask, currentPoint, mScene);
 
       // Only set the currentRenderTask for the primary hit actor.
       currentRenderTask = hitTestResults.renderTask;
@@ -444,11 +457,7 @@ bool TouchEventProcessor::ProcessTouchEvent(const Integration::TouchEvent& event
   //    time so set our last primary actor to NULL.  Do the same to the last consumed actor as well.
   if(primaryPointState == PointState::UP)
   {
-    mLastPrimaryHitActor.SetActor(nullptr);
-    mLastConsumedActor.SetActor(nullptr);
-    mCapturingTouchActor.SetActor(nullptr);
-    mLastRenderTask.Reset();
-    mLastPrimaryPointState = PointState::FINISHED;
+    Clear();
   }
   else
   {
@@ -472,11 +481,7 @@ bool TouchEventProcessor::ProcessTouchEvent(const Integration::TouchEvent& event
     }
     else
     {
-      mLastPrimaryHitActor.SetActor(nullptr);
-      mLastConsumedActor.SetActor(nullptr);
-      mCapturingTouchActor.SetActor(nullptr);
-      mLastRenderTask.Reset();
-      mLastPrimaryPointState = PointState::FINISHED;
+      Clear();
     }
   }
 
index 70a0fb98e8055ddd01e5c6d33af0509b26b2fe16..75849aecf850e26e08ca30de2fdc8bfd87967a65 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_TOUCH_EVENT_PROCESSOR_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -86,9 +86,15 @@ private:
    */
   void OnObservedActorDisconnected(Actor* actor);
 
+  /**
+   * Clears the value.
+   */
+  void Clear();
+
   ActorObserver    mLastPrimaryHitActor;    ///< Stores the last primary point hit actor
   ActorObserver    mLastConsumedActor;      ///< Stores the last consumed actor
   ActorObserver    mCapturingTouchActor;    ///< Stored the actor that captures touch
+  ActorObserver    mOwnTouchActor;          ///< Stored the actor that own touch
   ActorObserver    mTouchDownConsumedActor; ///< Stores the touch-down consumed actor
   RenderTaskPtr    mLastRenderTask;         ///< The RenderTask used for the last hit actor
   PointState::Type mLastPrimaryPointState;  ///< Stores the last primary point state