From f1cb5cceb3e02e15b1ff4bf1080c505ad717299a Mon Sep 17 00:00:00 2001 From: Bitsy Date: Fri, 10 Jul 2026 22:08:44 +0200 Subject: [PATCH] Fix IndexOutOfBoundsException in MultiSelectionLayout when a new selection starts past every selectable --- .../foundation/text/selection/SelectionLayout.kt | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/selection/SelectionLayout.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/selection/SelectionLayout.kt index e7d1adf3f47dd..20f53fd615154 100644 --- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/selection/SelectionLayout.kt +++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/selection/SelectionLayout.kt @@ -176,12 +176,9 @@ private class MultiSelectionLayout( when { startSlot < endSlot -> CrossStatus.NOT_CROSSED startSlot > endSlot -> CrossStatus.CROSSED - // because one of the slots is not-dragging, it must be on a text directly - // because one of the slots is on a text directly and the start/end slots are equal, - // they both must be odd. Given this, dividing the slot by 2 should give us the - // correct - // info index. - else -> infoList[startSlot / 2].rawCrossStatus + // Clamp: when the gesture starts past every selectable, both slots default + // to lastSlot = 2 * infoList.size, so slot / 2 would be out of bounds. + else -> infoList[(startSlot / 2).coerceAtMost(infoList.lastIndex)].rawCrossStatus } override val startInfo: SelectableInfo @@ -303,7 +300,9 @@ private class MultiSelectionLayout( private fun slotToIndex(slot: Int, isMinimumSlot: Boolean): Int { val slotAdjustment = if (isMinimumSlot) 0 else 1 - return (slot - slotAdjustment) / 2 + // Clamp: when the gesture starts past every selectable, slots default + // to lastSlot = 2 * infoList.size, so slot / 2 would be out of bounds. + return ((slot - slotAdjustment) / 2).coerceIn(0, infoList.lastIndex) } private fun getInfoListIndexBySelectableId(id: Long): Int =