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

DialogWindow throw the exception when showing - Jetpack Compose desktop #4592

Closed JasonTranz closed 2 months ago

JasonTranz commented 2 months ago

Describe the bug When I show the DialogWindow, the exception will be display.

Affected platforms

Versions

To Reproduce

  1. Show dialog

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

Screenshots If applicable, add screenshots to help explain your problem.

Additional context

SEVERE - #c.i.i.p.PluginManager - Cannot invoke "java.awt.image.BufferStrategy.contentsLost()" because "this.bufferStrategy" is null java.lang.NullPointerException: Cannot invoke "java.awt.image.BufferStrategy.contentsLost()" because "this.bufferStrategy" is null at java.desktop/javax.swing.BufferStrategyPaintManager.flushAccumulatedRegion(BufferStrategyPaintManager.java:379) at java.desktop/javax.swing.BufferStrategyPaintManager.endPaint(BufferStrategyPaintManager.java:343) at java.desktop/javax.swing.RepaintManager.endPaint(RepaintManager.java:1438) at java.desktop/javax.swing.JComponent._paintImmediately(JComponent.java:5266) at java.desktop/javax.swing.JComponent.paintImmediately(JComponent.java:5070) at java.desktop/javax.swing.RepaintManager$4.run(RepaintManager.java:882) at java.desktop/javax.swing.RepaintManager$4.run(RepaintManager.java:865) at java.base/java.security.AccessController.doPrivileged(AccessController.java:399) at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86) at java.desktop/javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:865) at java.desktop/javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:838) at java.desktop/javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:787) at java.desktop/javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1909) at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:318) at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:792) 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.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:761) at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.kt:695) at com.intellij.ide.IdeEventQueue._dispatchEvent$lambda$12(IdeEventQueue.kt:589) at com.intellij.openapi.application.impl.RwLockHolder.runWithoutImplicitRead(RwLockHolder.kt:44) at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.kt:589) at com.intellij.ide.IdeEventQueue.access$_dispatchEvent(IdeEventQueue.kt:72) at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1$1.compute(IdeEventQueue.kt:355) at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1$1.compute(IdeEventQueue.kt:354) at com.intellij.openapi.progress.impl.CoreProgressManager.computePrioritized(CoreProgressManager.java:793) at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1.invoke(IdeEventQueue.kt:354) at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1.invoke(IdeEventQueue.kt:349) at com.intellij.ide.IdeEventQueueKt.performActivity$lambda$1(IdeEventQueue.kt:1014) at com.intellij.openapi.application.TransactionGuardImpl.performActivity(TransactionGuardImpl.java:106) at com.intellij.ide.IdeEventQueueKt.performActivity(IdeEventQueue.kt:1014) at com.intellij.ide.IdeEventQueue.dispatchEvent$lambda$7(IdeEventQueue.kt:349) at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.kt:386) 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)

m-sasha commented 2 months ago

Can you post a reproducer? This works fine for me:

fun main() = singleWindowApplication {
    DialogWindow(
        onCloseRequest = { }
    ) {
        Text("Hello, World")
    }
}
JasonTranz commented 2 months ago

I just call it in composable function

@Composable
fun DialogWrapper(
    visible: Boolean,
) {
    DialogWindow(
        visible = visible,
        onCloseRequest = { }
    ) {
        Text("Hello, World")
    }
}
m-sasha commented 2 months ago

Please provide a complete, working reproduction of the bug. The full source code...

m-sasha commented 2 months ago

What environment are you running this in? I see com.intellij.ide classes in the stack trace.

Are you writing an IDEA plugin?

JasonTranz commented 2 months ago

Correct. Now, I'm working to write the IDEA plugin through the Compose Desktop & Jewel library.

As I mentioned before, I just call a simple DialogWindow in compose view and an exception happens.

m-sasha commented 2 months ago

I couldn't reproduce it.

Can you please share what’s runtime and VM, OS version do you use during development? You can do that by invoking action “About” and put its output here.

In my case I tried with current state of Jewel project (running samples:ide-plugin:runIde configuration):

IntelliJ IDEA 2024.1 (Community Edition)
Build #IC-241.14494.240, built on March 28, 2024
Runtime version: 17.0.9+7-b1087.7 aarch64
VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.
macOS 14.0

