perf: make icon lazy and add some performance notes

This commit is contained in:
Johannes Frohnmeyer 2024-07-22 17:00:55 +02:00
parent 8a3971584b
commit 015190af19
Signed by: Johannes
GPG Key ID: E76429612C2929F4
4 changed files with 19 additions and 14 deletions

View File

@ -144,7 +144,9 @@ tasks {
} }
buildSearchableOptions { buildSearchableOptions {
jvmArgs("-Dio.gitlab.jfronny.globalmenu.disable") jvmArgs(
"-Dio.gitlab.jfronny.globalmenu.disable"
)
} }
// Set the JVM compatibility versions // Set the JVM compatibility versions
@ -172,6 +174,9 @@ tasks {
} }
runIde { runIde {
this.jvmArgs("-Dawt.toolkit.name=WLToolkit") jvmArgs(
"-Dawt.toolkit.name=WLToolkit",
// "-Dio.gitlab.jfronny.globalmenu.debug"
)
} }
} }

View File

@ -3,6 +3,7 @@ package io.gitlab.jfronny.globalmenu
import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.diagnostic.Logger
object GlobalMenu { object GlobalMenu {
val debugging = System.getProperty("io.gitlab.jfronny.globalmenu.debug") != null
val Log: Logger = Logger.getInstance(GlobalMenu::class.java) val Log: Logger = Logger.getInstance(GlobalMenu::class.java)
val Native = Native() val Native = Native()
val Cleaner = java.lang.ref.Cleaner.create() val Cleaner = java.lang.ref.Cleaner.create()

View File

@ -72,7 +72,7 @@ class DbusmenuImpl(windowId: Long, private val menuHolder: MenuHolder) : Dbusmen
} }
override fun Event(id: Int, eventId: String, data: Variant<*>?, timestamp: UInt32?) { override fun Event(id: Int, eventId: String, data: Variant<*>?, timestamp: UInt32?) {
GlobalMenu.Log.warn("Event $eventId for menu $id (${menuHolder.find(id)})") if (GlobalMenu.debugging) GlobalMenu.Log.warn("Event $eventId for menu $id (${menuHolder.find(id)})")
try { try {
when (eventId) { when (eventId) {
"clicked" -> menuHolder.find(id)?.onEvent() "clicked" -> menuHolder.find(id)?.onEvent()
@ -86,7 +86,7 @@ class DbusmenuImpl(windowId: Long, private val menuHolder: MenuHolder) : Dbusmen
override fun EventGroup(events: MutableList<EventGroupStruct>?): MutableList<Int>? = null // not needed? override fun EventGroup(events: MutableList<EventGroupStruct>?): MutableList<Int>? = null // not needed?
override fun AboutToShow(id: Int): Boolean { override fun AboutToShow(id: Int): Boolean {
GlobalMenu.Log.warn("About to show menu $id") if (GlobalMenu.debugging) GlobalMenu.Log.warn("About to show menu $id")
try { try {
menuHolder.find(id)?.update() menuHolder.find(id)?.update()
return true return true

View File

@ -5,20 +5,17 @@ import com.intellij.openapi.actionSystem.impl.ActionMenuItem
import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.EDT import com.intellij.openapi.application.EDT
import io.gitlab.jfronny.globalmenu.GlobalMenu import io.gitlab.jfronny.globalmenu.GlobalMenu
import kotlinx.coroutines.* import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import org.apache.commons.io.output.ByteArrayOutputStream import org.apache.commons.io.output.ByteArrayOutputStream
import java.awt.event.ActionEvent
import java.awt.event.InputEvent import java.awt.event.InputEvent
import java.awt.event.KeyEvent import java.awt.event.KeyEvent
import java.awt.image.BufferedImage import java.awt.image.BufferedImage
import java.lang.reflect.Modifier import java.lang.reflect.Modifier
import java.util.* import java.util.*
import javax.imageio.ImageIO import javax.imageio.ImageIO
import javax.swing.JCheckBoxMenuItem import javax.swing.*
import javax.swing.JMenu
import javax.swing.JMenuItem
import javax.swing.JRadioButtonMenuItem
import javax.swing.JSeparator
class SwingMenu(private val menuItem: JMenuItem?, private val holder: SwingMenuHolder) : Menu { class SwingMenu(private val menuItem: JMenuItem?, private val holder: SwingMenuHolder) : Menu {
override val id = holder.getId(menuItem) override val id = holder.getId(menuItem)
@ -26,7 +23,9 @@ class SwingMenu(private val menuItem: JMenuItem?, private val holder: SwingMenuH
override val label: String get() = menuItem?.text ?: "" override val label: String get() = menuItem?.text ?: ""
override val isEnabled: Boolean get() = menuItem?.isEnabled ?: false override val isEnabled: Boolean get() = menuItem?.isEnabled ?: false
override val isVisible: Boolean get() = menuItem?.isVisible ?: false override val isVisible: Boolean get() = menuItem?.isVisible ?: false
override val iconData: ByteArray? get() = menuItem?.icon?.let { icon -> override val iconData: ByteArray? by lazy { menuItem?.icon?.let { icon ->
// This is somewhat expensive, but we need to do it
// At least avoid doing it multiple times
val width = icon.iconWidth val width = icon.iconWidth
val height = icon.iconHeight val height = icon.iconHeight
@ -46,7 +45,7 @@ class SwingMenu(private val menuItem: JMenuItem?, private val holder: SwingMenuH
GlobalMenu.Log.error("Failed to convert icon to byte array", e) GlobalMenu.Log.error("Failed to convert icon to byte array", e)
null null
} }
} } }
override val shortcut: Array<String>? get() = menuItem?.accelerator?.let { ks -> override val shortcut: Array<String>? get() = menuItem?.accelerator?.let { ks ->
val s = getModifiersText(ks.modifiers) val s = getModifiersText(ks.modifiers)
@ -129,7 +128,7 @@ class SwingMenu(private val menuItem: JMenuItem?, private val holder: SwingMenuH
if (each is ActionMenu) { if (each is ActionMenu) {
each.removeAll() each.removeAll()
each.isSelected = true each.isSelected = true
each.fillMenu() each.fillMenu() // This is REALLY expensive and on the EDT TODO: find out whether we can avoid it
} }
cmi.syncChildren(deepness - 1) cmi.syncChildren(deepness - 1)
} }