From 4100bafa4d6d2d1fab39f999658cbbc9a14f66ce Mon Sep 17 00:00:00 2001 From: "joogab.yun" Date: Wed, 22 Jun 2022 16:52:58 +0900 Subject: [PATCH] Add ALLOW_ONLY_OWN_TOUCH property. 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 | 40 ++++++++++ .../src/dali/utc-Dali-TouchProcessing.cpp | 77 ++++++++++++++++++- dali/devel-api/actors/actor-devel.h | 7 ++ dali/internal/event/actors/actor-impl.cpp | 2 + dali/internal/event/actors/actor-impl.h | 10 +++ .../event/actors/actor-property-handler.cpp | 18 ++++- .../event/events/hit-test-algorithm-impl.cpp | 13 +++- .../event/events/hit-test-algorithm-impl.h | 3 +- .../event/events/touch-event-processor.cpp | 43 ++++++----- .../event/events/touch-event-processor.h | 8 +- 10 files changed, 197 insertions(+), 24 deletions(-) diff --git a/automated-tests/src/dali/utc-Dali-Actor.cpp b/automated-tests/src/dali/utc-Dali-Actor.cpp index 5ea0d2235..32ff0fbcb 100644 --- a/automated-tests/src/dali/utc-Dali-Actor.cpp +++ b/automated-tests/src/dali/utc-Dali-Actor.cpp @@ -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(), false, TEST_LOCATION); + actor.SetProperty(DevelActor::Property::ALLOW_ONLY_OWN_TOUCH, true); + DALI_TEST_EQUALS(actor.GetProperty(DevelActor::Property::ALLOW_ONLY_OWN_TOUCH).Get(), 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 diff --git a/automated-tests/src/dali/utc-Dali-TouchProcessing.cpp b/automated-tests/src/dali/utc-Dali-TouchProcessing.cpp index d39266a98..33653e10d 100644 --- a/automated-tests/src/dali/utc-Dali-TouchProcessing.cpp +++ b/automated-tests/src/dali/utc-Dali-TouchProcessing.cpp @@ -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 diff --git a/dali/devel-api/actors/actor-devel.h b/dali/devel-api/actors/actor-devel.h index 9d4f0ae42..25b6cef0e 100644 --- a/dali/devel-api/actors/actor-devel.h +++ b/dali/devel-api/actors/actor-devel.h @@ -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 diff --git a/dali/internal/event/actors/actor-impl.cpp b/dali/internal/event/actors/actor-impl.cpp index 6dc060a23..f9de7945d 100644 --- a/dali/internal/event/actors/actor-impl.cpp +++ b/dali/internal/event/actors/actor-impl.cpp @@ -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), diff --git a/dali/internal/event/actors/actor-impl.h b/dali/internal/event/actors/actor-impl.h index 3392d0dbd..51fb710c7 100644 --- a/dali/internal/event/actors/actor-impl.h +++ b/dali/internal/event/actors/actor-impl.h @@ -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 diff --git a/dali/internal/event/actors/actor-property-handler.cpp b/dali/internal/event/actors/actor-property-handler.cpp index 4a7daccda..8e3aeaa77 100644 --- a/dali/internal/event/actors/actor-property-handler.cpp +++ b/dali/internal/event/actors/actor-property-handler.cpp @@ -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 diff --git a/dali/internal/event/events/hit-test-algorithm-impl.cpp b/dali/internal/event/events/hit-test-algorithm-impl.cpp index 0ed24bec7..e63271755 100644 --- a/dali/internal/event/events/hit-test-algorithm-impl.cpp +++ b/dali/internal/event/events/hit-test-algorithm-impl.cpp @@ -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); } diff --git a/dali/internal/event/events/hit-test-algorithm-impl.h b/dali/internal/event/events/hit-test-algorithm-impl.h index fa22507c8..5a4c2fc69 100644 --- a/dali/internal/event/events/hit-test-algorithm-impl.h +++ b/dali/internal/event/events/hit-test-algorithm-impl.h @@ -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 diff --git a/dali/internal/event/events/touch-event-processor.cpp b/dali/internal/event/events/touch-event-processor.cpp index e8673eda3..2eca85a00 100644 --- a/dali/internal/event/events/touch-event-processor.cpp +++ b/dali/internal/event/events/touch-event-processor.cpp @@ -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(); } } diff --git a/dali/internal/event/events/touch-event-processor.h b/dali/internal/event/events/touch-event-processor.h index 70a0fb98e..75849aecf 100644 --- a/dali/internal/event/events/touch-event-processor.h +++ b/dali/internal/event/events/touch-event-processor.h @@ -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 -- 2.34.1