image (9)

JasonTranz commented 2 months ago

Hi @m-sasha please see the video here: https://quangtrungcollege-my.sharepoint.com/:v:/g/personal/huutq98_ms365vip_com/EWiCIP-mSENLr7y3iScNG3AB9L6MTr4nic3nVIYAJ4qpIQ?e=ZBT7TW

JasonTranz commented 2 months ago
image

My OS: macOS 14.4.1 Jewel: org.jetbrains.jewel:jewel-ide-laf-bridge-232:0.15.2 Compose-Desktop: 1.6.10-dev1561 Kotlin: 1.9.21

m-sasha commented 2 months ago

Can you try with the latest (or at least 2024.1) version of IDEA?

JasonTranz commented 2 months ago

Can you try with the latest (or at least 2024.1) version of IDEA?

Yup, my current IDE is 2024.1. But my IDE plugin project support starts from v2023.3. If the exception happens on 2023.3 the error dialog will be displayed, right?

Can you set the props in the gradle.properties to try reproduce

pluginSinceBuild = 222.*
pluginUntilBuild = 233.*

platformType = IC
platformVersion = 2023.3
pluginVerifierIdeVersions = 2023.3
m-sasha commented 2 months ago

If the error is due to a bug in an older version of IDEA, we're not going to be able to fix it, unfortunately.

JasonTranz commented 2 months ago

Alright, I will try again in 2024.1.

m-sasha commented 2 months ago

Can you also check what happens if you open a regular java.awt.Dialog from the same place?

JasonTranz commented 2 months ago

It seems I don't see an error dialog when installing the plugin from disk on 2023.3.6 & 2024.1.

JasonTranz commented 2 months ago

Hi @m-sasha , I know this is not relevant, but I have a quick question about VerticalScrollbar. When I use it in LazyColumn via LazyListState, when I scroll their progress height increases/decreases abnormally. This doesn't happen on Column using verticalScrollState, but I need to know if it is a feature or bug to create/report.

I'm stuck with this for 2 days and trying to find out the work around but I can't. If I go back to Column and use verticalScroll it works perfectly, but I can't handle LazyLoad (it is related to performance, scrollbar index doesn't reload progress when adding more items to the top, etc.).

You can try this code below:

import androidx.compose.foundation.VerticalScrollbar
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollbarAdapter
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.unit.dp
import kotlin.random.Random

@Composable
fun VerticalScrollbarUsage() = Box {
    val state = rememberLazyListState()
    val itemCount = 100
    val heights = remember {
        val random = Random(10)
        (0 until itemCount).map { random.nextInt(0, 2000) }
    }

    LazyColumn(Modifier.graphicsLayer(alpha = 0.5f), state = state) {
        items((0 until itemCount).toList()) { i ->
            val itemHeight = 20.dp + 20.dp + heights[i].dp
            Text(i.toString(), Modifier.graphicsLayer(alpha = 0.5f).height(itemHeight))
        }
    }

    VerticalScrollbar(
        rememberScrollbarAdapter(state),
        Modifier.align(Alignment.CenterEnd)
    )
}
m-sasha commented 2 months ago

If you mean that the size of the scrollbar changes as you scroll, that's expected if the items in the list are of varying sizes.

In a LazyColumn, only the visible items are actually created, so the scrollbar can't know the "real" offset or the full height of the column (the sum of heights of all the elements). Instead it uses a heuristic to estimate these values. If the items have wildly different sizes, the heuristic will be wrong.

JasonTranz commented 2 months ago

If you mean that the size of the scrollbar changes as you scroll, that's expected if the items in the list are of varying sizes.

In a LazyColumn, only the visible items are actually created, so the scrollbar can't know the "real" offset or the full height of the column (the sum of heights of all the elements). Instead it uses a heuristic to estimate these values. If the items have wildly different sizes, the heuristic will be wrong.

Yeah, I know how LazyList works but is there any way to improve this, because the scrollbar UX is quite bad in case the items are different in height from each other?

m-sasha commented 2 months ago

Unfortunately no.

JasonTranz commented 2 months ago

Thanks for your support, Regarding the issue I mentioned before it seems not to happen on the production build. If I'm facing with this in the future, I will re-create the ticket. You can close it now.