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
16.24k stars 1.18k forks source link

IllegalStateException: SkiaLayer is disposed - in 1.0.0-rc2 #1448

Closed kirill-grouchnikov closed 2 years ago

kirill-grouchnikov commented 2 years ago

This is happening in Aurora when I dispose a ComposeWindow used to display popup content

Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: SkiaLayer is disposed
    at org.jetbrains.skiko.SkiaLayer.needRedraw(SkiaLayer.jvm.kt:408)
    at androidx.compose.ui.awt.ComposeLayer$scene$1.invoke(ComposeLayer.desktop.kt:103)
    at androidx.compose.ui.awt.ComposeLayer$scene$1.invoke(ComposeLayer.desktop.kt:103)
    at androidx.compose.ui.ComposeScene.invalidateIfNeeded(ComposeScene.skiko.kt:125)
    at androidx.compose.ui.ComposeScene.access$invalidateIfNeeded(ComposeScene.skiko.kt:80)
    at androidx.compose.ui.ComposeScene.sendPointerEvent-Kr8mkKM(ComposeScene.skiko.kt:572)
    at androidx.compose.ui.ComposeScene.sendPointerEvent-Kr8mkKM$default(ComposeScene.skiko.kt:392)
    at androidx.compose.ui.awt.ComposeLayer_desktopKt.onMouseEvent(ComposeLayer.desktop.kt:363)
    at androidx.compose.ui.awt.ComposeLayer_desktopKt.access$onMouseEvent(ComposeLayer.desktop.kt:1)
    at androidx.compose.ui.awt.ComposeLayer$onMouseEvent$1$1.invoke(ComposeLayer.desktop.kt:285)
    at androidx.compose.ui.awt.ComposeLayer$onMouseEvent$1$1.invoke(ComposeLayer.desktop.kt:284)
    at androidx.compose.ui.awt.ComposeLayer.catchExceptions(ComposeLayer.desktop.kt:93)
    at androidx.compose.ui.awt.ComposeLayer.access$catchExceptions(ComposeLayer.desktop.kt:69)
    at androidx.compose.ui.awt.ComposeLayer$onMouseEvent$1.invoke(ComposeLayer.desktop.kt:284)
    at androidx.compose.ui.awt.ComposeLayer$onMouseEvent$1.invoke(ComposeLayer.desktop.kt:283)
    at androidx.compose.ui.awt.AWTDebounceEventQueue$job$1.invokeSuspend(AWTDebounceEventQueue.desktop.kt:59)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
    at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:313)
    at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:770)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
    at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:740)
    at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
kirill-grouchnikov commented 2 years ago

Reproducer:

import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.ui.Modifier
import androidx.compose.ui.awt.ComposeWindow
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application
import java.awt.Rectangle

fun main() = application {
    Window(onCloseRequest = ::exitApplication, title = "Demo") {
        Box(modifier = Modifier.size(100.dp).background(Color.Red).clickable {
            val popupContentWindow = ComposeWindow()
            popupContentWindow.focusableWindowState = false
            popupContentWindow.type = java.awt.Window.Type.POPUP
            popupContentWindow.isAlwaysOnTop = true
            popupContentWindow.isUndecorated = true
            popupContentWindow.isResizable = false

            popupContentWindow.bounds = Rectangle(600, 400, 200, 200)
            popupContentWindow.setContent {
                Box(modifier = Modifier.fillMaxSize().background(Color.Blue).clickable {
                    popupContentWindow.isVisible = false
                    popupContentWindow.dispose()
                })
            }

            popupContentWindow.invalidate()
            popupContentWindow.validate()
            popupContentWindow.isVisible = true
        })
    }
}
kirill-grouchnikov commented 2 years ago

Click on the red square in the window. That creates a ComposeWindow with a blue box. Click that box to close the "popup" window and observe the stack trace

kirill-grouchnikov commented 2 years ago

Same in rc3

kirill-grouchnikov commented 2 years ago

In 1.0.0-rc4 I now have this:

Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: ComposeScene is closed
    at androidx.compose.ui.ComposeScene.sendPointerEvent-Kr8mkKM(ComposeScene.skiko.kt:402)
    at androidx.compose.ui.ComposeScene.sendPointerEvent-Kr8mkKM$default(ComposeScene.skiko.kt:392)
    at androidx.compose.ui.awt.ComposeLayer_desktopKt.onMouseEvent(ComposeLayer.desktop.kt:353)
    at androidx.compose.ui.awt.ComposeLayer_desktopKt.access$onMouseEvent(ComposeLayer.desktop.kt:1)
    at androidx.compose.ui.awt.ComposeLayer$onMouseEvent$1.invoke(ComposeLayer.desktop.kt:279)
    at androidx.compose.ui.awt.ComposeLayer$onMouseEvent$1.invoke(ComposeLayer.desktop.kt:278)
    at androidx.compose.ui.awt.ComposeLayer.catchExceptions(ComposeLayer.desktop.kt:88)
    at androidx.compose.ui.awt.ComposeLayer.onMouseEvent(ComposeLayer.desktop.kt:278)
    at androidx.compose.ui.awt.ComposeLayer.access$onMouseEvent(ComposeLayer.desktop.kt:69)
    at androidx.compose.ui.awt.ComposeLayer$4.mouseMoved(ComposeLayer.desktop.kt:261)
    at java.desktop/java.awt.AWTEventMulticaster.mouseMoved(AWTEventMulticaster.java:337)
    at java.desktop/java.awt.Component.processMouseMotionEvent(Component.java:6677)
    at java.desktop/java.awt.Component.processEvent(Component.java:6401)
    at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:5008)
    at java.desktop/java.awt.Component.dispatchEvent(Component.java:4840)
    at androidx.compose.ui.awt.ComposeLayer$ComponentImpl$scheduleSyntheticMoveEvent$1.run(ComposeLayer.desktop.kt:211)
    at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:313)
    at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:770)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:721)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:715)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:85)
    at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:740)
    at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
kirill-grouchnikov commented 2 years ago

Same demo. It doesn't happen every time the blue box in a popup window is clicked to close it, but happens frequently enough if you keep on clicking the red and then the blue

igordmn commented 2 years ago

Should be fixed in 1.0.0-rc5. Thanks for the reports :)

kirill-grouchnikov commented 2 years ago

Confirming the fixes in rc5

okushnikov commented 3 months ago

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