Fixes findNodeAtPoint when views were inverted (#45519)

Summary:
FIxes https://github.com/facebook/react-native/issues/45502 .  cc realsoelynn

## Changelog:

[GENERAL] [FIXED] - Fixes findNodeAtPoint when views were inverted

Pull Request resolved: https://github.com/facebook/react-native/pull/45519

Test Plan: Demo in https://github.com/facebook/react-native/issues/45502 .

Reviewed By: cipolleschi

Differential Revision: D59920660

Pulled By: realsoelynn

fbshipit-source-id: 9e1075406830aa3a3ec436d70d539ca0674f8d34
This commit is contained in:
zhongwuzw
2024-08-16 01:00:07 -07:00
committed by Facebook GitHub Bot
parent e864910a4d
commit 1d1646afd1
3 changed files with 75 additions and 3 deletions
@@ -261,8 +261,9 @@ ShadowNode::Shared LayoutableShadowNode::findNodeAtPoint(
return nullptr;
}
auto transform = layoutableShadowNode->getTransform();
auto frame = layoutableShadowNode->getLayoutMetrics().frame;
auto transformedFrame = frame * layoutableShadowNode->getTransform();
auto transformedFrame = frame * transform;
auto isPointInside = transformedFrame.containsPoint(point);
if (!isPointInside) {
@@ -271,6 +272,27 @@ ShadowNode::Shared LayoutableShadowNode::findNodeAtPoint(
return node;
}
if (Transform::isVerticalInversion(transform) ||
Transform::isHorizontalInversion(transform)) {
auto centerX =
transformedFrame.origin.x + transformedFrame.size.width / 2.0;
auto centerY =
transformedFrame.origin.y + transformedFrame.size.height / 2.0;
auto relativeX = point.x - centerX;
auto relativeY = point.y - centerY;
if (Transform::isVerticalInversion(transform)) {
relativeY = -relativeY;
}
if (Transform::isHorizontalInversion(transform)) {
relativeX = -relativeX;
}
point.x = centerX + relativeX;
point.y = centerY + relativeY;
}
auto newPoint = point - transformedFrame.origin -
layoutableShadowNode->getContentOriginOffset(false);
@@ -366,3 +366,52 @@ TEST(FindNodeAtPointTest, overlappingViewsWithParentPointerEventsNone) {
EXPECT_EQ(
LayoutableShadowNode::findNodeAtPoint(parentShadowNode, {50, 50}), nullptr);
}
TEST(FindNodeAtPointTest, invertedList) {
auto builder = simpleComponentBuilder();
// clang-format off
auto element =
Element<ScrollViewShadowNode>()
.props([] {
auto sharedProps = std::make_shared<ScrollViewProps>();
sharedProps->transform = Transform::VerticalInversion();
return sharedProps;
})
.tag(1)
.finalize([](ScrollViewShadowNode &shadowNode){
auto layoutMetrics = EmptyLayoutMetrics;
layoutMetrics.frame.size = {100, 200};
shadowNode.setLayoutMetrics(layoutMetrics);
})
.children({
Element<ViewShadowNode>()
.tag(2)
.finalize([](ViewShadowNode &shadowNode){
auto layoutMetrics = EmptyLayoutMetrics;
layoutMetrics.frame.origin = {0, 0};
layoutMetrics.frame.size = {100, 100};
shadowNode.setLayoutMetrics(layoutMetrics);
}),
Element<ViewShadowNode>()
.tag(3)
.finalize([](ViewShadowNode &shadowNode){
auto layoutMetrics = EmptyLayoutMetrics;
layoutMetrics.frame.origin = {0, 100};
layoutMetrics.frame.size = {100, 100};
shadowNode.setLayoutMetrics(layoutMetrics);
})
});
// clang-format on
auto parentShadowNode = builder.build(element);
EXPECT_EQ(
LayoutableShadowNode::findNodeAtPoint(parentShadowNode, {10, 10})
->getTag(),
3);
EXPECT_EQ(
LayoutableShadowNode::findNodeAtPoint(parentShadowNode, {10, 105})
->getTag(),
2);
}
@@ -11,6 +11,7 @@
#include <glog/logging.h>
#include <react/debug/react_native_assert.h>
#include <react/utils/FloatComparison.h>
namespace facebook::react {
@@ -305,11 +306,11 @@ Transform Transform::Interpolate(
}
bool Transform::isVerticalInversion(const Transform& transform) {
return transform.at(1, 1) == -1;
return facebook::react::floatEquality(transform.at(1, 1), -1.0f);
}
bool Transform::isHorizontalInversion(const Transform& transform) {
return transform.at(0, 0) == -1;
return facebook::react::floatEquality(transform.at(0, 0), -1.0f);
}
bool Transform::operator==(const Transform& rhs) const {