mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Refactor mount out of Binding.cpp
Summary: Binding.cpp shares many responsibilities, including surface management and mount. This change refactors mount (and mount items) into separate files, while retaining the same functionality and interface. Changelog: [Internal][Android] - Refactor mount into FabricMountingManager Reviewed By: mdvacca Differential Revision: D32977902 fbshipit-source-id: 07cdf5a19033fccaa81901e5b9a4d44192ec7853
This commit is contained in:
committed by
Facebook GitHub Bot
parent
dc5cae5a6f
commit
0a3ddce928
@@ -28,6 +28,7 @@ rn_xplat_cxx_library(
|
||||
react_native_xplat_target("react/renderer/animations:animations"),
|
||||
react_native_xplat_target("react/renderer/uimanager:uimanager"),
|
||||
react_native_xplat_target("react/renderer/scheduler:scheduler"),
|
||||
react_native_xplat_target("react/renderer/mounting:mounting"),
|
||||
react_native_xplat_target("react/renderer/componentregistry:componentregistry"),
|
||||
react_native_xplat_target("react/renderer/components/scrollview:scrollview"),
|
||||
react_native_xplat_target("runtimeexecutor:runtimeexecutor"),
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,6 +7,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "FabricMountingManager.h"
|
||||
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <react/jni/JRuntimeExecutor.h>
|
||||
#include <react/jni/JRuntimeScheduler.h>
|
||||
@@ -29,49 +31,6 @@ namespace react {
|
||||
|
||||
class Instance;
|
||||
|
||||
struct CppMountItem final {
|
||||
#pragma mark - Designated Initializers
|
||||
static CppMountItem CreateMountItem(ShadowView const &shadowView);
|
||||
static CppMountItem DeleteMountItem(ShadowView const &shadowView);
|
||||
static CppMountItem InsertMountItem(
|
||||
ShadowView const &parentView,
|
||||
ShadowView const &shadowView,
|
||||
int index);
|
||||
static CppMountItem RemoveMountItem(
|
||||
ShadowView const &parentView,
|
||||
ShadowView const &shadowView,
|
||||
int index);
|
||||
static CppMountItem UpdatePropsMountItem(ShadowView const &shadowView);
|
||||
static CppMountItem UpdateStateMountItem(ShadowView const &shadowView);
|
||||
static CppMountItem UpdateLayoutMountItem(ShadowView const &shadowView);
|
||||
static CppMountItem UpdateEventEmitterMountItem(ShadowView const &shadowView);
|
||||
static CppMountItem UpdatePaddingMountItem(ShadowView const &shadowView);
|
||||
|
||||
#pragma mark - Type
|
||||
|
||||
enum Type {
|
||||
Undefined = -1,
|
||||
Multiple = 1,
|
||||
Create = 2,
|
||||
Delete = 4,
|
||||
Insert = 8,
|
||||
Remove = 16,
|
||||
UpdateProps = 32,
|
||||
UpdateState = 64,
|
||||
UpdateLayout = 128,
|
||||
UpdateEventEmitter = 256,
|
||||
UpdatePadding = 512
|
||||
};
|
||||
|
||||
#pragma mark - Fields
|
||||
|
||||
Type type = {Create};
|
||||
ShadowView parentShadowView = {};
|
||||
ShadowView oldChildShadowView = {};
|
||||
ShadowView newChildShadowView = {};
|
||||
int index = {};
|
||||
};
|
||||
|
||||
class Binding : public jni::HybridClass<Binding>,
|
||||
public SchedulerDelegate,
|
||||
public LayoutAnimationStatusDelegate {
|
||||
@@ -79,18 +38,12 @@ class Binding : public jni::HybridClass<Binding>,
|
||||
constexpr static const char *const kJavaDescriptor =
|
||||
"Lcom/facebook/react/fabric/Binding;";
|
||||
|
||||
constexpr static auto UIManagerJavaDescriptor =
|
||||
"com/facebook/react/fabric/FabricUIManager";
|
||||
|
||||
constexpr static auto ReactFeatureFlagsJavaDescriptor =
|
||||
"com/facebook/react/config/ReactFeatureFlags";
|
||||
|
||||
static void registerNatives();
|
||||
|
||||
private:
|
||||
jni::global_ref<jobject> getJavaUIManager();
|
||||
std::shared_ptr<Scheduler> getScheduler();
|
||||
|
||||
void setConstraints(
|
||||
jint surfaceId,
|
||||
jfloat minWidth,
|
||||
@@ -144,10 +97,6 @@ class Binding : public jni::HybridClass<Binding>,
|
||||
void schedulerDidFinishTransaction(
|
||||
MountingCoordinator::Shared const &mountingCoordinator) override;
|
||||
|
||||
void preallocateShadowView(
|
||||
const SurfaceId surfaceId,
|
||||
const ShadowView &shadowView);
|
||||
|
||||
void schedulerDidRequestPreliminaryViewAllocation(
|
||||
const SurfaceId surfaceId,
|
||||
const ShadowNode &shadowNode) override;
|
||||
@@ -171,6 +120,8 @@ class Binding : public jni::HybridClass<Binding>,
|
||||
bool isJSResponder,
|
||||
bool blockNativeResponder) override;
|
||||
|
||||
void preallocateView(SurfaceId surfaceId, ShadowNode const &shadowNode);
|
||||
|
||||
void setPixelDensity(float pointScaleFactor);
|
||||
|
||||
void driveCxxAnimations();
|
||||
@@ -179,27 +130,30 @@ class Binding : public jni::HybridClass<Binding>,
|
||||
|
||||
// Private member variables
|
||||
better::shared_mutex installMutex_;
|
||||
jni::global_ref<jobject> javaUIManager_;
|
||||
std::shared_ptr<FabricMountingManager> mountingManager_;
|
||||
std::shared_ptr<Scheduler> scheduler_;
|
||||
|
||||
std::shared_ptr<Scheduler> getScheduler();
|
||||
std::shared_ptr<FabricMountingManager> verifyMountingManager(
|
||||
std::string const &locationHint);
|
||||
|
||||
// LayoutAnimations
|
||||
void onAnimationStarted() override;
|
||||
void onAllAnimationsComplete() override;
|
||||
|
||||
std::shared_ptr<LayoutAnimationDriver> animationDriver_;
|
||||
|
||||
std::unique_ptr<JBackgroundExecutor> backgroundExecutor_;
|
||||
|
||||
better::map<SurfaceId, SurfaceHandler> surfaceHandlerRegistry_{};
|
||||
better::shared_mutex
|
||||
surfaceHandlerRegistryMutex_; // Protects `surfaceHandlerRegistry_`.
|
||||
|
||||
std::recursive_mutex commitMutex_;
|
||||
|
||||
float pointScaleFactor_ = 1;
|
||||
|
||||
std::shared_ptr<const ReactNativeConfig> reactNativeConfig_{nullptr};
|
||||
bool disablePreallocateViews_{false};
|
||||
bool enableFabricLogs_{false};
|
||||
bool enableEarlyEventEmitterUpdate_{false};
|
||||
bool disableRevisionCheckForPreallocation_{false};
|
||||
bool enableEventEmitterRawPointer_{false};
|
||||
bool dispatchPreallocationInBackground_{false};
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include "FabricMountItem.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
CppMountItem CppMountItem::CreateMountItem(ShadowView const &shadowView) {
|
||||
return {CppMountItem::Type::Create, {}, {}, shadowView, -1};
|
||||
}
|
||||
CppMountItem CppMountItem::DeleteMountItem(ShadowView const &shadowView) {
|
||||
return {CppMountItem::Type::Delete, {}, shadowView, {}, -1};
|
||||
}
|
||||
CppMountItem CppMountItem::InsertMountItem(
|
||||
ShadowView const &parentView,
|
||||
ShadowView const &shadowView,
|
||||
int index) {
|
||||
return {CppMountItem::Type::Insert, parentView, {}, shadowView, index};
|
||||
}
|
||||
CppMountItem CppMountItem::RemoveMountItem(
|
||||
ShadowView const &parentView,
|
||||
ShadowView const &shadowView,
|
||||
int index) {
|
||||
return {CppMountItem::Type::Remove, parentView, shadowView, {}, index};
|
||||
}
|
||||
CppMountItem CppMountItem::UpdatePropsMountItem(ShadowView const &shadowView) {
|
||||
return {CppMountItem::Type::UpdateProps, {}, {}, shadowView, -1};
|
||||
}
|
||||
CppMountItem CppMountItem::UpdateStateMountItem(ShadowView const &shadowView) {
|
||||
return {CppMountItem::Type::UpdateState, {}, {}, shadowView, -1};
|
||||
}
|
||||
CppMountItem CppMountItem::UpdateLayoutMountItem(ShadowView const &shadowView) {
|
||||
return {CppMountItem::Type::UpdateLayout, {}, {}, shadowView, -1};
|
||||
}
|
||||
CppMountItem CppMountItem::UpdateEventEmitterMountItem(
|
||||
ShadowView const &shadowView) {
|
||||
return {CppMountItem::Type::UpdateEventEmitter, {}, {}, shadowView, -1};
|
||||
}
|
||||
CppMountItem CppMountItem::UpdatePaddingMountItem(
|
||||
ShadowView const &shadowView) {
|
||||
return {CppMountItem::Type::UpdatePadding, {}, {}, shadowView, -1};
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its 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>
|
||||
#include <react/renderer/mounting/ShadowView.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
struct JMountItem : public jni::JavaClass<JMountItem> {
|
||||
static constexpr auto kJavaDescriptor =
|
||||
"Lcom/facebook/react/fabric/mounting/mountitems/MountItem;";
|
||||
};
|
||||
|
||||
struct CppMountItem final {
|
||||
#pragma mark - Designated Initializers
|
||||
|
||||
static CppMountItem CreateMountItem(ShadowView const &shadowView);
|
||||
|
||||
static CppMountItem DeleteMountItem(ShadowView const &shadowView);
|
||||
|
||||
static CppMountItem InsertMountItem(
|
||||
ShadowView const &parentView,
|
||||
ShadowView const &shadowView,
|
||||
int index);
|
||||
|
||||
static CppMountItem RemoveMountItem(
|
||||
ShadowView const &parentView,
|
||||
ShadowView const &shadowView,
|
||||
int index);
|
||||
|
||||
static CppMountItem UpdatePropsMountItem(ShadowView const &shadowView);
|
||||
|
||||
static CppMountItem UpdateStateMountItem(ShadowView const &shadowView);
|
||||
|
||||
static CppMountItem UpdateLayoutMountItem(ShadowView const &shadowView);
|
||||
|
||||
static CppMountItem UpdateEventEmitterMountItem(ShadowView const &shadowView);
|
||||
|
||||
static CppMountItem UpdatePaddingMountItem(ShadowView const &shadowView);
|
||||
|
||||
#pragma mark - Type
|
||||
|
||||
enum Type {
|
||||
Undefined = -1,
|
||||
Multiple = 1,
|
||||
Create = 2,
|
||||
Delete = 4,
|
||||
Insert = 8,
|
||||
Remove = 16,
|
||||
UpdateProps = 32,
|
||||
UpdateState = 64,
|
||||
UpdateLayout = 128,
|
||||
UpdateEventEmitter = 256,
|
||||
UpdatePadding = 512
|
||||
};
|
||||
|
||||
#pragma mark - Fields
|
||||
|
||||
Type type = {Create};
|
||||
ShadowView parentShadowView = {};
|
||||
ShadowView oldChildShadowView = {};
|
||||
ShadowView newChildShadowView = {};
|
||||
int index = {};
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
@@ -0,0 +1,821 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include "FabricMountingManager.h"
|
||||
#include "EventEmitterWrapper.h"
|
||||
#include "StateWrapperImpl.h"
|
||||
|
||||
#include <react/jni/ReadableNativeMap.h>
|
||||
#include <react/renderer/components/scrollview/ScrollViewProps.h>
|
||||
#include <react/renderer/core/conversions.h>
|
||||
#include <react/renderer/debug/SystraceSection.h>
|
||||
#include <react/renderer/mounting/ShadowViewMutation.h>
|
||||
|
||||
#include <fbjni/fbjni.h>
|
||||
#include <glog/logging.h>
|
||||
|
||||
#include <cfenv>
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
|
||||
using namespace facebook::jni;
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
static inline int getIntBufferSizeForType(CppMountItem::Type mountItemType) {
|
||||
switch (mountItemType) {
|
||||
case CppMountItem::Type::Create:
|
||||
return 2; // tag, isLayoutable
|
||||
case CppMountItem::Type::Insert:
|
||||
case CppMountItem::Type::Remove:
|
||||
return 3; // tag, parentTag, index
|
||||
case CppMountItem::Type::Delete:
|
||||
case CppMountItem::Type::UpdateProps:
|
||||
case CppMountItem::Type::UpdateState:
|
||||
case CppMountItem::Type::UpdateEventEmitter:
|
||||
return 1; // tag
|
||||
case CppMountItem::Type::UpdatePadding:
|
||||
return 5; // tag, top, left, bottom, right
|
||||
case CppMountItem::Type::UpdateLayout:
|
||||
return 6; // tag, x, y, w, h, DisplayType
|
||||
case CppMountItem::Undefined:
|
||||
case CppMountItem::Multiple:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void updateBufferSizes(
|
||||
CppMountItem::Type mountItemType,
|
||||
int numInstructions,
|
||||
int &batchMountItemIntsSize,
|
||||
int &batchMountItemObjectsSize) {
|
||||
if (numInstructions == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
batchMountItemIntsSize +=
|
||||
numInstructions == 1 ? 1 : 2; // instructionType[, numInstructions]
|
||||
batchMountItemIntsSize +=
|
||||
numInstructions * getIntBufferSizeForType(mountItemType);
|
||||
|
||||
if (mountItemType == CppMountItem::Type::UpdateProps) {
|
||||
batchMountItemObjectsSize +=
|
||||
numInstructions; // props object * numInstructions
|
||||
} else if (mountItemType == CppMountItem::Type::UpdateState) {
|
||||
batchMountItemObjectsSize +=
|
||||
numInstructions; // state object * numInstructions
|
||||
} else if (mountItemType == CppMountItem::Type::UpdateEventEmitter) {
|
||||
batchMountItemObjectsSize +=
|
||||
numInstructions; // EventEmitter object * numInstructions
|
||||
}
|
||||
}
|
||||
|
||||
static inline void computeBufferSizes(
|
||||
int &batchMountItemIntsSize,
|
||||
int &batchMountItemObjectsSize,
|
||||
std::vector<CppMountItem> &cppCommonMountItems,
|
||||
std::vector<CppMountItem> &cppDeleteMountItems,
|
||||
std::vector<CppMountItem> &cppUpdatePropsMountItems,
|
||||
std::vector<CppMountItem> &cppUpdateStateMountItems,
|
||||
std::vector<CppMountItem> &cppUpdatePaddingMountItems,
|
||||
std::vector<CppMountItem> &cppUpdateLayoutMountItems,
|
||||
std::vector<CppMountItem> &cppUpdateEventEmitterMountItems) {
|
||||
CppMountItem::Type lastType = CppMountItem::Type::Undefined;
|
||||
int numSameType = 0;
|
||||
for (auto const &mountItem : cppCommonMountItems) {
|
||||
const auto &mountItemType = mountItem.type;
|
||||
|
||||
if (lastType == mountItemType) {
|
||||
numSameType++;
|
||||
if (numSameType == 2) {
|
||||
batchMountItemIntsSize += 1; // numInstructions
|
||||
}
|
||||
} else {
|
||||
numSameType = 1;
|
||||
lastType = mountItemType;
|
||||
batchMountItemIntsSize += 1; // instructionType
|
||||
}
|
||||
|
||||
batchMountItemIntsSize += getIntBufferSizeForType(mountItemType);
|
||||
if (mountItemType == CppMountItem::Type::Create) {
|
||||
batchMountItemObjectsSize +=
|
||||
4; // component name, props, state, event emitter
|
||||
}
|
||||
}
|
||||
|
||||
updateBufferSizes(
|
||||
CppMountItem::Type::UpdateProps,
|
||||
cppUpdatePropsMountItems.size(),
|
||||
batchMountItemIntsSize,
|
||||
batchMountItemObjectsSize);
|
||||
updateBufferSizes(
|
||||
CppMountItem::Type::UpdateState,
|
||||
cppUpdateStateMountItems.size(),
|
||||
batchMountItemIntsSize,
|
||||
batchMountItemObjectsSize);
|
||||
updateBufferSizes(
|
||||
CppMountItem::Type::UpdatePadding,
|
||||
cppUpdatePaddingMountItems.size(),
|
||||
batchMountItemIntsSize,
|
||||
batchMountItemObjectsSize);
|
||||
updateBufferSizes(
|
||||
CppMountItem::Type::UpdateLayout,
|
||||
cppUpdateLayoutMountItems.size(),
|
||||
batchMountItemIntsSize,
|
||||
batchMountItemObjectsSize);
|
||||
updateBufferSizes(
|
||||
CppMountItem::Type::UpdateEventEmitter,
|
||||
cppUpdateEventEmitterMountItems.size(),
|
||||
batchMountItemIntsSize,
|
||||
batchMountItemObjectsSize);
|
||||
updateBufferSizes(
|
||||
CppMountItem::Type::Delete,
|
||||
cppDeleteMountItems.size(),
|
||||
batchMountItemIntsSize,
|
||||
batchMountItemObjectsSize);
|
||||
}
|
||||
|
||||
static inline void writeIntBufferTypePreamble(
|
||||
int mountItemType,
|
||||
int numItems,
|
||||
_JNIEnv *env,
|
||||
jintArray &intBufferArray,
|
||||
int &intBufferPosition) {
|
||||
jint temp[2];
|
||||
if (numItems == 1) {
|
||||
temp[0] = mountItemType;
|
||||
env->SetIntArrayRegion(intBufferArray, intBufferPosition, 1, temp);
|
||||
intBufferPosition += 1;
|
||||
} else {
|
||||
temp[0] = mountItemType | CppMountItem::Type::Multiple;
|
||||
temp[1] = numItems;
|
||||
env->SetIntArrayRegion(intBufferArray, intBufferPosition, 2, temp);
|
||||
intBufferPosition += 2;
|
||||
}
|
||||
}
|
||||
|
||||
inline local_ref<ReadableMap::javaobject> castReadableMap(
|
||||
local_ref<ReadableNativeMap::javaobject> const &nativeMap) {
|
||||
return make_local(reinterpret_cast<ReadableMap::javaobject>(nativeMap.get()));
|
||||
}
|
||||
|
||||
inline local_ref<ReadableArray::javaobject> castReadableArray(
|
||||
local_ref<ReadableNativeArray::javaobject> const &nativeArray) {
|
||||
return make_local(
|
||||
reinterpret_cast<ReadableArray::javaobject>(nativeArray.get()));
|
||||
}
|
||||
|
||||
// TODO: this method will be removed when binding for components are code-gen
|
||||
local_ref<JString> getPlatformComponentName(ShadowView const &shadowView) {
|
||||
static std::string scrollViewComponentName = std::string("ScrollView");
|
||||
|
||||
local_ref<JString> componentName;
|
||||
if (scrollViewComponentName == shadowView.componentName) {
|
||||
auto newViewProps =
|
||||
std::static_pointer_cast<const ScrollViewProps>(shadowView.props);
|
||||
if (newViewProps->getProbablyMoreHorizontalThanVertical_DEPRECATED()) {
|
||||
componentName = make_jstring("AndroidHorizontalScrollView");
|
||||
return componentName;
|
||||
}
|
||||
}
|
||||
|
||||
componentName = make_jstring(shadowView.componentName);
|
||||
return componentName;
|
||||
}
|
||||
|
||||
static inline float scale(Float value, Float pointScaleFactor) {
|
||||
std::feclearexcept(FE_ALL_EXCEPT);
|
||||
float result = value * pointScaleFactor;
|
||||
if (std::fetestexcept(FE_OVERFLOW)) {
|
||||
LOG(ERROR) << "Binding::scale - FE_OVERFLOW - value: " << value
|
||||
<< " pointScaleFactor: " << pointScaleFactor
|
||||
<< " result: " << result;
|
||||
}
|
||||
if (std::fetestexcept(FE_UNDERFLOW)) {
|
||||
LOG(ERROR) << "Binding::scale - FE_UNDERFLOW - value: " << value
|
||||
<< " pointScaleFactor: " << pointScaleFactor
|
||||
<< " result: " << result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void FabricMountingManager::executeMount(
|
||||
MountingCoordinator::Shared const &mountingCoordinator) {
|
||||
std::lock_guard<std::recursive_mutex> lock(commitMutex_);
|
||||
|
||||
SystraceSection s(
|
||||
"FabricUIManagerBinding::schedulerDidFinishTransactionIntBuffer");
|
||||
auto finishTransactionStartTime = telemetryTimePointNow();
|
||||
|
||||
auto mountingTransaction = mountingCoordinator->pullTransaction();
|
||||
|
||||
if (!mountingTransaction.has_value()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto env = Environment::current();
|
||||
|
||||
auto telemetry = mountingTransaction->getTelemetry();
|
||||
auto surfaceId = mountingTransaction->getSurfaceId();
|
||||
auto &mutations = mountingTransaction->getMutations();
|
||||
|
||||
auto revisionNumber = telemetry.getRevisionNumber();
|
||||
|
||||
std::vector<CppMountItem> cppCommonMountItems;
|
||||
std::vector<CppMountItem> cppDeleteMountItems;
|
||||
std::vector<CppMountItem> cppUpdatePropsMountItems;
|
||||
std::vector<CppMountItem> cppUpdateStateMountItems;
|
||||
std::vector<CppMountItem> cppUpdatePaddingMountItems;
|
||||
std::vector<CppMountItem> cppUpdateLayoutMountItems;
|
||||
std::vector<CppMountItem> cppUpdateEventEmitterMountItems;
|
||||
|
||||
for (const auto &mutation : mutations) {
|
||||
const auto &parentShadowView = mutation.parentShadowView;
|
||||
const auto &oldChildShadowView = mutation.oldChildShadowView;
|
||||
const auto &newChildShadowView = mutation.newChildShadowView;
|
||||
auto &mutationType = mutation.type;
|
||||
auto &index = mutation.index;
|
||||
|
||||
bool isVirtual = mutation.mutatedViewIsVirtual();
|
||||
|
||||
bool noRevisionCheck =
|
||||
disablePreallocateViews_ || disableRevisionCheckForPreallocation_;
|
||||
|
||||
switch (mutationType) {
|
||||
case ShadowViewMutation::Create: {
|
||||
if (noRevisionCheck || newChildShadowView.props->revision > 1) {
|
||||
cppCommonMountItems.push_back(
|
||||
CppMountItem::CreateMountItem(newChildShadowView));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ShadowViewMutation::Remove: {
|
||||
if (!isVirtual) {
|
||||
cppCommonMountItems.push_back(CppMountItem::RemoveMountItem(
|
||||
parentShadowView, oldChildShadowView, index));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ShadowViewMutation::Delete: {
|
||||
cppDeleteMountItems.push_back(
|
||||
CppMountItem::DeleteMountItem(oldChildShadowView));
|
||||
break;
|
||||
}
|
||||
case ShadowViewMutation::Update: {
|
||||
if (!isVirtual) {
|
||||
if (oldChildShadowView.props != newChildShadowView.props) {
|
||||
cppUpdatePropsMountItems.push_back(
|
||||
CppMountItem::UpdatePropsMountItem(newChildShadowView));
|
||||
}
|
||||
if (oldChildShadowView.state != newChildShadowView.state) {
|
||||
cppUpdateStateMountItems.push_back(
|
||||
CppMountItem::UpdateStateMountItem(newChildShadowView));
|
||||
}
|
||||
|
||||
// Padding: padding mountItems must be executed before layout props
|
||||
// are updated in the view. This is necessary to ensure that events
|
||||
// (resulting from layout changes) are dispatched with the correct
|
||||
// padding information.
|
||||
if (oldChildShadowView.layoutMetrics.contentInsets !=
|
||||
newChildShadowView.layoutMetrics.contentInsets) {
|
||||
cppUpdatePaddingMountItems.push_back(
|
||||
CppMountItem::UpdatePaddingMountItem(newChildShadowView));
|
||||
}
|
||||
|
||||
if (oldChildShadowView.layoutMetrics !=
|
||||
newChildShadowView.layoutMetrics) {
|
||||
cppUpdateLayoutMountItems.push_back(
|
||||
CppMountItem::UpdateLayoutMountItem(
|
||||
mutation.newChildShadowView));
|
||||
}
|
||||
}
|
||||
|
||||
if (oldChildShadowView.eventEmitter !=
|
||||
newChildShadowView.eventEmitter) {
|
||||
cppUpdateEventEmitterMountItems.push_back(
|
||||
CppMountItem::UpdateEventEmitterMountItem(
|
||||
mutation.newChildShadowView));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ShadowViewMutation::Insert: {
|
||||
if (!isVirtual) {
|
||||
// Insert item
|
||||
cppCommonMountItems.push_back(CppMountItem::InsertMountItem(
|
||||
parentShadowView, newChildShadowView, index));
|
||||
|
||||
if (noRevisionCheck || newChildShadowView.props->revision > 1) {
|
||||
cppUpdatePropsMountItems.push_back(
|
||||
CppMountItem::UpdatePropsMountItem(newChildShadowView));
|
||||
}
|
||||
|
||||
// State
|
||||
if (newChildShadowView.state) {
|
||||
cppUpdateStateMountItems.push_back(
|
||||
CppMountItem::UpdateStateMountItem(newChildShadowView));
|
||||
}
|
||||
|
||||
// Padding: padding mountItems must be executed before layout props
|
||||
// are updated in the view. This is necessary to ensure that events
|
||||
// (resulting from layout changes) are dispatched with the correct
|
||||
// padding information.
|
||||
cppUpdatePaddingMountItems.push_back(
|
||||
CppMountItem::UpdatePaddingMountItem(
|
||||
mutation.newChildShadowView));
|
||||
|
||||
// Layout
|
||||
cppUpdateLayoutMountItems.push_back(
|
||||
CppMountItem::UpdateLayoutMountItem(mutation.newChildShadowView));
|
||||
}
|
||||
|
||||
// EventEmitter
|
||||
cppUpdateEventEmitterMountItems.push_back(
|
||||
CppMountItem::UpdateEventEmitterMountItem(
|
||||
mutation.newChildShadowView));
|
||||
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We now have all the information we need, including ordering of mount items,
|
||||
// to know exactly how much space must be allocated
|
||||
int batchMountItemIntsSize = 0;
|
||||
int batchMountItemObjectsSize = 0;
|
||||
computeBufferSizes(
|
||||
batchMountItemIntsSize,
|
||||
batchMountItemObjectsSize,
|
||||
cppCommonMountItems,
|
||||
cppDeleteMountItems,
|
||||
cppUpdatePropsMountItems,
|
||||
cppUpdateStateMountItems,
|
||||
cppUpdatePaddingMountItems,
|
||||
cppUpdateLayoutMountItems,
|
||||
cppUpdateEventEmitterMountItems);
|
||||
|
||||
static auto createMountItemsIntBufferBatchContainer =
|
||||
jni::findClassStatic(UIManagerJavaDescriptor)
|
||||
->getMethod<alias_ref<JMountItem>(
|
||||
jint, jintArray, jtypeArray<jobject>, jint)>(
|
||||
"createIntBufferBatchMountItem");
|
||||
|
||||
static auto scheduleMountItem = jni::findClassStatic(UIManagerJavaDescriptor)
|
||||
->getMethod<void(
|
||||
JMountItem::javaobject,
|
||||
jint,
|
||||
jlong,
|
||||
jlong,
|
||||
jlong,
|
||||
jlong,
|
||||
jlong,
|
||||
jlong,
|
||||
jlong)>("scheduleMountItem");
|
||||
|
||||
if (batchMountItemIntsSize == 0) {
|
||||
auto finishTransactionEndTime = telemetryTimePointNow();
|
||||
|
||||
scheduleMountItem(
|
||||
javaUIManager_,
|
||||
nullptr,
|
||||
telemetry.getRevisionNumber(),
|
||||
telemetryTimePointToMilliseconds(telemetry.getCommitStartTime()),
|
||||
telemetryTimePointToMilliseconds(telemetry.getDiffStartTime()),
|
||||
telemetryTimePointToMilliseconds(telemetry.getDiffEndTime()),
|
||||
telemetryTimePointToMilliseconds(telemetry.getLayoutStartTime()),
|
||||
telemetryTimePointToMilliseconds(telemetry.getLayoutEndTime()),
|
||||
telemetryTimePointToMilliseconds(finishTransactionStartTime),
|
||||
telemetryTimePointToMilliseconds(finishTransactionEndTime));
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate the intBuffer and object array, now that we know exact sizes
|
||||
// necessary
|
||||
// TODO: don't allocate at all if size is zero
|
||||
jintArray intBufferArray = env->NewIntArray(batchMountItemIntsSize);
|
||||
local_ref<JArrayClass<jobject>> objBufferArray =
|
||||
JArrayClass<jobject>::newArray(batchMountItemObjectsSize);
|
||||
|
||||
// Fill in arrays
|
||||
int intBufferPosition = 0;
|
||||
int objBufferPosition = 0;
|
||||
int prevMountItemType = -1;
|
||||
jint temp[7];
|
||||
for (int i = 0; i < cppCommonMountItems.size(); i++) {
|
||||
const auto &mountItem = cppCommonMountItems[i];
|
||||
const auto &mountItemType = mountItem.type;
|
||||
|
||||
// Get type here, and count forward how many items of this type are in a
|
||||
// row. Write preamble to any common type here.
|
||||
if (prevMountItemType != mountItemType) {
|
||||
int numSameItemTypes = 1;
|
||||
for (int j = i + 1; j < cppCommonMountItems.size() &&
|
||||
cppCommonMountItems[j].type == mountItemType;
|
||||
j++) {
|
||||
numSameItemTypes++;
|
||||
}
|
||||
|
||||
writeIntBufferTypePreamble(
|
||||
mountItemType,
|
||||
numSameItemTypes,
|
||||
env,
|
||||
intBufferArray,
|
||||
intBufferPosition);
|
||||
}
|
||||
prevMountItemType = mountItemType;
|
||||
|
||||
// TODO: multi-create, multi-insert, etc
|
||||
if (mountItemType == CppMountItem::Type::Create) {
|
||||
local_ref<JString> componentName =
|
||||
getPlatformComponentName(mountItem.newChildShadowView);
|
||||
|
||||
int isLayoutable =
|
||||
mountItem.newChildShadowView.layoutMetrics != EmptyLayoutMetrics ? 1
|
||||
: 0;
|
||||
|
||||
local_ref<ReadableMap::javaobject> props =
|
||||
castReadableMap(ReadableNativeMap::newObjectCxxArgs(
|
||||
mountItem.newChildShadowView.props->rawProps));
|
||||
|
||||
// Do not hold onto Java object from C
|
||||
// We DO want to hold onto C object from Java, since we don't know the
|
||||
// lifetime of the Java object
|
||||
local_ref<StateWrapperImpl::JavaPart> javaStateWrapper = nullptr;
|
||||
if (mountItem.newChildShadowView.state != nullptr) {
|
||||
javaStateWrapper = StateWrapperImpl::newObjectJavaArgs();
|
||||
StateWrapperImpl *cStateWrapper = cthis(javaStateWrapper);
|
||||
cStateWrapper->state_ = mountItem.newChildShadowView.state;
|
||||
}
|
||||
|
||||
// Do not hold a reference to javaEventEmitter from the C++ side.
|
||||
SharedEventEmitter eventEmitter =
|
||||
mountItem.newChildShadowView.eventEmitter;
|
||||
auto javaEventEmitter = EventEmitterWrapper::newObjectJavaArgs();
|
||||
EventEmitterWrapper *cEventEmitter = cthis(javaEventEmitter);
|
||||
if (enableEventEmitterRawPointer_) {
|
||||
cEventEmitter->eventEmitterPointer = eventEmitter.get();
|
||||
} else {
|
||||
cEventEmitter->eventEmitter = eventEmitter;
|
||||
}
|
||||
temp[0] = mountItem.newChildShadowView.tag;
|
||||
temp[1] = isLayoutable;
|
||||
env->SetIntArrayRegion(intBufferArray, intBufferPosition, 2, temp);
|
||||
intBufferPosition += 2;
|
||||
|
||||
(*objBufferArray)[objBufferPosition++] = componentName.get();
|
||||
(*objBufferArray)[objBufferPosition++] = props.get();
|
||||
(*objBufferArray)[objBufferPosition++] =
|
||||
javaStateWrapper != nullptr ? javaStateWrapper.get() : nullptr;
|
||||
(*objBufferArray)[objBufferPosition++] = javaEventEmitter.get();
|
||||
} else if (mountItemType == CppMountItem::Type::Insert) {
|
||||
temp[0] = mountItem.newChildShadowView.tag;
|
||||
temp[1] = mountItem.parentShadowView.tag;
|
||||
temp[2] = mountItem.index;
|
||||
env->SetIntArrayRegion(intBufferArray, intBufferPosition, 3, temp);
|
||||
intBufferPosition += 3;
|
||||
} else if (mountItemType == CppMountItem::Remove) {
|
||||
temp[0] = mountItem.oldChildShadowView.tag;
|
||||
temp[1] = mountItem.parentShadowView.tag;
|
||||
temp[2] = mountItem.index;
|
||||
env->SetIntArrayRegion(intBufferArray, intBufferPosition, 3, temp);
|
||||
intBufferPosition += 3;
|
||||
} else {
|
||||
LOG(ERROR) << "Unexpected CppMountItem type";
|
||||
}
|
||||
}
|
||||
if (!cppUpdatePropsMountItems.empty()) {
|
||||
writeIntBufferTypePreamble(
|
||||
CppMountItem::Type::UpdateProps,
|
||||
cppUpdatePropsMountItems.size(),
|
||||
env,
|
||||
intBufferArray,
|
||||
intBufferPosition);
|
||||
|
||||
for (const auto &mountItem : cppUpdatePropsMountItems) {
|
||||
temp[0] = mountItem.newChildShadowView.tag;
|
||||
env->SetIntArrayRegion(intBufferArray, intBufferPosition, 1, temp);
|
||||
intBufferPosition += 1;
|
||||
|
||||
auto newProps = mountItem.newChildShadowView.props->rawProps;
|
||||
local_ref<ReadableMap::javaobject> newPropsReadableMap =
|
||||
castReadableMap(ReadableNativeMap::newObjectCxxArgs(newProps));
|
||||
(*objBufferArray)[objBufferPosition++] = newPropsReadableMap.get();
|
||||
}
|
||||
}
|
||||
if (!cppUpdateStateMountItems.empty()) {
|
||||
writeIntBufferTypePreamble(
|
||||
CppMountItem::Type::UpdateState,
|
||||
cppUpdateStateMountItems.size(),
|
||||
env,
|
||||
intBufferArray,
|
||||
intBufferPosition);
|
||||
|
||||
for (const auto &mountItem : cppUpdateStateMountItems) {
|
||||
temp[0] = mountItem.newChildShadowView.tag;
|
||||
env->SetIntArrayRegion(intBufferArray, intBufferPosition, 1, temp);
|
||||
intBufferPosition += 1;
|
||||
|
||||
auto state = mountItem.newChildShadowView.state;
|
||||
// Do not hold onto Java object from C
|
||||
// We DO want to hold onto C object from Java, since we don't know the
|
||||
// lifetime of the Java object
|
||||
local_ref<StateWrapperImpl::JavaPart> javaStateWrapper = nullptr;
|
||||
if (state != nullptr) {
|
||||
javaStateWrapper = StateWrapperImpl::newObjectJavaArgs();
|
||||
StateWrapperImpl *cStateWrapper = cthis(javaStateWrapper);
|
||||
cStateWrapper->state_ = state;
|
||||
}
|
||||
|
||||
(*objBufferArray)[objBufferPosition++] =
|
||||
(javaStateWrapper != nullptr ? javaStateWrapper.get() : nullptr);
|
||||
}
|
||||
}
|
||||
if (!cppUpdatePaddingMountItems.empty()) {
|
||||
writeIntBufferTypePreamble(
|
||||
CppMountItem::Type::UpdatePadding,
|
||||
cppUpdatePaddingMountItems.size(),
|
||||
env,
|
||||
intBufferArray,
|
||||
intBufferPosition);
|
||||
|
||||
for (const auto &mountItem : cppUpdatePaddingMountItems) {
|
||||
auto layoutMetrics = mountItem.newChildShadowView.layoutMetrics;
|
||||
auto pointScaleFactor = layoutMetrics.pointScaleFactor;
|
||||
auto contentInsets = layoutMetrics.contentInsets;
|
||||
|
||||
int left = floor(scale(contentInsets.left, pointScaleFactor));
|
||||
int top = floor(scale(contentInsets.top, pointScaleFactor));
|
||||
int right = floor(scale(contentInsets.right, pointScaleFactor));
|
||||
int bottom = floor(scale(contentInsets.bottom, pointScaleFactor));
|
||||
|
||||
temp[0] = mountItem.newChildShadowView.tag;
|
||||
temp[1] = left;
|
||||
temp[2] = top;
|
||||
temp[3] = right;
|
||||
temp[4] = bottom;
|
||||
env->SetIntArrayRegion(intBufferArray, intBufferPosition, 5, temp);
|
||||
intBufferPosition += 5;
|
||||
}
|
||||
}
|
||||
if (!cppUpdateLayoutMountItems.empty()) {
|
||||
writeIntBufferTypePreamble(
|
||||
CppMountItem::Type::UpdateLayout,
|
||||
cppUpdateLayoutMountItems.size(),
|
||||
env,
|
||||
intBufferArray,
|
||||
intBufferPosition);
|
||||
|
||||
for (const auto &mountItem : cppUpdateLayoutMountItems) {
|
||||
auto layoutMetrics = mountItem.newChildShadowView.layoutMetrics;
|
||||
auto pointScaleFactor = layoutMetrics.pointScaleFactor;
|
||||
auto frame = layoutMetrics.frame;
|
||||
|
||||
int x = round(scale(frame.origin.x, pointScaleFactor));
|
||||
int y = round(scale(frame.origin.y, pointScaleFactor));
|
||||
int w = round(scale(frame.size.width, pointScaleFactor));
|
||||
int h = round(scale(frame.size.height, pointScaleFactor));
|
||||
int displayType =
|
||||
toInt(mountItem.newChildShadowView.layoutMetrics.displayType);
|
||||
|
||||
temp[0] = mountItem.newChildShadowView.tag;
|
||||
temp[1] = x;
|
||||
temp[2] = y;
|
||||
temp[3] = w;
|
||||
temp[4] = h;
|
||||
temp[5] = displayType;
|
||||
env->SetIntArrayRegion(intBufferArray, intBufferPosition, 6, temp);
|
||||
intBufferPosition += 6;
|
||||
}
|
||||
}
|
||||
if (!cppUpdateEventEmitterMountItems.empty()) {
|
||||
writeIntBufferTypePreamble(
|
||||
CppMountItem::Type::UpdateEventEmitter,
|
||||
cppUpdateEventEmitterMountItems.size(),
|
||||
env,
|
||||
intBufferArray,
|
||||
intBufferPosition);
|
||||
|
||||
for (const auto &mountItem : cppUpdateEventEmitterMountItems) {
|
||||
temp[0] = mountItem.newChildShadowView.tag;
|
||||
env->SetIntArrayRegion(intBufferArray, intBufferPosition, 1, temp);
|
||||
intBufferPosition += 1;
|
||||
|
||||
SharedEventEmitter eventEmitter =
|
||||
mountItem.newChildShadowView.eventEmitter;
|
||||
|
||||
// Do not hold a reference to javaEventEmitter from the C++ side.
|
||||
auto javaEventEmitter = EventEmitterWrapper::newObjectJavaArgs();
|
||||
EventEmitterWrapper *cEventEmitter = cthis(javaEventEmitter);
|
||||
if (enableEventEmitterRawPointer_) {
|
||||
cEventEmitter->eventEmitterPointer = eventEmitter.get();
|
||||
} else {
|
||||
cEventEmitter->eventEmitter = eventEmitter;
|
||||
}
|
||||
|
||||
(*objBufferArray)[objBufferPosition++] = javaEventEmitter.get();
|
||||
}
|
||||
}
|
||||
|
||||
// Write deletes last - so that all prop updates, etc, for the tag in the same
|
||||
// batch don't fail. Without additional machinery, moving deletes here
|
||||
// requires that the differ never produces "DELETE...CREATE" in that order for
|
||||
// the same tag. It's nice to be able to batch all similar operations together
|
||||
// for space efficiency.
|
||||
if (!cppDeleteMountItems.empty()) {
|
||||
writeIntBufferTypePreamble(
|
||||
CppMountItem::Type::Delete,
|
||||
cppDeleteMountItems.size(),
|
||||
env,
|
||||
intBufferArray,
|
||||
intBufferPosition);
|
||||
|
||||
for (const auto &mountItem : cppDeleteMountItems) {
|
||||
temp[0] = mountItem.oldChildShadowView.tag;
|
||||
env->SetIntArrayRegion(intBufferArray, intBufferPosition, 1, temp);
|
||||
intBufferPosition += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// If there are no items, we pass a nullptr instead of passing the object
|
||||
// through the JNI
|
||||
auto batch = createMountItemsIntBufferBatchContainer(
|
||||
javaUIManager_,
|
||||
surfaceId,
|
||||
batchMountItemIntsSize == 0 ? nullptr : intBufferArray,
|
||||
batchMountItemObjectsSize == 0 ? nullptr : objBufferArray.get(),
|
||||
revisionNumber);
|
||||
|
||||
auto finishTransactionEndTime = telemetryTimePointNow();
|
||||
|
||||
scheduleMountItem(
|
||||
javaUIManager_,
|
||||
batch.get(),
|
||||
telemetry.getRevisionNumber(),
|
||||
telemetryTimePointToMilliseconds(telemetry.getCommitStartTime()),
|
||||
telemetryTimePointToMilliseconds(telemetry.getDiffStartTime()),
|
||||
telemetryTimePointToMilliseconds(telemetry.getDiffEndTime()),
|
||||
telemetryTimePointToMilliseconds(telemetry.getLayoutStartTime()),
|
||||
telemetryTimePointToMilliseconds(telemetry.getLayoutEndTime()),
|
||||
telemetryTimePointToMilliseconds(finishTransactionStartTime),
|
||||
telemetryTimePointToMilliseconds(finishTransactionEndTime));
|
||||
|
||||
env->DeleteLocalRef(intBufferArray);
|
||||
}
|
||||
|
||||
void FabricMountingManager::preallocateShadowView(
|
||||
SurfaceId surfaceId,
|
||||
ShadowView const &shadowView) {
|
||||
bool isLayoutableShadowNode = shadowView.layoutMetrics != EmptyLayoutMetrics;
|
||||
|
||||
static auto preallocateView = jni::findClassStatic(UIManagerJavaDescriptor)
|
||||
->getMethod<void(
|
||||
jint,
|
||||
jint,
|
||||
jstring,
|
||||
ReadableMap::javaobject,
|
||||
jobject,
|
||||
jobject,
|
||||
jboolean)>("preallocateView");
|
||||
|
||||
// Do not hold onto Java object from C
|
||||
// We DO want to hold onto C object from Java, since we don't know the
|
||||
// lifetime of the Java object
|
||||
local_ref<StateWrapperImpl::JavaPart> javaStateWrapper = nullptr;
|
||||
if (shadowView.state != nullptr) {
|
||||
javaStateWrapper = StateWrapperImpl::newObjectJavaArgs();
|
||||
StateWrapperImpl *cStateWrapper = cthis(javaStateWrapper);
|
||||
cStateWrapper->state_ = shadowView.state;
|
||||
}
|
||||
|
||||
// Do not hold a reference to javaEventEmitter from the C++ side.
|
||||
local_ref<EventEmitterWrapper::JavaPart> javaEventEmitter = nullptr;
|
||||
if (enableEarlyEventEmitterUpdate_) {
|
||||
SharedEventEmitter eventEmitter = shadowView.eventEmitter;
|
||||
if (eventEmitter != nullptr) {
|
||||
javaEventEmitter = EventEmitterWrapper::newObjectJavaArgs();
|
||||
EventEmitterWrapper *cEventEmitter = cthis(javaEventEmitter);
|
||||
if (enableEventEmitterRawPointer_) {
|
||||
cEventEmitter->eventEmitterPointer = eventEmitter.get();
|
||||
} else {
|
||||
cEventEmitter->eventEmitter = eventEmitter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
local_ref<ReadableMap::javaobject> props = castReadableMap(
|
||||
ReadableNativeMap::newObjectCxxArgs(shadowView.props->rawProps));
|
||||
auto component = getPlatformComponentName(shadowView);
|
||||
|
||||
preallocateView(
|
||||
javaUIManager_,
|
||||
surfaceId,
|
||||
shadowView.tag,
|
||||
component.get(),
|
||||
props.get(),
|
||||
(javaStateWrapper != nullptr ? javaStateWrapper.get() : nullptr),
|
||||
(javaEventEmitter != nullptr ? javaEventEmitter.get() : nullptr),
|
||||
isLayoutableShadowNode);
|
||||
}
|
||||
|
||||
void FabricMountingManager::dispatchCommand(
|
||||
ShadowView const &shadowView,
|
||||
std::string const &commandName,
|
||||
folly::dynamic const &args) {
|
||||
static auto dispatchCommand =
|
||||
jni::findClassStatic(UIManagerJavaDescriptor)
|
||||
->getMethod<void(jint, jint, jstring, ReadableArray::javaobject)>(
|
||||
"dispatchCommand");
|
||||
|
||||
local_ref<JString> command = make_jstring(commandName);
|
||||
|
||||
local_ref<ReadableArray::javaobject> argsArray =
|
||||
castReadableArray(ReadableNativeArray::newObjectCxxArgs(args));
|
||||
|
||||
dispatchCommand(
|
||||
javaUIManager_,
|
||||
shadowView.surfaceId,
|
||||
shadowView.tag,
|
||||
command.get(),
|
||||
argsArray.get());
|
||||
}
|
||||
|
||||
void FabricMountingManager::sendAccessibilityEvent(
|
||||
ShadowView const &shadowView,
|
||||
std::string const &eventType) {
|
||||
local_ref<JString> eventTypeStr = make_jstring(eventType);
|
||||
|
||||
static auto sendAccessibilityEventFromJS =
|
||||
jni::findClassStatic(UIManagerJavaDescriptor)
|
||||
->getMethod<void(jint, jint, jstring)>(
|
||||
"sendAccessibilityEventFromJS");
|
||||
|
||||
sendAccessibilityEventFromJS(
|
||||
javaUIManager_, shadowView.surfaceId, shadowView.tag, eventTypeStr.get());
|
||||
}
|
||||
|
||||
void FabricMountingManager::setIsJSResponder(
|
||||
ShadowView const &shadowView,
|
||||
bool isJSResponder,
|
||||
bool blockNativeResponder) {
|
||||
static auto setJSResponder =
|
||||
jni::findClassStatic(UIManagerJavaDescriptor)
|
||||
->getMethod<void(jint, jint, jint, jboolean)>("setJSResponder");
|
||||
|
||||
static auto clearJSResponder = jni::findClassStatic(UIManagerJavaDescriptor)
|
||||
->getMethod<void()>("clearJSResponder");
|
||||
|
||||
if (isJSResponder) {
|
||||
setJSResponder(
|
||||
javaUIManager_,
|
||||
shadowView.surfaceId,
|
||||
shadowView.tag,
|
||||
// The closest non-flattened ancestor of the same value if the node is
|
||||
// not flattened. For now, we don't support the case when the node can
|
||||
// be flattened because the only component that uses this feature -
|
||||
// ScrollView - cannot be flattened.
|
||||
shadowView.tag,
|
||||
(jboolean)blockNativeResponder);
|
||||
} else {
|
||||
clearJSResponder(javaUIManager_);
|
||||
}
|
||||
}
|
||||
|
||||
void FabricMountingManager::onAnimationStarted() {
|
||||
static auto layoutAnimationsStartedJNI =
|
||||
jni::findClassStatic(UIManagerJavaDescriptor)
|
||||
->getMethod<void()>("onAnimationStarted");
|
||||
|
||||
layoutAnimationsStartedJNI(javaUIManager_);
|
||||
}
|
||||
|
||||
void FabricMountingManager::onAllAnimationsComplete() {
|
||||
static auto allAnimationsCompleteJNI =
|
||||
jni::findClassStatic(UIManagerJavaDescriptor)
|
||||
->getMethod<void()>("onAllAnimationsComplete");
|
||||
|
||||
allAnimationsCompleteJNI(javaUIManager_);
|
||||
}
|
||||
|
||||
FabricMountingManager::FabricMountingManager(
|
||||
std::shared_ptr<const ReactNativeConfig> &config,
|
||||
global_ref<jobject> &javaUIManager)
|
||||
: javaUIManager_(javaUIManager) {
|
||||
enableEarlyEventEmitterUpdate_ =
|
||||
config->getBool("react_fabric:enable_early_event_emitter_update");
|
||||
enableEventEmitterRawPointer_ =
|
||||
config->getBool("react_fabric:enable_event_emitter_wrapper_raw_pointer");
|
||||
disablePreallocateViews_ =
|
||||
config->getBool("react_fabric:disabled_view_preallocation_android");
|
||||
disableRevisionCheckForPreallocation_ =
|
||||
config->getBool("react_fabric:disable_revision_check_for_preallocation");
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its 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 "FabricMountItem.h"
|
||||
|
||||
#include <react/config/ReactNativeConfig.h>
|
||||
#include <react/renderer/animations/LayoutAnimationDriver.h>
|
||||
#include <react/renderer/mounting/MountingCoordinator.h>
|
||||
#include <react/renderer/mounting/ShadowView.h>
|
||||
#include <react/renderer/uimanager/LayoutAnimationStatusDelegate.h>
|
||||
#include <react/utils/ContextContainer.h>
|
||||
|
||||
#include <fbjni/fbjni.h>
|
||||
|
||||
#include <mutex>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class FabricMountingManager {
|
||||
public:
|
||||
constexpr static auto UIManagerJavaDescriptor =
|
||||
"com/facebook/react/fabric/FabricUIManager";
|
||||
|
||||
FabricMountingManager(
|
||||
std::shared_ptr<const ReactNativeConfig> &config,
|
||||
jni::global_ref<jobject> &javaUIManager);
|
||||
|
||||
void preallocateShadowView(SurfaceId surfaceId, const ShadowView &shadowView);
|
||||
|
||||
void executeMount(MountingCoordinator::Shared const &mountingCoordinator);
|
||||
|
||||
void dispatchCommand(
|
||||
ShadowView const &shadowView,
|
||||
std::string const &commandName,
|
||||
folly::dynamic const &args);
|
||||
|
||||
void sendAccessibilityEvent(
|
||||
const ShadowView &shadowView,
|
||||
std::string const &eventType);
|
||||
|
||||
void setIsJSResponder(
|
||||
ShadowView const &shadowView,
|
||||
bool isJSResponder,
|
||||
bool blockNativeResponder);
|
||||
|
||||
void onAnimationStarted();
|
||||
|
||||
void onAllAnimationsComplete();
|
||||
|
||||
virtual ~FabricMountingManager() = default;
|
||||
|
||||
private:
|
||||
jni::global_ref<jobject> javaUIManager_;
|
||||
|
||||
std::recursive_mutex commitMutex_;
|
||||
|
||||
bool enableEventEmitterRawPointer_{false};
|
||||
bool enableEarlyEventEmitterUpdate_{false};
|
||||
bool disablePreallocateViews_{false};
|
||||
bool disableRevisionCheckForPreallocation_{false};
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
Reference in New Issue
Block a user