From 44bfc4be447680096f01fd00a1344c2cd398a981 Mon Sep 17 00:00:00 2001 From: Joshua Gross Date: Tue, 27 Aug 2019 18:46:40 -0700 Subject: [PATCH] Support for UpdatePaddingMountItem Summary: Some views (TextInput!) need padding props. Reviewed By: mdvacca Differential Revision: D17081799 fbshipit-source-id: 4f5d6a139bb4dd878f90af0ed4a30fe3810e3429 --- .../react/fabric/FabricJSIModuleProvider.java | 2 + .../react/fabric/FabricUIManager.java | 7 +++ .../com/facebook/react/fabric/jni/Binding.cpp | 40 +++++++++++++++ .../fabric/mounting/MountingManager.java | 18 +++++++ .../mountitems/UpdatePaddingMountItem.java | 51 +++++++++++++++++++ 5 files changed, 118 insertions(+) create mode 100644 ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/UpdatePaddingMountItem.java diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricJSIModuleProvider.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricJSIModuleProvider.java index 47f6ffbc4f6dec..e38da400e9772c 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricJSIModuleProvider.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricJSIModuleProvider.java @@ -22,6 +22,7 @@ import com.facebook.react.fabric.mounting.mountitems.UpdateEventEmitterMountItem; import com.facebook.react.fabric.mounting.mountitems.UpdateLayoutMountItem; import com.facebook.react.fabric.mounting.mountitems.UpdateLocalDataMountItem; +import com.facebook.react.fabric.mounting.mountitems.UpdatePaddingMountItem; import com.facebook.react.fabric.mounting.mountitems.UpdatePropsMountItem; import com.facebook.react.uimanager.StateWrapper; import com.facebook.react.uimanager.UIManagerModule; @@ -108,6 +109,7 @@ private static void loadClasses() { UpdateEventEmitterMountItem.class.getClass(); UpdateLayoutMountItem.class.getClass(); UpdateLocalDataMountItem.class.getClass(); + UpdatePaddingMountItem.class.getClass(); UpdatePropsMountItem.class.getClass(); LayoutMetricsConversions.class.getClass(); MountingManager.class.getClass(); diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java index 515c10b4e290c7..2bfa8d17798bbb 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java @@ -54,6 +54,7 @@ import com.facebook.react.fabric.mounting.mountitems.UpdateEventEmitterMountItem; import com.facebook.react.fabric.mounting.mountitems.UpdateLayoutMountItem; import com.facebook.react.fabric.mounting.mountitems.UpdateLocalDataMountItem; +import com.facebook.react.fabric.mounting.mountitems.UpdatePaddingMountItem; import com.facebook.react.fabric.mounting.mountitems.UpdatePropsMountItem; import com.facebook.react.fabric.mounting.mountitems.UpdateStateMountItem; import com.facebook.react.modules.core.ReactChoreographer; @@ -285,6 +286,12 @@ private MountItem updateLayoutMountItem( return new UpdateLayoutMountItem(reactTag, x, y, width, height, layoutDirection); } + @DoNotStrip + @SuppressWarnings("unused") + private MountItem updatePaddingMountItem(int reactTag, int left, int top, int right, int bottom) { + return new UpdatePaddingMountItem(reactTag, left, top, right, bottom); + } + @DoNotStrip @SuppressWarnings("unused") private MountItem updatePropsMountItem(int reactTag, ReadableMap map) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp index 94ef5ef5e49fe5..2a7dfede65ab1d 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp @@ -338,6 +338,34 @@ local_ref createUpdateLayoutMountItem( return nullptr; } +local_ref createUpdatePaddingMountItem( + const jni::global_ref &javaUIManager, + const ShadowViewMutation &mutation) { + + auto oldChildShadowView = mutation.oldChildShadowView; + auto newChildShadowView = mutation.newChildShadowView; + + if (oldChildShadowView.layoutMetrics.contentInsets == newChildShadowView.layoutMetrics.contentInsets) { + return nullptr; + } + + static auto updateLayoutInstruction = + jni::findClassStatic(UIManagerJavaDescriptor) + ->getMethod(jint, jint, jint, jint, jint)>( + "updatePaddingMountItem"); + + auto layoutMetrics = newChildShadowView.layoutMetrics; + auto pointScaleFactor = layoutMetrics.pointScaleFactor; + auto contentInsets = layoutMetrics.contentInsets; + + int left = round(contentInsets.left * pointScaleFactor); + int top = round(contentInsets.top * pointScaleFactor); + int right = round(contentInsets.right * pointScaleFactor); + int bottom = round(contentInsets.bottom * pointScaleFactor); + + return updateLayoutInstruction(javaUIManager, newChildShadowView.tag, left, top, right, bottom); +} + local_ref createInsertMountItem( const jni::global_ref &javaUIManager, const ShadowViewMutation &mutation) { @@ -559,6 +587,11 @@ void Binding::schedulerDidFinishTransaction( if (updateLayoutMountItem) { mountItems[position++] = updateLayoutMountItem; } + + auto updatePaddingMountItem = createUpdatePaddingMountItem(localJavaUIManager, mutation); + if (updatePaddingMountItem) { + mountItems[position++] = updatePaddingMountItem; + } } if (mutation.oldChildShadowView.eventEmitter != @@ -602,6 +635,13 @@ void Binding::schedulerDidFinishTransaction( if (updateLayoutMountItem) { mountItems[position++] = updateLayoutMountItem; } + + // Padding + auto updatePaddingMountItem = + createUpdatePaddingMountItem(localJavaUIManager, mutation); + if (updatePaddingMountItem) { + mountItems[position++] = updatePaddingMountItem; + } } // EventEmitter diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountingManager.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountingManager.java index fbc3f0018525d5..f48548fbe1d653 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountingManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountingManager.java @@ -246,6 +246,24 @@ public void updateLayout(int reactTag, int x, int y, int width, int height) { viewToUpdate.layout(x, y, x + width, y + height); } + @UiThread + public void updatePadding(int reactTag, int left, int top, int right, int bottom) { + UiThreadUtil.assertOnUiThread(); + + ViewState viewState = getViewState(reactTag); + // Do not layout Root Views + if (viewState.mIsRoot) { + return; + } + + View viewToUpdate = viewState.mView; + if (viewToUpdate == null) { + throw new IllegalStateException("Unable to find View for tag: " + reactTag); + } + + viewToUpdate.setPadding(left, top, right, bottom); + } + @UiThread public void deleteView(int reactTag) { UiThreadUtil.assertOnUiThread(); diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/UpdatePaddingMountItem.java b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/UpdatePaddingMountItem.java new file mode 100644 index 00000000000000..446bece80afb99 --- /dev/null +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/UpdatePaddingMountItem.java @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2014-present, Facebook, Inc. + * + *

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.mounting.mountitems; + +import com.facebook.react.fabric.mounting.MountingManager; + +/** + * A MountItem that represents setting the padding properties of a view (left, top, right, bottom). + * This is distinct from layout because it happens far less frequently from layout; so it is a perf + * optimization to transfer this data and execute the methods strictly less than the layout-related + * properties. + */ +public class UpdatePaddingMountItem implements MountItem { + + private final int mReactTag; + private final int mLeft; + private final int mTop; + private final int mRight; + private final int mBottom; + + public UpdatePaddingMountItem(int reactTag, int left, int top, int right, int bottom) { + mReactTag = reactTag; + mLeft = left; + mTop = top; + mRight = right; + mBottom = bottom; + } + + @Override + public void execute(MountingManager mountingManager) { + mountingManager.updatePadding(mReactTag, mLeft, mTop, mRight, mBottom); + } + + @Override + public String toString() { + return "UpdatePaddingMountItem [" + + mReactTag + + "] - left: " + + mLeft + + " - top: " + + mTop + + " - right: " + + mRight + + " - bottom: " + + mBottom; + } +}