Skip to content

Commit e0a453c

Browse files
Abbondanzometa-codesync[bot]
authored andcommitted
Dispatch FPS events from ACTION_SCROLL events (#56601)
Summary: Pull Request resolved: #56601 `ACTION_SCROLL` events (mouse wheel, trackpad, joystick) were not participating in FPS performance logging. Touch-driven scrolls already called `enableFpsListener`/`disableFpsListener` through `handlePostTouchScrolling`, which uses a stable-frames heuristic to detect when scrolling has settled (3 consecutive frames with no position change). ACTION_SCROLL events bypassed this entirely. This adds FPS listener support to the `ACTION_SCROLL` path by calling `enableFpsListener` when a scroll event arrives, then delegating to `handlePostTouchScrolling` for lifecycle management: - **Snapping ScrollViews (`ReactScrollView`, `ReactHorizontalScrollView`):** The existing debounce runnable calls `flingAndSnap` to animate to a snap point. After the snap, `handlePostTouchScrolling` monitors the animation via the stable-frames mechanism and disables the FPS listener once settled. - **Non-snapping ScrollViews (`ReactScrollView`):** `handlePostTouchScrolling` is called directly. Its re-entry guard (`mPostTouchRunnable != null`) naturally deduplicates across rapid scroll events, while `onScrollChanged` keeps the monitor alive by setting `mActivelyScrolling`. Also nulls `mPostTouchRunnable` before reassignment in the debounce cancel path to avoid stale references. Changelog: [Android][Fixed] - Dispatch FPS performance events for mouse wheel and trackpad scroll interactions in ScrollView Reviewed By: javache, jehartzog Differential Revision: D102347043 fbshipit-source-id: aab91858404db54b1c44146d4d071193baaae7a1
1 parent 610564c commit e0a453c

3 files changed

Lines changed: 18 additions & 2 deletions

File tree

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -859,16 +859,18 @@ public boolean dispatchGenericMotionEvent(MotionEvent ev) {
859859
float hScroll = ev.getAxisValue(MotionEvent.AXIS_HSCROLL);
860860
if (hScroll != 0) {
861861
// Perform the scroll
862+
enableFpsListener();
862863
boolean result = super.dispatchGenericMotionEvent(ev);
863864
// Schedule snap alignment to run after scrolling stops
864865
if (result
865866
&& (mPagingEnabled
866867
|| mSnapInterval != 0
867868
|| mSnapOffsets != null
868869
|| mSnapToAlignment != SNAP_ALIGNMENT_DISABLED)) {
869-
// Cancel any pending runnable and reschedule
870+
// Cancel any pending post-touch runnable and reschedule
870871
if (mPostTouchRunnable != null) {
871872
removeCallbacks(mPostTouchRunnable);
873+
mPostTouchRunnable = null;
872874
}
873875
mPostTouchRunnable =
874876
new Runnable() {
@@ -882,9 +884,12 @@ public void run() {
882884
velocityX = 0;
883885
}
884886
flingAndSnap(velocityX);
887+
handlePostTouchScrolling(velocityX, 0);
885888
}
886889
};
887890
postOnAnimationDelayed(mPostTouchRunnable, ReactScrollViewHelper.MOMENTUM_DELAY);
891+
} else {
892+
handlePostTouchScrolling(0, 0);
888893
}
889894
return result;
890895
}
@@ -1212,6 +1217,7 @@ public void run() {
12121217
}
12131218
ReactScrollViewHelper.notifyUserDrivenScrollEnded_internal(
12141219
ReactHorizontalScrollView.this);
1220+
disableFpsListener();
12151221
} else {
12161222
if (mPagingEnabled && !mSnappingToPage) {
12171223
// If we have pagingEnabled and we have not snapped to the page

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactNestedScrollView.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<a0490be2c6f7eb42376e8e64abf9ce5e>>
7+
* @generated SignedSource<<41d03f4948562c0fae870a660e6e1eac>>
88
*/
99

1010
/**
@@ -700,6 +700,7 @@ public boolean dispatchGenericMotionEvent(MotionEvent ev) {
700700
float vScroll = ev.getAxisValue(MotionEvent.AXIS_VSCROLL);
701701
if (vScroll != 0) {
702702
// Perform the scroll
703+
enableFpsListener();
703704
boolean result = super.dispatchGenericMotionEvent(ev);
704705
// Schedule snap alignment to run after scrolling stops
705706
if (result
@@ -710,6 +711,7 @@ public boolean dispatchGenericMotionEvent(MotionEvent ev) {
710711
// Cancel any pending post-touch runnable and reschedule
711712
if (mPostTouchRunnable != null) {
712713
removeCallbacks(mPostTouchRunnable);
714+
mPostTouchRunnable = null;
713715
}
714716
mPostTouchRunnable =
715717
new Runnable() {
@@ -723,9 +725,12 @@ public void run() {
723725
velocityY = 0;
724726
}
725727
flingAndSnap(velocityY);
728+
handlePostTouchScrolling(0, velocityY);
726729
}
727730
};
728731
postOnAnimationDelayed(mPostTouchRunnable, ReactScrollViewHelper.MOMENTUM_DELAY);
732+
} else {
733+
handlePostTouchScrolling(0, 0);
729734
}
730735
return result;
731736
}

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,7 @@ public boolean dispatchGenericMotionEvent(MotionEvent ev) {
692692
float vScroll = ev.getAxisValue(MotionEvent.AXIS_VSCROLL);
693693
if (vScroll != 0) {
694694
// Perform the scroll
695+
enableFpsListener();
695696
boolean result = super.dispatchGenericMotionEvent(ev);
696697
// Schedule snap alignment to run after scrolling stops
697698
if (result
@@ -702,6 +703,7 @@ public boolean dispatchGenericMotionEvent(MotionEvent ev) {
702703
// Cancel any pending post-touch runnable and reschedule
703704
if (mPostTouchRunnable != null) {
704705
removeCallbacks(mPostTouchRunnable);
706+
mPostTouchRunnable = null;
705707
}
706708
mPostTouchRunnable =
707709
new Runnable() {
@@ -715,9 +717,12 @@ public void run() {
715717
velocityY = 0;
716718
}
717719
flingAndSnap(velocityY);
720+
handlePostTouchScrolling(0, velocityY);
718721
}
719722
};
720723
postOnAnimationDelayed(mPostTouchRunnable, ReactScrollViewHelper.MOMENTUM_DELAY);
724+
} else {
725+
handlePostTouchScrolling(0, 0);
721726
}
722727
return result;
723728
}

0 commit comments

Comments
 (0)