bool gTouchCallBackCalled = false;
bool gTouchCallBackCalled2 = false;
bool gTouchCallBackCalled3 = false;
+bool gHitTestTouchCallBackCalled = false;
bool gHoverCallBackCalled = false;
END_TEST;
}
+static bool TestHitTestTouchCallback(Actor, const TouchEvent&)
+{
+ gHitTestTouchCallBackCalled = true;
+ return false;
+ END_TEST;
+}
+
static void ResetTouchCallbacks()
{
gTouchCallBackCalled = false;
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");
// 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.
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;
+}
#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.
* @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
*/
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
/*
- * 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.
#include <dali/devel-api/common/capabilities.h>
#include <dali/integration-api/debug.h>
+#include <dali/integration-api/events/touch-integ.h>
#include <dali/internal/event/actors/actor-coords.h>
#include <dali/internal/event/actors/actor-parent.h>
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
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();
mOnRelayoutSignal(),
mVisibilityChangedSignal(),
mLayoutDirectionChangedSignal(),
+ mHitTestResultSignal(),
mTargetOrientation(Quaternion::IDENTITY),
mTargetColor(Color::WHITE),
mTargetPosition(Vector3::ZERO),
mCaptureAllTouchAfterStart(false),
mIsBlendEquationSet(false),
mNeedGesturePropagation(false),
+ mUserInteractionEnabled(true),
mLayoutDirection(LayoutDirection::LEFT_TO_RIGHT),
mDrawMode(DrawMode::NORMAL),
mColorMode(Node::DEFAULT_COLOR_MODE),
#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.
#include <dali/devel-api/actors/actor-devel.h>
#include <dali/devel-api/rendering/renderer-devel.h>
+#include <dali/integration-api/events/touch-event-integ.h>
+
#include <dali/internal/common/const-string.h>
#include <dali/internal/common/internal-constants.h>
#include <dali/internal/common/memory-pool-object-allocator.h>
}
/**
+ * 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);
}
/**
+ * 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.
*/
*/
bool IsHittable() const
{
- return IsSensitive() && IsVisible() && (GetCurrentWorldColor().a > FULLY_TRANSPARENT) && IsNodeConnected();
+ return (IsUserInteractionEnabled()) && IsSensitive() && IsVisible() && (GetCurrentWorldColor().a > FULLY_TRANSPARENT) && IsNodeConnected();
}
/**
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()
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
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