Fix: text selection context menu should reappear after a non-fling scroll on Android and iOS#185054
Conversation
…e in same frame ScrollEndNotification (from a drag ending) and ScrollStartNotification (from the subsequent ballistic animation) can be dispatched in the same build phase. The previous addPostFrameCallback ran after both had been processed, showing the toolbar during an active ballistic scroll. Replaced addPostFrameCallback with scheduleFrameCallback so the toolbar-show logic runs at the beginning of the next frame, before any new scroll notifications are dispatched in that frame's build phase.
There was a problem hiding this comment.
Code Review
This pull request modifies EditableText to use scheduleFrameCallback instead of addPostFrameCallback for toolbar scheduling and adds a regression test for context menu visibility during scrolls when semantics are disabled. Review feedback suggests reverting to addPostFrameCallback to ensure accurate positioning after layout, using ensureVisualUpdate() to guarantee the callback executes, and restoring the debugLabel for improved debuggability.
| } | ||
| _showToolbarOnScreenScheduled = true; | ||
| SchedulerBinding.instance.addPostFrameCallback((Duration _) { | ||
| SchedulerBinding.instance.scheduleFrameCallback((Duration _) { |
There was a problem hiding this comment.
Using scheduleFrameCallback changes the execution timing to the transient phase of the frame (before layout and paint). For a context menu that needs to be positioned accurately relative to the text, it is generally safer to use addPostFrameCallback to ensure that any layout changes (such as those from the scroll) have been applied. To address the issue where no frame is scheduled after a non-fling scroll, you can call SchedulerBinding.instance.ensureVisualUpdate() after registering the callback.
SchedulerBinding.instance.addPostFrameCallback((Duration _) {There was a problem hiding this comment.
I don't see any precedent for using ensureVisualUpdate outside of binding.dart. I've updated the implementation to call addPostFrameCallback when the scheduler phase is within an active frame, scheduling a post frame callback here ensures the callback will run after that frame. If we are in the idle phase or postFrameCallback phase we cannot guarantee that there is another frame after so we have to call scheduleFrameCallback in that scenario.
| _dataWhenToolbarShowScheduled = null; | ||
| } | ||
| }, debugLabel: 'EditableText.scheduleToolbar'); | ||
| }); |
There was a problem hiding this comment.
There was a problem hiding this comment.
I don't see any precedent for using ensureVisualUpdate outside of binding.dart so i'm not sure if that's the direction we want to go in.
|
Opened up #185230 , the behavior before/after this PR is the same with system context menus. |
…n-fling scroll on Android and iOS (flutter/flutter#185054)
…n-fling scroll on Android and iOS (flutter/flutter#185054)
…n-fling scroll on Android and iOS (flutter/flutter#185054)
…n-fling scroll on Android and iOS (flutter/flutter#185054)
flutter/flutter@8e8a194...2844af6 2026-04-19 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from bWoigpGIb60B6C7hD... to aDbXQm6WA0wFCAUp-... (flutter/flutter#185253) 2026-04-18 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from di3JdYrdE9OFu8Iyl... to bWoigpGIb60B6C7hD... (flutter/flutter#185231) 2026-04-18 rmolivares@renzo-olivares.dev Fix: text selection context menu should reappear after a non-fling scroll on Android and iOS (flutter/flutter#185054) 2026-04-18 flar@google.com Rect constructors for circle bounds (MakeCircle/EllipseBounds) (flutter/flutter#185110) 2026-04-17 97480502+b-luk@users.noreply.github.com Change uber SDF to get pixel size (for AA) using euclidean distance rather than manhattan distance. (flutter/flutter#184984) 2026-04-17 engine-flutter-autoroll@skia.org Roll Dart SDK from 7c2564c18770 to 9648f446f131 (7 revisions) (flutter/flutter#185223) 2026-04-17 47866232+chunhtai@users.noreply.github.com Rewrites no-response workflow to work with pr as well (flutter/flutter#185163) 2026-04-17 15619084+vashworth@users.noreply.github.com Only use LLDB breakpoint in debug mode (flutter/flutter#185158) 2026-04-17 flar@google.com add playground to test SDF primitive rendering under transforms (flutter/flutter#185010) 2026-04-17 30870216+gaaclarke@users.noreply.github.com Adds sdf rrects (and fixes opacity + color source) (flutter/flutter#184999) 2026-04-17 matt.kosarek@canonical.com Implementation of popup windows for Win32 (flutter/flutter#184516) 2026-04-17 engine-flutter-autoroll@skia.org Roll Fuchsia Test Scripts from R2EllDf4DgBXVNuiN... to dQ4PjIJB5kZFU8Y32... (flutter/flutter#185207) 2026-04-17 chris@bracken.jp [iOS] Update previousCompositionOrder to return Obj-C type (flutter/flutter#185136) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages Please CC boetger@google.com,stuartmorgan@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
…r#11531) flutter/flutter@8e8a194...2844af6 2026-04-19 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from bWoigpGIb60B6C7hD... to aDbXQm6WA0wFCAUp-... (flutter/flutter#185253) 2026-04-18 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from di3JdYrdE9OFu8Iyl... to bWoigpGIb60B6C7hD... (flutter/flutter#185231) 2026-04-18 rmolivares@renzo-olivares.dev Fix: text selection context menu should reappear after a non-fling scroll on Android and iOS (flutter/flutter#185054) 2026-04-18 flar@google.com Rect constructors for circle bounds (MakeCircle/EllipseBounds) (flutter/flutter#185110) 2026-04-17 97480502+b-luk@users.noreply.github.com Change uber SDF to get pixel size (for AA) using euclidean distance rather than manhattan distance. (flutter/flutter#184984) 2026-04-17 engine-flutter-autoroll@skia.org Roll Dart SDK from 7c2564c18770 to 9648f446f131 (7 revisions) (flutter/flutter#185223) 2026-04-17 47866232+chunhtai@users.noreply.github.com Rewrites no-response workflow to work with pr as well (flutter/flutter#185163) 2026-04-17 15619084+vashworth@users.noreply.github.com Only use LLDB breakpoint in debug mode (flutter/flutter#185158) 2026-04-17 flar@google.com add playground to test SDF primitive rendering under transforms (flutter/flutter#185010) 2026-04-17 30870216+gaaclarke@users.noreply.github.com Adds sdf rrects (and fixes opacity + color source) (flutter/flutter#184999) 2026-04-17 matt.kosarek@canonical.com Implementation of popup windows for Win32 (flutter/flutter#184516) 2026-04-17 engine-flutter-autoroll@skia.org Roll Fuchsia Test Scripts from R2EllDf4DgBXVNuiN... to dQ4PjIJB5kZFU8Y32... (flutter/flutter#185207) 2026-04-17 chris@bracken.jp [iOS] Update previousCompositionOrder to return Obj-C type (flutter/flutter#185136) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages Please CC boetger@google.com,stuartmorgan@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
Fixes #185052
This change fixes an issue where the context menu would not reappear on the end of a non-fling scroll (a short scroll that does not create any ballistic simulation). This was due to no frames being scheduled after a non-fling scroll so the scheduled
addPostFrameCallbackcould not run.This issue was not caught by any of our tests because in
testWidgetssemantics is enabled by default. When semantics is enabled we hit a special case where a semantics update schedules an additional frame at the end of a scroll. The added regression test simulates this by running with semantics disabled.setIgnorePointeris called at the end of a scrollflutter/packages/flutter/lib/src/widgets/scrollable.dart
Lines 845 to 855 in 2c50daf
and
setIgnorePointertrigers a semantics updateflutter/packages/flutter/lib/src/rendering/proxy_box.dart
Lines 3767 to 3775 in 2c50daf
and
RenderObject.markNeedsSemanticsUpdateshort-circuits if semantics/screenreader is disabled resulting in no additional frames scheduled.flutter/packages/flutter/lib/src/rendering/object.dart
Lines 3904 to 3916 in 2c50daf
Screen.Recording.2026-04-14.at.3.46.01.PM.mov
Pre-launch Checklist
///).