[go: nahoru, domu]

Fix selection related crashes when a word is overflowing

Positioning of selection behaviors would try to look up non-visible text offsets when maxLines is set and text is overflowing. This change adds more checks to avoid looking up offsets that aren't visible.

Test: ./gradlew :com:f:f:cAT
Test: ./gradlew :com:f:f:tDUT
Fixes: b/221580975
Fixes: b/300502152
Change-Id: I4e5348fadaa06998c6f4b06aef28e741c888831f
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/selection/SelectionManager.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/selection/SelectionManager.kt
index 9ed470a..915309a 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/selection/SelectionManager.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/selection/SelectionManager.kt
@@ -363,6 +363,7 @@
             // affects multiple text selection when selected text is configured with maxLines=1
             // and overflow=clip.
             val handlePosition = startSelectable.getHandlePosition(selection, isStartHandle = true)
+            if (handlePosition.isUnspecified) return@let null
             val position = containerCoordinates.localPositionOf(handleCoordinates, handlePosition)
             position.takeIf {
                 draggingHandle == Handle.SelectionStart || visibleBounds.containsInclusive(it)
@@ -371,6 +372,7 @@
 
         this.endHandlePosition = endLayoutCoordinates?.let { handleCoordinates ->
             val handlePosition = endSelectable.getHandlePosition(selection, isStartHandle = false)
+            if (handlePosition.isUnspecified) return@let null
             val position = containerCoordinates.localPositionOf(handleCoordinates, handlePosition)
             position.takeIf {
                 draggingHandle == Handle.SelectionEnd || visibleBounds.containsInclusive(it)
@@ -780,11 +782,11 @@
             }
             val otherSelectable =
                 selectionRegistrar.selectableMap[otherSelectableId] ?: return@let null
+            val handlePosition = otherSelectable.getHandlePosition(selection, !isStartHandle)
+            if (handlePosition.isUnspecified) return@let null
             convertToContainerCoordinates(
                 otherSelectable.getLayoutCoordinates()!!,
-                getAdjustedCoordinates(
-                    otherSelectable.getHandlePosition(selection, !isStartHandle)
-                )
+                getAdjustedCoordinates(handlePosition)
             )
         } ?: return false