From 798666376c953723db8e978e32abf183d2fab5d2 Mon Sep 17 00:00:00 2001 From: Sebastiano Poggi Date: Fri, 22 Sep 2023 13:48:57 +0200 Subject: [PATCH] Use new Swing rendering pipeline by default --- README.md | 16 ++++++++++++++++ .../jewel/foundation/Compatibility.kt | 19 +++++++++++++++++++ ...omposePanel.kt => ToolWindowExtensions.kt} | 5 +++++ 3 files changed, 40 insertions(+) create mode 100644 core/src/main/kotlin/org/jetbrains/jewel/foundation/Compatibility.kt rename ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/{ComposePanel.kt => ToolWindowExtensions.kt} (71%) diff --git a/README.md b/README.md index 7751795cd0..7beeb8f683 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,23 @@ val svgLoader = service().svgLoader val painterProvider = retrieveStatelessIcon("icons/bot-toolwindow.svg", svgLoader, iconData) ``` +#### 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, especially on Windows, where +> HW acceleration is not yet available. + ### 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 0000000000..02f930604f --- /dev/null +++ b/core/src/main/kotlin/org/jetbrains/jewel/foundation/Compatibility.kt @@ -0,0 +1,19 @@ +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 on Windows (as of 1.5.1) because there is no + * DirectX HW acceleration. Linux and macOS have HW acceleration though. + * + * 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 09c28ff10f..4e192def5b 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)