JetBrains / compose-multiplatform

Compose Multiplatform, a modern UI framework for Kotlin that makes building performant and beautiful user interfaces easy and enjoyable.
https://jetbrains.com/lp/compose-multiplatform
Apache License 2.0
15.96k stars 1.16k forks source link

BasicTextField NPE-crash on JBR 17.0.9 on Linux when clicked #4115

Closed rock3r closed 8 months ago

rock3r commented 8 months ago

Describe the bug Clicking on a BasicTextField when running on the JBR 17.0.9 on Linux crashes the app.

Affected platforms

If the bug is Android-only, report it in the Jetpack Compose tracker

Versions

To Reproduce

Run this:

import androidx.compose.foundation.border
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.singleWindowApplication

fun main() = singleWindowApplication {
    var text by remember { mutableStateOf("") }
    BasicTextField(text, { text = it }, modifier = Modifier.padding(8.dp).border(1.dp, Color.Red))
}

Run the function making sure you're using JBR 17.0.9 and click the text field. Observe the crash:

``` ERROR: Unhandled exception in [androidx.compose.ui.awt.ComposeBridge$coroutineExceptionHandler$1@3384b078, androidx.compose.runtime.BroadcastFrameClock@50e0c941, StandaloneCoroutine{Cancelling}@a2bfb53, FlushCoroutineDispatcher@35413f0] java.lang.NullPointerException: Parameter specified as non-null is null: method androidx.compose.ui.platform.PlatformInput$methodRequestsForInput$1.getTextLocation, parameter offset at androidx.compose.ui.platform.PlatformInput$methodRequestsForInput$1.getTextLocation(DesktopPlatformInput.desktop.kt) at java.desktop/sun.awt.X11.XInputMethod.updateCandidatesNativeWindowPosition(XInputMethod.java:379) at java.desktop/sun.awt.X11.XInputMethod.activate(XInputMethod.java:85) at java.desktop/sun.awt.im.InputContext.activateInputMethod(InputContext.java:396) at java.desktop/sun.awt.im.InputContext.focusGained(InputContext.java:338) at java.desktop/sun.awt.im.InputContext.dispatchEvent(InputContext.java:245) at java.desktop/sun.awt.im.InputMethodContext.dispatchEvent(InputMethodContext.java:197) at java.desktop/java.awt.Component.enableInputMethods(Component.java:1666) at org.jetbrains.skiko.SkiaLayer.enableInputMethods(SkiaLayer.awt.kt:412) at androidx.compose.ui.awt.ComposeBridge$platformComponent$1.enableInput(ComposeBridge.desktop.kt:107) at androidx.compose.ui.platform.PlatformInput.startInput(DesktopPlatformInput.desktop.kt:71) at androidx.compose.ui.text.input.TextInputService.startInput(TextInputService.kt:56) at androidx.compose.foundation.text.TextFieldDelegate$Companion.restartInput$foundation(TextFieldDelegate.kt:251) at androidx.compose.foundation.text.TextFieldDelegate$Companion.onFocus$foundation(TextFieldDelegate.kt:280) at androidx.compose.foundation.text.CoreTextFieldKt.startInputSession(CoreTextField.kt:970) at androidx.compose.foundation.text.CoreTextFieldKt.access$startInputSession(CoreTextField.kt:1) at androidx.compose.foundation.text.CoreTextFieldKt$CoreTextField$focusModifier$1.invoke(CoreTextField.kt:307) at androidx.compose.foundation.text.CoreTextFieldKt$CoreTextField$focusModifier$1.invoke(CoreTextField.kt:295) at androidx.compose.ui.focus.FocusChangedNode.onFocusEvent(FocusChangedModifier.kt:59) at androidx.compose.ui.focus.FocusEventModifierNodeKt.refreshFocusEventNodes(FocusEventModifierNode.kt:68) at androidx.compose.ui.focus.FocusTransactionsKt.requestFocusForChild(FocusTransactions.kt:197) at androidx.compose.ui.focus.FocusTransactionsKt.performRequestFocus(FocusTransactions.kt:68) at androidx.compose.ui.focus.FocusTransactionsKt.requestFocus(FocusTransactions.kt:44) at androidx.compose.ui.focus.FocusRequester.focus$ui(FocusRequester.kt:72) at androidx.compose.ui.focus.FocusRequester.requestFocus(FocusRequester.kt:63) at androidx.compose.foundation.text.selection.TextFieldSelectionManager$mouseSelectionObserver$1.onStart-3MmeM6k(TextFieldSelectionManager.kt:300) at androidx.compose.foundation.text.selection.TextSelectionMouseDetectorKt$mouseSelectionDetector$2.invokeSuspend(TextSelectionMouseDetector.kt:100) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:179) at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:168) at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:474) at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl(CancellableContinuationImpl.kt:508) at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$default(CancellableContinuationImpl.kt:497) at kotlinx.coroutines.CancellableContinuationImpl.resumeWith(CancellableContinuationImpl.kt:368) at androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNodeImpl$PointerEventHandlerCoroutine.offerPointerEvent(SuspendingPointerInputFilter.kt:672) at androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNodeImpl.dispatchPointerEvent(SuspendingPointerInputFilter.kt:549) at androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNodeImpl.onPointerEvent-H0pRuoY(SuspendingPointerInputFilter.kt:571) at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:326) at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:312) at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:312) at androidx.compose.ui.input.pointer.NodeParent.dispatchMainEventPass(HitPathTracker.kt:185) at androidx.compose.ui.input.pointer.HitPathTracker.dispatchChanges(HitPathTracker.kt:104) at androidx.compose.ui.input.pointer.PointerInputEventProcessor.process-BIzXfog(PointerInputEventProcessor.kt:97) at androidx.compose.ui.platform.SkiaBasedOwner.processPointerInput-gBdvCQM$ui(SkiaBasedOwner.skiko.kt:362) at androidx.compose.ui.platform.SkiaBasedOwner.processPointerInput-gBdvCQM$ui$default(SkiaBasedOwner.skiko.kt:355) at androidx.compose.ui.ComposeScene.processPress(ComposeScene.skiko.kt:722) at androidx.compose.ui.ComposeScene.processPointerInput(ComposeScene.skiko.kt:697) at androidx.compose.ui.ComposeScene.access$processPointerInput(ComposeScene.skiko.kt:68) at androidx.compose.ui.ComposeScene$syntheticEventSender$1.invoke(ComposeScene.skiko.kt:299) at androidx.compose.ui.ComposeScene$syntheticEventSender$1.invoke(ComposeScene.skiko.kt:299) at androidx.compose.ui.SyntheticEventSender.sendInternal(SyntheticEventSender.kt:179) at androidx.compose.ui.SyntheticEventSender.send(SyntheticEventSender.kt:83) at androidx.compose.ui.ComposeScene.sendPointerEvent-WlEVilQ(ComposeScene.skiko.kt:668) at androidx.compose.ui.ComposeScene.sendPointerEvent-BGSDPeU(ComposeScene.skiko.kt:610) at androidx.compose.ui.ComposeScene.sendPointerEvent-BGSDPeU$default(ComposeScene.skiko.kt:593) at androidx.compose.ui.awt.ComposeBridge_desktopKt.onMouseEvent(ComposeBridge.desktop.kt:440) at androidx.compose.ui.awt.ComposeBridge_desktopKt.access$onMouseEvent(ComposeBridge.desktop.kt:1) at androidx.compose.ui.awt.ComposeBridge$onMouseEvent$1.invoke(ComposeBridge.desktop.kt:271) at androidx.compose.ui.awt.ComposeBridge$onMouseEvent$1.invoke(ComposeBridge.desktop.kt:264) at androidx.compose.ui.awt.ComposeBridge.catchExceptions(ComposeBridge.desktop.kt:150) at androidx.compose.ui.awt.ComposeBridge.onMouseEvent(ComposeBridge.desktop.kt:264) at androidx.compose.ui.awt.ComposeBridge.access$onMouseEvent(ComposeBridge.desktop.kt:64) at androidx.compose.ui.awt.ComposeBridge$attachComposeToComponent$3.mousePressed(ComposeBridge.desktop.kt:244) at java.desktop/java.awt.Component.processMouseEvent(Component.java:6654) at java.desktop/java.awt.Component.processEvent(Component.java:6422) at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:5027) at java.desktop/java.awt.Component.dispatchEvent(Component.java:4855) at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:794) at java.desktop/java.awt.EventQueue$3.run(EventQueue.java:739) at java.desktop/java.awt.EventQueue$3.run(EventQueue.java:733) at java.base/java.security.AccessController.doPrivileged(AccessController.java:399) at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86) at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:97) at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:766) at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:764) at java.base/java.security.AccessController.doPrivileged(AccessController.java:399) at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86) at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:763) at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:207) at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128) at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117) at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113) at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105) at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:92) Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException: Parameter specified as non-null is null: method androidx.compose.ui.platform.PlatformInput$methodRequestsForInput$1.getTextLocation, parameter offset at androidx.compose.ui.platform.PlatformInput$methodRequestsForInput$1.getTextLocation(DesktopPlatformInput.desktop.kt) at java.desktop/sun.awt.X11.XInputMethod.updateCandidatesNativeWindowPosition(XInputMethod.java:379) at java.desktop/sun.awt.X11.XInputMethod.activate(XInputMethod.java:85) at java.desktop/sun.awt.im.InputContext.activateInputMethod(InputContext.java:396) at java.desktop/sun.awt.im.InputContext.focusGained(InputContext.java:338) at java.desktop/sun.awt.im.InputContext.dispatchEvent(InputContext.java:245) at java.desktop/sun.awt.im.InputMethodContext.dispatchEvent(InputMethodContext.java:197) at java.desktop/java.awt.Component.enableInputMethods(Component.java:1666) at org.jetbrains.skiko.SkiaLayer.enableInputMethods(SkiaLayer.awt.kt:412) at androidx.compose.ui.awt.ComposeBridge$platformComponent$1.enableInput(ComposeBridge.desktop.kt:107) at androidx.compose.ui.platform.PlatformInput.startInput(DesktopPlatformInput.desktop.kt:71) at androidx.compose.ui.text.input.TextInputService.startInput(TextInputService.kt:56) at androidx.compose.foundation.text.TextFieldDelegate$Companion.restartInput$foundation(TextFieldDelegate.kt:251) at androidx.compose.foundation.text.TextFieldDelegate$Companion.onFocus$foundation(TextFieldDelegate.kt:280) at androidx.compose.foundation.text.CoreTextFieldKt.startInputSession(CoreTextField.kt:970) at androidx.compose.foundation.text.CoreTextFieldKt.access$startInputSession(CoreTextField.kt:1) at androidx.compose.foundation.text.CoreTextFieldKt$CoreTextField$focusModifier$1.invoke(CoreTextField.kt:307) at androidx.compose.foundation.text.CoreTextFieldKt$CoreTextField$focusModifier$1.invoke(CoreTextField.kt:295) at androidx.compose.ui.focus.FocusChangedNode.onFocusEvent(FocusChangedModifier.kt:59) at androidx.compose.ui.focus.FocusEventModifierNodeKt.refreshFocusEventNodes(FocusEventModifierNode.kt:68) at androidx.compose.ui.focus.FocusTransactionsKt.requestFocusForChild(FocusTransactions.kt:197) at androidx.compose.ui.focus.FocusTransactionsKt.performRequestFocus(FocusTransactions.kt:68) at androidx.compose.ui.focus.FocusTransactionsKt.requestFocus(FocusTransactions.kt:44) at androidx.compose.ui.focus.FocusRequester.focus$ui(FocusRequester.kt:72) at androidx.compose.ui.focus.FocusRequester.requestFocus(FocusRequester.kt:63) at androidx.compose.foundation.text.selection.TextFieldSelectionManager$mouseSelectionObserver$1.onStart-3MmeM6k(TextFieldSelectionManager.kt:300) at androidx.compose.foundation.text.selection.TextSelectionMouseDetectorKt$mouseSelectionDetector$2.invokeSuspend(TextSelectionMouseDetector.kt:100) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:179) at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:168) at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:474) at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl(CancellableContinuationImpl.kt:508) at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$default(CancellableContinuationImpl.kt:497) at kotlinx.coroutines.CancellableContinuationImpl.resumeWith(CancellableContinuationImpl.kt:368) at androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNodeImpl$PointerEventHandlerCoroutine.offerPointerEvent(SuspendingPointerInputFilter.kt:672) at androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNodeImpl.dispatchPointerEvent(SuspendingPointerInputFilter.kt:549) at androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNodeImpl.onPointerEvent-H0pRuoY(SuspendingPointerInputFilter.kt:571) at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:326) at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:312) at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:312) at androidx.compose.ui.input.pointer.NodeParent.dispatchMainEventPass(HitPathTracker.kt:185) at androidx.compose.ui.input.pointer.HitPathTracker.dispatchChanges(HitPathTracker.kt:104) at androidx.compose.ui.input.pointer.PointerInputEventProcessor.process-BIzXfog(PointerInputEventProcessor.kt:97) at androidx.compose.ui.platform.SkiaBasedOwner.processPointerInput-gBdvCQM$ui(SkiaBasedOwner.skiko.kt:362) at androidx.compose.ui.platform.SkiaBasedOwner.processPointerInput-gBdvCQM$ui$default(SkiaBasedOwner.skiko.kt:355) at androidx.compose.ui.ComposeScene.processPress(ComposeScene.skiko.kt:722) at androidx.compose.ui.ComposeScene.processPointerInput(ComposeScene.skiko.kt:697) at androidx.compose.ui.ComposeScene.access$processPointerInput(ComposeScene.skiko.kt:68) at androidx.compose.ui.ComposeScene$syntheticEventSender$1.invoke(ComposeScene.skiko.kt:299) at androidx.compose.ui.ComposeScene$syntheticEventSender$1.invoke(ComposeScene.skiko.kt:299) at androidx.compose.ui.SyntheticEventSender.sendInternal(SyntheticEventSender.kt:179) at androidx.compose.ui.SyntheticEventSender.send(SyntheticEventSender.kt:83) at androidx.compose.ui.ComposeScene.sendPointerEvent-WlEVilQ(ComposeScene.skiko.kt:668) at androidx.compose.ui.ComposeScene.sendPointerEvent-BGSDPeU(ComposeScene.skiko.kt:610) at androidx.compose.ui.ComposeScene.sendPointerEvent-BGSDPeU$default(ComposeScene.skiko.kt:593) at androidx.compose.ui.awt.ComposeBridge_desktopKt.onMouseEvent(ComposeBridge.desktop.kt:440) at androidx.compose.ui.awt.ComposeBridge_desktopKt.access$onMouseEvent(ComposeBridge.desktop.kt:1) at androidx.compose.ui.awt.ComposeBridge$onMouseEvent$1.invoke(ComposeBridge.desktop.kt:271) at androidx.compose.ui.awt.ComposeBridge$onMouseEvent$1.invoke(ComposeBridge.desktop.kt:264) at androidx.compose.ui.awt.ComposeBridge.catchExceptions(ComposeBridge.desktop.kt:150) at androidx.compose.ui.awt.ComposeBridge.onMouseEvent(ComposeBridge.desktop.kt:264) at androidx.compose.ui.awt.ComposeBridge.access$onMouseEvent(ComposeBridge.desktop.kt:64) at androidx.compose.ui.awt.ComposeBridge$attachComposeToComponent$3.mousePressed(ComposeBridge.desktop.kt:244) at java.desktop/java.awt.Component.processMouseEvent(Component.java:6654) at java.desktop/java.awt.Component.processEvent(Component.java:6422) at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:5027) at java.desktop/java.awt.Component.dispatchEvent(Component.java:4855) at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:794) at java.desktop/java.awt.EventQueue$3.run(EventQueue.java:739) at java.desktop/java.awt.EventQueue$3.run(EventQueue.java:733) at java.base/java.security.AccessController.doPrivileged(AccessController.java:399) at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86) at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:97) at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:766) at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:764) at java.base/java.security.AccessController.doPrivileged(AccessController.java:399) at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86) at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:763) at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:207) at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128) at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117) at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113) at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105) at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:92) Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [androidx.compose.ui.awt.ComposeBridge$coroutineExceptionHandler$1@3384b078, androidx.compose.runtime.BroadcastFrameClock@50e0c941, StandaloneCoroutine{Cancelling}@a2bfb53, FlushCoroutineDispatcher@35413f0] ```

