Add UserInteractionEnabled property on actor for controlling user interaction. 15/271115/11
authorEverLEEst(SangHyeon Lee) <sh10233.lee@samsung.com>
Tue, 15 Feb 2022 11:33:43 +0000 (20:33 +0900)
committerSangHyeon Lee <sh10233lee@samsung.com>
Mon, 7 Mar 2022 05:37:17 +0000 (21:37 -0800)
actor can be disabled touch event by setting SetSensitive(false),
and also can be disabled keyboard event by setting
SetKeyboardFocusable(false),
and touch focus on SetTouchFocusable(false).

but we do not provide universal user interaction controls to disable
actor events and behavior, so this property is neceesary.

regardless of value on Sensitive or Focusable,
UserInteractionEnable has high priority over the negative action.

Change-Id: Ia339cc4c94e2fa36f80cb8672aa16d7a664c858c

automated-tests/src/dali/utc-Dali-Actor.cpp
automated-tests/src/dali/utc-Dali-HoverProcessing.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

index 05b5732..a897ae1 100644 (file)
@@ -2598,6 +2598,29 @@ int UtcDaliActorIsTouchFocusable(void)
   END_TEST;
 }
 
+int UtcDaliActorSetUserInteractionEnabled(void)
+{
+  TestApplication application;
+  Actor           actor = Actor::New();
+
+  bool enabled = !actor.GetProperty<bool>(DevelActor::Property::USER_INTERACTION_ENABLED);
+
+  actor.SetProperty(DevelActor::Property::USER_INTERACTION_ENABLED, enabled);
+
+  DALI_TEST_CHECK(enabled == actor.GetProperty<bool>(DevelActor::Property::USER_INTERACTION_ENABLED));
+  END_TEST;
+}
+
+int UtcDaliActorIsUserInteractionEnabled(void)
+{
+  TestApplication application;
+  Actor           actor = Actor::New();
+  actor.SetProperty(DevelActor::Property::USER_INTERACTION_ENABLED, true);
+
+  DALI_TEST_CHECK(true == actor.GetProperty<bool>(DevelActor::Property::USER_INTERACTION_ENABLED));
+  END_TEST;
+}
+
 int UtcDaliActorRemoveConstraints(void)
 {
   tet_infoline(" UtcDaliActorRemoveConstraints");
index 70393de..6c07092 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include <dali-test-suite-utils.h>
+#include <dali/devel-api/actors/actor-devel.h>
 #include <dali/devel-api/events/hover-event-devel.h>
 #include <dali/integration-api/events/hover-event-integ.h>
 #include <dali/integration-api/render-task-list-integ.h>
@@ -756,6 +757,41 @@ int UtcDaliHoverActorBecomesInsensitiveParentConsumer(void)
   END_TEST;
 }
 
