Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import com.facebook.common.logging.FLog;
import com.facebook.infer.annotation.Assertions;
import com.facebook.react.common.ReactConstants;
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags;
import com.facebook.react.uimanager.TouchTargetHelper.ViewTarget;
import com.facebook.react.uimanager.events.EventDispatcher;
import com.facebook.react.uimanager.events.PointerEvent;
Expand Down Expand Up @@ -133,9 +134,17 @@ private void onUp(
boolean listeningForUp =
isAnyoneListeningForBubblingEvent(activeHitPath, EVENT.UP, EVENT.UP_CAPTURE);
if (listeningForUp) {
List<Integer> activeHitPathViewIds =
ReactNativeFeatureFlags.cxxNativeAnimatedEnabled()
? eventState.getHitPathViewIdsForActivePointer()
: null;
eventDispatcher.dispatchEvent(
PointerEvent.obtain(
PointerEventHelper.POINTER_UP, activeTargetTag, eventState, motionEvent));
PointerEventHelper.POINTER_UP,
activeTargetTag,
eventState,
motionEvent,
activeHitPathViewIds));
}

boolean supportsHover = mHoveringPointerIds.contains(activePointerId);
Expand Down Expand Up @@ -230,9 +239,17 @@ private void onDown(
boolean listeningForDown =
isAnyoneListeningForBubblingEvent(activeHitPath, EVENT.DOWN, EVENT.DOWN_CAPTURE);
if (listeningForDown) {
List<Integer> activeHitPathViewIds =
ReactNativeFeatureFlags.cxxNativeAnimatedEnabled()
? eventState.getHitPathViewIdsForActivePointer()
: null;
eventDispatcher.dispatchEvent(
PointerEvent.obtain(
PointerEventHelper.POINTER_DOWN, activeTargetTag, eventState, motionEvent));
PointerEventHelper.POINTER_DOWN,
activeTargetTag,
eventState,
motionEvent,
activeHitPathViewIds));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,22 @@ internal class PointerEvent private constructor() : Event<PointerEvent>() {
private var coalescingKey = UNSET_COALESCING_KEY
private var pointersEventData: List<WritableMap>? = null
private var eventState: PointerEventState? = null
private var activeHitPathViewIds: List<Int>? = null

private fun init(
eventName: String,
targetTag: Int,
eventState: PointerEventState,
motionEventToCopy: MotionEvent,
coalescingKey: Short,
activeHitPathViewIds: List<Int>?,
) {
super.init(eventState.getSurfaceId(), targetTag, motionEventToCopy.eventTime)
this._eventName = eventName
this.motionEvent = MotionEvent.obtain(motionEventToCopy)
this.coalescingKey = coalescingKey
this.eventState = eventState
this.activeHitPathViewIds = activeHitPathViewIds
}

override fun getEventName(): String = _eventName
Expand Down Expand Up @@ -213,6 +216,13 @@ internal class PointerEvent private constructor() : Event<PointerEvent>() {
pointerEvent.putDouble("pressure", pressure)
pointerEvent.putDouble("tangentialPressure", 0.0)

if (activeHitPathViewIds != null) {
pointerEvent.putArray(
"hitPathForEventListener",
Arguments.makeNativeArray(activeHitPathViewIds),
)
}

addModifierKeyData(pointerEvent, motionEvent.metaState)

return pointerEvent
Expand Down Expand Up @@ -296,6 +306,9 @@ internal class PointerEvent private constructor() : Event<PointerEvent>() {

val hitPathForActivePointer: List<ViewTarget>
get() = checkNotNull(hitPathByPointerId[activePointerId])

val hitPathViewIdsForActivePointer: List<Int>
get() = checkNotNull(hitPathByPointerId[activePointerId]).map { it.getViewId() }
}

companion object {
Expand All @@ -310,6 +323,15 @@ internal class PointerEvent private constructor() : Event<PointerEvent>() {
targetTag: Int,
eventState: PointerEventState,
motionEventToCopy: MotionEvent?,
): PointerEvent = obtain(eventName, targetTag, eventState, motionEventToCopy, null)

@JvmStatic
fun obtain(
eventName: String,
targetTag: Int,
eventState: PointerEventState,
motionEventToCopy: MotionEvent?,
activeHitPathViewIds: List<Int>?,
): PointerEvent {
var event = EVENTS_POOL.acquire()
if (event == null) {
Expand All @@ -321,6 +343,7 @@ internal class PointerEvent private constructor() : Event<PointerEvent>() {
eventState,
Assertions.assertNotNull(motionEventToCopy),
0.toShort(),
activeHitPathViewIds,
)
return event
}
Expand All @@ -343,6 +366,7 @@ internal class PointerEvent private constructor() : Event<PointerEvent>() {
eventState,
Assertions.assertNotNull(motionEventToCopy),
coalescingKey,
null,
)
return event
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,22 @@
#include "DynamicEventPayload.h"

#include <jsi/JSIDynamic.h>
#include <react/renderer/core/DynamicPointerEvent.h>

namespace facebook::react {

DynamicEventPayload::DynamicEventPayload(folly::dynamic&& payload)
: payload_(std::move(payload)) {}

/* static */ SharedEventPayload DynamicEventPayload::create(
folly::dynamic&& payload) {
if (payload.find("pointerId") != payload.items().end()) {
return std::make_shared<DynamicPointerEvent>(std::move(payload));
} else {
return std::make_shared<DynamicEventPayload>(std::move(payload));
}
}

jsi::Value DynamicEventPayload::asJSIValue(jsi::Runtime& runtime) const {
return jsi::valueFromDynamic(runtime, payload_);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,22 @@

namespace facebook::react {

/*
* EventPayload sent from android native via JNI.
*/
struct DynamicEventPayload : public EventPayload {
explicit DynamicEventPayload(folly::dynamic &&payload);

static SharedEventPayload create(folly::dynamic &&payload);

/*
* EventPayload implementations
*/
jsi::Value asJSIValue(jsi::Runtime &runtime) const override;
EventPayloadType getType() const override;
std::optional<double> extractValue(const std::vector<std::string> &path) const override;

private:
protected:
folly::dynamic payload_;
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* 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 "DynamicPointerEvent.h"

#include <jsi/JSIDynamic.h>

namespace facebook::react {

DynamicPointerEvent::DynamicPointerEvent(folly::dynamic&& payload)
: DynamicEventPayload(std::move(payload)) {
const auto& hitPath = payload_["hitPathForEventListener"];
if (hitPath.type() == folly::dynamic::Type::ARRAY) {
hitPathForEventListener_ = std::vector<Tag>{};
for (const auto& item : hitPath) {
hitPathForEventListener_->push_back(static_cast<Tag>(item.asInt()));
}
}
}

const std::optional<std::vector<Tag>>&
DynamicPointerEvent::getHitPathForEventListener() const {
return hitPathForEventListener_;
}

} // namespace facebook::react
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* 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 <folly/dynamic.h>
#include <react/renderer/core/DynamicEventPayload.h>
#include <react/renderer/core/EventPayload.h>
#include <react/renderer/core/ReactPrimitives.h>

namespace facebook::react {

/*
* Payload of PointerEvent sent from android native via JNI.
*/
struct DynamicPointerEvent : public DynamicEventPayload {
explicit DynamicPointerEvent(folly::dynamic &&payload);

const std::optional<std::vector<Tag>> &getHitPathForEventListener() const;

private:
std::optional<std::vector<Tag>> hitPathForEventListener_;
};

} // namespace facebook::react
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,19 @@
#include <cxxreact/TraceSection.h>
#include <folly/dynamic.h>
#include <jsi/jsi.h>

#include "DynamicEventPayload.h"
#include "RawEvent.h"
#include <react/renderer/core/DynamicEventPayload.h>
#include <react/renderer/core/RawEvent.h>

namespace facebook::react {

static bool hasPrefix(const std::string& str, const std::string& prefix) {
return str.compare(0, prefix.length(), prefix) == 0;
}

// TODO(T29874519): Get rid of "top" prefix once and for all.
/*
* Replaces "on" with "top" if present. Or capitalizes the first letter and adds
* "top" prefix. E.g. "eventName" becomes "topEventName", "onEventName" also
* becomes "topEventName".
* Replaces "on" with "top" if present. Or capitalizes the first letter and
* adds "top" prefix. E.g. "eventName" becomes "topEventName", "onEventName"
* also becomes "topEventName".
*/
/* static */ std::string EventEmitter::normalizeEventType(std::string type) {
auto prefixedType = std::move(type);
Expand Down Expand Up @@ -61,16 +59,15 @@ void EventEmitter::dispatchEvent(
RawEvent::Category category) const {
dispatchEvent(
std::move(type),
std::make_shared<DynamicEventPayload>(std::move(payload)),
DynamicEventPayload::create(std::move(payload)),
category);
}

void EventEmitter::dispatchUniqueEvent(
std::string type,
folly::dynamic&& payload) const {
dispatchUniqueEvent(
std::move(type),
std::make_shared<DynamicEventPayload>(std::move(payload)));
std::move(type), DynamicEventPayload::create(std::move(payload)));
}

void EventEmitter::dispatchEvent(
Expand Down Expand Up @@ -139,10 +136,10 @@ void EventEmitter::setEnabled(bool enabled) const {
}
}

// Note: Initially, the state of `eventTarget_` and the value `enableCounter_`
// is mismatched intentionally (it's `non-null` and `0` accordingly). We need
// this to support an initial nebula state where the event target must be
// retained without any associated mounted node.
// Note: Initially, the state of `eventTarget_` and the value
// `enableCounter_` is mismatched intentionally (it's `non-null` and `0`
// accordingly). We need this to support an initial nebula state where the
// event target must be retained without any associated mounted node.
bool shouldBeRetained = enableCounter_ > 0;
if (shouldBeRetained != (eventTarget_ != nullptr)) {
if (!shouldBeRetained) {
Expand Down
Loading