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.24k stars 1.11k forks source link

Crash when using `rememberWindowState`: DpSize is unspecified #4945

Closed iamcalledrob closed 2 weeks ago

iamcalledrob commented 2 weeks ago

Describe the bug rememberWindowState() causes a crash: java.lang.IllegalStateException: DpSize is unspecified

The relevant part of the stack trace is this: at androidx.compose.ui.window.WindowStateImpl$Companion$Saver$1.invoke(WindowState.desktop.kt:230)

fun Saver(unspecifiedPosition: WindowPosition) = listSaver<WindowState, Any>(

    save = {

        listOf(

            it.placement.ordinal,

            it.isMinimized,

            it.position.isSpecified,

            it.position.x.value,

            it.position.y.value,

            it.size.width.value,
  // <-- Attempting a direct read of Dp.value,
            it.size.height.value,
 // <-- which throws when Unspecified
        )

    },
    .....

DpSize.Unspecified is a valid initial value for WindowState, but it appears that the state saver can't accommodate it. I am only seeing this crash within certain composable hierarchies, so perhaps there's a condition where the saver is invoked before the window has calculated its real size?

Affected platforms

Versions

To Reproduce Steps to reproduce the behavior:

  1. Run this code snippet:
    fun main() = application {
    
    Window(onCloseRequest = ::exitApplication) {
    
        LazyColumn {

            item {
    
                rememberWindowState(size = DpSize.Unspecified)

            }

        }

    }
    
}

Expected behavior A clear and concise description of what you expected to happen.

Additional context This also affects rememberDialogState. The impact of this bug is that I'm unable to open dialogs from within lazy list items.

As a workround, remember { WindowState(size = DpSize.Unspecified) } works, since it doesn't invoke rememberSaveable.