mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Use SurfaceHandler in ReactSurface
Summary: Changelog: [Internal] Updates `ReactSurface` to use `SurfaceHandler` internally. This removes most of the internal state in `ReactSurface` and propagates all the calls to the `SurfaceHandler`. `FabricUIManager` now uses `SurfaceHandler` to start/stop the surface. SurfaceId is still used for view operations. SurfaceId is also now mutable to play better with existing Android infra. Reviewed By: shergin, mdvacca Differential Revision: D26112992 fbshipit-source-id: 52e6860084d739381317035dc3011956d452063c
This commit is contained in:
committed by
Facebook GitHub Bot
parent
8b821f8f12
commit
8dc5ca6a6a
@@ -100,4 +100,8 @@ public class Binding {
|
||||
public void unregister() {
|
||||
uninstallFabricUIManager();
|
||||
}
|
||||
|
||||
public native void registerSurface(SurfaceHandlerBinding surfaceHandler);
|
||||
|
||||
public native void unregisterSurface(SurfaceHandlerBinding surfaceHandler);
|
||||
}
|
||||
|
||||
@@ -269,6 +269,39 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
|
||||
return rootTag;
|
||||
}
|
||||
|
||||
public void startSurface(final View rootView, SurfaceHandler surfaceHandler) {
|
||||
final int rootTag = ReactRootViewTagGenerator.getNextRootViewTag();
|
||||
|
||||
Context context = rootView.getContext();
|
||||
ThemedReactContext reactContext =
|
||||
new ThemedReactContext(
|
||||
mReactApplicationContext, context, surfaceHandler.getModuleName(), rootTag);
|
||||
mMountingManager.startSurface(rootTag, rootView, reactContext);
|
||||
|
||||
surfaceHandler.setSurfaceId(rootTag);
|
||||
if (surfaceHandler instanceof SurfaceHandlerBinding) {
|
||||
mBinding.registerSurface((SurfaceHandlerBinding) surfaceHandler);
|
||||
}
|
||||
surfaceHandler.start();
|
||||
}
|
||||
|
||||
public void stopSurface(SurfaceHandler surfaceHandler) {
|
||||
if (!surfaceHandler.isRunning()) {
|
||||
ReactSoftException.logSoftException(
|
||||
FabricUIManager.TAG,
|
||||
new IllegalStateException("Trying to stop surface that hasn't started yet"));
|
||||
return;
|
||||
}
|
||||
|
||||
mMountingManager.stopSurface(surfaceHandler.getSurfaceId());
|
||||
|
||||
surfaceHandler.stop();
|
||||
|
||||
if (surfaceHandler instanceof SurfaceHandlerBinding) {
|
||||
mBinding.unregisterSurface((SurfaceHandlerBinding) surfaceHandler);
|
||||
}
|
||||
}
|
||||
|
||||
/** Method called when an event has been dispatched on the C++ side. */
|
||||
@DoNotStrip
|
||||
@SuppressWarnings("unused")
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.facebook.react.fabric;
|
||||
|
||||
import com.facebook.react.bridge.NativeMap;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/** Represents a Java variant of the surface, its status and inner data required to display it. */
|
||||
@ThreadSafe
|
||||
public interface SurfaceHandler {
|
||||
|
||||
/** Starts the surface if the surface is not running */
|
||||
void start();
|
||||
|
||||
/** Stops the surface if it is currently running */
|
||||
void stop();
|
||||
|
||||
void setProps(NativeMap props);
|
||||
|
||||
/**
|
||||
* Provides current surface id. Id should be updated after each call to {@link
|
||||
* SurfaceHandler#stop}
|
||||
*/
|
||||
int getSurfaceId();
|
||||
|
||||
/**
|
||||
* Updates current surface id. Id should be updated after each call to {@link SurfaceHandler#stop}
|
||||
*/
|
||||
void setSurfaceId(int surfaceId);
|
||||
|
||||
boolean isRunning();
|
||||
|
||||
String getModuleName();
|
||||
|
||||
void setLayoutConstraints(
|
||||
int widthMeasureSpec,
|
||||
int heightMeasureSpec,
|
||||
int offsetX,
|
||||
int offsetY,
|
||||
boolean doLeftAndRightSwapInRTL,
|
||||
boolean isRTL);
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.facebook.react.fabric;
|
||||
|
||||
import static com.facebook.react.fabric.mounting.LayoutMetricsConversions.getMaxSize;
|
||||
import static com.facebook.react.fabric.mounting.LayoutMetricsConversions.getMinSize;
|
||||
|
||||
import com.facebook.jni.HybridData;
|
||||
import com.facebook.proguard.annotations.DoNotStrip;
|
||||
import com.facebook.react.bridge.NativeMap;
|
||||
|
||||
public class SurfaceHandlerBinding implements SurfaceHandler {
|
||||
static {
|
||||
FabricSoLoader.staticInit();
|
||||
}
|
||||
|
||||
private static final int NO_SURFACE_ID = 0;
|
||||
|
||||
@DoNotStrip private final HybridData mHybridData;
|
||||
private final float mPixelDensity;
|
||||
|
||||
private static native HybridData initHybrid(int surfaceId, String moduleName);
|
||||
|
||||
public SurfaceHandlerBinding(String moduleName, float pixelDensity) {
|
||||
mHybridData = initHybrid(NO_SURFACE_ID, moduleName);
|
||||
mPixelDensity = pixelDensity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSurfaceId() {
|
||||
return getSurfaceIdNative();
|
||||
}
|
||||
|
||||
private native int getSurfaceIdNative();
|
||||
|
||||
@Override
|
||||
public void setSurfaceId(int surfaceId) {
|
||||
setSurfaceIdNative(surfaceId);
|
||||
}
|
||||
|
||||
private native void setSurfaceIdNative(int surfaceId);
|
||||
|
||||
@Override
|
||||
public String getModuleName() {
|
||||
return getModuleNameNative();
|
||||
}
|
||||
|
||||
private native String getModuleNameNative();
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
startNative();
|
||||
}
|
||||
|
||||
private native void startNative();
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
stopNative();
|
||||
}
|
||||
|
||||
private native void stopNative();
|
||||
|
||||
@Override
|
||||
public boolean isRunning() {
|
||||
return isRunningNative();
|
||||
}
|
||||
|
||||
private native boolean isRunningNative();
|
||||
|
||||
@Override
|
||||
public void setLayoutConstraints(
|
||||
int widthMeasureSpec,
|
||||
int heightMeasureSpec,
|
||||
int offsetX,
|
||||
int offsetY,
|
||||
boolean doLeftAndRightSwapInRTL,
|
||||
boolean isRTL) {
|
||||
setLayoutConstraintsNative(
|
||||
getMinSize(widthMeasureSpec) / mPixelDensity,
|
||||
getMaxSize(widthMeasureSpec) / mPixelDensity,
|
||||
getMinSize(heightMeasureSpec) / mPixelDensity,
|
||||
getMaxSize(heightMeasureSpec) / mPixelDensity,
|
||||
offsetX / mPixelDensity,
|
||||
offsetY / mPixelDensity,
|
||||
doLeftAndRightSwapInRTL,
|
||||
isRTL,
|
||||
mPixelDensity);
|
||||
}
|
||||
|
||||
private native void setLayoutConstraintsNative(
|
||||
float minWidth,
|
||||
float maxWidth,
|
||||
float minHeight,
|
||||
float maxHeight,
|
||||
float offsetX,
|
||||
float offsetY,
|
||||
boolean doLeftAndRightSwapInRTL,
|
||||
boolean isRTL,
|
||||
float pixelDensity);
|
||||
|
||||
@Override
|
||||
public void setProps(NativeMap props) {
|
||||
setPropsNative(props);
|
||||
}
|
||||
|
||||
private native void setPropsNative(NativeMap props);
|
||||
}
|
||||
@@ -376,6 +376,14 @@ void Binding::stopSurface(jint surfaceId) {
|
||||
}
|
||||
}
|
||||
|
||||
void Binding::registerSurface(SurfaceHandlerBinding *surfaceHandler) {
|
||||
surfaceHandler->registerScheduler(getScheduler());
|
||||
}
|
||||
|
||||
void Binding::unregisterSurface(SurfaceHandlerBinding *surfaceHandler) {
|
||||
surfaceHandler->unregisterScheduler(getScheduler());
|
||||
}
|
||||
|
||||
static inline float scale(Float value, Float pointScaleFactor) {
|
||||
std::feclearexcept(FE_ALL_EXCEPT);
|
||||
float result = value * pointScaleFactor;
|
||||
@@ -1214,21 +1222,24 @@ void Binding::schedulerDidSetIsJSResponder(
|
||||
}
|
||||
|
||||
void Binding::registerNatives() {
|
||||
registerHybrid(
|
||||
{makeNativeMethod("initHybrid", Binding::initHybrid),
|
||||
makeNativeMethod(
|
||||
"installFabricUIManager", Binding::installFabricUIManager),
|
||||
makeNativeMethod("startSurface", Binding::startSurface),
|
||||
makeNativeMethod(
|
||||
"startSurfaceWithConstraints", Binding::startSurfaceWithConstraints),
|
||||
makeNativeMethod(
|
||||
"renderTemplateToSurface", Binding::renderTemplateToSurface),
|
||||
makeNativeMethod("stopSurface", Binding::stopSurface),
|
||||
makeNativeMethod("setConstraints", Binding::setConstraints),
|
||||
makeNativeMethod("setPixelDensity", Binding::setPixelDensity),
|
||||
makeNativeMethod("driveCxxAnimations", Binding::driveCxxAnimations),
|
||||
makeNativeMethod(
|
||||
"uninstallFabricUIManager", Binding::uninstallFabricUIManager)});
|
||||
registerHybrid({
|
||||
makeNativeMethod("initHybrid", Binding::initHybrid),
|
||||
makeNativeMethod(
|
||||
"installFabricUIManager", Binding::installFabricUIManager),
|
||||
makeNativeMethod("startSurface", Binding::startSurface),
|
||||
makeNativeMethod(
|
||||
"startSurfaceWithConstraints", Binding::startSurfaceWithConstraints),
|
||||
makeNativeMethod(
|
||||
"renderTemplateToSurface", Binding::renderTemplateToSurface),
|
||||
makeNativeMethod("stopSurface", Binding::stopSurface),
|
||||
makeNativeMethod("setConstraints", Binding::setConstraints),
|
||||
makeNativeMethod("setPixelDensity", Binding::setPixelDensity),
|
||||
makeNativeMethod("driveCxxAnimations", Binding::driveCxxAnimations),
|
||||
makeNativeMethod(
|
||||
"uninstallFabricUIManager", Binding::uninstallFabricUIManager),
|
||||
makeNativeMethod("registerSurface", Binding::registerSurface),
|
||||
makeNativeMethod("unregisterSurface", Binding::unregisterSurface),
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "ComponentFactory.h"
|
||||
#include "EventBeatManager.h"
|
||||
#include "JBackgroundExecutor.h"
|
||||
#include "SurfaceHandlerBinding.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
@@ -124,6 +125,10 @@ class Binding : public jni::HybridClass<Binding>,
|
||||
|
||||
void stopSurface(jint surfaceId);
|
||||
|
||||
void registerSurface(SurfaceHandlerBinding *surfaceHandler);
|
||||
|
||||
void unregisterSurface(SurfaceHandlerBinding *surfaceHandler);
|
||||
|
||||
void schedulerDidFinishTransaction(
|
||||
MountingCoordinator::Shared const &mountingCoordinator) override;
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "EventBeatManager.h"
|
||||
#include "EventEmitterWrapper.h"
|
||||
#include "StateWrapperImpl.h"
|
||||
#include "SurfaceHandlerBinding.h"
|
||||
|
||||
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
|
||||
return facebook::jni::initialize(vm, [] {
|
||||
@@ -22,5 +23,6 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
|
||||
facebook::react::StateWrapperImpl::registerNatives();
|
||||
facebook::react::ComponentFactory::registerNatives();
|
||||
facebook::react::CoreComponentsRegistry::registerNatives();
|
||||
facebook::react::SurfaceHandlerBinding::registerNatives();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* 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 "SurfaceHandlerBinding.h"
|
||||
#include <react/renderer/scheduler/Scheduler.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
SurfaceHandlerBinding::SurfaceHandlerBinding(
|
||||
SurfaceId surfaceId,
|
||||
std::string const &moduleName)
|
||||
: surfaceHandler_(moduleName, surfaceId) {}
|
||||
|
||||
void SurfaceHandlerBinding::start() {
|
||||
std::unique_lock<better::shared_mutex> lock(lifecycleMutex_);
|
||||
|
||||
surfaceHandler_.setDisplayMode(SurfaceHandler::DisplayMode::Visible);
|
||||
if (surfaceHandler_.getStatus() != SurfaceHandler::Status::Running) {
|
||||
surfaceHandler_.start();
|
||||
}
|
||||
}
|
||||
|
||||
void SurfaceHandlerBinding::stop() {
|
||||
std::unique_lock<better::shared_mutex> lock(lifecycleMutex_);
|
||||
|
||||
if (surfaceHandler_.getStatus() == SurfaceHandler::Status::Running) {
|
||||
surfaceHandler_.stop();
|
||||
}
|
||||
}
|
||||
|
||||
jint SurfaceHandlerBinding::getSurfaceId() {
|
||||
return surfaceHandler_.getSurfaceId();
|
||||
}
|
||||
|
||||
void SurfaceHandlerBinding::setSurfaceId(jint surfaceId) {
|
||||
surfaceHandler_.setSurfaceId(surfaceId);
|
||||
}
|
||||
|
||||
jboolean SurfaceHandlerBinding::isRunning() {
|
||||
return surfaceHandler_.getStatus() == SurfaceHandler::Status::Running;
|
||||
}
|
||||
|
||||
jni::local_ref<jstring> SurfaceHandlerBinding::getModuleName() {
|
||||
return jni::make_jstring(surfaceHandler_.getModuleName());
|
||||
}
|
||||
|
||||
jni::local_ref<SurfaceHandlerBinding::jhybriddata>
|
||||
SurfaceHandlerBinding::initHybrid(
|
||||
jni::alias_ref<jclass>,
|
||||
jint surfaceId,
|
||||
jni::alias_ref<jstring> moduleName) {
|
||||
auto env = jni::Environment::current();
|
||||
const char *moduleNameValue =
|
||||
env->GetStringUTFChars(moduleName.get(), JNI_FALSE);
|
||||
env->ReleaseStringUTFChars(moduleName.get(), moduleNameValue);
|
||||
|
||||
return makeCxxInstance(surfaceId, moduleNameValue);
|
||||
}
|
||||
|
||||
void SurfaceHandlerBinding::registerScheduler(
|
||||
std::shared_ptr<Scheduler> scheduler) {
|
||||
scheduler->registerSurface(surfaceHandler_);
|
||||
}
|
||||
|
||||
void SurfaceHandlerBinding::unregisterScheduler(
|
||||
std::shared_ptr<Scheduler> scheduler) {
|
||||
scheduler->unregisterSurface(surfaceHandler_);
|
||||
}
|
||||
|
||||
void SurfaceHandlerBinding::setLayoutConstraints(
|
||||
jfloat minWidth,
|
||||
jfloat maxWidth,
|
||||
jfloat minHeight,
|
||||
jfloat maxHeight,
|
||||
jfloat offsetX,
|
||||
jfloat offsetY,
|
||||
jboolean doLeftAndRightSwapInRTL,
|
||||
jboolean isRTL,
|
||||
jfloat pixelDensity) {
|
||||
LayoutConstraints constraints = {};
|
||||
constraints.minimumSize = {minWidth, minHeight};
|
||||
constraints.maximumSize = {maxWidth, maxHeight};
|
||||
constraints.layoutDirection =
|
||||
isRTL ? LayoutDirection::RightToLeft : LayoutDirection::LeftToRight;
|
||||
|
||||
LayoutContext context = {};
|
||||
context.swapLeftAndRightInRTL = doLeftAndRightSwapInRTL;
|
||||
context.pointScaleFactor = pixelDensity;
|
||||
context.viewportOffset = {offsetX, offsetY};
|
||||
|
||||
surfaceHandler_.constraintLayout(constraints, context);
|
||||
}
|
||||
|
||||
void SurfaceHandlerBinding::setProps(NativeMap *props) {
|
||||
surfaceHandler_.setProps(props->consume());
|
||||
}
|
||||
|
||||
void SurfaceHandlerBinding::registerNatives() {
|
||||
registerHybrid({
|
||||
makeNativeMethod("initHybrid", SurfaceHandlerBinding::initHybrid),
|
||||
makeNativeMethod(
|
||||
"getSurfaceIdNative", SurfaceHandlerBinding::getSurfaceId),
|
||||
makeNativeMethod(
|
||||
"setSurfaceIdNative", SurfaceHandlerBinding::setSurfaceId),
|
||||
makeNativeMethod("isRunningNative", SurfaceHandlerBinding::isRunning),
|
||||
makeNativeMethod(
|
||||
"getModuleNameNative", SurfaceHandlerBinding::getModuleName),
|
||||
makeNativeMethod("startNative", SurfaceHandlerBinding::start),
|
||||
makeNativeMethod("stopNative", SurfaceHandlerBinding::stop),
|
||||
makeNativeMethod(
|
||||
"setLayoutConstraintsNative",
|
||||
SurfaceHandlerBinding::setLayoutConstraints),
|
||||
makeNativeMethod("setPropsNative", SurfaceHandlerBinding::setProps),
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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/jni/ReadableNativeMap.h>
|
||||
#include <react/renderer/scheduler/SurfaceHandler.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class SurfaceHandlerBinding : public jni::HybridClass<SurfaceHandlerBinding> {
|
||||
public:
|
||||
constexpr static const char *const kJavaDescriptor =
|
||||
"Lcom/facebook/react/fabric/SurfaceHandlerBinding;";
|
||||
|
||||
static void registerNatives();
|
||||
|
||||
SurfaceHandlerBinding(SurfaceId surfaceId, std::string const &moduleName);
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
void registerScheduler(std::shared_ptr<Scheduler> scheduler);
|
||||
void unregisterScheduler(std::shared_ptr<Scheduler> scheduler);
|
||||
|
||||
jint getSurfaceId();
|
||||
void setSurfaceId(jint surfaceId);
|
||||
jni::local_ref<jstring> getModuleName();
|
||||
|
||||
jboolean isRunning();
|
||||
|
||||
void setLayoutConstraints(
|
||||
jfloat minWidth,
|
||||
jfloat maxWidth,
|
||||
jfloat minHeight,
|
||||
jfloat maxHeight,
|
||||
jfloat offsetX,
|
||||
jfloat offsetY,
|
||||
jboolean doLeftAndRightSwapInRTL,
|
||||
jboolean isRTL,
|
||||
jfloat pixelDensity);
|
||||
|
||||
void setProps(NativeMap *props);
|
||||
|
||||
private:
|
||||
mutable better::shared_mutex lifecycleMutex_;
|
||||
const SurfaceHandler surfaceHandler_;
|
||||
|
||||
jni::alias_ref<SurfaceHandlerBinding::jhybriddata> jhybridobject_;
|
||||
|
||||
static jni::local_ref<jhybriddata> initHybrid(
|
||||
jni::alias_ref<jclass>,
|
||||
jint surfaceId,
|
||||
jni::alias_ref<jstring> moduleName);
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
Reference in New Issue
Block a user