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 @@ -10,10 +10,8 @@ package com.facebook.react.views.scroll
import android.os.SystemClock
import androidx.core.util.Pools.SynchronizedPool
import com.facebook.infer.annotation.Assertions
import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.ReactSoftExceptionLogger
import com.facebook.react.bridge.WritableMap
import com.facebook.react.bridge.buildReadableMap
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
import com.facebook.react.uimanager.PixelUtil.toDIPFromPixel
import com.facebook.react.uimanager.common.ViewUtil
Expand Down Expand Up @@ -76,46 +74,24 @@ public class ScrollEvent private constructor() : Event<ScrollEvent>() {
override fun canCoalesce(): Boolean = scrollEventType == ScrollEventType.SCROLL

override fun getEventData(): WritableMap {
val contentInset = buildReadableMap {
put("top", 0.0)
put("bottom", 0.0)
put("left", 0.0)
put("right", 0.0)
}

val contentOffset = buildReadableMap {
put("x", toDIPFromPixel(scrollX).toDouble())
put("y", toDIPFromPixel(scrollY).toDouble())
}

val contentSize = buildReadableMap {
put("width", toDIPFromPixel(contentWidth.toFloat()).toDouble())
put("height", toDIPFromPixel(contentHeight.toFloat()).toDouble())
}

val layoutMeasurement = buildReadableMap {
put("width", toDIPFromPixel(scrollViewWidth.toFloat()).toDouble())
put("height", toDIPFromPixel(scrollViewHeight.toFloat()).toDouble())
}

val velocity = buildReadableMap {
put("x", toDIPFromPixel(xVelocity).toDouble())
put("y", toDIPFromPixel(yVelocity).toDouble())
}

val event = Arguments.createMap()
event.putMap("contentInset", contentInset)
event.putMap("contentOffset", contentOffset)
event.putMap("contentSize", contentSize)
event.putMap("layoutMeasurement", layoutMeasurement)
event.putMap("velocity", velocity)
event.putInt("target", viewTag)
event.putDouble("timestamp", timestamp.toDouble())
event.putBoolean(
"responderIgnoreScroll",
val data = DoubleArray(ScrollEventHelper.FIELDS)
data[ScrollEventHelper.CONTENT_OFFSET_X_INDEX] = toDIPFromPixel(scrollX).toDouble()
data[ScrollEventHelper.CONTENT_OFFSET_Y_INDEX] = toDIPFromPixel(scrollY).toDouble()
data[ScrollEventHelper.CONTENT_WIDTH_INDEX] = toDIPFromPixel(contentWidth.toFloat()).toDouble()
data[ScrollEventHelper.CONTENT_HEIGHT_INDEX] =
toDIPFromPixel(contentHeight.toFloat()).toDouble()
data[ScrollEventHelper.LAYOUT_WIDTH_INDEX] =
toDIPFromPixel(scrollViewWidth.toFloat()).toDouble()
data[ScrollEventHelper.LAYOUT_HEIGHT_INDEX] =
toDIPFromPixel(scrollViewHeight.toFloat()).toDouble()
data[ScrollEventHelper.VELOCITY_X_INDEX] = toDIPFromPixel(xVelocity).toDouble()
data[ScrollEventHelper.VELOCITY_Y_INDEX] = toDIPFromPixel(yVelocity).toDouble()
data[ScrollEventHelper.TIMESTAMP_INDEX] = timestamp.toDouble()
return ScrollEventHelper.nativeCreateScrollPayload(
data,
viewTag,
!ReactNativeFeatureFlags.shouldTriggerResponderTransferOnScrollAndroid(),
)
return event
}

public companion object {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* 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.
*/

package com.facebook.react.views.scroll

import com.facebook.proguard.annotations.DoNotStrip
import com.facebook.react.bridge.ReactNativeJNISoLoader
import com.facebook.react.bridge.WritableNativeMap

/** Builds the payload of a [ScrollEvent] in one native call. */
@DoNotStrip
internal object ScrollEventHelper {
init {
ReactNativeJNISoLoader.staticInit()
}

// Keep in sync with the field indices in ScrollEventHelper.cpp.
const val CONTENT_OFFSET_X_INDEX = 0
const val CONTENT_OFFSET_Y_INDEX = 1
const val CONTENT_WIDTH_INDEX = 2
const val CONTENT_HEIGHT_INDEX = 3
const val LAYOUT_WIDTH_INDEX = 4
const val LAYOUT_HEIGHT_INDEX = 5
const val VELOCITY_X_INDEX = 6
const val VELOCITY_Y_INDEX = 7
const val TIMESTAMP_INDEX = 8
const val FIELDS = 9

/**
* Creates the payload of a scroll event: `contentInset` (all zero), `contentOffset`,
* `contentSize`, `layoutMeasurement`, `velocity`, `target`, `timestamp` and
* `responderIgnoreScroll`.
*
* @param data [FIELDS] values, in DIPs, at the indices above.
*/
@DoNotStrip
@JvmStatic
external fun nativeCreateScrollPayload(
data: DoubleArray,
target: Int,
responderIgnoreScroll: Boolean,
): WritableNativeMap
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ add_library(
OnLoad-common.cpp
ReadableNativeArray.cpp
ReadableNativeMap.cpp
ScrollEventHelper.cpp
TouchesHelper.cpp
TransformHelper.cpp
WritableNativeArray.cpp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <fbjni/fbjni.h>

#include "InspectorNetworkRequestListener.h"
#include "ScrollEventHelper.h"
#include "TouchesHelper.h"
#include "TransformHelper.h"

Expand All @@ -35,6 +36,7 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
FLAGS_minloglevel = 0;
#endif
InspectorNetworkRequestListener::registerNatives();
ScrollEventHelper::registerNatives();
TouchesHelper::registerNatives();
TransformHelper::registerNatives();
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* 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 "ScrollEventHelper.h"

#include <stdexcept>

#include "WritableNativeMap.h"

using namespace facebook::jni;

namespace facebook::react {

namespace {

// Keep in sync with the field indices in ScrollEventHelper.kt.
constexpr jint kContentOffsetXIndex = 0;
constexpr jint kContentOffsetYIndex = 1;
constexpr jint kContentWidthIndex = 2;
constexpr jint kContentHeightIndex = 3;
constexpr jint kLayoutWidthIndex = 4;
constexpr jint kLayoutHeightIndex = 5;
constexpr jint kVelocityXIndex = 6;
constexpr jint kVelocityYIndex = 7;
constexpr jint kTimestampIndex = 8;
constexpr jint kFields = 9;

local_ref<WritableNativeMap::jhybridobject> createScrollPayload(
alias_ref<jclass> /*unused*/,
alias_ref<JArrayDouble> data,
jint target,
jboolean responderIgnoreScroll) {
if (data->size() != kFields) {
throw std::invalid_argument("Invalid scroll event data");
}
auto values = data->getRegion(0, kFields);
const double* fields = values.get();

auto jPayload = WritableNativeMap::newObjectJavaArgs();
auto* payload = jPayload->cthis();
// NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic)
WritableNativeMap contentInset(
folly::dynamic::object("top", 0.0)("bottom", 0.0)("left", 0.0)(
"right", 0.0));
payload->putNativeMap("contentInset", &contentInset);
WritableNativeMap contentOffset(
folly::dynamic::object("x", fields[kContentOffsetXIndex])(
"y", fields[kContentOffsetYIndex]));
payload->putNativeMap("contentOffset", &contentOffset);
WritableNativeMap contentSize(
folly::dynamic::object("width", fields[kContentWidthIndex])(
"height", fields[kContentHeightIndex]));
payload->putNativeMap("contentSize", &contentSize);
WritableNativeMap layoutMeasurement(
folly::dynamic::object("width", fields[kLayoutWidthIndex])(
"height", fields[kLayoutHeightIndex]));
payload->putNativeMap("layoutMeasurement", &layoutMeasurement);
WritableNativeMap velocity(
folly::dynamic::object("x", fields[kVelocityXIndex])(
"y", fields[kVelocityYIndex]));
payload->putNativeMap("velocity", &velocity);
payload->putInt("target", target);
payload->putDouble("timestamp", fields[kTimestampIndex]);
// NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
payload->putBoolean("responderIgnoreScroll", responderIgnoreScroll != 0u);
return jPayload;
}

} // namespace

void ScrollEventHelper::registerNatives() {
javaClassLocal()->registerNatives({
makeNativeMethod("nativeCreateScrollPayload", createScrollPayload),
});
}

} // namespace facebook::react
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* 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 <fbjni/fbjni.h>

namespace facebook::react {

class ScrollEventHelper : public jni::JavaClass<ScrollEventHelper> {
public:
static auto constexpr *kJavaDescriptor = "Lcom/facebook/react/views/scroll/ScrollEventHelper;";

static void registerNatives();
};

} // namespace facebook::react
5 changes: 5 additions & 0 deletions scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api
Original file line number Diff line number Diff line change
Expand Up @@ -2203,6 +2203,11 @@ class facebook::react::SafeAreaViewProps : public facebook::react::HostPlatformV
public virtual folly::dynamic getDiffProps(const facebook::react::Props* prevProps) const override;
}

class facebook::react::ScrollEventHelper : public facebook::jni::JavaClass<facebook::react::ScrollEventHelper> {
public static constexpr auto * kJavaDescriptor;
public static void registerNatives();
}

class facebook::react::Sealable {
public Sealable();
public Sealable(const facebook::react::Sealable& other);
Expand Down
5 changes: 5 additions & 0 deletions scripts/cxx-api/api-snapshots/ReactAndroidFrameworksCxx.api
Original file line number Diff line number Diff line change
Expand Up @@ -3567,6 +3567,11 @@ class facebook::react::SchedulerDelegate {
public virtual ~SchedulerDelegate() noexcept = default;
}

class facebook::react::ScrollEventHelper : public facebook::jni::JavaClass<facebook::react::ScrollEventHelper> {
public static constexpr auto * kJavaDescriptor;
public static void registerNatives();
}

class facebook::react::ScrollViewEventEmitter : public facebook::react::BaseViewEventEmitter {
public using EndDragMetrics = facebook::react::ScrollEndDragEvent;
public using Metrics = facebook::react::ScrollEvent;
Expand Down
5 changes: 5 additions & 0 deletions scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api
Original file line number Diff line number Diff line change
Expand Up @@ -2202,6 +2202,11 @@ class facebook::react::SafeAreaViewProps : public facebook::react::HostPlatformV
public virtual folly::dynamic getDiffProps(const facebook::react::Props* prevProps) const override;
}

class facebook::react::ScrollEventHelper : public facebook::jni::JavaClass<facebook::react::ScrollEventHelper> {
public static constexpr auto * kJavaDescriptor;
public static void registerNatives();
}

class facebook::react::Sealable {
public bool getSealed() const;
public void ensureUnsealed() const;
Expand Down
5 changes: 5 additions & 0 deletions scripts/cxx-api/api-snapshots/ReactAndroidReleaseCxx.api
Original file line number Diff line number Diff line change
Expand Up @@ -2202,6 +2202,11 @@ class facebook::react::SafeAreaViewProps : public facebook::react::HostPlatformV
public virtual folly::dynamic getDiffProps(const facebook::react::Props* prevProps) const override;
}

class facebook::react::ScrollEventHelper : public facebook::jni::JavaClass<facebook::react::ScrollEventHelper> {
public static constexpr auto * kJavaDescriptor;
public static void registerNatives();
}

class facebook::react::Sealable {
public bool getSealed() const;
public void ensureUnsealed() const;
Expand Down
Loading