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.9k stars 1.16k forks source link

Can not display Chinese with a Tray in Windows. #4486

Open michaellee123 opened 6 months ago

michaellee123 commented 6 months ago

Describe the bug

If it works in macOS, it's fine, but it can not work in Windows.

image
Tray(
    icon = TrayIcon,
    tooltip = "你好",
    menu = {
        Item("你好") {
            // do something
        }
    }
)
object TrayIcon : Painter() {
    override val intrinsicSize = Size(1024f, 1024f)

    override fun DrawScope.onDraw() {
        useResource("drawable/ic_icon_dark.png") {
            val image = ImageIO.read(it)
            val w = size.width.toInt()
            val h = size.height.toInt()
            val imageNew = BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB)
            imageNew.createGraphics().apply {
                drawImage(image, 0, 0, w, h, null)
                dispose()
            }
            println("width:$w, height: $h")

            drawImage(image = imageNew.toComposeImageBitmap())
        }
    }
}

And something else, the icon ain't clearly, I think the point is at this line:

//codes in [androidx.compose.ui.window.Tray.desktop.kt] line 106
    val awtIcon = remember(icon) {
        // We shouldn't use LocalDensity here because Tray's density doesn't equal it. It
        // equals to the density of the screen on which it shows. Currently Swing doesn't
        // provide us such information, it only requests an image with the desired width/height
        // (see MultiResolutionImage.getResolutionVariant). Resources like svg/xml should look okay
        // because they don't use absolute '.dp' values to draw, they use values which are
        // relative to their viewport.

        icon.toAwtImage(GlobalDensity, GlobalLayoutDirection, iconSize)// this line will make the icon blur
        icon.toAwtImage(Density(1f), LayoutDirection.Ltr) // this line will make the icon be cleaner
    }

Affected platforms

Versions Kotlin: 1.9.10 Groovy: 3.0.17 OS: Windows 11 and Windows 10, maybe Windows 7 too, but I don't have it.

eymar commented 6 months ago

What Compose Multiplatform version are you using? What Java version/manufacturer is used to run the app? Could you please attach a complete reproducer code (with app/window initialization)?

michaellee123 commented 6 months ago

What Compose Multiplatform version are you using? What Java version/manufacturer is used to run the app? Could you please attach a complete reproducer code (with app/window initialization)?

Compose Multiplatform version is 1.6.2, and I tried JDK version each from 17 to 21 (Amazon, Oracle , OpenJDK).

And there's another problem, if JDK version is 17 and the packageName has Chinese words, then I run ./gradlew package it will throw an exception (so I run this app around JDK >= 18 most time). My friend told me that maybe jdk version 17 the tray menu display correctly.

But I didn't try JDK 17 separately to see if that's right or not because I need a Chinese packageName. I don't have a Windows PC, so I'm sorry I can't try more solutions for this problem.

The app init code just same as this: https://github.com/JetBrains/compose-multiplatform/blob/master/tutorials/Tray_Notifications_MenuBar_new/README.md

I think that if you run a simple tray demo, and input some Chinese words into the tray's menuItem, and JDK version >= 18, you'll see this problem.

And I thought maybe Windows cannot show a UTF-8 charset word, I tried "你好".toByteArray(Charsets.UTF_8).toString(Charset.forName("GBK"))(and more another charsets) , it didn't work 😅.

I found that, if I use this lib: https://github.com/dorkbox/SystemTray , this lib uses JMenu not Menu, and it works, and I tried create a JMenu and Menu without tray, JMenu was correct, and Menu was wrong. But this lib has another problem, it can't display in some Windows 11 devices after mouse clicked, and has no logs.

So in the end, I gave up on using the tray. If you're interested in solving this issue, I would be grateful.

michaellee123 commented 6 months ago

Sorry, Compose Multiplatform version maybe 1.6.0, there's my toml file:

[versions]
compose = "1.6.2"
compose-plugin = "1.6.0"
junit = "4.13.2"
kotlin = "1.9.22"
coroutines = "1.8.0"
ktor = "2.3.8"
kamelImage = "0.9.3"

[libraries]
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
kotlin-test-junit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlin" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling", version.ref = "compose" }
compose-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview", version.ref = "compose" }
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" }
ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" }
ktor-client-logging = { module = "io.ktor:ktor-client-logging", version.ref = "ktor" }
ktor-client-serialization = { module = "io.ktor:ktor-client-serialization", version.ref = "ktor" }
ktor-client-darwin = { module = "io.ktor:ktor-client-darwin", version.ref = "ktor" }
ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor" }
ktor-client-cio = { module = "io.ktor:ktor-client-cio", version.ref = "ktor" }
ktor-client-content-negotiation = { module = "io.ktor:ktor-client-content-negotiation", version.ref = "ktor" }
ktor-serialization-kotlinx-json = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" }

kamel-image = { module = "media.kamel:kamel-image", version.ref = "kamelImage" }

[plugins]
jetbrainsCompose = { id = "org.jetbrains.compose", version.ref = "compose-plugin" }
kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
virogu commented 5 months ago

我猜测你应该是根据网上一些远古文章教程在某个地方配置了编码格式,比如-Dfile.encoding=UTF-8或-Dfile.encoding=GBK这样的配置, image 你可以删除所有类似这样的配置再试试,我这边测试jdk17、19、21都没有乱码问题,但是gradle运行参数中加上上面截图那个配置就会出现和你上面一样的乱码问题。

virogu commented 5 months ago

我猜测你应该是根据网上一些远古文章教程在某个地方配置了编码格式,比如-Dfile.encoding=UTF-8或-Dfile.encoding=GBK这样的配置, image 你可以删除所有类似这样的配置再试试,我这边测试jdk17、19、21都没有乱码问题,但是gradle运行参数中加上上面截图那个配置就会出现和你上面一样的乱码问题。

image hai'y还有IDEA 的这个配置也不要加

virogu commented 5 months ago

或者你在build配置里面加上这个,也是能解决乱码的问题

compose.desktop {
    application {
        mainClass = "MainKt"
        jvmArgs += listOf("-Dfile.encoding=GBK")
       // ... ...
    }
}
michaellee123 commented 5 months ago

我猜测你应该是根据网上一些远古文章教程在某个地方配置了编码格式,比如-Dfile.encoding=UTF-8或-Dfile.encoding=GBK这样的配置, image 你可以删除所有类似这样的配置再试试,我这边测试jdk17、19、21都没有乱码问题,但是gradle运行参数中加上上面截图那个配置就会出现和你上面一样的乱码问题。

我看了这个文件里面确实有UTF-8这个编码设置,但是不是我加的,我从compose这个创建项目的网页下载下来就是这样的,我后面有时间试试你这个方法,现在已经把这个东西给干掉了😄,多谢

okushnikov commented 2 weeks ago

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