From 6273834cc3be2c8fb1b42799ceb31ff92830fcec Mon Sep 17 00:00:00 2001 From: Fabrizio Cucci Date: Thu, 22 Jan 2026 06:12:56 -0800 Subject: [PATCH] Fix crash when dispatching cancel events to reparented views Summary: Changelog: [Internal] When `FloatingView` reparents its content to a `SurfaceControlViewHost` (for z-offset elevation), the child views are no longer descendants of the main React root view hierarchy. If a pointer cancel event is dispatched while the view is in this state, `JSPointerDispatcher.getChildOffsetRelativeToRoot()` calls `offsetDescendantRectToMyCoords()` which throws `IllegalArgumentException: parameter must be a descendant of this view`. This fix makes `getChildOffsetRelativeToRoot()` return `null` when the view is not a descendant (catching only the specific "descendant" exception), and skips dispatching the cancel event in that case while still cleaning up internal pointer state. This crash was occurring in IGVR when scrolling through story pogs with thumbstick input, as each pog uses `FloatingView` with elevation. Reviewed By: javache Differential Revision: D90988373 --- .../com/facebook/react/uimanager/JSPointerDispatcher.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSPointerDispatcher.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSPointerDispatcher.java index 25e8f6fc0862..f418ce62ff31 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSPointerDispatcher.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/JSPointerDispatcher.java @@ -678,6 +678,12 @@ private void dispatchCancelEventForTarget( // returns child (0, 0) relative to root coordinate system private int[] getChildOffsetRelativeToRoot(View childView) { + if (childView.getRootView() != mRootViewGroup.getRootView()) { + // NOTE: if we are here it means the target view has been reparented, so we can't call + // mRootViewGroup.offsetDescendantRectToMyCoords because an exception will be thrown. + // We still return (0, 0) to ensure the cancel event is dispatched. + return new int[] {0, 0}; + } Rect childCoords = new Rect(0, 0, 1, 1); mRootViewGroup.offsetDescendantRectToMyCoords(childView, childCoords); return new int[] {childCoords.top, childCoords.left};