Original report: https://github.com/JetBrains/jewel/issues/281 — note this issue is NOT Jewel-related.

Expected behavior No crash.

Screenshots N/A

Additional context I have also tested with Zulu 17 and JBR 17.0.8.1b1080 and these don't repro the crash. Both 17.0.9b1162.7 and 17.0.9b1087.9 repro the issue.

MatkovIvan commented 8 months ago

It should be already fixed by https://github.com/JetBrains/compose-multiplatform-core/pull/973

rock3r commented 8 months ago

@MatkovIvan alas, not the case. It only works up to a certain version; I tested:

:white_check_mark: 17.0.9-b1000.46 :white_check_mark: 17.0.9-b1000.47 :white_check_mark: 17.0.9-b1087.3 :white_check_mark: 17.0.9-b1087.7 :x: 17.0.9-b1087.9 <--- First failing build :x: 17.0.9-b1087.11 :x: 17.0.9-b1162.7

Using Compose 1.6.0-dev1362 on Kotlin 1.8.21

rock3r commented 8 months ago

Turns out Gradle, for whatever reason, decided not to use Compose 1.6.0-dev1362 but rather 1.5.11. I ran clean --refresh-dependencies and can confirm the fix in https://github.com/JetBrains/compose-multiplatform-core/pull/973 works. Will close this issue.

okushnikov commented 2 months ago

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.