[Fabric] Eliminate forks needed for onMouseEnter/Leave (#12161)

* [Fabric] Eliminate forks needed for onMouseEnter/Leave

We previously forked TouchEventEmitter and BaseViewProps to detect
onMouseEnter/onMouseLeave events. Now that there are host platform
extension points for ViewEventEmitter and ViewProps, we can move 100% of
the enter/leave event handling to host platform logic.

* Change files
This commit is contained in:
Eric Rozell 2023-09-20 16:46:19 -04:00 коммит произвёл GitHub
Родитель bb94c7d276
Коммит c62e76f330
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
14 изменённых файлов: 59 добавлений и 968 удалений

Просмотреть файл

@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "[Fabric] Eliminate forks needed for onMouseEnter/Leave",
"packageName": "react-native-windows",
"email": "erozell@outlook.com",
"dependentChangeType": "patch"
}

Просмотреть файл

@ -7,7 +7,7 @@
#include <functional/functor.h>
#include <inspectable.h>
#include <react/renderer/componentregistry/ComponentDescriptorProvider.h>
#include <react/renderer/components/view/TouchEventEmitter.h>
#include <react/renderer/components/view/ViewEventEmitter.h>
#include <react/renderer/components/view/ViewProps.h>
#include <react/renderer/core/LayoutMetrics.h>
@ -68,8 +68,8 @@ struct IComponentView {
virtual void onFocusLost() noexcept = 0;
virtual void onFocusGained() noexcept = 0;
virtual bool focusable() const noexcept = 0;
virtual facebook::react::SharedTouchEventEmitter touchEventEmitterAtPoint(facebook::react::Point pt) noexcept = 0;
virtual facebook::react::SharedTouchEventEmitter touchEventEmitter() noexcept = 0;
virtual facebook::react::SharedViewEventEmitter eventEmitterAtPoint(facebook::react::Point pt) noexcept = 0;
virtual facebook::react::SharedViewEventEmitter eventEmitter() noexcept = 0;
virtual facebook::react::Tag tag() const noexcept = 0;
// By default, hitTests according the pointerEvents prop on the Component.
// If ignorePointerEvents = true, all Components are treated as valid targets

Просмотреть файл

@ -31,6 +31,14 @@ bool IsViewListeningToEvent(IComponentView *view, facebook::react::ViewEvents::O
return false;
}
bool IsViewListeningToEvent(IComponentView *view, facebook::react::WindowsViewEvents::Offset eventType) {
if (view) {
auto const &viewProps = *std::static_pointer_cast<facebook::react::ViewProps const>(view->props());
return viewProps.windowsEvents[eventType];
}
return false;
}
bool IsAnyViewInPathListeningToEvent(
std::vector<IComponentView *> &path,
facebook::react::ViewEvents::Offset eventType) {
@ -44,7 +52,7 @@ bool IsAnyViewInPathListeningToEvent(
IComponentView *FindClosestFabricManagedTouchableView(IComponentView *componentView) {
while (componentView) {
if (componentView->touchEventEmitter()) {
if (componentView->eventEmitter()) {
return componentView;
}
componentView = componentView->parent();
@ -211,7 +219,7 @@ int64_t CompositionEventHandler::SendMessage(uint32_t msg, uint64_t wParam, int6
std::vector<IComponentView *> GetTouchableViewsInPathToRoot(IComponentView *view) {
std::vector<IComponentView *> results;
while (view) {
if (view->touchEventEmitter()) {
if (view->eventEmitter()) {
results.push_back(view);
}
view = view->parent();
@ -254,7 +262,7 @@ void CompositionEventHandler::HandleIncomingPointerEvent(
if (targetView != nullptr && previousTargetTag != targetView->tag()) {
bool shouldEmitOverEvent =
IsAnyViewInPathListeningToEvent(eventPathViews, facebook::react::ViewEvents::Offset::PointerOver);
facebook::react::SharedTouchEventEmitter eventEmitter = targetView->touchEventEmitterAtPoint(event.offsetPoint);
const auto eventEmitter = targetView->eventEmitterAtPoint(event.offsetPoint);
if (shouldEmitOverEvent && eventEmitter != nullptr) {
eventEmitter->onPointerOver(event);
}
@ -276,12 +284,12 @@ void CompositionEventHandler::HandleIncomingPointerEvent(
bool shouldEmitEvent = componentView != nullptr &&
(hasParentEnterListener ||
IsViewListeningToEvent(componentView, facebook::react::ViewEvents::Offset::PointerEnter) ||
IsViewListeningToEvent(componentView, facebook::react::ViewEvents::Offset::MouseEnter));
IsViewListeningToEvent(componentView, facebook::react::WindowsViewEvents::Offset::MouseEnter));
if (shouldEmitEvent &&
std::find(currentlyHoveredViews.begin(), currentlyHoveredViews.end(), componentView) ==
currentlyHoveredViews.end()) {
facebook::react::SharedTouchEventEmitter eventEmitter = componentView->touchEventEmitter();
const auto eventEmitter = componentView->eventEmitter();
if (eventEmitter) {
eventEmitter->onPointerEnter(event);
if (IsMousePointerEvent(event)) {
@ -302,7 +310,7 @@ void CompositionEventHandler::HandleIncomingPointerEvent(
if (previousTargetTag != -1 && previousTargetTag != (targetView ? targetView->tag() : -1)) {
bool shouldEmitOutEvent =
IsAnyViewInPathListeningToEvent(currentlyHoveredViews, facebook::react::ViewEvents::Offset::PointerOut);
facebook::react::SharedTouchEventEmitter eventEmitter = prevTargetView->touchEventEmitter();
const auto eventEmitter = prevTargetView->eventEmitter();
if (shouldEmitOutEvent && eventEmitter != nullptr) {
eventEmitter->onPointerOut(event);
}
@ -327,7 +335,7 @@ void CompositionEventHandler::HandleIncomingPointerEvent(
bool shouldEmitEvent = componentView != nullptr &&
(hasParentLeaveListener ||
IsViewListeningToEvent(componentView, facebook::react::ViewEvents::Offset::PointerLeave) ||
IsViewListeningToEvent(componentView, facebook::react::ViewEvents::Offset::MouseLeave));
IsViewListeningToEvent(componentView, facebook::react::WindowsViewEvents::Offset::MouseLeave));
if (shouldEmitEvent &&
std::find(eventPathViews.begin(), eventPathViews.end(), componentView) == eventPathViews.end()) {
@ -343,7 +351,7 @@ void CompositionEventHandler::HandleIncomingPointerEvent(
itComponentView++) { // for (UIView *componentView in [viewsToEmitLeaveEventsTo reverseObjectEnumerator]) {
auto componentView = *itComponentView;
facebook::react::SharedTouchEventEmitter eventEmitter = componentView->touchEventEmitter();
const auto eventEmitter = componentView->eventEmitter();
if (eventEmitter) {
eventEmitter->onPointerLeave(event);
if (IsMousePointerEvent(event)) {
@ -440,8 +448,7 @@ void CompositionEventHandler::MouseMove(uint32_t msg, uint64_t wParam, int64_t l
facebook::react::PointerEvent pointerEvent = CreatePointerEventFromIncompleteHoverData(ptScaled, ptLocal);
auto handler = [targetView, &pointerEvent](std::vector<IComponentView *> &eventPathViews) {
facebook::react::SharedTouchEventEmitter eventEmitter =
targetView ? targetView->touchEventEmitterAtPoint(pointerEvent.offsetPoint) : nullptr;
const auto eventEmitter = targetView ? targetView->eventEmitterAtPoint(pointerEvent.offsetPoint) : nullptr;
bool hasMoveEventListeners =
IsAnyViewInPathListeningToEvent(eventPathViews, facebook::react::ViewEvents::Offset::PointerMove) ||
IsAnyViewInPathListeningToEvent(eventPathViews, facebook::react::ViewEvents::Offset::PointerMoveCapture);
@ -506,7 +513,7 @@ void CompositionEventHandler::PointerPressed(uint32_t msg, uint64_t wParam, int6
auto componentView = targetComponentView;
while (componentView) {
if (auto eventEmitter = componentView->touchEventEmitter()) {
if (auto eventEmitter = componentView->eventEmitter()) {
activeTouch.eventEmitter = eventEmitter;
activeTouch.touch.target = componentView->tag();
// activeTouch.componentView = componentView;
@ -570,7 +577,7 @@ void CompositionEventHandler::ButtonDown(uint32_t msg, uint64_t wParam, int64_t
auto componentView = targetComponentView;
while (componentView) {
if (auto eventEmitter = componentView->touchEventEmitterAtPoint(ptLocal)) {
if (auto eventEmitter = componentView->eventEmitterAtPoint(ptLocal)) {
activeTouch.eventEmitter = eventEmitter;
activeTouch.touch.target = componentView->tag();
// activeTouch.componentView = componentView;

Просмотреть файл

@ -1275,11 +1275,11 @@ void CompositionBaseComponentView::EnsureTransformMatrixFacade() noexcept {
.StartAnimation(L"TransformMatrix", expression);
}
facebook::react::SharedTouchEventEmitter CompositionBaseComponentView::touchEventEmitter() noexcept {
facebook::react::SharedViewEventEmitter CompositionBaseComponentView::eventEmitter() noexcept {
return m_eventEmitter;
}
facebook::react::SharedTouchEventEmitter CompositionBaseComponentView::touchEventEmitterAtPoint(
facebook::react::SharedViewEventEmitter CompositionBaseComponentView::eventEmitterAtPoint(
facebook::react::Point /*pt*/) noexcept {
return m_eventEmitter;
}

Просмотреть файл

@ -38,8 +38,8 @@ struct CompositionBaseComponentView : public IComponentView,
bool focusable() const noexcept override;
std::vector<facebook::react::ComponentDescriptorProvider> supplementalComponentDescriptorProviders() noexcept
override;
facebook::react::SharedTouchEventEmitter touchEventEmitter() noexcept override;
facebook::react::SharedTouchEventEmitter touchEventEmitterAtPoint(facebook::react::Point pt) noexcept override;
facebook::react::SharedViewEventEmitter eventEmitter() noexcept override;
facebook::react::SharedViewEventEmitter eventEmitterAtPoint(facebook::react::Point pt) noexcept override;
facebook::react::Tag tag() const noexcept override;
int64_t sendMessage(uint32_t msg, uint64_t wParam, int64_t lParam) noexcept override;

Просмотреть файл

@ -133,7 +133,7 @@ facebook::react::Tag ParagraphComponentView::hitTest(
return -1;
}
facebook::react::SharedTouchEventEmitter ParagraphComponentView::touchEventEmitterAtPoint(
facebook::react::SharedViewEventEmitter ParagraphComponentView::eventEmitterAtPoint(
facebook::react::Point pt) noexcept {
if (m_attributedStringBox.getValue().getFragments().size()) {
BOOL isTrailingHit = false;
@ -145,7 +145,7 @@ facebook::react::SharedTouchEventEmitter ParagraphComponentView::touchEventEmitt
for (auto fragment : m_attributedStringBox.getValue().getFragments()) {
if (textPosition < fragment.string.length()) {
return std::static_pointer_cast<const facebook::react::TouchEventEmitter>(
return std::static_pointer_cast<const facebook::react::ViewEventEmitter>(
fragment.parentShadowView.eventEmitter);
}
textPosition -= static_cast<uint32_t>(fragment.string.length());

Просмотреть файл

@ -39,7 +39,7 @@ struct ParagraphComponentView : CompositionBaseComponentView {
facebook::react::Tag hitTest(facebook::react::Point pt, facebook::react::Point &localPt, bool ignorePointerEvents)
const noexcept override;
void OnRenderingDeviceLost() noexcept override;
facebook::react::SharedTouchEventEmitter touchEventEmitterAtPoint(facebook::react::Point pt) noexcept override;
facebook::react::SharedViewEventEmitter eventEmitterAtPoint(facebook::react::Point pt) noexcept override;
winrt::Microsoft::ReactNative::Composition::IVisual Visual() const noexcept override;
virtual std::string DefaultControlType() const noexcept override;

Просмотреть файл

@ -36,6 +36,24 @@ void HostPlatformViewEventEmitter::onBlur() const {
dispatchEvent("blur");
}
#pragma mark - Mouse Events
void HostPlatformViewEventEmitter::onMouseEnter(PointerEvent const &pointerEvent) const {
dispatchEvent(
"mouseEnter",
std::make_shared<PointerEvent>(pointerEvent),
EventPriority::AsynchronousBatched,
RawEvent::Category::ContinuousStart);
}
void HostPlatformViewEventEmitter::onMouseLeave(PointerEvent const &pointerEvent) const {
dispatchEvent(
"mouseLeave",
std::make_shared<PointerEvent>(pointerEvent),
EventPriority::AsynchronousBatched,
RawEvent::Category::ContinuousStart);
}
} // namespace facebook::react
// @generated SignedSource<<a6f36c63efa0edf80beb29b0187deb77>>

Просмотреть файл

@ -21,6 +21,11 @@ class HostPlatformViewEventEmitter : public BaseViewEventEmitter {
void onFocus() const;
void onBlur() const;
#pragma mark - Mouse Events
void onMouseEnter(PointerEvent const &pointerEvent) const;
void onMouseLeave(PointerEvent const &pointerEvent) const;
};
} // namespace facebook::react

Просмотреть файл

@ -1,368 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "BaseViewProps.h"
#include <algorithm>
#include <react/renderer/components/view/conversions.h>
#include <react/renderer/components/view/propsConversions.h>
#include <react/renderer/core/graphicsConversions.h>
#include <react/renderer/core/propsConversions.h>
#include <react/renderer/debug/debugStringConvertibleUtils.h>
#include <react/utils/CoreFeatures.h>
namespace facebook::react {
BaseViewProps::BaseViewProps(
const PropsParserContext &context,
BaseViewProps const &sourceProps,
RawProps const &rawProps,
bool shouldSetRawProps)
: YogaStylableProps(context, sourceProps, rawProps, shouldSetRawProps),
AccessibilityProps(context, sourceProps, rawProps),
opacity(
CoreFeatures::enablePropIteratorSetter ? sourceProps.opacity
: convertRawProp(
context,
rawProps,
"opacity",
sourceProps.opacity,
(Float)1.0)),
backgroundColor(
CoreFeatures::enablePropIteratorSetter
? sourceProps.backgroundColor
: convertRawProp(
context,
rawProps,
"backgroundColor",
sourceProps.backgroundColor,
{})),
borderRadii(
CoreFeatures::enablePropIteratorSetter ? sourceProps.borderRadii
: convertRawProp(
context,
rawProps,
"border",
"Radius",
sourceProps.borderRadii,
{})),
borderColors(
CoreFeatures::enablePropIteratorSetter ? sourceProps.borderColors
: convertRawProp(
context,
rawProps,
"border",
"Color",
sourceProps.borderColors,
{})),
borderCurves(
CoreFeatures::enablePropIteratorSetter ? sourceProps.borderCurves
: convertRawProp(
context,
rawProps,
"border",
"Curve",
sourceProps.borderCurves,
{})),
borderStyles(
CoreFeatures::enablePropIteratorSetter ? sourceProps.borderStyles
: convertRawProp(
context,
rawProps,
"border",
"Style",
sourceProps.borderStyles,
{})),
shadowColor(
CoreFeatures::enablePropIteratorSetter ? sourceProps.shadowColor
: convertRawProp(
context,
rawProps,
"shadowColor",
sourceProps.shadowColor,
{})),
shadowOffset(
CoreFeatures::enablePropIteratorSetter ? sourceProps.shadowOffset
: convertRawProp(
context,
rawProps,
"shadowOffset",
sourceProps.shadowOffset,
{})),
shadowOpacity(
CoreFeatures::enablePropIteratorSetter
? sourceProps.shadowOpacity
: convertRawProp(
context,
rawProps,
"shadowOpacity",
sourceProps.shadowOpacity,
{})),
shadowRadius(
CoreFeatures::enablePropIteratorSetter ? sourceProps.shadowRadius
: convertRawProp(
context,
rawProps,
"shadowRadius",
sourceProps.shadowRadius,
{})),
transform(
CoreFeatures::enablePropIteratorSetter ? sourceProps.transform
: convertRawProp(
context,
rawProps,
"transform",
sourceProps.transform,
{})),
backfaceVisibility(
CoreFeatures::enablePropIteratorSetter
? sourceProps.backfaceVisibility
: convertRawProp(
context,
rawProps,
"backfaceVisibility",
sourceProps.backfaceVisibility,
{})),
shouldRasterize(
CoreFeatures::enablePropIteratorSetter
? sourceProps.shouldRasterize
: convertRawProp(
context,
rawProps,
"shouldRasterize",
sourceProps.shouldRasterize,
{})),
zIndex(
CoreFeatures::enablePropIteratorSetter ? sourceProps.zIndex
: convertRawProp(
context,
rawProps,
"zIndex",
sourceProps.zIndex,
{})),
pointerEvents(
CoreFeatures::enablePropIteratorSetter
? sourceProps.pointerEvents
: convertRawProp(
context,
rawProps,
"pointerEvents",
sourceProps.pointerEvents,
{})),
hitSlop(
CoreFeatures::enablePropIteratorSetter ? sourceProps.hitSlop
: convertRawProp(
context,
rawProps,
"hitSlop",
sourceProps.hitSlop,
{})),
onLayout(
CoreFeatures::enablePropIteratorSetter ? sourceProps.onLayout
: convertRawProp(
context,
rawProps,
"onLayout",
sourceProps.onLayout,
{})),
events(
CoreFeatures::enablePropIteratorSetter
? sourceProps.events
: convertRawProp(context, rawProps, sourceProps.events, {})),
collapsable(
CoreFeatures::enablePropIteratorSetter ? sourceProps.collapsable
: convertRawProp(
context,
rawProps,
"collapsable",
sourceProps.collapsable,
true)),
removeClippedSubviews(
CoreFeatures::enablePropIteratorSetter
? sourceProps.removeClippedSubviews
: convertRawProp(
context,
rawProps,
"removeClippedSubviews",
sourceProps.removeClippedSubviews,
false)){}
#define VIEW_EVENT_CASE(eventType) \
case CONSTEXPR_RAW_PROPS_KEY_HASH("on" #eventType): { \
const auto offset = ViewEvents::Offset::eventType; \
ViewEvents defaultViewEvents{}; \
bool res = defaultViewEvents[offset]; \
if (value.hasValue()) { \
fromRawValue(context, value, res); \
} \
events[offset] = res; \
return; \
}
void BaseViewProps::setProp(
const PropsParserContext &context,
RawPropsPropNameHash hash,
const char *propName,
RawValue const &value) {
// All Props structs setProp methods must always, unconditionally,
// call all super::setProp methods, since multiple structs may
// reuse the same values.
YogaStylableProps::setProp(context, hash, propName, value);
AccessibilityProps::setProp(context, hash, propName, value);
static auto defaults = BaseViewProps{};
switch (hash) {
RAW_SET_PROP_SWITCH_CASE_BASIC(opacity);
RAW_SET_PROP_SWITCH_CASE_BASIC(backgroundColor);
RAW_SET_PROP_SWITCH_CASE_BASIC(shadowColor);
RAW_SET_PROP_SWITCH_CASE_BASIC(shadowOffset);
RAW_SET_PROP_SWITCH_CASE_BASIC(shadowOpacity);
RAW_SET_PROP_SWITCH_CASE_BASIC(shadowRadius);
RAW_SET_PROP_SWITCH_CASE_BASIC(transform);
RAW_SET_PROP_SWITCH_CASE_BASIC(backfaceVisibility);
RAW_SET_PROP_SWITCH_CASE_BASIC(shouldRasterize);
RAW_SET_PROP_SWITCH_CASE_BASIC(zIndex);
RAW_SET_PROP_SWITCH_CASE_BASIC(pointerEvents);
RAW_SET_PROP_SWITCH_CASE_BASIC(hitSlop);
RAW_SET_PROP_SWITCH_CASE_BASIC(onLayout);
RAW_SET_PROP_SWITCH_CASE_BASIC(collapsable);
RAW_SET_PROP_SWITCH_CASE_BASIC(removeClippedSubviews);
RAW_SET_PROP_SWITCH_CASE_BASIC(experimental_layoutConformance);
// events field
VIEW_EVENT_CASE(PointerEnter);
VIEW_EVENT_CASE(PointerEnterCapture);
VIEW_EVENT_CASE(PointerMove);
VIEW_EVENT_CASE(PointerMoveCapture);
VIEW_EVENT_CASE(PointerLeave);
VIEW_EVENT_CASE(PointerLeaveCapture);
VIEW_EVENT_CASE(PointerOver);
VIEW_EVENT_CASE(PointerOut);
VIEW_EVENT_CASE(MoveShouldSetResponder);
VIEW_EVENT_CASE(MoveShouldSetResponderCapture);
VIEW_EVENT_CASE(StartShouldSetResponder);
VIEW_EVENT_CASE(StartShouldSetResponderCapture);
VIEW_EVENT_CASE(ResponderGrant);
VIEW_EVENT_CASE(ResponderReject);
VIEW_EVENT_CASE(ResponderStart);
VIEW_EVENT_CASE(ResponderEnd);
VIEW_EVENT_CASE(ResponderRelease);
VIEW_EVENT_CASE(ResponderMove);
VIEW_EVENT_CASE(ResponderTerminate);
VIEW_EVENT_CASE(ResponderTerminationRequest);
VIEW_EVENT_CASE(ShouldBlockNativeResponder);
VIEW_EVENT_CASE(TouchStart);
VIEW_EVENT_CASE(TouchMove);
VIEW_EVENT_CASE(TouchEnd);
VIEW_EVENT_CASE(TouchCancel);
VIEW_EVENT_CASE(MouseEnter); // [Windows]
VIEW_EVENT_CASE(MouseLeave); // [Windows]
// BorderRadii
SET_CASCADED_RECTANGLE_CORNERS(borderRadii, "border", "Radius", value);
SET_CASCADED_RECTANGLE_EDGES(borderColors, "border", "Color", value);
SET_CASCADED_RECTANGLE_EDGES(borderStyles, "border", "Style", value);
}
}
#pragma mark - Convenience Methods
static BorderRadii ensureNoOverlap(BorderRadii const &radii, Size const &size) {
// "Corner curves must not overlap: When the sum of any two adjacent border
// radii exceeds the size of the border box, UAs must proportionally reduce
// the used values of all border radii until none of them overlap."
// Source: https://www.w3.org/TR/css-backgrounds-3/#corner-overlap
auto insets = EdgeInsets{
/* .left = */ radii.topLeft + radii.bottomLeft,
/* .top = */ radii.topLeft + radii.topRight,
/* .right = */ radii.topRight + radii.bottomRight,
/* .bottom = */ radii.bottomLeft + radii.bottomRight,
};
auto insetsScale = EdgeInsets{
/* .left = */
insets.left > 0 ? std::min((Float)1.0, size.height / insets.left) : 0,
/* .top = */
insets.top > 0 ? std::min((Float)1.0, size.width / insets.top) : 0,
/* .right = */
insets.right > 0 ? std::min((Float)1.0, size.height / insets.right) : 0,
/* .bottom = */
insets.bottom > 0 ? std::min((Float)1.0, size.width / insets.bottom) : 0,
};
return BorderRadii{
/* topLeft = */
radii.topLeft * std::min(insetsScale.top, insetsScale.left),
/* topRight = */
radii.topRight * std::min(insetsScale.top, insetsScale.right),
/* bottomLeft = */
radii.bottomLeft * std::min(insetsScale.bottom, insetsScale.left),
/* bottomRight = */
radii.bottomRight * std::min(insetsScale.bottom, insetsScale.right),
};
}
BorderMetrics BaseViewProps::resolveBorderMetrics(
LayoutMetrics const &layoutMetrics) const {
auto isRTL =
bool{layoutMetrics.layoutDirection == LayoutDirection::RightToLeft};
auto borderWidths = CascadedBorderWidths{
/* .left = */ optionalFloatFromYogaValue(yogaStyle.border()[YGEdgeLeft]),
/* .top = */ optionalFloatFromYogaValue(yogaStyle.border()[YGEdgeTop]),
/* .right = */
optionalFloatFromYogaValue(yogaStyle.border()[YGEdgeRight]),
/* .bottom = */
optionalFloatFromYogaValue(yogaStyle.border()[YGEdgeBottom]),
/* .start = */
optionalFloatFromYogaValue(yogaStyle.border()[YGEdgeStart]),
/* .end = */ optionalFloatFromYogaValue(yogaStyle.border()[YGEdgeEnd]),
/* .horizontal = */
optionalFloatFromYogaValue(yogaStyle.border()[YGEdgeHorizontal]),
/* .vertical = */
optionalFloatFromYogaValue(yogaStyle.border()[YGEdgeVertical]),
/* .all = */ optionalFloatFromYogaValue(yogaStyle.border()[YGEdgeAll]),
};
return {
/* .borderColors = */ borderColors.resolve(isRTL, {}),
/* .borderWidths = */ borderWidths.resolve(isRTL, 0),
/* .borderRadii = */
ensureNoOverlap(borderRadii.resolve(isRTL, 0), layoutMetrics.frame.size),
/* .borderCurves = */ borderCurves.resolve(isRTL, BorderCurve::Circular),
/* .borderStyles = */ borderStyles.resolve(isRTL, BorderStyle::Solid),
};
}
bool BaseViewProps::getClipsContentToBounds() const {
return yogaStyle.overflow() != YGOverflowVisible;
}
#pragma mark - DebugStringConvertible
#if RN_DEBUG_STRING_CONVERTIBLE
SharedDebugStringConvertibleList BaseViewProps::getDebugProps() const {
const auto &defaultBaseViewProps = BaseViewProps();
return AccessibilityProps::getDebugProps() +
YogaStylableProps::getDebugProps() +
SharedDebugStringConvertibleList{
debugStringConvertibleItem(
"opacity", opacity, defaultBaseViewProps.opacity),
debugStringConvertibleItem(
"backgroundColor",
backgroundColor,
defaultBaseViewProps.backgroundColor),
debugStringConvertibleItem(
"zIndex", zIndex, defaultBaseViewProps.zIndex.value_or(0)),
};
}
#endif
} // namespace facebook::react

Просмотреть файл

@ -1,204 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "TouchEventEmitter.h"
namespace facebook::react {
#pragma mark - Touches
static jsi::Value touchesPayload(
jsi::Runtime &runtime,
Touches const &touches) {
auto array = jsi::Array(runtime, touches.size());
int i = 0;
for (auto const &touch : touches) {
auto object = jsi::Object(runtime);
setTouchPayloadOnObject(object, runtime, touch);
array.setValueAtIndex(runtime, i++, object);
}
return array;
}
static jsi::Value touchEventPayload(
jsi::Runtime &runtime,
TouchEvent const &event) {
auto object = jsi::Object(runtime);
object.setProperty(
runtime, "touches", touchesPayload(runtime, event.touches));
object.setProperty(
runtime, "changedTouches", touchesPayload(runtime, event.changedTouches));
object.setProperty(
runtime, "targetTouches", touchesPayload(runtime, event.targetTouches));
if (!event.changedTouches.empty()) {
auto const &firstChangedTouch = *event.changedTouches.begin();
setTouchPayloadOnObject(object, runtime, firstChangedTouch);
}
return object;
}
void TouchEventEmitter::dispatchTouchEvent(
std::string type,
TouchEvent const &event,
EventPriority priority,
RawEvent::Category category) const {
dispatchEvent(
std::move(type),
[event](jsi::Runtime &runtime) {
return touchEventPayload(runtime, event);
},
priority,
category);
}
void TouchEventEmitter::dispatchPointerEvent(
std::string type,
PointerEvent const &event,
EventPriority priority,
RawEvent::Category category) const {
dispatchEvent(
std::move(type),
std::make_shared<PointerEvent>(event),
priority,
category);
}
void TouchEventEmitter::onTouchStart(TouchEvent const &event) const {
dispatchTouchEvent(
"touchStart",
event,
EventPriority::AsynchronousBatched,
RawEvent::Category::ContinuousStart);
}
void TouchEventEmitter::onTouchMove(TouchEvent const &event) const {
dispatchUniqueEvent("touchMove", [event](jsi::Runtime &runtime) {
return touchEventPayload(runtime, event);
});
}
void TouchEventEmitter::onTouchEnd(TouchEvent const &event) const {
dispatchTouchEvent(
"touchEnd",
event,
EventPriority::AsynchronousBatched,
RawEvent::Category::ContinuousEnd);
}
void TouchEventEmitter::onTouchCancel(TouchEvent const &event) const {
dispatchTouchEvent(
"touchCancel",
event,
EventPriority::AsynchronousBatched,
RawEvent::Category::ContinuousEnd);
}
void TouchEventEmitter::onClick(const PointerEvent &event) const {
dispatchPointerEvent(
"click",
event,
EventPriority::AsynchronousBatched,
RawEvent::Category::Discrete);
}
void TouchEventEmitter::onPointerCancel(const PointerEvent &event) const {
dispatchPointerEvent(
"pointerCancel",
event,
EventPriority::AsynchronousBatched,
RawEvent::Category::ContinuousEnd);
}
void TouchEventEmitter::onPointerDown(const PointerEvent &event) const {
dispatchPointerEvent(
"pointerDown",
event,
EventPriority::AsynchronousBatched,
RawEvent::Category::ContinuousStart);
}
void TouchEventEmitter::onPointerMove(const PointerEvent &event) const {
dispatchUniqueEvent("pointerMove", std::make_shared<PointerEvent>(event));
}
void TouchEventEmitter::onPointerUp(const PointerEvent &event) const {
dispatchPointerEvent(
"pointerUp",
event,
EventPriority::AsynchronousBatched,
RawEvent::Category::ContinuousEnd);
}
void TouchEventEmitter::onPointerEnter(const PointerEvent &event) const {
dispatchPointerEvent(
"pointerEnter",
event,
EventPriority::AsynchronousBatched,
RawEvent::Category::ContinuousStart);
}
void TouchEventEmitter::onPointerLeave(const PointerEvent &event) const {
dispatchPointerEvent(
"pointerLeave",
event,
EventPriority::AsynchronousBatched,
RawEvent::Category::ContinuousEnd);
}
void TouchEventEmitter::onPointerOver(const PointerEvent &event) const {
dispatchPointerEvent(
"pointerOver",
event,
EventPriority::AsynchronousBatched,
RawEvent::Category::ContinuousStart);
}
void TouchEventEmitter::onPointerOut(const PointerEvent &event) const {
dispatchPointerEvent(
"pointerOut",
event,
EventPriority::AsynchronousBatched,
RawEvent::Category::ContinuousStart);
}
void TouchEventEmitter::onGotPointerCapture(const PointerEvent &event) const {
dispatchPointerEvent(
"gotPointerCapture",
event,
EventPriority::AsynchronousBatched,
RawEvent::Category::ContinuousStart);
}
void TouchEventEmitter::onLostPointerCapture(const PointerEvent &event) const {
dispatchPointerEvent(
"lostPointerCapture",
event,
EventPriority::AsynchronousBatched,
RawEvent::Category::ContinuousEnd);
}
// [Windows
void TouchEventEmitter::onMouseEnter(PointerEvent const &event) const {
dispatchPointerEvent(
"mouseEnter",
event,
EventPriority::AsynchronousBatched,
RawEvent::Category::ContinuousStart);
}
void TouchEventEmitter::onMouseLeave(PointerEvent const &event) const {
dispatchPointerEvent(
"mouseLeave",
event,
EventPriority::AsynchronousBatched,
RawEvent::Category::ContinuousStart);
}
// Windows]
} // namespace facebook::react

Просмотреть файл

@ -1,60 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <react/renderer/components/view/PointerEvent.h>
#include <react/renderer/components/view/TouchEvent.h>
#include <react/renderer/core/EventEmitter.h>
#include <react/renderer/core/LayoutMetrics.h>
#include <react/renderer/core/ReactPrimitives.h>
#include <react/renderer/debug/DebugStringConvertible.h>
namespace facebook::react {
class TouchEventEmitter;
using SharedTouchEventEmitter = std::shared_ptr<TouchEventEmitter const>;
class TouchEventEmitter : public EventEmitter {
public:
using EventEmitter::EventEmitter;
void onTouchStart(TouchEvent const &event) const;
void onTouchMove(TouchEvent const &event) const;
void onTouchEnd(TouchEvent const &event) const;
void onTouchCancel(TouchEvent const &event) const;
void onClick(PointerEvent const &event) const;
void onPointerCancel(PointerEvent const &event) const;
void onPointerDown(PointerEvent const &event) const;
void onPointerMove(PointerEvent const &event) const;
void onPointerUp(PointerEvent const &event) const;
void onPointerEnter(PointerEvent const &event) const;
void onPointerLeave(PointerEvent const &event) const;
void onPointerOver(PointerEvent const &event) const;
void onPointerOut(PointerEvent const &event) const;
void onGotPointerCapture(PointerEvent const &event) const;
void onLostPointerCapture(PointerEvent const &event) const;
void onMouseEnter(PointerEvent const &event) const; // [Windows]
void onMouseLeave(PointerEvent const &event) const; // [Windows]
private:
void dispatchTouchEvent(
std::string type,
TouchEvent const &event,
EventPriority priority,
RawEvent::Category category) const;
void dispatchPointerEvent(
std::string type,
PointerEvent const &event,
EventPriority priority,
RawEvent::Category category) const;
};
} // namespace facebook::react

Просмотреть файл

@ -1,290 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <react/renderer/graphics/Color.h>
#include <react/renderer/graphics/RectangleCorners.h>
#include <react/renderer/graphics/RectangleEdges.h>
#include <array>
#include <bitset>
#include <cmath>
#include <optional>
namespace facebook::react {
enum class PointerEventsMode : uint8_t { Auto, None, BoxNone, BoxOnly };
struct ViewEvents {
std::bitset<64> bits{};
enum class Offset : std::size_t {
// Pointer events
PointerEnter = 0,
PointerMove = 1,
PointerLeave = 2,
// PanResponder callbacks
MoveShouldSetResponder = 3,
MoveShouldSetResponderCapture = 4,
StartShouldSetResponder = 5,
StartShouldSetResponderCapture = 6,
ResponderGrant = 7,
ResponderReject = 8,
ResponderStart = 9,
ResponderEnd = 10,
ResponderRelease = 11,
ResponderMove = 12,
ResponderTerminate = 13,
ResponderTerminationRequest = 14,
ShouldBlockNativeResponder = 15,
// Touch events
TouchStart = 16,
TouchMove = 17,
TouchEnd = 18,
TouchCancel = 19,
// W3C Pointer Events
PointerEnterCapture = 23,
PointerLeaveCapture = 24,
PointerMoveCapture = 25,
PointerOver = 26,
PointerOut = 27,
PointerOverCapture = 28,
PointerOutCapture = 29,
Click = 30,
ClickCapture = 31,
GotPointerCapture = 32,
LostPointerCapture = 33,
PointerDown = 34,
PointerDownCapture = 35,
PointerUp = 36,
PointerUpCapture = 37,
MouseEnter = 30, // Windows
MouseLeave = 31, // Windows
};
constexpr bool operator[](const Offset offset) const {
return bits[static_cast<std::size_t>(offset)];
}
std::bitset<64>::reference operator[](const Offset offset) {
return bits[static_cast<std::size_t>(offset)];
}
};
inline static bool operator==(ViewEvents const &lhs, ViewEvents const &rhs) {
return lhs.bits == rhs.bits;
}
inline static bool operator!=(ViewEvents const &lhs, ViewEvents const &rhs) {
return lhs.bits != rhs.bits;
}
enum class BackfaceVisibility : uint8_t { Auto, Visible, Hidden };
enum class BorderCurve : uint8_t { Circular, Continuous };
enum class BorderStyle : uint8_t { Solid, Dotted, Dashed };
enum class LayoutConformance : uint8_t { Undefined, Classic, Strict };
template <typename T>
struct CascadedRectangleEdges {
using Counterpart = RectangleEdges<T>;
using OptionalT = std::optional<T>;
OptionalT left{};
OptionalT top{};
OptionalT right{};
OptionalT bottom{};
OptionalT start{};
OptionalT end{};
OptionalT horizontal{};
OptionalT vertical{};
OptionalT all{};
OptionalT block{};
OptionalT blockStart{};
OptionalT blockEnd{};
Counterpart resolve(bool isRTL, T defaults) const {
const auto leadingEdge = isRTL ? end : start;
const auto trailingEdge = isRTL ? start : end;
const auto horizontalOrAllOrDefault =
horizontal.value_or(all.value_or(defaults));
const auto verticalOrAllOrDefault =
vertical.value_or(all.value_or(defaults));
return {
/* .left = */
left.value_or(leadingEdge.value_or(horizontalOrAllOrDefault)),
/* .top = */
blockStart.value_or(
block.value_or(top.value_or(verticalOrAllOrDefault))),
/* .right = */
right.value_or(trailingEdge.value_or(horizontalOrAllOrDefault)),
/* .bottom = */
blockEnd.value_or(
block.value_or(bottom.value_or(verticalOrAllOrDefault))),
};
}
bool operator==(const CascadedRectangleEdges<T> &rhs) const {
return std::tie(
this->left,
this->top,
this->right,
this->bottom,
this->start,
this->end,
this->horizontal,
this->vertical,
this->all,
this->block,
this->blockStart,
this->blockEnd) ==
std::tie(
rhs.left,
rhs.top,
rhs.right,
rhs.bottom,
rhs.start,
rhs.end,
rhs.horizontal,
rhs.vertical,
rhs.all,
rhs.block,
rhs.blockStart,
rhs.blockEnd);
}
bool operator!=(const CascadedRectangleEdges<T> &rhs) const {
return !(*this == rhs);
}
};
template <typename T>
struct CascadedRectangleCorners {
using Counterpart = RectangleCorners<T>;
using OptionalT = std::optional<T>;
OptionalT topLeft{};
OptionalT topRight{};
OptionalT bottomLeft{};
OptionalT bottomRight{};
OptionalT topStart{};
OptionalT topEnd{};
OptionalT bottomStart{};
OptionalT bottomEnd{};
OptionalT all{};
OptionalT endEnd{};
OptionalT endStart{};
OptionalT startEnd{};
OptionalT startStart{};
Counterpart resolve(bool isRTL, T defaults) const {
const auto logicalTopStart = topStart ? topStart : startStart;
const auto logicalTopEnd = topEnd ? topEnd : startEnd;
const auto logicalBottomStart = bottomStart ? bottomStart : endStart;
const auto logicalBottomEnd = bottomEnd ? bottomEnd : endEnd;
const auto topLeading = isRTL ? logicalTopEnd : logicalTopStart;
const auto topTrailing = isRTL ? logicalTopStart : logicalTopEnd;
const auto bottomLeading = isRTL ? logicalBottomEnd : logicalBottomStart;
const auto bottomTrailing = isRTL ? logicalBottomStart : logicalBottomEnd;
return {
/* .topLeft = */ topLeft.value_or(
topLeading.value_or(all.value_or(defaults))),
/* .topRight = */
topRight.value_or(topTrailing.value_or(all.value_or(defaults))),
/* .bottomLeft = */
bottomLeft.value_or(bottomLeading.value_or(all.value_or(defaults))),
/* .bottomRight = */
bottomRight.value_or(bottomTrailing.value_or(all.value_or(defaults))),
};
}
bool operator==(const CascadedRectangleCorners<T> &rhs) const {
return std::tie(
this->topLeft,
this->topRight,
this->bottomLeft,
this->bottomRight,
this->topStart,
this->topEnd,
this->bottomStart,
this->bottomEnd,
this->all,
this->endEnd,
this->endStart,
this->startEnd,
this->startStart) ==
std::tie(
rhs.topLeft,
rhs.topRight,
rhs.bottomLeft,
rhs.bottomRight,
rhs.topStart,
rhs.topEnd,
rhs.bottomStart,
rhs.bottomEnd,
rhs.all,
rhs.endEnd,
rhs.endStart,
rhs.startEnd,
rhs.startStart);
}
bool operator!=(const CascadedRectangleCorners<T> &rhs) const {
return !(*this == rhs);
}
};
using BorderWidths = RectangleEdges<Float>;
using BorderCurves = RectangleCorners<BorderCurve>;
using BorderStyles = RectangleEdges<BorderStyle>;
using BorderColors = RectangleEdges<SharedColor>;
using BorderRadii = RectangleCorners<Float>;
using CascadedBorderWidths = CascadedRectangleEdges<Float>;
using CascadedBorderCurves = CascadedRectangleCorners<BorderCurve>;
using CascadedBorderStyles = CascadedRectangleEdges<BorderStyle>;
using CascadedBorderColors = CascadedRectangleEdges<SharedColor>;
using CascadedBorderRadii = CascadedRectangleCorners<Float>;
struct BorderMetrics {
BorderColors borderColors{};
BorderWidths borderWidths{};
BorderRadii borderRadii{};
BorderCurves borderCurves{};
BorderStyles borderStyles{};
bool operator==(const BorderMetrics &rhs) const {
return std::tie(
this->borderColors,
this->borderWidths,
this->borderRadii,
this->borderCurves,
this->borderStyles) ==
std::tie(
rhs.borderColors,
rhs.borderWidths,
rhs.borderRadii,
rhs.borderCurves,
rhs.borderStyles);
}
bool operator!=(const BorderMetrics &rhs) const {
return !(*this == rhs);
}
};
} // namespace facebook::react

Просмотреть файл

@ -73,30 +73,6 @@
"baseHash": "c0335b67345452991d3356ffe83808434d290724",
"issue": 7821
},
{
"type": "derived",
"file": "ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/view/BaseViewProps.cpp",
"baseFile": "packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp",
"baseHash": "a9be2d4068cb18a94b8ee8f289afae6695a2f35e"
},
{
"type": "derived",
"file": "ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/view/primitives.h",
"baseFile": "packages/react-native/ReactCommon/react/renderer/components/view/primitives.h",
"baseHash": "ad53fd4887145b0b804d730fd6cd8731b029419d"
},
{
"type": "derived",
"file": "ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/view/TouchEventEmitter.cpp",
"baseFile": "packages/react-native/ReactCommon/react/renderer/components/view/TouchEventEmitter.cpp",
"baseHash": "76ca148d4715dd053ffb0279782c472e8dcc0ba9"
},
{
"type": "derived",
"file": "ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/view/TouchEventEmitter.h",
"baseFile": "packages/react-native/ReactCommon/react/renderer/components/view/TouchEventEmitter.h",
"baseHash": "a76c1bf4ee03ffa180990c86d31af2c3d9d08d62"
},
{
"type": "patch",
"file": "ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/view/YogaLayoutableShadowNode.cpp",