Status Update
Comments
gr...@google.com <gr...@google.com> #2
Based on the stack trace, it looks like the crash is during a long press that is registered with the SelectionContainer
.
Can you provide more detail on why you think it has to do with Navigation as well to help us reproduce the issue?
xu...@gmail.com <xu...@gmail.com> #3
I have confirmed the code that crashed and it is not related to Navigation. I used both combinedClickable long click and SelectionContainer. The code:
Box(
modifier = Modifier
.combinedClickable(
role = null,
onClick = { },
onLongClick = {
// long click
}
)
) {
SelectionContainer(
modifier = Modifier
.fillMaxSize(),
) {
// Text()
}
}
gr...@google.com <gr...@google.com> #4
Thanks for the sample.
Did it require any specific gestures to cause the crash? I cannot seem to cause a crash with the sample above and selecting text.
I think I found the issue. Looks like the touches can be just outside of the bounds of the text because of a minimum touch size that the pointer input system uses. Because of this, selection gestures in non-selectable space can be passed through, causing the crash.
Anyways, to reproduce, simply make a small text (default BasicText works for me) in a selection container and long press right above it, as close to the border as possible while still being above.
SelectionContainer(Modifier.fillMaxWidth()) {
BasicText(
text = "text",
modifier = Modifier.border(Dp.Hairline, Color.LightGray),
)
}
xu...@gmail.com <xu...@gmail.com> #5
Thanks a million.
ap...@google.com <ap...@google.com> #6
Branch: androidx-main
commit 121f8ffa2464d63a84cdd61c7bae4cd2148ea85a
Author: Grant Toepfer <grantapher@google.com>
Date: Wed Sep 13 18:01:58 2023
Support starting a touch selection gesture in the minimum touch target of text
A selection that started in the minimum touch target of a text but not on the text directly would crash the app. Now, it will instead coerce the gesture into the bounds of the text and start the selection there.
Bug:
Test: ./gradlew :com:found:found:cAT
Test: ./gradlew :com:found:found:tDUT
Change-Id: Ide3a82b8155fb43f02e30a53c4390b09d2abdbbe
A compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/ComposeSmallMultiTextSelection.kt
M compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/ComposeTextSelection.kt
M compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/TextDemos.kt
A compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/selection/gestures/MultiTextMinTouchBoundsSelectionGesturesTest.kt
M compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/selection/SelectionManager.kt
gr...@google.com <gr...@google.com> #7
The above change should fix it. Let me know if you continue to run into issues, and feel free to re-open if it does.
bl...@gmail.com <bl...@gmail.com> #8
Seems like it's still an issue in 1.6.0-beta03? Could be something else, the Play Console did not print the error message.
Exception java.lang.IllegalStateException:
at androidx.compose.foundation.text.selection.SelectionLayoutBuilder.build (SelectionLayout.kt:1)
at androidx.compose.foundation.text.selection.SelectionManager.getSelectionLayout-Wko1d7g (SelectionManager.kt:1)
at androidx.compose.foundation.text.selection.SelectionManager.updateSelection-jyLRC_s$foundation_release (SelectionManager.kt:1)
at androidx.compose.foundation.text.selection.SelectionManager.updateSelection-qNKwrvQ$foundation_release (SelectionManager.kt:1)
at androidx.compose.foundation.text.selection.SelectionManager$4.invoke-pGV3PM0 (SelectionManager.kt:1)
at androidx.compose.foundation.text.selection.SelectionManager$4.invoke (SelectionManager.kt:1)
at androidx.compose.foundation.text.selection.SelectionRegistrarImpl.notifySelectionUpdate-njBpvok (SelectionRegistrarImpl.kt:1)
at androidx.compose.foundation.text.modifiers.SelectionControllerKt$makeSelectionModifier$longPressDragObserver$1.onDrag-k-4lQ0M (SelectionController.kt:1)
at androidx.compose.foundation.text.selection.SelectionGesturesKt$touchSelection$2.invoke (SelectionGestures.kt:1)
at androidx.compose.foundation.text.selection.SelectionGesturesKt$touchSelection$2.invoke (SelectionGestures.kt:1)
at androidx.compose.foundation.gestures.DragGestureDetectorKt.drag-jO51t88 (DragGestureDetector.kt:1)
at androidx.compose.foundation.gestures.DragGestureDetectorKt$drag$1.invokeSuspend (DragGestureDetector.kt:1)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith (ContinuationImpl.kt:1)
at kotlinx.coroutines.DispatchedTaskKt.resume (DispatchedTask.kt:1)
at kotlinx.coroutines.DispatchedTaskKt.dispatch (DispatchedTask.kt:1)
at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume (CancellableContinuationImpl.kt:1)
at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl (CancellableContinuationImpl.kt:1)
at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$default (CancellableContinuationImpl.kt:1)
at kotlinx.coroutines.CancellableContinuationImpl.resumeWith (CancellableContinuationImpl.kt:1)
at androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNodeImpl$PointerEventHandlerCoroutine.offerPointerEvent (SuspendingPointerInputFilter.kt:1)
at androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNodeImpl.dispatchPointerEvent (SuspendingPointerInputFilter.kt:1)
at androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNodeImpl.onPointerEvent-H0pRuoY (SuspendingPointerInputFilter.kt:1)
at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass (HitPathTracker.kt:1)
at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass (HitPathTracker.kt:1)
at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass (HitPathTracker.kt:1)
at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass (HitPathTracker.kt:1)
at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass (HitPathTracker.kt:1)
at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass (HitPathTracker.kt:1)
at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass (HitPathTracker.kt:1)
at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass (HitPathTracker.kt:1)
at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass (HitPathTracker.kt:1)
at androidx.compose.ui.input.pointer.NodeParent.dispatchMainEventPass (HitPathTracker.kt:1)
at androidx.compose.ui.input.pointer.HitPathTracker.dispatchChanges (HitPathTracker.kt:1)
at androidx.compose.ui.input.pointer.PointerInputEventProcessor.process-BIzXfog (PointerInputEventProcessor.kt:1)
at androidx.compose.ui.platform.AndroidComposeView.sendMotionEvent-8iAsVTc (AndroidComposeView.android.kt:1)
at androidx.compose.ui.platform.AndroidComposeView.handleMotionEvent-8iAsVTc (AndroidComposeView.android.kt:1)
at androidx.compose.ui.platform.AndroidComposeView.dispatchTouchEvent (AndroidComposeView.android.kt)
at android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:3923)
at android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:3597)
at android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:3923)
at android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:3597)
at android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:3923)
at android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:3597)
at android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:3923)
at android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:3597)
at com.android.internal.policy.DecorView.superDispatchTouchEvent (DecorView.java:1016)
at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent (PhoneWindow.java:1962)
at android.app.Activity.dispatchTouchEvent (Activity.java:4265)
at com.android.internal.policy.DecorView.dispatchTouchEvent (DecorView.java:974)
at android.view.View.dispatchPointerEvent (View.java:15335)
at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent (ViewRootImpl.java:7807)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess (ViewRootImpl.java:7580)
at android.view.ViewRootImpl$InputStage.deliver (ViewRootImpl.java:6914)
at android.view.ViewRootImpl$InputStage.onDeliverToNext (ViewRootImpl.java:6971)
at android.view.ViewRootImpl$InputStage.forward (ViewRootImpl.java:6937)
at android.view.ViewRootImpl$AsyncInputStage.forward (ViewRootImpl.java:7135)
at android.view.ViewRootImpl$InputStage.apply (ViewRootImpl.java:6945)
at android.view.ViewRootImpl$AsyncInputStage.apply (ViewRootImpl.java:7192)
at android.view.ViewRootImpl$InputStage.deliver (ViewRootImpl.java:6918)
at android.view.ViewRootImpl$InputStage.onDeliverToNext (ViewRootImpl.java:6971)
at android.view.ViewRootImpl$InputStage.forward (ViewRootImpl.java:6937)
at android.view.ViewRootImpl$InputStage.apply (ViewRootImpl.java:6945)
at android.view.ViewRootImpl$InputStage.deliver (ViewRootImpl.java:6918)
at android.view.ViewRootImpl.deliverInputEvent (ViewRootImpl.java:10367)
at android.view.ViewRootImpl.doProcessInputEvents (ViewRootImpl.java:10215)
at android.view.ViewRootImpl.enqueueInputEvent (ViewRootImpl.java:10171)
at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent (ViewRootImpl.java:10499)
at android.view.InputEventReceiver.dispatchInputEvent (InputEventReceiver.java:259)
at android.view.InputEventReceiver.nativeConsumeBatchedInputEvents
at android.view.InputEventReceiver.consumeBatchedInputEvents (InputEventReceiver.java:239)
at android.view.ViewRootImpl.doConsumeBatchedInput (ViewRootImpl.java:10447)
at android.view.ViewRootImpl$ConsumeBatchedInputRunnable.run (ViewRootImpl.java:10588)
at android.view.Choreographer$CallbackRecord.run (Choreographer.java:1108)
at android.view.Choreographer.doCallbacks (Choreographer.java:866)
at android.view.Choreographer.doFrame (Choreographer.java:789)
at android.view.Choreographer$FrameDisplayEventReceiver.run (Choreographer.java:1092)
at android.os.Handler.handleCallback (Handler.java:938)
at android.os.Handler.dispatchMessage (Handler.java:99)
at android.os.Looper.loopOnce (Looper.java:226)
at android.os.Looper.loop (Looper.java:313)
at android.app.ActivityThread.main (ActivityThread.java:8663)
at java.lang.reflect.Method.invoke
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:571)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1135)
gr...@google.com <gr...@google.com> #9
See
Description
- Jetpack Compose component used:
- Android Studio Build:
- Kotlin version: 1.8.21
- Devices/Android versions reproduced on: Redmi K20 Pro / LSA-AN00 / BAL-AL60 (Android 11 / 12)
- Keyboard (i.e. Gboard, Samsung, etc):
If this is a bug in the library, we would appreciate if you could attach:
- Sample project to trigger the issue.
- A screenrecord or screenshots showing the issue (if UI related).
- Stack trace (if applicable)
When there is text in the page that can be selected, it may crash (possibly) when using Navigation to jump to other pages. I am not sure how to reproduce it, but I have received more crash messages from users
java.lang.IllegalStateException: SelectionLayout must have at least one SelectableInfo.
androidx.compose.foundation.text.selection.SelectionLayoutBuilder.build SelectionLayoutBuilder.java
androidx.compose.foundation.text.selection.SelectionManager.getSelectionLayout-428G9Dg SelectionManager.java
androidx.compose.foundation.text.selection.SelectionManager.updateSelection-NX8WgWU$foundation_release SelectionManager.java
androidx.compose.foundation.text.selection.SelectionManager.startSelection-9KIMszo SelectionManager.java
androidx.compose.foundation.text.selection.SelectionManager.access$startSelection-9KIMszo SelectionManager.java
androidx.compose.foundation.text.selection.SelectionManager$2.invoke-Rg1IO4c SelectionManager.java
androidx.compose.foundation.text.selection.SelectionManager$2.invoke SelectionManager.java
androidx.compose.foundation.text.selection.SelectionRegistrarImpl.notifySelectionUpdateStart-ubNVwUQ SelectionRegistrarImpl.java
androidx.compose.foundation.text.modifiers.SelectionControllerKt$makeSelectionModifier$longPressDragObserver$1.onStart-k-4lQ0M SelectionControllerKt.java
androidx.compose.foundation.text.selection.SelectionGesturesKt.touchSelection SelectionGesturesKt.java
androidx.compose.foundation.text.selection.SelectionGesturesKt.access$touchSelection SelectionGesturesKt.java
androidx.compose.foundation.text.selection.SelectionGesturesKt$touchSelection$1.invokeSuspend SelectionGesturesKt.java
kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith BaseContinuationImpl.java:9
kotlinx.coroutines.DispatchedTaskKt.resume DispatchedTaskKt.java
kotlinx.coroutines.DispatchedTaskKt.dispatch DispatchedTaskKt.java:51
kotlinx.coroutines.CancellableContinuationImpl.dispatchResume CancellableContinuationImpl.java:7
kotlinx.coroutines.CancellableContinuationImpl.resumeImpl CancellableContinuationImpl.java:34
kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$default CancellableContinuationImpl.java
kotlinx.coroutines.CancellableContinuationImpl.resumeWith CancellableContinuationImpl.java:10
androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNodeImpl$PointerEventHandlerCoroutine$withTimeout$job$1.invokeSuspend SuspendingPointerInputModifierNodeImpl.java
kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith BaseContinuationImpl.java:9
kotlinx.coroutines.DispatchedTask.run DispatchedTask.java:101
androidx.compose.ui.platform.AndroidUiDispatcher.performTrampolineDispatch AndroidUiDispatcher.java
androidx.compose.ui.platform.AndroidUiDispatcher.access$performTrampolineDispatch AndroidUiDispatcher.java
androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.run AndroidUiDispatcher.java:3
android.os.Handler.handleCallback Handler.java:967
android.os.Handler.dispatchMessage Handler.java:107
android.os.Looper.loopOnce Looper.java:206
android.os.Looper.loop Looper.java:296
android.app.ActivityThread.main ActivityThread.java:9064
java.lang.reflect.Method.invoke Method.java:-2
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run RuntimeInit.java:582
com.android.internal.os.ZygoteInit.main ZygoteInit.java:968