From: SangHyeon Lee Date: Thu, 17 Mar 2022 10:46:02 +0000 (+0000) Subject: Merge "Add UserInteractionEnabled property on actor for controlling user interaction... X-Git-Tag: dali_2.1.14~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d31b66464764ba00f944b5984947e4fdfadafc3c;hp=-c;p=platform%2Fcore%2Fuifw%2Fdali-core.git Merge "Add UserInteractionEnabled property on actor for controlling user interaction." into devel/master --- d31b66464764ba00f944b5984947e4fdfadafc3c diff --combined automated-tests/src/dali/utc-Dali-Actor.cpp index 0071883,a897ae1..9873aa7 --- a/automated-tests/src/dali/utc-Dali-Actor.cpp +++ b/automated-tests/src/dali/utc-Dali-Actor.cpp @@@ -53,7 -53,6 +53,7 @@@ namespac bool gTouchCallBackCalled = false; bool gTouchCallBackCalled2 = false; bool gTouchCallBackCalled3 = false; +bool gHitTestTouchCallBackCalled = false; bool gHoverCallBackCalled = false; @@@ -113,13 -112,6 +113,13 @@@ static bool TestTouchCallback3(Actor, c END_TEST; } +static bool TestHitTestTouchCallback(Actor, const TouchEvent&) +{ + gHitTestTouchCallBackCalled = true; + return false; + END_TEST; +} + static void ResetTouchCallbacks() { gTouchCallBackCalled = false; @@@ -2606,6 -2598,29 +2606,29 @@@ int UtcDaliActorIsTouchFocusable(void END_TEST; } + int UtcDaliActorSetUserInteractionEnabled(void) + { + TestApplication application; + Actor actor = Actor::New(); + + bool enabled = !actor.GetProperty(DevelActor::Property::USER_INTERACTION_ENABLED); + + actor.SetProperty(DevelActor::Property::USER_INTERACTION_ENABLED, enabled); + + DALI_TEST_CHECK(enabled == actor.GetProperty(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(DevelActor::Property::USER_INTERACTION_ENABLED)); + END_TEST; + } + int UtcDaliActorRemoveConstraints(void) { tet_infoline(" UtcDaliActorRemoveConstraints"); @@@ -4953,6 -4968,8 +4976,6 @@@ int UtcDaliActorPropertyClippingActorWi // Check stencil functions are not called. DALI_TEST_CHECK(!stencilTrace.FindMethod("StencilFunc")); - // TODO: Temporarily commented out the line below when caching is disabled. Will need to add it back. - // DALI_TEST_CHECK(!stencilTrace.FindMethod("StencilMask")); DALI_TEST_CHECK(!stencilTrace.FindMethod("StencilOp")); // Check that scissor clipping is overriden by the renderer properties. @@@ -10287,108 -10304,3 +10310,108 @@@ int UtcDaliActorRegisterProperty(void END_TEST; } + +int UtcDaliActorDoesWantedHitTest(void) +{ + struct HitTestData + { + public: + HitTestData(const Vector3& scale, const Vector2& touchPoint, bool result) + : mScale(scale), + mTouchPoint(touchPoint), + mResult(result) + { + } + + Vector3 mScale; + Vector2 mTouchPoint; + bool mResult; + }; + + TestApplication application; + tet_infoline(" UtcDaliActorDoesWantedHitTest"); + + // Fill a vector with different hit tests. + struct HitTestData* hitTestData[] = { + // scale touch point result + new HitTestData(Vector3(100.f, 100.f, 1.f), Vector2(289.f, 400.f), true), // touch point close to the right edge (inside) + new HitTestData(Vector3(100.f, 100.f, 1.f), Vector2(291.f, 400.f), false), // touch point close to the right edge (outside) + new HitTestData(Vector3(110.f, 100.f, 1.f), Vector2(291.f, 400.f), true), // same point as above with a wider scale. Should be inside. + new HitTestData(Vector3(100.f, 100.f, 1.f), Vector2(200.f, 451.f), false), // touch point close to the down edge (outside) + new HitTestData(Vector3(100.f, 110.f, 1.f), Vector2(200.f, 451.f), true), // same point as above with a wider scale. Should be inside. + NULL, + }; + + // get the root layer + Actor actor = Actor::New(); + actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); + actor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + + Actor lowerActor = Actor::New(); + lowerActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); + lowerActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + + // actor and lowerActor have no relationship. + application.GetScene().Add(lowerActor); + application.GetScene().Add(actor); + + ResetTouchCallbacks(); + gHitTestTouchCallBackCalled = false; + + unsigned int index = 0; + while(NULL != hitTestData[index]) + { + actor.SetProperty(Actor::Property::SIZE, Vector2(1.f, 1.f)); + actor.SetProperty(Actor::Property::SCALE, Vector3(hitTestData[index]->mScale.x, hitTestData[index]->mScale.y, hitTestData[index]->mScale.z)); + + lowerActor.SetProperty(Actor::Property::SIZE, Vector2(1.f, 1.f)); + lowerActor.SetProperty(Actor::Property::SCALE, Vector3(hitTestData[index]->mScale.x, hitTestData[index]->mScale.y, hitTestData[index]->mScale.z)); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(!gTouchCallBackCalled); + DALI_TEST_CHECK(!gTouchCallBackCalled2); + DALI_TEST_CHECK(!gHitTestTouchCallBackCalled); + + // connect to its touch signal + actor.TouchedSignal().Connect(TestTouchCallback); + lowerActor.TouchedSignal().Connect(TestTouchCallback2); + + // connect to its hit-test signal + Dali::DevelActor::HitTestResultSignal(actor).Connect(TestHitTestTouchCallback); + + Dali::Integration::Point point; + point.SetState(PointState::DOWN); + point.SetScreenPosition(Vector2(hitTestData[index]->mTouchPoint.x, hitTestData[index]->mTouchPoint.y)); + Dali::Integration::TouchEvent event; + event.AddPoint(point); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + application.ProcessEvent(event); + + // check hit-test events + DALI_TEST_CHECK(gHitTestTouchCallBackCalled == hitTestData[index]->mResult); + // Passed all hit-tests of actor. + DALI_TEST_CHECK(gTouchCallBackCalled == false); + // The lowerActor was hit-tested. + DALI_TEST_CHECK(gTouchCallBackCalled2 == hitTestData[index]->mResult); + + if(gTouchCallBackCalled2 != hitTestData[index]->mResult) + tet_printf("Test failed:\nScale %f %f %f\nTouchPoint %f, %f\nResult %d\n", + hitTestData[index]->mScale.x, + hitTestData[index]->mScale.y, + hitTestData[index]->mScale.z, + hitTestData[index]->mTouchPoint.x, + hitTestData[index]->mTouchPoint.y, + hitTestData[index]->mResult); + + ResetTouchCallbacks(); + gHitTestTouchCallBackCalled = false; + ++index; + } + END_TEST; +} diff --combined dali/devel-api/actors/actor-devel.h index 5cda265,e1a0896..9d4f0ae --- a/dali/devel-api/actors/actor-devel.h +++ b/dali/devel-api/actors/actor-devel.h @@@ -2,7 -2,7 +2,7 @@@ #define DALI_ACTOR_DEVEL_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. @@@ -177,7 -177,14 +177,14 @@@ enum Typ * @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 @@@ -348,39 -355,6 +355,39 @@@ DALI_CORE_API void SetNeedGesturePropag */ DALI_CORE_API void SwitchParent(Actor actor, Actor newParent); +/** + * @brief This signal is emitted when an actor is hit through hit-test. + * + * A callback of the following type may be connected: + * @code + * void MyCallbackName( Actor actor ); + * @endcode + * actor The actor to intercept + * + * @note This callback is called when the actor is hit. + * If true is returned, TouchEvent is called from the this actor. + * If false is returned, the hit test starts again from the next lower actor. + * + * @note example + * Actor topActor = Actor::New(); + * Actor bottomActor = Actor::New(); + * topActor.TouchedSignal().Connect(&application, topActorFunctor); + * bottomActor.TouchedSignal().Connect(&application, bottomActorFunctor); + * The two actors have no relationship. + * So when the topActor is touched, the event cannot be propagated to the bottomActor. + * + * If you connect HitTestResultSignal to topActor. + * Dali::DevelActor::HitTestResultSignal(topActor).Connect(&application, hitTestResultFunctor); + * + * If the hitTestResult Functor returns false, it passes the hit-test and starts the hit-test again from the next lower actor. + * So the bottomActor can be hit and receive touch events. + * If hitTestResult returns true, it means that it has been hit. So it receives a TouchEvent from itself. + * + * @return The signal to connect to + * @pre The Actor has been initialized + */ +DALI_CORE_API Actor::TouchEventSignalType& HitTestResultSignal(Actor actor); + } // namespace DevelActor } // namespace Dali diff --combined dali/internal/event/actors/actor-impl.cpp index 73756a6,2df7181..6dc060a --- a/dali/internal/event/actors/actor-impl.cpp +++ b/dali/internal/event/actors/actor-impl.cpp @@@ -1,5 -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. @@@ -34,7 -34,6 +34,7 @@@ #include #include +#include #include #include @@@ -148,6 -147,7 +148,7 @@@ DALI_PROPERTY("touchAreaOffset", RECTAN 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 @@@ -1015,22 -1015,6 +1016,22 @@@ void Actor::EmitLayoutDirectionChangedS EmitSignal(*this, mLayoutDirectionChangedSignal, type); } +bool Actor::EmitHitTestResultSignal(Integration::Point point, Vector2 hitPointLocal, uint32_t timeStamp) +{ + bool hit = true; + + if(IsHitTestResultRequired()) + { + Dali::Actor handle(this); + Integration::Point newPoint(point); + newPoint.SetHitActor(handle); + newPoint.SetLocalPosition(hitPointLocal); + Dali::TouchEvent touchEvent = Dali::Integration::NewTouchEvent(timeStamp, newPoint); + hit = mHitTestResultSignal.Emit(handle, touchEvent); + } + return hit; +} + DevelActor::ChildChangedSignalType& Actor::ChildAddedSignal() { return mParentImpl.ChildAddedSignal(); @@@ -1065,7 -1049,6 +1066,7 @@@ Actor::Actor(DerivedType derivedType, c mOnRelayoutSignal(), mVisibilityChangedSignal(), mLayoutDirectionChangedSignal(), + mHitTestResultSignal(), mTargetOrientation(Quaternion::IDENTITY), mTargetColor(Color::WHITE), mTargetPosition(Vector3::ZERO), @@@ -1092,6 -1075,7 +1093,7 @@@ mCaptureAllTouchAfterStart(false), mIsBlendEquationSet(false), mNeedGesturePropagation(false), + mUserInteractionEnabled(true), mLayoutDirection(LayoutDirection::LEFT_TO_RIGHT), mDrawMode(DrawMode::NORMAL), mColorMode(Node::DEFAULT_COLOR_MODE), diff --combined dali/internal/event/actors/actor-impl.h index bade273,b1050a7..3392d0d --- a/dali/internal/event/actors/actor-impl.h +++ b/dali/internal/event/actors/actor-impl.h @@@ -2,7 -2,7 +2,7 @@@ #define DALI_INTERNAL_ACTOR_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. @@@ -33,8 -33,6 +33,8 @@@ #include #include +#include + #include #include #include @@@ -646,6 -644,41 +646,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); @@@ -1207,15 -1240,6 +1242,15 @@@ public } /** + * Query whether the application or derived actor type requires hit-test result events. + * @return True if hit-test result events are required. + */ + bool IsHitTestResultRequired() const + { + return !mHitTestResultSignal.Empty(); + } + + /** * Query whether the application or derived actor type requires intercept touch events. * @return True if intercept touch events are required. */ @@@ -1258,7 -1282,7 +1293,7 @@@ */ bool IsHittable() const { - return IsSensitive() && IsVisible() && (GetCurrentWorldColor().a > FULLY_TRANSPARENT) && IsNodeConnected(); + return (IsUserInteractionEnabled()) && IsSensitive() && IsVisible() && (GetCurrentWorldColor().a > FULLY_TRANSPARENT) && IsNodeConnected(); } /** @@@ -1351,23 -1375,6 +1386,23 @@@ void EmitLayoutDirectionChangedSignal(LayoutDirection::Type type); /** + * Used by the EventProcessor to emit hit-test result touch event signals. + * @param[in] point The point of event touched. + * @param[in] hitPointLocal The hit point in the Actor's local reference system. + * @param[in] timeStamp The time the event occurred. + * @return True if the event was consumed. + */ + bool EmitHitTestResultSignal(Integration::Point point, Vector2 hitPointLocal, uint32_t timeStamp); + + /** + * @copydoc DevelActor::HitTestResultSignal() + */ + Dali::Actor::TouchEventSignalType& HitTestResultSignal() + { + return mHitTestResultSignal; + } + + /** * @copydoc DevelActor::InterceptTouchedSignal() */ Dali::Actor::TouchEventSignalType& InterceptTouchedSignal() @@@ -1858,7 -1865,6 +1893,7 @@@ protected Dali::Actor::OnRelayoutSignalType mOnRelayoutSignal; DevelActor::VisibilityChangedSignalType mVisibilityChangedSignal; Dali::Actor::LayoutDirectionChangedSignalType mLayoutDirectionChangedSignal; + Dali::Actor::TouchEventSignalType mHitTestResultSignal; Quaternion mTargetOrientation; ///< Event-side storage for orientation Vector4 mTargetColor; ///< Event-side storage for color @@@ -1888,6 -1894,7 +1923,7 @@@ 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