+int UtcDaliHoverActorBecomesUserInteractionDisabled(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 hovered signal
+  SignalData        data;
+  HoverEventFunctor functor(data);
+  actor.HoveredSignal().Connect(&application, functor);
+
+  // Emit a started signal
+  application.ProcessEvent(GenerateSingleHover(PointState::STARTED, Vector2(10.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(PointState::STARTED, data.hoverEvent.GetState(0), TEST_LOCATION);
+  data.Reset();
+
+  // Change actor to disable user interaction.
+  actor.SetProperty(DevelActor::Property::USER_INTERACTION_ENABLED, false);
+
+  // Emit a motion signal, signalled with an interrupted
+  application.ProcessEvent(GenerateSingleHover(PointState::MOTION, Vector2(200.0f, 200.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(PointState::INTERRUPTED, data.hoverEvent.GetState(0), TEST_LOCATION);
+  data.Reset();
+  END_TEST;
+}
+
 int UtcDaliHoverMultipleLayers(void)
 {
   TestApplication application;
index 26e4aa5..d39266a 100644 (file)
@@ -944,6 +944,41 @@ int UtcDaliTouchEventActorBecomesInsensitiveParentConsumer(void)
   END_TEST;
 }
 
+int UtcDaliTouchEventActorBecomesUserInteractionDisabled(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
+  application.ProcessEvent(GenerateSingleTouch(PointState::DOWN, Vector2(10.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(PointState::DOWN, data.receivedTouch.points[0].state, TEST_LOCATION);
+  data.Reset();
+
+  // Change actor to disable user interaction.
+  actor.SetProperty(DevelActor::Property::USER_INTERACTION_ENABLED, false);
+
+  // Emit a motion signal, signalled with an interrupted
+  application.ProcessEvent(GenerateSingleTouch(PointState::MOTION, Vector2(200.0f, 200.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(PointState::INTERRUPTED, data.receivedTouch.points[0].state, TEST_LOCATION);
+  data.Reset();
+  END_TEST;
+}
+
 int UtcDaliTouchEventMultipleLayers(void)
 {
   TestApplication application;
index aca2b6e..e1a0896 100644 (file)
@@ -177,7 +177,14 @@ enum Type
    * @details Name "keyboardFocusableChildren", type Property::BOOLEAN.
    * @note Default value is true.
    */
-  KEYBOARD_FOCUSABLE_CHILDREN
+  KEYBOARD_FOCUSABLE_CHILDREN,
+
+  /**
+  * @brief The flag whether the actor should be enabled all user interaction including touch, focus and activation. this value have higher priority over the sensitve and focusable in negative action.
+  * @details Name "userInteractionEnabled", type Property::BOOLEAN.
+  * @note Default value is true.
+  */
+  USER_INTERACTION_ENABLED,
 };
 
 } // namespace Property
index 174f5e3..2df7181 100644 (file)
@@ -147,6 +147,7 @@ DALI_PROPERTY("touchAreaOffset", RECTANGLE, true, false, false, Dali::DevelActor
 DALI_PROPERTY("blendEquation", INTEGER, true, false, false, Dali::DevelActor::Property::BLEND_EQUATION)
 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_TABLE_END(DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperties)
 
 // Signals
@@ -1074,6 +1075,7 @@ Actor::Actor(DerivedType derivedType, const SceneGraph::Node& node)
   mCaptureAllTouchAfterStart(false),
   mIsBlendEquationSet(false),
   mNeedGesturePropagation(false),
+  mUserInteractionEnabled(true),
   mLayoutDirection(LayoutDirection::LEFT_TO_RIGHT),
   mDrawMode(DrawMode::NORMAL),
   mColorMode(Node::DEFAULT_COLOR_MODE),
index 8ab4be7..b1050a7 100644 (file)
@@ -644,6 +644,41 @@ public:
   }
 
   /**
+   * Sets whether an actor should be enabled all user interaction including touch, focus and activation.
+   * This value have higher priority over the sensitve and focusable in negative action,
+   * which means IsSensitive() or IsFocusable() and enable is false, actor will not emits touch or focus event.
+   * An actor is enabled by default.
+   *
+   * If the application wishes to temporarily disable user interaction:
+   * @code
+   * actor.SetUserInteractionEnabled(false);
+   * @endcode
+   *
+   * Then, to re-enable user interaction, the application should call:
+   * @code
+   * actor.SetUserInteractionEnabled(true);
+   * @endcode
+   *
+   * @see IsSensitive(), IsHittable(), IsKeyboardFocusable() and IsTouchFocusable().
+   * @note If an actor's disabled, child still can be enabled.
+   * @param[in]  enabled  true to enable user interaction, false otherwise.
+   */
+  void SetUserInteractionEnabled(bool enabled)
+  {
+    mUserInteractionEnabled = enabled;
+  }
+
+  /**
+   * Query whether an actor is enabled user interaction.
+   * @see SetSensitive(bool)
+   * @return true, if user interaction is enabled, false otherwise.
+   */
+  bool IsUserInteractionEnabled() const
+  {
+    return mUserInteractionEnabled;
+  }
+
+  /**
    * @copydoc Dali::Actor::SetDrawMode
    */
   void SetDrawMode(DrawMode::Type drawMode);
@@ -1247,7 +1282,7 @@ public:
    */
   bool IsHittable() const
   {
-    return IsSensitive() && IsVisible() && (GetCurrentWorldColor().a > FULLY_TRANSPARENT) && IsNodeConnected();
+    return (IsUserInteractionEnabled()) && IsSensitive() && IsVisible() && (GetCurrentWorldColor().a > FULLY_TRANSPARENT) && IsNodeConnected();
   }
 
   /**
@@ -1859,6 +1894,7 @@ protected:
   bool                     mCaptureAllTouchAfterStart : 1; ///< Whether the actor should capture all touch after touch starts even if the motion moves outside of the actor area.
   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.
   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 2012ed1..4a7dacc 100644 (file)
@@ -619,6 +619,16 @@ void Actor::PropertyHandler::SetDefaultProperty(Internal::Actor& actor, Property
       break;
     }
 
+    case Dali::DevelActor::Property::USER_INTERACTION_ENABLED:
+    {
+      bool value = false;
+      if(property.Get(value))
+      {
+        actor.SetUserInteractionEnabled(value);
+      }
+      break;
+    }
+
     default:
     {
       // this can happen in the case of a non-animatable default property so just do nothing
@@ -1656,6 +1666,12 @@ bool Actor::PropertyHandler::GetCachedPropertyValue(const Internal::Actor& actor
       break;
     }
 
+    case Dali::DevelActor::Property::USER_INTERACTION_ENABLED:
+    {
+      value = actor.IsUserInteractionEnabled();
+      break;
+    }
+
     default:
     {
       // Must be a scene-graph only property