[problem] Currently, the only way to stop gestures being delivered to actors behind a layer is
by attaching the layer to a gesture detector which is cumbersome.
[cause] N/A
[solution] Implemented an API which allows the user to set whether a layer should consume all
touch. When this is set on a layer, any layers behind that layer are not hit-test.
Change-Id: I34468c13a3b7b5f81a53ca4746a5c97a4ece09ba
Signed-off-by: Adeel Kazmi <adeel.kazmi@samsung.com>
extern int UtcDaliLayerSetDepthTestDisabled(void);
extern int UtcDaliLayerCreateDestroy(void);
extern int UtcDaliLayerPropertyIndices(void);
+extern int UtcDaliLayerTouchConsumed(void);
extern int UtcDaliLongPressGestureConstructor(void);
extern int UtcDaliLongPressGestureAssignment(void);
extern int UtcDaliLongPressGestureDetectorConstructor(void);
extern int UtcDaliLongPressGestureSystemOverlay(void);
extern int UtcDaliLongPressGestureBehindTouchableSystemOverlay(void);
extern int UtcDaliLongPressGestureTouchBehindGesturedSystemOverlay(void);
+extern int UtcDaliLongPressGestureLayerConsumesTouch(void);
extern int UtcDaliMaterialNew01(void);
extern int UtcDaliMaterialDownCast(void);
extern int UtcDaliMaterialSettersAndGetters(void);
extern int UtcDaliPanGestureSetProperties(void);
extern int UtcDaliPanGestureSetPropertiesAlreadyPanning(void);
extern int UtcDaliPanGesturePropertyIndices(void);
+extern int UtcDaliPanGestureLayerConsumesTouch(void);
extern int UtcDaliPinchGestureConstructor(void);
extern int UtcDaliPinchGestureAssignment(void);
extern int UtcDaliPinchGestureDetectorConstructor(void);
extern int UtcDaliPinchGestureSystemOverlay(void);
extern int UtcDaliPinchGestureBehindTouchableSystemOverlay(void);
extern int UtcDaliPinchGestureTouchBehindGesturedSystemOverlay(void);
+extern int UtcDaliPinchGestureLayerConsumesTouch(void);
extern int UtcDaliPixelHasAlpha(void);
extern int UtcDaliPixelGetBytesPerPixel(void);
extern int UtcDaliPixelGetAlphaOffsetAndMask(void);
extern int UtcDaliTapGestureSystemOverlay(void);
extern int UtcDaliTapGestureBehindTouchableSystemOverlay(void);
extern int UtcDaliTapGestureTouchBehindGesturedSystemOverlay(void);
+extern int UtcDaliTapGestureLayerConsumesTouch(void);
extern int UtcDaliTextConstructor(void);
extern int UtcDaliTextCopyConstructor(void);
extern int UtcDaliTextAssignmentOperator(void);
extern int UtcDaliTouchActorSignalNotConsumed(void);
extern int UtcDaliTouchActorUnStaged(void);
extern int UtcDaliTouchSystemOverlayActor(void);
+extern int UtcDaliTouchLayerConsumesTouch(void);
extern int UtcDaliVector2Cons(void);
extern int UtcDaliVector2FitInside(void);
extern int UtcDaliVector2FitScaleToFill(void);
{"UtcDaliLayerSetDepthTestDisabled", UtcDaliLayerSetDepthTestDisabled, layer_test_startup, layer_test_cleanup},
{"UtcDaliLayerCreateDestroy", UtcDaliLayerCreateDestroy, layer_test_startup, layer_test_cleanup},
{"UtcDaliLayerPropertyIndices", UtcDaliLayerPropertyIndices, layer_test_startup, layer_test_cleanup},
+ {"UtcDaliLayerTouchConsumed", UtcDaliLayerTouchConsumed, layer_test_startup, layer_test_cleanup},
{"UtcDaliLongPressGestureConstructor", UtcDaliLongPressGestureConstructor, utc_dali_long_press_gesture_startup, utc_dali_long_press_gesture_cleanup},
{"UtcDaliLongPressGestureAssignment", UtcDaliLongPressGestureAssignment, utc_dali_long_press_gesture_startup, utc_dali_long_press_gesture_cleanup},
{"UtcDaliLongPressGestureDetectorConstructor", UtcDaliLongPressGestureDetectorConstructor, utc_dali_long_press_gesture_detector_startup, utc_dali_long_press_gesture_detector_cleanup},
{"UtcDaliLongPressGestureSystemOverlay", UtcDaliLongPressGestureSystemOverlay, utc_dali_long_press_gesture_detector_startup, utc_dali_long_press_gesture_detector_cleanup},
{"UtcDaliLongPressGestureBehindTouchableSystemOverlay", UtcDaliLongPressGestureBehindTouchableSystemOverlay, utc_dali_long_press_gesture_detector_startup, utc_dali_long_press_gesture_detector_cleanup},
{"UtcDaliLongPressGestureTouchBehindGesturedSystemOverlay", UtcDaliLongPressGestureTouchBehindGesturedSystemOverlay, utc_dali_long_press_gesture_detector_startup, utc_dali_long_press_gesture_detector_cleanup},
+ {"UtcDaliLongPressGestureLayerConsumesTouch", UtcDaliLongPressGestureLayerConsumesTouch, utc_dali_long_press_gesture_detector_startup, utc_dali_long_press_gesture_detector_cleanup},
{"UtcDaliMaterialNew01", UtcDaliMaterialNew01, utc_dali_material_startup, utc_dali_material_cleanup},
{"UtcDaliMaterialDownCast", UtcDaliMaterialDownCast, utc_dali_material_startup, utc_dali_material_cleanup},
{"UtcDaliMaterialSettersAndGetters", UtcDaliMaterialSettersAndGetters, utc_dali_material_startup, utc_dali_material_cleanup},
{"UtcDaliPanGestureSetProperties", UtcDaliPanGestureSetProperties, utc_dali_pan_gesture_detector_startup, utc_dali_pan_gesture_detector_cleanup},
{"UtcDaliPanGestureSetPropertiesAlreadyPanning", UtcDaliPanGestureSetPropertiesAlreadyPanning, utc_dali_pan_gesture_detector_startup, utc_dali_pan_gesture_detector_cleanup},
{"UtcDaliPanGesturePropertyIndices", UtcDaliPanGesturePropertyIndices, utc_dali_pan_gesture_detector_startup, utc_dali_pan_gesture_detector_cleanup},
+ {"UtcDaliPanGestureLayerConsumesTouch", UtcDaliPanGestureLayerConsumesTouch, utc_dali_pan_gesture_detector_startup, utc_dali_pan_gesture_detector_cleanup},
{"UtcDaliPinchGestureConstructor", UtcDaliPinchGestureConstructor, utc_dali_pinch_gesture_startup, utc_dali_pinch_gesture_cleanup},
{"UtcDaliPinchGestureAssignment", UtcDaliPinchGestureAssignment, utc_dali_pinch_gesture_startup, utc_dali_pinch_gesture_cleanup},
{"UtcDaliPinchGestureDetectorConstructor", UtcDaliPinchGestureDetectorConstructor, utc_dali_pinch_gesture_detector_startup, utc_dali_pinch_gesture_detector_cleanup},
{"UtcDaliPinchGestureSystemOverlay", UtcDaliPinchGestureSystemOverlay, utc_dali_pinch_gesture_detector_startup, utc_dali_pinch_gesture_detector_cleanup},
{"UtcDaliPinchGestureBehindTouchableSystemOverlay", UtcDaliPinchGestureBehindTouchableSystemOverlay, utc_dali_pinch_gesture_detector_startup, utc_dali_pinch_gesture_detector_cleanup},
{"UtcDaliPinchGestureTouchBehindGesturedSystemOverlay", UtcDaliPinchGestureTouchBehindGesturedSystemOverlay, utc_dali_pinch_gesture_detector_startup, utc_dali_pinch_gesture_detector_cleanup},
+ {"UtcDaliPinchGestureLayerConsumesTouch", UtcDaliPinchGestureLayerConsumesTouch, utc_dali_pinch_gesture_detector_startup, utc_dali_pinch_gesture_detector_cleanup},
{"UtcDaliPixelHasAlpha", UtcDaliPixelHasAlpha, utc_dali_pixel_startup, utc_dali_pixel_cleanup},
{"UtcDaliPixelGetBytesPerPixel", UtcDaliPixelGetBytesPerPixel, utc_dali_pixel_startup, utc_dali_pixel_cleanup},
{"UtcDaliPixelGetAlphaOffsetAndMask", UtcDaliPixelGetAlphaOffsetAndMask, utc_dali_pixel_startup, utc_dali_pixel_cleanup},
{"UtcDaliTapGestureSystemOverlay", UtcDaliTapGestureSystemOverlay, utc_dali_tap_gesture_detector_startup, utc_dali_tap_gesture_detector_cleanup},
{"UtcDaliTapGestureBehindTouchableSystemOverlay", UtcDaliTapGestureBehindTouchableSystemOverlay, utc_dali_tap_gesture_detector_startup, utc_dali_tap_gesture_detector_cleanup},
{"UtcDaliTapGestureTouchBehindGesturedSystemOverlay", UtcDaliTapGestureTouchBehindGesturedSystemOverlay, utc_dali_tap_gesture_detector_startup, utc_dali_tap_gesture_detector_cleanup},
+ {"UtcDaliTapGestureLayerConsumesTouch", UtcDaliTapGestureLayerConsumesTouch, utc_dali_tap_gesture_detector_startup, utc_dali_tap_gesture_detector_cleanup},
{"UtcDaliTextConstructor", UtcDaliTextConstructor, utc_dali_text_startup, utc_dali_text_cleanup},
{"UtcDaliTextCopyConstructor", UtcDaliTextCopyConstructor, utc_dali_text_startup, utc_dali_text_cleanup},
{"UtcDaliTextAssignmentOperator", UtcDaliTextAssignmentOperator, utc_dali_text_startup, utc_dali_text_cleanup},
{"UtcDaliTouchActorSignalNotConsumed", UtcDaliTouchActorSignalNotConsumed, utc_dali_touch_processing_startup, utc_dali_touch_processing_cleanup},
{"UtcDaliTouchActorUnStaged", UtcDaliTouchActorUnStaged, utc_dali_touch_processing_startup, utc_dali_touch_processing_cleanup},
{"UtcDaliTouchSystemOverlayActor", UtcDaliTouchSystemOverlayActor, utc_dali_touch_processing_startup, utc_dali_touch_processing_cleanup},
+ {"UtcDaliTouchLayerConsumesTouch", UtcDaliTouchLayerConsumesTouch, utc_dali_touch_processing_startup, utc_dali_touch_processing_cleanup},
{"UtcDaliVector2Cons", UtcDaliVector2Cons, utc_dali_vector2_startup, utc_dali_vector2_cleanup},
{"UtcDaliVector2FitInside", UtcDaliVector2FitInside, utc_dali_vector2_startup, utc_dali_vector2_cleanup},
{"UtcDaliVector2FitScaleToFill", UtcDaliVector2FitScaleToFill, utc_dali_vector2_startup, utc_dali_vector2_cleanup},
DALI_TEST_EQUALS( indices.size(), layer.GetPropertyCount(), TEST_LOCATION );
END_TEST;
}
+
+int UtcDaliLayerTouchConsumed(void)
+{
+ TestApplication application;
+ Layer layer = Layer::New();
+
+ DALI_TEST_EQUALS( layer.IsTouchConsumed(), false, TEST_LOCATION );
+ layer.SetTouchConsumed( true );
+ DALI_TEST_EQUALS( layer.IsTouchConsumed(), true, TEST_LOCATION );
+ END_TEST;
+}
END_TEST;
}
+
+int UtcDaliLongPressGestureLayerConsumesTouch(void)
+{
+ TestApplication application;
+
+ Actor actor = Actor::New();
+ actor.SetSize(100.0f, 100.0f);
+ actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ Stage::GetCurrent().Add(actor);
+
+ // Add a detector
+ SignalData data;
+ GestureReceivedFunctor functor(data);
+ LongPressGestureDetector detector = LongPressGestureDetector::New();
+ detector.Attach(actor);
+ detector.DetectedSignal().Connect( &application, functor );
+
+ // Add a layer to overlap the actor
+ Layer layer = Layer::New();
+ layer.SetSize(100.0f, 100.0f);
+ layer.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ Stage::GetCurrent().Add( layer );
+ layer.RaiseToTop();
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ Vector2 screenCoords( 50.0f, 50.0f );
+
+ // Emit signals, should receive
+ application.ProcessEvent( GenerateLongPress( Gesture::Possible, 1u, screenCoords ) );
+ application.ProcessEvent( GenerateLongPress( Gesture::Started, 1u, screenCoords ) );
+ application.ProcessEvent( GenerateLongPress( Gesture::Finished, 1u, screenCoords ) );
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Set layer to consume all touch
+ layer.SetTouchConsumed( true );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Emit the same signals again, should not receive
+ application.ProcessEvent( GenerateLongPress( Gesture::Possible, 1u, screenCoords ) );
+ application.ProcessEvent( GenerateLongPress( Gesture::Started, 1u, screenCoords ) );
+ application.ProcessEvent( GenerateLongPress( Gesture::Finished, 1u, screenCoords ) );
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ END_TEST;
+}
DALI_TEST_EQUALS( indices.size(), detector.GetPropertyCount(), TEST_LOCATION );
END_TEST;
}
+
+int UtcDaliPanGestureLayerConsumesTouch(void)
+{
+ TestApplication application;
+
+ Actor actor = Actor::New();
+ actor.SetSize(100.0f, 100.0f);
+ actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ Stage::GetCurrent().Add(actor);
+
+ // Add a pan detector
+ PanGestureDetector detector = PanGestureDetector::New();
+ detector.Attach( actor );
+ SignalData data;
+ GestureReceivedFunctor functor( data );
+ detector.DetectedSignal().Connect( &application, functor );
+
+ // Add a layer to overlap the actor
+ Layer layer = Layer::New();
+ layer.SetSize(100.0f, 100.0f);
+ layer.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ Stage::GetCurrent().Add( layer );
+ layer.RaiseToTop();
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Emit signals, should receive
+ application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+ application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+ application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Set layer to consume all touch
+ layer.SetTouchConsumed( true );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Emit the same signals again, should not receive
+ application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+ application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+ application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ END_TEST;
+}
END_TEST;
}
+
+int UtcDaliPinchGestureLayerConsumesTouch(void)
+{
+ TestApplication application;
+
+ Actor actor = Actor::New();
+ actor.SetSize(100.0f, 100.0f);
+ actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ Stage::GetCurrent().Add(actor);
+
+ // Add a detector
+ SignalData data;
+ GestureReceivedFunctor functor(data);
+ PinchGestureDetector detector = PinchGestureDetector::New();
+ detector.Attach(actor);
+ detector.DetectedSignal().Connect( &application, functor );
+
+ // Add a layer to overlap the actor
+ Layer layer = Layer::New();
+ layer.SetSize(100.0f, 100.0f);
+ layer.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ Stage::GetCurrent().Add( layer );
+ layer.RaiseToTop();
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ Vector2 screenCoords( 50.0f, 50.0f );
+ float scale ( 10.0f );
+ float speed ( 50.0f );
+
+ // Emit signals, should receive
+ application.ProcessEvent( GeneratePinch( Gesture::Started, scale, speed, screenCoords ) );
+ application.ProcessEvent( GeneratePinch( Gesture::Finished, scale, speed, screenCoords ) );
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Set layer to consume all touch
+ layer.SetTouchConsumed( true );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Emit the same signals again, should not receive
+ application.ProcessEvent( GeneratePinch( Gesture::Started, scale, speed, screenCoords ) );
+ application.ProcessEvent( GeneratePinch( Gesture::Finished, scale, speed, screenCoords ) );
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ END_TEST;
+}
END_TEST;
}
+
+int UtcDaliTapGestureLayerConsumesTouch(void)
+{
+ TestApplication application;
+
+ Actor actor = Actor::New();
+ actor.SetSize(100.0f, 100.0f);
+ actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ Stage::GetCurrent().Add(actor);
+
+ // Add a detector
+ SignalData data;
+ GestureReceivedFunctor functor(data);
+ TapGestureDetector detector = TapGestureDetector::New();
+ detector.Attach(actor);
+ detector.DetectedSignal().Connect( &application, functor );
+
+ // Add a layer to overlap the actor
+ Layer layer = Layer::New();
+ layer.SetSize(100.0f, 100.0f);
+ layer.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ Stage::GetCurrent().Add( layer );
+ layer.RaiseToTop();
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ Vector2 screenCoords( 50.0f, 50.0f );
+
+ // Emit signals, should receive
+ application.ProcessEvent( GenerateTap( Gesture::Possible, 1u, 1u, screenCoords ) );
+ application.ProcessEvent( GenerateTap( Gesture::Started, 1u, 1u, screenCoords ) );
+ DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ // Set layer to consume all touch
+ layer.SetTouchConsumed( true );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Emit the same signals again, should not receive
+ application.ProcessEvent( GenerateTap( Gesture::Possible, 1u, 1u, screenCoords ) );
+ application.ProcessEvent( GenerateTap( Gesture::Started, 1u, 1u, screenCoords ) );
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ END_TEST;
+}
DALI_TEST_CHECK( systemActor == data.touchedActor );
END_TEST;
}
+
+int UtcDaliTouchLayerConsumesTouch(void)
+{
+ TestApplication application;
+
+ Actor actor = Actor::New();
+ actor.SetSize(100.0f, 100.0f);
+ actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ Stage::GetCurrent().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 );
+
+ // Add a layer to overlap the actor
+ Layer layer = Layer::New();
+ layer.SetSize(100.0f, 100.0f);
+ layer.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+ Stage::GetCurrent().Add( layer );
+ layer.RaiseToTop();
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Emit a few touch signals
+ application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+ application.ProcessEvent( GenerateSingleTouch( TouchPoint::Up, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+ data.Reset();
+
+ // Set layer to consume all touch
+ layer.SetTouchConsumed( true );
+
+ // Render and notify
+ application.SendNotification();
+ application.Render();
+
+ // Emit the same signals again, should not receive
+ application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+ application.ProcessEvent( GenerateSingleTouch( TouchPoint::Up, Vector2( 10.0f, 10.0f ) ) );
+ DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+ data.Reset();
+
+ END_TEST;
+}
* - Before we perform a hit test within a layer, we check if all the layer's parents are visible
* and sensitive.
* - If they are not, we skip hit testing the actors in that layer altogether.
+ * - If a layer is set to consume all touch, then we do not check any layers behind this layer.
*
* - Actors
* - The final part of hit testing is performed by walking through the actor tree within a layer.
*/
void SetSortFunction( SortFunctionType function );
+ /**
+ * @brief This allows the user to specify whether this layer should consume touch (including gestures).
+ *
+ * If set, any layers behind this layer will not be hit-test.
+ *
+ * @param[in] consume Whether the layer should consume touch (including gestures).
+ */
+ void SetTouchConsumed( bool consume );
+
+ /**
+ * @brief Retrieves whether the layer consumes touch (including gestures).
+ *
+ * @return true if consuming touch, false otherwise.
+ */
+ bool IsTouchConsumed() const;
+
public: // Not intended for application developers
/**
mClippingBox(0,0,0,0),
mSortFunction(Dali::Layer::ZValue),
mIsClipping(false),
- mDepthTestDisabled(false)
+ mDepthTestDisabled(false),
+ mTouchConsumed(false)
{
}
}
}
+void Layer::SetTouchConsumed( bool consume )
+{
+ mTouchConsumed = consume;
+}
+
+bool Layer::IsTouchConsumed() const
+{
+ return mTouchConsumed;
+}
+
SceneGraph::Node* Layer::CreateNode() const
{
return SceneGraph::Layer::New();
void SetSortFunction(Dali::Layer::SortFunctionType function);
/**
+ * @copydoc Dali::Layer::SetTouchConsumed()
+ */
+ void SetTouchConsumed( bool consume );
+
+ /**
+ * @copydoc Dali::Layer::IsTouchConsumed()
+ */
+ bool IsTouchConsumed() const;
+
+ /**
* Helper function to get the scene object.
* This should only be called by Stage
* @return the scene object for the layer.
bool mIsClipping:1; ///< True when clipping is enabled
bool mDepthTestDisabled:1; ///< Whether depth test is disabled.
+ bool mTouchConsumed:1; ///< Whether we should consume touch (including gesture).
static bool mFirstInstance;
static DefaultPropertyLookup* mDefaultLayerPropertyLookup; ///< Default properties
// INTERNAL INCLUDES
#include <dali/integration-api/debug.h>
#include <dali/internal/event/actors/actor-impl.h>
+#include <dali/internal/event/actors/layer-impl.h>
#include <dali/internal/event/events/hit-test-algorithm-impl.h>
#include <dali/internal/event/events/actor-gesture-data.h>
#include <dali/internal/event/render-tasks/render-task-impl.h>
actor->IsSensitive(); // Actor is sensitive, if insensitive none of its children should be hittable either.
}
+ virtual bool DoesLayerConsumeHit( Layer* layer )
+ {
+ return layer->IsTouchConsumed();
+ }
+
Gesture::Type mType;
};
return mFunc( Dali::Actor( actor ), Dali::HitTestAlgorithm::DESCEND_ACTOR_TREE );
}
+ virtual bool DoesLayerConsumeHit( Layer* layer )
+ {
+ // Layer::IsTouchConsumed() focuses on touch only. Here we are a wrapper for the public-api
+ // where the caller may want to check for something completely different.
+ // TODO: Should provide a means to let caller decide. For now do not allow layers to consume
+ return false;
+ }
+
Dali::HitTestAlgorithm::HitTestFunction mFunc;
};
return actor->IsVisible() && // Actor is visible, if not visible then none of its children are visible.
actor->IsSensitive(); // Actor is sensitive, if insensitive none of its children should be hittable either.
}
+
+ virtual bool DoesLayerConsumeHit( Layer* layer )
+ {
+ return layer->IsTouchConsumed();
+ }
};
/**
HitActor hit;
bool stencilOnLayer = false;
bool stencilHit = false;
+ bool layerConsumesHit = false;
const Vector2& stageSize = Stage::GetCurrent()->GetSize();
for (int i=layers.GetLayerCount()-1; i>=0 && !(hit.actor); --i)
// Recursively hit test all the actors, without crossing into other layers.
hit = HitTestWithinLayer( *layer, results.rayOrigin, results.rayDirection, false, nearClippingPlane, farClippingPlane, hitCheck, stencilOnLayer, stencilHit, false );
}
+
// If a stencil on this layer hasn't been hit, then discard hit results for this layer
if ( stencilOnLayer && !stencilHit )
{
hit = previousHit;
}
+
+ // If this layer is set to consume the hit, then do not check any layers behind it
+ if ( hitCheck.DoesLayerConsumeHit( layer ) )
+ {
+ layerConsumesHit = true;
+ break;
+ }
}
}
if ( hit.actor )
results.actorCoordinates.y = hit.y;
return true; // Success
}
+ else if ( layerConsumesHit )
+ {
+ return true; // Also success if layer is consuming the hit
+ }
}
}
}
/**
* Iterate through RenderTaskList and perform hit test.
+ *
+ * @return true if we have a hit, false otherwise
*/
-
-void HitTestForEachRenderTask( LayerList& layers,
+bool HitTestForEachRenderTask( LayerList& layers,
RenderTaskList& taskList,
const Vector2& screenCoordinates,
Results& results,
if ( HitTestRenderTask( layers, renderTask, screenCoordinates, results, hitCheck ) )
{
- // Exit when an actor is hit
- return; // don't bother checking off screen tasks
+ // Return true when an actor is hit (or layer in our render-task consumes the hit)
+ return true; // don't bother checking off screen tasks
}
}
if ( HitTestRenderTask( layers, renderTask, screenCoordinates, results, hitCheck ) )
{
- // Exit when an actor is hit
- break;
+ // Return true when an actor is hit (or a layer in our render-task consumes the hit)
+ return true;
}
}
}
+ return false;
}
} // unnamed namespace
Results hitTestResults;
HitTestFunctionWrapper hitTestFunctionWrapper( func );
- HitTestForEachRenderTask( layerList, taskList, screenCoordinates, hitTestResults, hitTestFunctionWrapper );
-
- results.actor = hitTestResults.actor;
- results.actorCoordinates = hitTestResults.actorCoordinates;
+ if ( HitTestForEachRenderTask( layerList, taskList, screenCoordinates, hitTestResults, hitTestFunctionWrapper ) )
+ {
+ results.actor = hitTestResults.actor;
+ results.actorCoordinates = hitTestResults.actorCoordinates;
+ }
}
void HitTest( Stage& stage, const Vector2& screenCoordinates, Results& results, HitTestInterface& hitTestInterface )
{
+ bool hit = false;
+
// Hit-test the system-overlay actors first
SystemOverlay* systemOverlay = stage.GetSystemOverlayInternal();
RenderTaskList& overlayTaskList = systemOverlay->GetOverlayRenderTasks();
LayerList& overlayLayerList = systemOverlay->GetLayerList();
- HitTestForEachRenderTask( overlayLayerList, overlayTaskList, screenCoordinates, results, hitTestInterface );
+ hit = HitTestForEachRenderTask( overlayLayerList, overlayTaskList, screenCoordinates, results, hitTestInterface );
}
// Hit-test the regular on-stage actors
- if ( !results.actor )
+ if ( !hit )
{
RenderTaskList& taskList = stage.GetRenderTaskList();
LayerList& layerList = stage.GetLayerList();
{
Results hitTestResults;
HitTestFunctionWrapper hitTestFunctionWrapper( func );
- HitTestRenderTask( stage.GetLayerList(), renderTask, screenCoordinates, hitTestResults, hitTestFunctionWrapper );
- results.actor = hitTestResults.actor;
- results.actorCoordinates = hitTestResults.actorCoordinates;
+ if ( HitTestRenderTask( stage.GetLayerList(), renderTask, screenCoordinates, hitTestResults, hitTestFunctionWrapper ) )
+ {
+ results.actor = hitTestResults.actor;
+ results.actorCoordinates = hitTestResults.actorCoordinates;
+ }
}
} // namespace HitTestAlgorithm
namespace Internal
{
+class Layer;
+
/**
* This namespace is provided for application developers to do hit test for the actors.
*/
{
/**
* Called by the hit-test algorithm to determine whether the actor is hittable or not.
+ *
* @param[in] actor Raw pointer to an Actor object.
+ *
+ * @return true if actor is hittable, false otherwise.
*/
virtual bool IsActorHittable( Actor* actor ) = 0;
/**
* Called by the hit-test algorithm to determine whether the algorithm should descend the actor's
* hierarchy (and hit-test its children as well).
+ *
* @param[in] actor Raw pointer to an Actor object.
+ *
+ * @return true if we should descend the actor's hierarchy, false otherwise.
*/
virtual bool DescendActorHierarchy( Actor* actor ) = 0;
+
+ /**
+ * Called by the hit-test algorithm to determine whether the layer specified consumes the hit
+ * regardless of whether an actor in the layer requires it or not.
+ *
+ * @note If true is returned, then no layers behind this layer will be hit-test.
+ *
+ * @param[in] layer Raw pointer to a Layer object.
+ *
+ * @return true if the layer should consume the hit, false otherwise.
+ */
+ virtual bool DoesLayerConsumeHit( Layer* layer ) = 0;
};
/**
GetImplementation(*this).SetSortFunction(function);
}
+void Layer::SetTouchConsumed( bool consume )
+{
+ GetImplementation( *this ).SetTouchConsumed( consume );
+}
+
+bool Layer::IsTouchConsumed() const
+{
+ return GetImplementation( *this ).IsTouchConsumed();
+}
+
Layer::Layer(Internal::Layer* internal)
: Actor(internal)
{