From 67648f919bb23d76751d6ef4f3d2dfdb9c83f1c0 Mon Sep 17 00:00:00 2001 From: Yuriy Artamonov Date: Fri, 17 Oct 2025 16:39:43 +0200 Subject: [PATCH] [compose] IJPL-213469 Skia loading causes UI freezes (cherry picked from commit e7f9d2f71b2be2188547214bc6f18a7383d42499) (cherry picked from commit a499a3063c5f4e3b8622d1453b85bd80c918b476) IJ-MR-179919 GitOrigin-RevId: 61cffc1bb097419e72bb99fbe4d8d7ed16181ec3 --- platform/compose/BUILD.bazel | 3 +++ .../compose/intellij.platform.compose.iml | 1 + .../resources/intellij.platform.compose.xml | 2 ++ .../platform/compose/SkikoPreloader.kt | 25 +++++++++++++++++++ .../jewel/bridge/JewelComposePanelWrapper.kt | 14 ++++++++--- 5 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 platform/compose/src/com/intellij/platform/compose/SkikoPreloader.kt diff --git a/platform/compose/BUILD.bazel b/platform/compose/BUILD.bazel index 55826c9479a3..3c694d30110d 100644 --- a/platform/compose/BUILD.bazel +++ b/platform/compose/BUILD.bazel @@ -25,6 +25,7 @@ jvm_library( "@lib//:jetbrains-annotations", "@lib//:kotlinx-coroutines-core", "@lib//:jetbrains-compose-components-ui-tooling-preview-desktop", + "//platform/diagnostic/telemetry", ], exports = [ "//platform/jewel/ui", @@ -57,6 +58,8 @@ jvm_library( "@lib//:jetbrains-compose-components-ui-tooling-preview-desktop", "@lib//:junit4", "//platform/jewel/int-ui/int-ui-standalone:jewel-intUi-standalone", + "//platform/diagnostic/telemetry", + "//platform/diagnostic/telemetry:telemetry_test_lib", ], exports = [ "//platform/jewel/ui", diff --git a/platform/compose/intellij.platform.compose.iml b/platform/compose/intellij.platform.compose.iml index ef92e34aded5..9ca45e43e224 100644 --- a/platform/compose/intellij.platform.compose.iml +++ b/platform/compose/intellij.platform.compose.iml @@ -43,5 +43,6 @@ + \ No newline at end of file diff --git a/platform/compose/resources/intellij.platform.compose.xml b/platform/compose/resources/intellij.platform.compose.xml index 50d974208773..c10c3706c22b 100644 --- a/platform/compose/resources/intellij.platform.compose.xml +++ b/platform/compose/resources/intellij.platform.compose.xml @@ -6,6 +6,8 @@ description="Allows changing how ComposePanel is rendered using rendering on Graphics (when `true`, it provides smooth Swing interop) or on native AWT texture (when `false`). Works only in internal mode" key="compose.swing.render.on.graphics"/> + + diff --git a/platform/compose/src/com/intellij/platform/compose/SkikoPreloader.kt b/platform/compose/src/com/intellij/platform/compose/SkikoPreloader.kt new file mode 100644 index 000000000000..d49053254f01 --- /dev/null +++ b/platform/compose/src/com/intellij/platform/compose/SkikoPreloader.kt @@ -0,0 +1,25 @@ +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.platform.compose + +import com.intellij.ide.ApplicationActivity +import com.intellij.openapi.diagnostic.thisLogger +import com.intellij.platform.diagnostic.telemetry.Scope +import com.intellij.platform.diagnostic.telemetry.TelemetryManager +import kotlinx.coroutines.withContext +import org.jetbrains.jewel.bridge.setSkikoLibraryPath +import org.jetbrains.skiko.Library + +// org.jetbrains.skiko.Library.load seems expensive, better have it loaded before the first rendering happens +internal class SkikoPreloader : ApplicationActivity { + private val SKIKO: Scope = Scope("skiko") + + override suspend fun execute() { + val tracer = TelemetryManager.getInstance().getSimpleTracer(SKIKO) + withContext(tracer.span("org.jetbrains.skiko.Library.load")) { + thisLogger().debug("Preloading Skiko") + + setSkikoLibraryPath() + Library.load() + } + } +} diff --git a/platform/jewel/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/JewelComposePanelWrapper.kt b/platform/jewel/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/JewelComposePanelWrapper.kt index 68cd7d188574..b621f1315ad3 100644 --- a/platform/jewel/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/JewelComposePanelWrapper.kt +++ b/platform/jewel/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/JewelComposePanelWrapper.kt @@ -193,10 +193,8 @@ public fun JewelComposeNoThemePanel( public fun JewelComposeNoThemePanel(config: ComposePanel.() -> Unit = {}, content: @Composable () -> Unit): JComponent = JewelComposeNoThemePanel(focusOnClickInside = false, config, content) -private fun createJewelComposePanel( - focusOnClickInside: Boolean, - config: ComposePanel.(JewelComposePanelWrapper) -> Unit, -): JewelComposePanelWrapper { +@ApiStatus.Internal +public fun setSkikoLibraryPath() { if (System.getProperty("skiko.library.path") == null) { val bundledSkikoFolder = File(PathManager.getLibPath(), "/skiko-awt-runtime-all") if (bundledSkikoFolder.isDirectory && bundledSkikoFolder.canRead()) { @@ -205,6 +203,14 @@ private fun createJewelComposePanel( JewelLogger.getInstance("SkikoLoader").warn("Bundled Skiko not found/not readable, falling back to default") } } +} + +private fun createJewelComposePanel( + focusOnClickInside: Boolean, + config: ComposePanel.(JewelComposePanelWrapper) -> Unit, +): JewelComposePanelWrapper { + setSkikoLibraryPath() + val jewelPanel = JewelComposePanelWrapper(focusOnClickInside) jewelPanel.composePanel.config(jewelPanel) ComposeUiInspector(jewelPanel)