Skip to content

Fix selecting backwards when involving widget spans#184423

Merged
auto-submit[bot] merged 12 commits into
flutter:masterfrom
Renzo-Olivares:selectableregion-backwards-selection-widgetspan-fix
Apr 24, 2026
Merged

Fix selecting backwards when involving widget spans#184423
auto-submit[bot] merged 12 commits into
flutter:masterfrom
Renzo-Olivares:selectableregion-backwards-selection-widgetspan-fix

Conversation

@Renzo-Olivares

@Renzo-Olivares Renzo-Olivares commented Mar 31, 2026

Copy link
Copy Markdown
Contributor

Original discussion: #184031

Fixes #166462

Before this change _initSelection would always begin its selection search at index 0, this caused issues when selecting backwards and the children of the selection delegate also contained children. This happens because when we select backwards and always start our selection search at index 0, if our pointer moves backwards from point b to point a and point a is already on index 0 (of a selection container with N selectables), the selection logic will short-circuit early thinking we found the selection, skipping any selectables in between point b and point a.

After this change _initSelection will begin its selection search at the opposite edge if it exists. This fixes the issue because when entering a new selectable, while dragging backwards and updating the end edge, first the selectable will call ensureChildUpdated and synthesize a start edge. Then it processes the end edge event and begins to search for that selection edge, we now start this search at the opposite edge which allows us ensure all items between both edges are visited so we can create a continuous selection.

Since starting _initSelection at the opposite edge is what _SelectableTextContainerDelegate does with its _initSelection we can remove it. I added a test to verify we aren't breaking anything here.

Pre-launch Checklist

  • I read the [Contributor Guide] and followed the process outlined there for submitting PRs.
  • I read the [AI contribution guidelines] and understand my responsibilities, or I am not using AI tools.
  • I read the [Tree Hygiene] wiki page, which explains my responsibilities.
  • I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement].
  • I signed the [CLA].
  • I listed at least one issue that this PR fixes in the description above.
  • I updated/added relevant documentation (doc comments with ///).
  • I added new tests to check the change I am making, or this PR is [test-exempt].
  • I followed the [breaking change policy] and added [Data Driven Fixes] where supported.
  • All existing and new tests are passing.

@github-actions github-actions Bot added the framework flutter/packages/flutter repository. See also f: labels. label Mar 31, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the selection logic in MultiSelectableSelectionContainerDelegate to support bidirectional sweeping starting from an existing selection edge, which addresses issues with backwards selection. It also adds a regression test to verify selection behavior across multiple Text widgets and WidgetSpan elements. Review feedback suggests simplifying the control flow within the SelectionResult switch cases to improve readability and using the null-coalescing operator for a more idiomatic index update.

Comment thread packages/flutter/lib/src/widgets/selectable_region.dart
Comment thread packages/flutter/lib/src/widgets/selectable_region.dart
Comment thread packages/flutter/lib/src/widgets/selectable_region.dart Outdated
@Renzo-Olivares

Copy link
Copy Markdown
Contributor Author

I created another PR because I somehow managed to break my old one (and a few others). Apologies for any confusion.

@Renzo-Olivares Renzo-Olivares force-pushed the selectableregion-backwards-selection-widgetspan-fix branch from b808519 to ec28d05 Compare April 15, 2026 05:53
@github-actions github-actions Bot added the a: text input Entering text in a text field or keyboard related problems label Apr 15, 2026
@Renzo-Olivares Renzo-Olivares added the CICD Run CI/CD label Apr 15, 2026
@github-actions github-actions Bot removed the CICD Run CI/CD label Apr 15, 2026
@Renzo-Olivares Renzo-Olivares added the CICD Run CI/CD label Apr 15, 2026
final Offset localPosition = MatrixUtils.transformPoint(transform, globalPosition);
if (_rect.isEmpty) {
return SelectionUtils.getResultBasedOnRect(_rect, localPosition);
final SelectionResult result = SelectionUtils.getResultBasedOnRect(_rect, localPosition);

@Renzo-Olivares Renzo-Olivares Apr 15, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and elsewhere we snap the selection edge to the appropriate boundary so that this fragment's internal state is consistent with the SelectionResult it reports. Without this, the edge stays null and the fragment creates a gap in the selection range.

This covers the test, 'triple-click-drag backwards involving WidgetSpans', where a selectable fragment may be of zero-width since it only contains a new line. Without it the new lines are not included in the selection.

loic-sharma
loic-sharma previously approved these changes Apr 18, 2026

@loic-sharma loic-sharma left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me, but my understanding of selection is weak so please also get an approval from @chunhtai! :)

@Renzo-Olivares

Copy link
Copy Markdown
Contributor Author

Google testing failures seem unrelated on this one.

chunhtai
chunhtai previously approved these changes Apr 22, 2026

@chunhtai chunhtai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

Comment thread packages/flutter/lib/src/widgets/selectable_region.dart Outdated
@Renzo-Olivares Renzo-Olivares dismissed stale reviews from chunhtai and loic-sharma via a8576c4 April 22, 2026 21:34
@github-actions github-actions Bot removed the CICD Run CI/CD label Apr 22, 2026
@Renzo-Olivares Renzo-Olivares force-pushed the selectableregion-backwards-selection-widgetspan-fix branch from a8576c4 to 9152072 Compare April 22, 2026 21:35
@Renzo-Olivares Renzo-Olivares added the CICD Run CI/CD label Apr 22, 2026
@github-actions github-actions Bot removed the CICD Run CI/CD label Apr 22, 2026
@Renzo-Olivares Renzo-Olivares added the CICD Run CI/CD label Apr 22, 2026
@Renzo-Olivares

Copy link
Copy Markdown
Contributor Author

I have applied the suggestion in #184423 (comment).

@loic-sharma loic-sharma left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-LGTM

@chunhtai chunhtai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

a: text input Entering text in a text field or keyboard related problems CICD Run CI/CD framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Broken text selection when selecting backwards from TextSpan into WidgetSpan within SelectionArea

3 participants