From 71ea008bc985fb640e2a193d6c5af270e9b897e5 Mon Sep 17 00:00:00 2001 From: Adeel Kazmi Date: Wed, 18 Jun 2014 10:17:26 +0900 Subject: [PATCH] (HitTest) Added API to layer so that it can consume all touch if required [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 --- automated-tests/src/dali/tct-dali-core.h | 12 +++++ automated-tests/src/dali/utc-Dali-Layer.cpp | 11 ++++ .../src/dali/utc-Dali-LongPressGestureDetector.cpp | 53 ++++++++++++++++++ .../src/dali/utc-Dali-PanGestureDetector.cpp | 51 ++++++++++++++++++ .../src/dali/utc-Dali-PinchGestureDetector.cpp | 53 ++++++++++++++++++ .../src/dali/utc-Dali-TapGestureDetector.cpp | 51 ++++++++++++++++++ .../src/dali/utc-Dali-TouchProcessing.cpp | 51 ++++++++++++++++++ capi/dali/public-api/actors/actor.h | 1 + capi/dali/public-api/actors/layer.h | 16 ++++++ dali/internal/event/actors/layer-impl.cpp | 13 ++++- dali/internal/event/actors/layer-impl.h | 11 ++++ dali/internal/event/events/gesture-processor.cpp | 6 +++ .../event/events/hit-test-algorithm-impl.cpp | 63 ++++++++++++++++------ .../event/events/hit-test-algorithm-impl.h | 20 +++++++ dali/public-api/actors/layer.cpp | 10 ++++ 15 files changed, 406 insertions(+), 16 deletions(-) diff --git a/automated-tests/src/dali/tct-dali-core.h b/automated-tests/src/dali/tct-dali-core.h index 23066b4..106da49 100644 --- a/automated-tests/src/dali/tct-dali-core.h +++ b/automated-tests/src/dali/tct-dali-core.h @@ -741,6 +741,7 @@ extern int UtcDaliLayerDefaultProperties(void); 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); @@ -771,6 +772,7 @@ extern int UtcDaliLongPressGestureActorStagedAndDestroyed(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); @@ -877,6 +879,7 @@ extern int UtcDaliPanGestureDirectionProcessing(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); @@ -903,6 +906,7 @@ extern int UtcDaliPinchGestureActorStagedAndDestroyed(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); @@ -1173,6 +1177,7 @@ extern int UtcDaliTapGestureActorRemovedWhilePossible(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); @@ -1266,6 +1271,7 @@ extern int UtcDaliTouchActorRemovedInSignal(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); @@ -1958,6 +1964,7 @@ testcase tc_array[] = { {"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}, @@ -1988,6 +1995,7 @@ testcase tc_array[] = { {"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}, @@ -2094,6 +2102,7 @@ testcase tc_array[] = { {"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}, @@ -2120,6 +2129,7 @@ testcase tc_array[] = { {"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}, @@ -2390,6 +2400,7 @@ testcase tc_array[] = { {"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}, @@ -2483,6 +2494,7 @@ testcase tc_array[] = { {"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}, diff --git a/automated-tests/src/dali/utc-Dali-Layer.cpp b/automated-tests/src/dali/utc-Dali-Layer.cpp index 23e9ddd..8e9dc56 100644 --- a/automated-tests/src/dali/utc-Dali-Layer.cpp +++ b/automated-tests/src/dali/utc-Dali-Layer.cpp @@ -512,3 +512,14 @@ int UtcDaliLayerPropertyIndices(void) 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; +} diff --git a/automated-tests/src/dali/utc-Dali-LongPressGestureDetector.cpp b/automated-tests/src/dali/utc-Dali-LongPressGestureDetector.cpp index 1b04d5f..433082b 100644 --- a/automated-tests/src/dali/utc-Dali-LongPressGestureDetector.cpp +++ b/automated-tests/src/dali/utc-Dali-LongPressGestureDetector.cpp @@ -1374,3 +1374,56 @@ int UtcDaliLongPressGestureTouchBehindGesturedSystemOverlay(void) 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; +} diff --git a/automated-tests/src/dali/utc-Dali-PanGestureDetector.cpp b/automated-tests/src/dali/utc-Dali-PanGestureDetector.cpp index 3a588e1..63f1203 100644 --- a/automated-tests/src/dali/utc-Dali-PanGestureDetector.cpp +++ b/automated-tests/src/dali/utc-Dali-PanGestureDetector.cpp @@ -2133,3 +2133,54 @@ int UtcDaliPanGesturePropertyIndices(void) 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; +} diff --git a/automated-tests/src/dali/utc-Dali-PinchGestureDetector.cpp b/automated-tests/src/dali/utc-Dali-PinchGestureDetector.cpp index 2b487a5..bd8c58b 100644 --- a/automated-tests/src/dali/utc-Dali-PinchGestureDetector.cpp +++ b/automated-tests/src/dali/utc-Dali-PinchGestureDetector.cpp @@ -1299,3 +1299,56 @@ int UtcDaliPinchGestureTouchBehindGesturedSystemOverlay(void) 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; +} diff --git a/automated-tests/src/dali/utc-Dali-TapGestureDetector.cpp b/automated-tests/src/dali/utc-Dali-TapGestureDetector.cpp index 3e8293e..0e85555 100644 --- a/automated-tests/src/dali/utc-Dali-TapGestureDetector.cpp +++ b/automated-tests/src/dali/utc-Dali-TapGestureDetector.cpp @@ -1282,3 +1282,54 @@ int UtcDaliTapGestureTouchBehindGesturedSystemOverlay(void) 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; +} diff --git a/automated-tests/src/dali/utc-Dali-TouchProcessing.cpp b/automated-tests/src/dali/utc-Dali-TouchProcessing.cpp index cdbf448..0847158 100644 --- a/automated-tests/src/dali/utc-Dali-TouchProcessing.cpp +++ b/automated-tests/src/dali/utc-Dali-TouchProcessing.cpp @@ -1192,3 +1192,54 @@ int UtcDaliTouchSystemOverlayActor(void) 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; +} diff --git a/capi/dali/public-api/actors/actor.h b/capi/dali/public-api/actors/actor.h index 220f5b9..dddd842 100644 --- a/capi/dali/public-api/actors/actor.h +++ b/capi/dali/public-api/actors/actor.h @@ -99,6 +99,7 @@ typedef ActorContainer::const_iterator ActorConstIter; ///< Const iterator for D * - 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. diff --git a/capi/dali/public-api/actors/layer.h b/capi/dali/public-api/actors/layer.h index 7cb6e1f..b0fbe09 100644 --- a/capi/dali/public-api/actors/layer.h +++ b/capi/dali/public-api/actors/layer.h @@ -303,6 +303,22 @@ public: */ 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 /** diff --git a/dali/internal/event/actors/layer-impl.cpp b/dali/internal/event/actors/layer-impl.cpp index 1aed323..fbe8973 100644 --- a/dali/internal/event/actors/layer-impl.cpp +++ b/dali/internal/event/actors/layer-impl.cpp @@ -111,7 +111,8 @@ Layer::Layer( Actor::DerivedType type ) mClippingBox(0,0,0,0), mSortFunction(Dali::Layer::ZValue), mIsClipping(false), - mDepthTestDisabled(false) + mDepthTestDisabled(false), + mTouchConsumed(false) { } @@ -270,6 +271,16 @@ void Layer::SetSortFunction(Dali::Layer::SortFunctionType function) } } +void Layer::SetTouchConsumed( bool consume ) +{ + mTouchConsumed = consume; +} + +bool Layer::IsTouchConsumed() const +{ + return mTouchConsumed; +} + SceneGraph::Node* Layer::CreateNode() const { return SceneGraph::Layer::New(); diff --git a/dali/internal/event/actors/layer-impl.h b/dali/internal/event/actors/layer-impl.h index e48e296..affc8cd 100644 --- a/dali/internal/event/actors/layer-impl.h +++ b/dali/internal/event/actors/layer-impl.h @@ -160,6 +160,16 @@ public: 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. @@ -263,6 +273,7 @@ private: 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 diff --git a/dali/internal/event/events/gesture-processor.cpp b/dali/internal/event/events/gesture-processor.cpp index 297a4bd..95f798f 100644 --- a/dali/internal/event/events/gesture-processor.cpp +++ b/dali/internal/event/events/gesture-processor.cpp @@ -21,6 +21,7 @@ // INTERNAL INCLUDES #include #include +#include #include #include #include @@ -56,6 +57,11 @@ struct GestureHitTestCheck : public HitTestAlgorithm::HitTestInterface 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; }; diff --git a/dali/internal/event/events/hit-test-algorithm-impl.cpp b/dali/internal/event/events/hit-test-algorithm-impl.cpp index 49df17c..22fe563 100644 --- a/dali/internal/event/events/hit-test-algorithm-impl.cpp +++ b/dali/internal/event/events/hit-test-algorithm-impl.cpp @@ -92,6 +92,14 @@ struct HitTestFunctionWrapper : public HitTestInterface 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; }; @@ -112,6 +120,11 @@ struct ActorTouchableCheck : public HitTestInterface 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(); + } }; /** @@ -351,6 +364,7 @@ bool HitTestRenderTask( LayerList& layers, 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) @@ -375,11 +389,19 @@ bool HitTestRenderTask( LayerList& layers, // 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 ) @@ -390,6 +412,10 @@ bool HitTestRenderTask( LayerList& layers, results.actorCoordinates.y = hit.y; return true; // Success } + else if ( layerConsumesHit ) + { + return true; // Also success if layer is consuming the hit + } } } } @@ -398,9 +424,10 @@ bool HitTestRenderTask( LayerList& layers, /** * 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, @@ -432,8 +459,8 @@ void HitTestForEachRenderTask( LayerList& layers, 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 } } @@ -457,11 +484,12 @@ void HitTestForEachRenderTask( LayerList& layers, 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 @@ -474,14 +502,17 @@ void HitTest( Stage& stage, const Vector2& screenCoordinates, Dali::HitTestAlgor 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(); @@ -490,11 +521,11 @@ void HitTest( Stage& stage, const Vector2& screenCoordinates, Results& results, 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(); @@ -514,9 +545,11 @@ void HitTest( Stage& stage, RenderTask& renderTask, const Vector2& screenCoordin { 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 diff --git a/dali/internal/event/events/hit-test-algorithm-impl.h b/dali/internal/event/events/hit-test-algorithm-impl.h index 21d8da0..1225900 100644 --- a/dali/internal/event/events/hit-test-algorithm-impl.h +++ b/dali/internal/event/events/hit-test-algorithm-impl.h @@ -28,6 +28,8 @@ namespace Dali namespace Internal { +class Layer; + /** * This namespace is provided for application developers to do hit test for the actors. */ @@ -51,16 +53,34 @@ struct HitTestInterface { /** * 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; }; /** diff --git a/dali/public-api/actors/layer.cpp b/dali/public-api/actors/layer.cpp index 15cb9a0..bfaa85e 100644 --- a/dali/public-api/actors/layer.cpp +++ b/dali/public-api/actors/layer.cpp @@ -143,6 +143,16 @@ void Layer::SetSortFunction(SortFunctionType function) 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) { -- 2.7.4