Closed ParrotCoder closed 6 months ago
The difference in our version that causes this is in MultiWidgetSelectionDelegate.kt
:
internal fun SelectionLayoutBuilder.appendSelectableInfo(
textLayoutResult: TextLayoutResult,
localPosition: Offset,
previousHandlePosition: Offset,
selectableId: Long,
) {
val bounds = Rect(
0.0f,
0.0f,
textLayoutResult.multiParagraph.width.toFloat(),
textLayoutResult.multiParagraph.height.toFloat()
)
...
}
We use textLayoutResult.multiParagraph
for the bounds size, while Android uses textLayoutResult.size
. In the reproducer, textLayoutResult.size
includes the entire Text
(height is large), while textLayoutResult.multiParagraph
only includes (vertically, at least) the area with the visual text itself (height is small; although width is large, not sure why).
Due to this, the code that follows it immediately behaves differently. currentYDirection
is AFTER
instead of ON
, and then isSelected()
a few lines below returns false
, which causes the function to return without calling appendInfo
. Then SelectionManager.getSelectionLayout
calls SelectionLayoutBuilder.build
, which throws an exception since infoList
is empty.
I can't say whether the bug is the use of textLayoutResult.multiParagraph
itself, or perhaps SelectionManager.getSelectionLayout
should not assume that appendSelectableInfoToBuilder
succeeded, or maybe appendSelectableInfo
should behave differently when currentYDirection
is AFTER
.
It makes sense that even if dragging begins outside of the bounds of the visible text, it should still start selecting, so that when the cursor is dragged inside the visible text, the selection works. So I think appendSelectableInfo
should call appendInfo
in this case.
The change was introduced in 2021 in commit 37564c1fd132a637afd8d31466e52c290c1bfb17 and was meant to fix several bugs. I've changed the code to use, as in Android, textLayoutResult.size
, and checked all the cases the commit refers to. All of them work correctly.
Because of this, and because it's much easier to revert to the Android version than to understand and agree on how the surrounding code should behave, then change and upstream it, I'd recommend reverting to the Android version.
@igordmn ?
Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.
Describe the bug In Compose 1.6.1 version, declare the Text component in SelectionContainer and set the size of the Text component. When clicking an area without text, an error occurs: "java.lang.IllegalStateException: SelectionLayout must not be empty." The same code is in Compose 1.5.10 Version will not cause errors
Affected platforms
Versions
To Reproduce
fun main() = application { Window( onCloseRequest = ::exitApplication, state = rememberWindowState( position = WindowPosition(Alignment.Center) ) ) { App() } }
@Composable private fun App() { Box( modifier = Modifier.padding(10.dp) ) { SelectionContainer { val text by remember { mutableStateOf("Text Content\r\nText Content2") } Text( text = text, modifier = Modifier .fillMaxSize() .background(Color.LightGray) ) } } }