Fix setting js responder for null react view for tag

Reviewed By: kmagiera

Differential Revision: D2637015

fb-gh-sync-id: 03af870cee82519ed34a4bbbcbd2c72146fcf00f
This commit is contained in:
Andrei Coman
2015-11-18 03:18:29 -08:00
committed by facebook-github-bot-4
parent d5daef08ef
commit 32c19c1994
3 changed files with 39 additions and 12 deletions

View File

@@ -442,13 +442,26 @@ import com.facebook.react.touch.JSResponderHandler;
return TouchTargetHelper.findTargetTagForTouch(touchY, touchX, (ViewGroup) view); return TouchTargetHelper.findTargetTagForTouch(touchY, touchX, (ViewGroup) view);
} }
public void setJSResponder(int reactTag, boolean blockNativeResponder) { public void setJSResponder(int reactTag, int initialReactTag, boolean blockNativeResponder) {
if (!blockNativeResponder) {
mJSResponderHandler.setJSResponder(initialReactTag, null);
return;
}
View view = mTagsToViews.get(reactTag);
if (initialReactTag != reactTag && view instanceof ViewParent) {
// In this case, initialReactTag corresponds to a virtual/layout-only View, and we already
// have a parent of that View in reactTag, so we can use it.
mJSResponderHandler.setJSResponder(initialReactTag, (ViewParent) view);
return;
}
if (mRootTags.get(reactTag)) { if (mRootTags.get(reactTag)) {
SoftAssertions.assertUnreachable( SoftAssertions.assertUnreachable(
"Cannot block native responder on " + reactTag + " that is a root view"); "Cannot block native responder on " + reactTag + " that is a root view");
} }
ViewParent viewParent = blockNativeResponder ? mTagsToViews.get(reactTag).getParent() : null; mJSResponderHandler
mJSResponderHandler.setJSResponder(reactTag, viewParent); .setJSResponder(initialReactTag, view.getParent());
} }
public void clearJSResponder() { public void clearJSResponder() {

View File

@@ -20,16 +20,14 @@ import java.util.concurrent.TimeUnit;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import com.facebook.csslayout.CSSLayoutContext; import com.facebook.csslayout.CSSLayoutContext;
import com.facebook.infer.annotation.Assertions;
import com.facebook.react.animation.Animation; import com.facebook.react.animation.Animation;
import com.facebook.react.animation.AnimationRegistry; import com.facebook.react.animation.AnimationRegistry;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.debug.NotThreadSafeUiManagerDebugListener;
import com.facebook.react.uimanager.events.EventDispatcher;
import com.facebook.infer.annotation.Assertions;
import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.LifecycleEventListener; import com.facebook.react.bridge.LifecycleEventListener;
import com.facebook.react.bridge.OnBatchCompleteListener; import com.facebook.react.bridge.OnBatchCompleteListener;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableArray;
@@ -37,6 +35,8 @@ import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.SoftAssertions; import com.facebook.react.bridge.SoftAssertions;
import com.facebook.react.bridge.UiThreadUtil; import com.facebook.react.bridge.UiThreadUtil;
import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableArray;
import com.facebook.react.uimanager.debug.NotThreadSafeUiManagerDebugListener;
import com.facebook.react.uimanager.events.EventDispatcher;
import com.facebook.systrace.Systrace; import com.facebook.systrace.Systrace;
import com.facebook.systrace.SystraceMessage; import com.facebook.systrace.SystraceMessage;
@@ -664,7 +664,11 @@ public class UIManagerModule extends ReactContextBaseJavaModule implements
@ReactMethod @ReactMethod
public void setJSResponder(int reactTag, boolean blockNativeResponder) { public void setJSResponder(int reactTag, boolean blockNativeResponder) {
assertViewExists(reactTag, "setJSResponder"); assertViewExists(reactTag, "setJSResponder");
mOperationsQueue.enqueueSetJSResponder(reactTag, blockNativeResponder); ReactShadowNode node = mShadowNodeRegistry.getNode(reactTag);
while (node.isVirtual() || node.isLayoutOnly()) {
node = node.getParent();
}
mOperationsQueue.enqueueSetJSResponder(node.getReactTag(), reactTag, blockNativeResponder);
} }
@ReactMethod @ReactMethod

View File

@@ -186,14 +186,17 @@ public class UIViewOperationQueue {
private final class ChangeJSResponderOperation extends ViewOperation { private final class ChangeJSResponderOperation extends ViewOperation {
private final int mInitialTag;
private final boolean mBlockNativeResponder; private final boolean mBlockNativeResponder;
private final boolean mClearResponder; private final boolean mClearResponder;
public ChangeJSResponderOperation( public ChangeJSResponderOperation(
int tag, int tag,
int initialTag,
boolean clearResponder, boolean clearResponder,
boolean blockNativeResponder) { boolean blockNativeResponder) {
super(tag); super(tag);
mInitialTag = initialTag;
mClearResponder = clearResponder; mClearResponder = clearResponder;
mBlockNativeResponder = blockNativeResponder; mBlockNativeResponder = blockNativeResponder;
} }
@@ -201,7 +204,7 @@ public class UIViewOperationQueue {
@Override @Override
public void execute() { public void execute() {
if (!mClearResponder) { if (!mClearResponder) {
mNativeViewHierarchyManager.setJSResponder(mTag, mBlockNativeResponder); mNativeViewHierarchyManager.setJSResponder(mTag, mInitialTag, mBlockNativeResponder);
} else { } else {
mNativeViewHierarchyManager.clearJSResponder(); mNativeViewHierarchyManager.clearJSResponder();
} }
@@ -450,14 +453,21 @@ public class UIViewOperationQueue {
mOperations.add(new RemoveRootViewOperation(rootViewTag)); mOperations.add(new RemoveRootViewOperation(rootViewTag));
} }
public void enqueueSetJSResponder(int reactTag, boolean blockNativeResponder) { public void enqueueSetJSResponder(
int tag,
int initialTag,
boolean blockNativeResponder) {
mOperations.add( mOperations.add(
new ChangeJSResponderOperation(reactTag, false /*clearResponder*/, blockNativeResponder)); new ChangeJSResponderOperation(
tag,
initialTag,
false /*clearResponder*/,
blockNativeResponder));
} }
public void enqueueClearJSResponder() { public void enqueueClearJSResponder() {
// Tag is 0 because JSResponderHandler doesn't need one in order to clear the responder. // Tag is 0 because JSResponderHandler doesn't need one in order to clear the responder.
mOperations.add(new ChangeJSResponderOperation(0, true /*clearResponder*/, false)); mOperations.add(new ChangeJSResponderOperation(0, 0, true /*clearResponder*/, false));
} }
public void enqueueDispatchCommand( public void enqueueDispatchCommand(