mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
fix[LayoutableShadowNode::findNodeAtPoint]: consider layoutMetrics.overflowInset (#49701)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/49701 # Changelog: [General] [Fixed] - findNodeAtPoint now considers overflow area of the parent node This may happen when the child overflows the parent without resizing it. For example, when child has `position: 'absolute'` and absolute coordinates. See - https://fb.workplace.com/groups/rn.debugger.feedback/posts/1075015864052657/ - https://fb.workplace.com/groups/rn.debugger.feedback/permalink/1180445730176336/ - https://fb.workplace.com/groups/ford.eng.discussions/permalink/1961390260971262/ for more context Reviewed By: NickGerleman Differential Revision: D63328182 fbshipit-source-id: 9d5ed3ec8d88d8d65455aa3664588dc7d7273888
This commit is contained in:
committed by
Facebook GitHub Bot
parent
b95424d159
commit
d8bc7c68c0
@@ -261,15 +261,22 @@ ShadowNode::Shared LayoutableShadowNode::findNodeAtPoint(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto layoutMetrics = layoutableShadowNode->getLayoutMetrics();
|
||||
auto transform = layoutableShadowNode->getTransform();
|
||||
auto frame = layoutableShadowNode->getLayoutMetrics().frame;
|
||||
auto transformedFrame = frame * transform;
|
||||
auto transformedFrame = layoutMetrics.frame * transform;
|
||||
auto isPointInside = transformedFrame.containsPoint(point);
|
||||
|
||||
if (!isPointInside) {
|
||||
return nullptr;
|
||||
} else if (!layoutableShadowNode->canChildrenBeTouchTarget()) {
|
||||
if (isPointInside && !layoutableShadowNode->canChildrenBeTouchTarget()) {
|
||||
return node;
|
||||
} else if (!isPointInside) {
|
||||
auto overflowFrame =
|
||||
insetBy(layoutMetrics.frame, layoutMetrics.overflowInset);
|
||||
auto transformedOverflowFrame = overflowFrame * transform;
|
||||
// If child overflows parent, the touch may be intercepted by the child
|
||||
// only, so we should continue recursing.
|
||||
if (!transformedOverflowFrame.containsPoint(point)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (Transform::isVerticalInversion(transform) ||
|
||||
|
||||
@@ -415,3 +415,37 @@ TEST(FindNodeAtPointTest, invertedList) {
|
||||
->getTag(),
|
||||
2);
|
||||
}
|
||||
|
||||
TEST(FindNodeAtPointTest, considersOverflowAreaOfTheParent) {
|
||||
auto builder = simpleComponentBuilder();
|
||||
|
||||
auto element =
|
||||
Element<ViewShadowNode>()
|
||||
.tag(1)
|
||||
.finalize([](ViewShadowNode& shadowNode) {
|
||||
auto layoutMetrics = EmptyLayoutMetrics;
|
||||
layoutMetrics.frame.size = {100, 100};
|
||||
shadowNode.setLayoutMetrics(layoutMetrics);
|
||||
})
|
||||
.children({Element<ViewShadowNode>()
|
||||
.tag(2)
|
||||
.finalize([](ViewShadowNode& shadowNode) {
|
||||
auto layoutMetrics = EmptyLayoutMetrics;
|
||||
layoutMetrics.frame.size = {100, 0};
|
||||
layoutMetrics.overflowInset = {0, 0, 0, -100};
|
||||
|
||||
shadowNode.setLayoutMetrics(layoutMetrics);
|
||||
})
|
||||
.children({Element<ViewShadowNode>().tag(3).finalize(
|
||||
[](ViewShadowNode& shadowNode) {
|
||||
auto layoutMetrics = EmptyLayoutMetrics;
|
||||
layoutMetrics.frame.size = {100, 100};
|
||||
shadowNode.setLayoutMetrics(layoutMetrics);
|
||||
})})});
|
||||
|
||||
auto parentShadowNode = builder.build(element);
|
||||
EXPECT_EQ(
|
||||
LayoutableShadowNode::findNodeAtPoint(parentShadowNode, {1, 99})
|
||||
->getTag(),
|
||||
3);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user