Repository navigation
fix: text selection two handles directionality. - #179928
auto-submit[bot] merged 39 commits into
Conversation
There was a problem hiding this comment.
Code Review
This pull request effectively addresses an issue with text selection handle directionality in mixed LTR/RTL scenarios. The logic is updated to base handle types on the visual position of selection endpoints, which is a solid approach. The new tests are comprehensive and cover the relevant edge cases, ensuring the fix is robust. I have a few suggestions to improve the new test code for better readability and maintainability.
|
Hi @loic-sharma, |
|
@muhammadkamel It's the holidays in the US, a good chunk of the team is on vacation. Reviews might be a bit slower until January :) |
|
Hi @muhammadkamel thank you for your patience during the holidays. I'll be taking a look this week. |
Renzo-Olivares
left a comment
There was a problem hiding this comment.
Thank you for the contribution @muhammadkamel, this change definitely helps improve the text selection experience.
I verified that this is also the behavior on native mobile platforms.
Jetpack Compose (Android) with RTL set for application.
SwiftUI (iOS) with RTL set at application level
WRT to RTL text in general I think this also improves the experience slightly but text selection is still a bit buggy in RTL when using the text selection handles. The magnifier also seems to be broken when the application level text directionality is RTL and the textfield is LTR. That can be improved in a separate PR.
|
Hi @muhammadkamel, just wanted to follow up if there is any updates on this PR I should review? During my review last week I was still observing issues #179928 (comment). Let me know if I should take a look again. |
Hi @Renzo-Olivares |
|
Could you please take a look at the latest changes? |
|
Could you please add another reviewer so this PR can be merged as soon as possible? |
|
Hi @muhammadkamel, thank you for your patience on this one. After confirming some of the native behavior on Jetpack compose and Android View API's, I think we are able to closely match the native behavior with your previous change in 7ff9971 . Checking the I was mistaken about the multi-line behavior before in #179928 (comment). Though I still think there may be a bug when moving the selection across multiple lines in the scenario where the App's directionality is RTL but the text is LTR, in the linked image the selection originally started on the first line on the word "world" but moving that selection to the line below, adds the "?" on the first line to the selection. This can be solved in a different PR though as the issue existed before this change. I think some of the recent additional changes like passing the directionality to the |
I've updated the PR based on your feedback. The changes now match Android native and Jetpack Compose behavior: ✅ Removed the Directionality wrapper from handle builders I also kept a small addition in didChangeDependencies() to handle dynamic layout direction switching, ensuring handles reposition correctly when users switch between LTR and RTL layouts. |
Renzo-Olivares
left a comment
There was a problem hiding this comment.
Hi @muhammadkamel, thank you for the quick changes, I left a few comments. I'm also still seeing the changes to getEndPointsForSelection and EditableText.
|
Hi @muhammadkamel, just checking in if this needs a re-review. I'm still seeing the changes to Before merging this PR should also pass all existing tests. |
|
@muhammadkamel I'm going to close this PR as inactive, but if you end up deciding to come back to it just let me know and I'll reopen. |
|
Hi @justinmc Sorry for late, I was busy. Could you please re-open it? |
|
An existing Git SHA, To re-trigger presubmits after closing or re-opeing a PR, or pushing a HEAD commit (i.e. with |
|
@Renzo-Olivares Could you take another look when you have a chance? I addressed the latest comments and narrowed the remaining changes. |
|
@muhammadkamel FYI you have a branch conflict to resolve here. |
Hi @justinmc Thanks! |
…n-mixed-directionality
|
@muhammadkamel can you try to rebase this to the latest |
…doc, and clarify endpoint-fallback comment.
|
Hi @Renzo-Olivares — addressed your latest comments: Removed the unused ValueKey from DirectionalitySpyTextSelectionControls (the spy already asserts via builtHandleTypes). |
Renzo-Olivares
left a comment
There was a problem hiding this comment.
LGTM w/ one small nit. Thank you for your patience on this one!
Renzo-Olivares
left a comment
There was a problem hiding this comment.
RE-LGTM, thank you for the contribution @muhammadkamel!
You're welcome! :) |
…n-mixed-directionality
Fixes #187799
This PR fixes an issue where text selection handles would render facing the wrong direction when the text directionality differed from the ambient directionality (e.g., selecting English (LTR) text within an application set to Arabic (RTL)), and also when a single selection spans both LTR and RTL runs.
Previously,
TextSelectionOverlaydetermined the start and end handle types based primarily on the ambientTextDirectionand the logical selection range. This caused handles to swap (pointing away from the selection) in mixed-directionality scenarios.This change updates the logic in
_updateSelectionOverlayto derive each handle's type from the per-endpointTextDirectionreported byTextSelectionPoint.direction, falling back to the render object'stextDirectionwhen an endpoint does not provide one:TextDirection.ltr→TextSelectionHandleType.left,TextDirection.rtl→TextSelectionHandleType.right.TextDirection.ltr→TextSelectionHandleType.right,TextDirection.rtl→TextSelectionHandleType.left.Because each endpoint is evaluated independently, selections that cross a directionality boundary (e.g.
"abc مرحبا") get handle types that match the local direction at each end, so both handles continue to "hug" the selection.On iOS, UIKit conventionally keeps selection handles aligned with the field's own direction rather than the per-endpoint direction. To preserve platform behavior, when
defaultTargetPlatform == TargetPlatform.iOSboth handles use the render object'stextDirectioninstead of the endpoint directions.When a non-collapsed selection yields fewer than two endpoints (e.g. the selection is scrolled or clipped out of view), handle direction falls back to the field's
textDirectioninstead of asserting.Collapsed selections continue to use
TextSelectionHandleType.collapsedfor both handles and are unaffected by this change.Tests added
Added new tests in
text_selection_test.dart:Android (
TargetPlatformVariant.only(TargetPlatform.android)), driven by a table of_DirectionalityTestCases that assert the endpoint directions reported byRenderEditableand the handle types received by a spyTextSelectionControls:"abc مرحبا"(English then Arabic)"abc مرحبا"(English then Arabic)iOS (
TargetPlatformVariant.only(TargetPlatform.iOS)):"abc مرحبا"selection under ambient LTR, both handles follow the field'stextDirection(i.e.left/right) rather than the per-endpoint directions — exercising the UIKit-compatibility branch.The new directionality tests set
selectAllOnFocus: falseexplicitly (with an inline comment) because web CI defaultsEditableText.selectAllOnFocustotrue, which can select all text on focus and prevent handle rebuilds in these tests.Pre-launch Checklist
///).If you need help, consider asking for advice on the #hackers-new channel on Discord.
Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the
gemini-code-assistbot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.