Skip to content

Commit 8774947

Browse files
Abbondanzofacebook-github-bot
authored andcommitted
Ensure active touches are swept before accepting a child native gesture (#52995)
Summary: Pull Request resolved: #52995 Fabric retains views by ID when `JSTouchDispatcher` receives a touch event, but does not sweep these same views if a child native gesture is started between the `ACTION_DOWN` and `ACTION_UP` actions of the touch. As a result, we never end up calling into that view's manager's `onDropViewInstance` method and can't perform reliable teardown of the view since it's stuck in this "touched" state. This is change adds a new condition to check if `JSTouchDispatcher` should sweep active touches when a child native gesture is started, and only applies the check to `ReactSurfaceView` to start. The check is also only enabled if the `sweepActiveTouchOnChildNativeGesturesAndroid` flag is set. Changelog: [Internal] Reviewed By: jehartzog Differential Revision: D79230277 fbshipit-source-id: c15b888ec932319f1bda05b8ef5eec39e5d08710
1 parent f2964e1 commit 8774947

2 files changed

Lines changed: 20 additions & 1 deletion

File tree

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactSurfaceView.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,8 @@ public class ReactSurfaceView(context: Context?, private val surface: ReactSurfa
116116
*/
117117
override fun onChildStartedNativeGesture(childView: View?, ev: MotionEvent) {
118118
val eventDispatcher = surface.eventDispatcher ?: return
119-
jsTouchDispatcher.onChildStartedNativeGesture(ev, eventDispatcher)
119+
jsTouchDispatcher.onChildStartedNativeGesture(
120+
ev, eventDispatcher, surface.reactHost?.currentReactContext)
120121
childView?.let { jsPointerDispatcher?.onChildStartedNativeGesture(it, ev, eventDispatcher) }
121122
}
122123

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSTouchDispatcher.kt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import com.facebook.common.logging.FLog
1313
import com.facebook.infer.annotation.Assertions
1414
import com.facebook.react.bridge.ReactContext
1515
import com.facebook.react.common.ReactConstants
16+
import com.facebook.react.common.annotations.UnstableReactNativeAPI
17+
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
1618
import com.facebook.react.uimanager.common.UIManagerType
1719
import com.facebook.react.uimanager.events.EventDispatcher
1820
import com.facebook.react.uimanager.events.TouchEvent
@@ -33,9 +35,19 @@ public class JSTouchDispatcher(private val viewGroup: ViewGroup) {
3335
private val touchEventCoalescingKeyHelper: TouchEventCoalescingKeyHelper =
3436
TouchEventCoalescingKeyHelper()
3537

38+
@OptIn(UnstableReactNativeAPI::class)
3639
public fun onChildStartedNativeGesture(
3740
androidEvent: MotionEvent,
3841
eventDispatcher: EventDispatcher
42+
) {
43+
onChildStartedNativeGesture(androidEvent, eventDispatcher, null)
44+
}
45+
46+
@UnstableReactNativeAPI
47+
public fun onChildStartedNativeGesture(
48+
androidEvent: MotionEvent,
49+
eventDispatcher: EventDispatcher,
50+
reactContext: ReactContext?,
3951
) {
4052
if (childIsHandlingNativeGesture) {
4153
// This means we previously had another child start handling this native gesture and now a
@@ -46,6 +58,12 @@ public class JSTouchDispatcher(private val viewGroup: ViewGroup) {
4658

4759
dispatchCancelEvent(androidEvent, eventDispatcher)
4860
childIsHandlingNativeGesture = true
61+
62+
if (targetTag != -1 && ReactNativeFeatureFlags.sweepActiveTouchOnChildNativeGesturesAndroid()) {
63+
val surfaceId = UIManagerHelper.getSurfaceId(viewGroup)
64+
sweepActiveTouchForTag(surfaceId, targetTag, reactContext)
65+
}
66+
4967
targetTag = -1
5068
}
5169

0 commit comments

Comments
 (0)