diff --git a/README.md b/README.md index 7751795cd..66bbf1061 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,24 @@ val svgLoader = service().svgLoader val painterProvider = retrieveStatelessIcon("icons/bot-toolwindow.svg", svgLoader, iconData) ``` -### Need help? +### Swing interoperability + +As this is Compose for Desktop, you get a good degree of interoperability with Swing. To avoid glitches and z-order +issues, you should enable the +[experimental Swing rendering pipeline](https://blog.jetbrains.com/kotlin/2023/08/compose-multiplatform-1-5-0-release/#enhanced-swing-interop) +before you initialize Compose content. + +The `ToolWindow.addComposeTab()` extension function provided by the `ide-laf-bridge` module will take care of that for +you, but if you want to also enable it in other scenarios and in standalone applications, you can call the +`enableNewSwingCompositing()` function in your Compose entry points (that is, right before creating a `ComposePanel`). + +> [!NOTE] +> The new Swing rendering pipeline is experimental and may have performance repercussions when using infinitely +> repeating animations. This is a known issue by the Compose Multiplatform team, that requires changes in the Java +> runtime to fix. Once the required changes are made in the JetBrains Runtime, we'll remove this notice. + +## Need help? + You can find help on the [`#jewel`](https://app.slack.com/client/T09229ZC6/C05T8U2C31T) channel on the Kotlin Slack. If you don't already have access to the Kotlin Slack, you can request it [here](https://surveys.jetbrains.com/s3/kotlin-slack-sign-up). diff --git a/core/src/main/kotlin/org/jetbrains/jewel/foundation/Compatibility.kt b/core/src/main/kotlin/org/jetbrains/jewel/foundation/Compatibility.kt new file mode 100644 index 000000000..139de6d04 --- /dev/null +++ b/core/src/main/kotlin/org/jetbrains/jewel/foundation/Compatibility.kt @@ -0,0 +1,18 @@ +package org.jetbrains.jewel.foundation + +import org.jetbrains.jewel.ExperimentalJewelApi + +/** + * Enables the new compositing strategy for rendering directly into Swing + * Graphics. This fixes z-order problems and artifacts on resizing, but + * has a performance penalty when using infinitely repeating animations. + * + * We assume the majority of our users will want this flag to be on, so + * this convenience function is provided to that end. Make sure you call + * it **before** you initialize any Compose content. The function is + * idempotent and extremely cheap, so you can call it on any entry point. + */ +@ExperimentalJewelApi +fun enableNewSwingCompositing() { + System.setProperty("compose.swing.render.on.graphics", "true") +} diff --git a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/ComposePanel.kt b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/ToolWindowExtensions.kt similarity index 71% rename from ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/ComposePanel.kt rename to ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/ToolWindowExtensions.kt index 09c28ff10..4e192def5 100644 --- a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/ComposePanel.kt +++ b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/ToolWindowExtensions.kt @@ -3,6 +3,7 @@ package org.jetbrains.jewel.bridge import androidx.compose.runtime.Composable import androidx.compose.ui.awt.ComposePanel import com.intellij.openapi.wm.ToolWindow +import org.jetbrains.jewel.foundation.enableNewSwingCompositing fun ToolWindow.addComposeTab( tabDisplayName: String, @@ -10,6 +11,10 @@ fun ToolWindow.addComposeTab( isCloseable: Boolean = false, content: @Composable () -> Unit, ) { + // We need to make sure this is done before Compose is attached. + // The operation is idempotent, so we can safely do it every time. + enableNewSwingCompositing() + val composePanel = ComposePanel() composePanel.setContent(content) val tabContent = contentManager.factory.createContent(composePanel, tabDisplayName, isLockable)