@@ -13,15 +13,24 @@ import com.kdroid.composetray.utils.IconRenderProperties
1313import com.kdroid.composetray.utils.extractToTempIfDifferent
1414import com.kdroid.kmplog.Log
1515import com.kdroid.kmplog.d
16- import io.github.kdroidfilter.platformtools.OperatingSystem
16+ import com.kdroid.kmplog.e
17+ import io.github.kdroidfilter.platformtools.OperatingSystem.LINUX
18+ import io.github.kdroidfilter.platformtools.OperatingSystem.MACOS
19+ import io.github.kdroidfilter.platformtools.OperatingSystem.UNKNOWN
20+ import io.github.kdroidfilter.platformtools.OperatingSystem.WINDOWS
1721import io.github.kdroidfilter.platformtools.getOperatingSystem
1822import kotlinx.coroutines.CoroutineScope
1923import kotlinx.coroutines.Dispatchers
2024import kotlinx.coroutines.SupervisorJob
2125import kotlinx.coroutines.launch
26+ import java.util.concurrent.atomic.AtomicBoolean
27+
2228
2329internal class NativeTray {
24- val trayScope = CoroutineScope (Dispatchers .IO + SupervisorJob ())
30+
31+ private val trayScope = CoroutineScope (Dispatchers .IO + SupervisorJob ())
32+
33+ private val awtTrayUsed = AtomicBoolean (false )
2534
2635 /* *
2736 * Constructor that accepts file paths for icons
@@ -58,7 +67,7 @@ internal class NativeTray {
5867 Log .d(" NativeTray" , " Generated PNG icon path: $pngIconPath " )
5968
6069 // For Windows, we need an ICO file
61- val windowsIconPath = if (getOperatingSystem() == OperatingSystem . WINDOWS ) {
70+ val windowsIconPath = if (getOperatingSystem() == WINDOWS ) {
6271 // Create a temporary ICO file
6372 ComposableIconUtils .renderComposableToIcoFile(iconRenderProperties, iconContent).also {
6473 Log .d(" NativeTray" , " Generated Windows ICO path: $it " )
@@ -79,37 +88,53 @@ internal class NativeTray {
7988 menuContent : (TrayMenuBuilder .() -> Unit )? = null
8089 ) {
8190 trayScope.launch {
82- when (getOperatingSystem()) {
83- OperatingSystem . LINUX -> {
84- Log .d( " NativeTray " , " Initializing Linux tray with icon path: $iconPath " )
85- LinuxTrayInitializer .initialize(iconPath, tooltip, primaryAction, primaryActionLinuxLabel, menuContent)
86- }
87- OperatingSystem . WINDOWS -> {
88- Log .d( " NativeTray " , " Initializing Windows tray with icon path: $windowsIconPath " )
89- WindowsTrayInitializer .initialize(
90- windowsIconPath,
91- tooltip,
92- primaryAction,
93- menuContent
94- )
95- }
96- OperatingSystem . MACOS , OperatingSystem . UNKNOWN -> {
97- Log .d( " NativeTray " , " Initializing AWT tray with icon path: $iconPath " )
98- AwtTrayInitializer .initialize(iconPath, tooltip, primaryAction, menuContent)
91+ var trayInitialized = false
92+ val os = getOperatingSystem()
93+ try {
94+ when (os) {
95+ LINUX -> {
96+ Log .d( " NativeTray " , " Initializing Linux tray with icon path: $iconPath " )
97+ LinuxTrayInitializer .initialize(iconPath, tooltip, primaryAction, primaryActionLinuxLabel, menuContent )
98+ trayInitialized = true
99+ }
100+
101+ WINDOWS -> {
102+ Log .d( " NativeTray " , " Initializing Windows tray with icon path: $windowsIconPath " )
103+ WindowsTrayInitializer .initialize(windowsIconPath, tooltip, primaryAction, menuContent )
104+ trayInitialized = true
105+ }
106+
107+ else -> {}
99108 }
109+ } catch (e: Exception ) {
110+ Log .e(" NativeTray" , " Error initializing tray:" , e)
111+ }
100112
101- else -> {}
113+ val awtTrayRequired = os == MACOS || os == UNKNOWN || ! trayInitialized
114+ if (awtTrayRequired) {
115+ if (AwtTrayInitializer .isSupported()) {
116+ try {
117+ Log .d(" NativeTray" , " Initializing AWT tray with icon path: $iconPath " )
118+ AwtTrayInitializer .initialize(iconPath, tooltip, primaryAction, menuContent)
119+ awtTrayUsed.set(true )
120+ } catch (e: Exception ) {
121+ Log .e(" NativeTray" , " Error initializing AWT tray:" , e)
122+ }
123+ } else {
124+ Log .d(" NativeTray" , " AWT tray is not supported" )
125+ }
102126 }
103127 }
104128 }
105129
106- /* *
107- * Creates a temporary file that will be deleted when the JVM exits.
108- */
109- private fun createTempFile (prefix : String = "tray_icon_", suffix : String ): java.io.File {
110- val tempFile = java.io.File .createTempFile(prefix, suffix)
111- tempFile.deleteOnExit()
112- return tempFile
130+ internal fun dispose () {
131+ val os = getOperatingSystem()
132+ when {
133+ awtTrayUsed.get() -> AwtTrayInitializer .dispose()
134+ os == LINUX -> LinuxTrayInitializer .dispose()
135+ os == WINDOWS -> WindowsTrayInitializer .dispose()
136+ else -> {}
137+ }
113138 }
114139}
115140
@@ -152,7 +177,7 @@ fun ApplicationScope.Tray(
152177 primaryActionLinuxLabel,
153178 menuContent
154179 ) {
155- NativeTray (
180+ val tray = NativeTray (
156181 iconPath = absoluteIconPath,
157182 windowsIconPath = absoluteWindowsIconPath,
158183 tooltip = tooltip,
@@ -163,12 +188,7 @@ fun ApplicationScope.Tray(
163188
164189 onDispose {
165190 Log .d(" NativeTray" , " onDispose" )
166- when (getOperatingSystem()) {
167- OperatingSystem .WINDOWS -> WindowsTrayInitializer .dispose()
168- OperatingSystem .MACOS , OperatingSystem .UNKNOWN -> AwtTrayInitializer .dispose()
169- OperatingSystem .LINUX -> LinuxTrayInitializer .dispose()
170- else -> {}
171- }
191+ tray.dispose()
172192 }
173193 }
174194}
@@ -205,7 +225,7 @@ fun ApplicationScope.Tray(
205225 menuContent,
206226 contentHash, // Use the content hash as an implicit key
207227 ) {
208- NativeTray (
228+ val tray = NativeTray (
209229 iconContent = iconContent,
210230 iconRenderProperties = iconRenderProperties,
211231 tooltip = tooltip,
@@ -216,12 +236,7 @@ fun ApplicationScope.Tray(
216236
217237 onDispose {
218238 Log .d(" NativeTray" , " onDispose" )
219- when (getOperatingSystem()) {
220- OperatingSystem .WINDOWS -> WindowsTrayInitializer .dispose()
221- OperatingSystem .MACOS , OperatingSystem .UNKNOWN -> AwtTrayInitializer .dispose()
222- OperatingSystem .LINUX -> LinuxTrayInitializer .dispose()
223- else -> {}
224- }
239+ tray.dispose()
225240 }
226241 }
227242}
0 commit comments