Skip to content

Consider publishing libsystray for Linux arm64 #376

@asapha

Description

@asapha

As far as I understand, the lib can't use the LinuxTray implementation on arm64 because the native lib systray isn't published for it.

Logs from the app:

[2026-02-26 13:05:55.613] [NativeTray] Error initializing tray: java.lang.UnsatisfiedLinkError: Unable to load library 'systray':
libsystray.so: cannot open shared object file: No such file or directory                                                                                                                       
libsystray.so: cannot open shared object file: No such file or directory                                                                                                                       
Native library (linux-aarch64/libsystray.so) not found in resource path […]

Tested on Ubuntu 24.04 ARM64 via parallels on macOS.


This leads it to use the AwtTray implementation which has all the downsides of the default cmp impl in addition to somehow, causing deadlocks. When testing, the main window doesn't show up. According to a thread dump, it's because the AWT thread is blocked:

"AWT-EventQueue-0 @coroutine#26" prio=0 tid=0x0 nid=0x0 blocked
     java.lang.Thread.State: BLOCKED
 on java.awt.Component$AWTTreeLock@5be2db1e owned by "DefaultDispatcher-worker-15 @coroutine#193" Id=67
	at java.desktop@25.0.1/java.awt.Component.invalidate(Component.java:2990)
	at java.desktop@25.0.1/java.awt.Container.invalidate(Container.java:1611)
	at java.desktop@25.0.1/javax.swing.JComponent.revalidate(JComponent.java:4960)
	at app//org.jetbrains.skiko.SkiaLayer._init_$lambda$2(SkiaLayer.awt.kt:181)
	at app//org.jetbrains.skiko.SkiaLayer$$Lambda/0x00000008018b0000.propertyChange(Unknown Source)
	at java.desktop@25.0.1/java.beans.PropertyChangeSupport.fire(PropertyChangeSupport.java:343)
	at java.desktop@25.0.1/java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:336)
	at java.desktop@25.0.1/java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:268)
	at java.desktop@25.0.1/java.awt.Component.firePropertyChange(Component.java:8670)
	at app//org.jetbrains.skiko.SkiaLayer.checkContentScale(SkiaLayer.awt.kt:456)
	at app//org.jetbrains.skiko.SkiaLayer.update$skiko(SkiaLayer.awt.kt:599)
	at app//org.jetbrains.skiko.redrawer.AWTRedrawer.update(AWTRedrawer.kt:54)
	at app//org.jetbrains.skiko.redrawer.Redrawer$DefaultImpls.update$default(Redrawer.kt:12)
	at app//org.jetbrains.skiko.redrawer.AbstractDirectSoftwareRedrawer.renderImmediately(AbstractDirectSoftwareRedrawer.kt:39)
	at app//org.jetbrains.skiko.redrawer.LinuxSoftwareRedrawer.renderImmediately(LinuxSoftwareRedrawer.kt:35)
	at app//org.jetbrains.skiko.SkiaLayer.renderImmediately(SkiaLayer.awt.kt:592)
	at app//androidx.compose.ui.scene.skia.WindowSkiaLayerComponent.renderImmediately(WindowSkiaLayerComponent.desktop.kt:166)
	at app//androidx.compose.ui.scene.ComposeSceneMediator.renderImmediately(ComposeSceneMediator.desktop.kt:723)
	at app//androidx.compose.ui.scene.ComposeContainer.renderImmediately(ComposeContainer.desktop.kt:301)
	at app//androidx.compose.ui.awt.ComposeWindowPanel.renderImmediately(ComposeWindowPanel.desktop.kt:181)
	at app//androidx.compose.ui.awt.ComposeWindow.renderImmediately(ComposeWindow.desktop.kt:295)
	at app//androidx.compose.ui.awt.SwingWindow_desktopKt.SwingWindow$lambda$7$0(SwingWindow.desktop.kt:139)
	at app//androidx.compose.ui.awt.SwingWindow_desktopKt$$Lambda/0x00000008017b2c00.invoke(Unknown Source)
	at app//androidx.compose.ui.awt.AwtWindow_desktopKt.AwtWindow$lambda$3$0(AwtWindow.desktop.kt:77)
	at app//androidx.compose.ui.awt.AwtWindow_desktopKt$$Lambda/0x00000008017b8400.invoke(Unknown Source)
	at app//androidx.compose.ui.util.UpdateEffect_desktopKt.UpdateEffect$lambda$3$0$performUpdate$1(UpdateEffect.desktop.kt:59)
	at app//androidx.compose.ui.util.UpdateEffect_desktopKt$$Lambda/0x0000000801907c00.invoke(Unknown Source)
	at app//androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:730)
	at app//androidx.compose.ui.util.UpdateEffect_desktopKt.UpdateEffect$lambda$3$0$performUpdate(UpdateEffect.desktop.kt:55)
	at app//androidx.compose.ui.util.UpdateEffect_desktopKt.UpdateEffect$lambda$3$0(UpdateEffect.desktop.kt:64)
	at app//androidx.compose.ui.util.UpdateEffect_desktopKt$$Lambda/0x00000008017ba800.invoke(Unknown Source)
	at app//androidx.compose.runtime.DisposableEffectImpl.onRemembered(Effects.kt:87)
	at app//androidx.compose.runtime.internal.RememberEventDispatcher.dispatchRememberList(RememberEventDispatcher.kt:256)
	at app//androidx.compose.runtime.internal.RememberEventDispatcher.dispatchRememberObservers(RememberEventDispatcher.kt:228)
	at app//androidx.compose.runtime.CompositionImpl.applyChangesInLocked(Composition.kt:1209)
	at app//androidx.compose.runtime.CompositionImpl.applyChanges(Composition.kt:1236)
	at app//androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2.invokeSuspend$lambda$2(Recomposer.kt:733)
	at app//androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$$Lambda/0x0000000801455400.invoke(Unknown Source)
	at app//androidx.compose.ui.window.YieldFrameClock.withFrameNanos(Application.desktop.kt:262)
	at app//androidx.compose.ui.window.YieldFrameClock$withFrameNanos$1.invokeSuspend(Application.desktop.kt)
	at app//kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:34)
	at app//kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:100)
	at java.desktop@25.0.1/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:323)
	at java.desktop@25.0.1/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:723)
	at java.desktop@25.0.1/java.awt.EventQueue.dispatchEvent(EventQueue.java:702)
	at java.desktop@25.0.1/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
	at java.desktop@25.0.1/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
	at java.desktop@25.0.1/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
	at java.desktop@25.0.1/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
	at java.desktop@25.0.1/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
	at java.desktop@25.0.1/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
"DefaultDispatcher-worker-15 @coroutine#193" prio=0 tid=0x0 nid=0x0 waiting on condition
     java.lang.Thread.State: WAITING
 on java.util.concurrent.locks.ReentrantLock$NonfairSync@2e04b364 owned by "AWT-EventQueue-0 @coroutine#26" Id=58
	at java.base@25.0.1/jdk.internal.misc.Unsafe.park(Native Method)
	at java.base@25.0.1/java.util.concurrent.locks.LockSupport.park(LockSupport.java:223)
	at java.base@25.0.1/java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:790)
	at java.base@25.0.1/java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1030)
	at java.base@25.0.1/java.util.concurrent.locks.ReentrantLock$Sync.lock(ReentrantLock.java:154)
	at java.base@25.0.1/java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:323)
	at java.desktop@25.0.1/sun.awt.SunToolkit.awtLock(SunToolkit.java:233)
	at java.desktop@25.0.1/sun.awt.X11.XFramePeer.setInitialState(XFramePeer.java:425)
	at java.desktop@25.0.1/sun.awt.X11.XFramePeer.setupState(XFramePeer.java:137)
	at java.desktop@25.0.1/sun.awt.X11.XFramePeer.setVisible(XFramePeer.java:412)
	at java.desktop@25.0.1/sun.awt.X11.XEmbeddedFramePeer.setVisible(XEmbeddedFramePeer.java:39)
	at java.desktop@25.0.1/java.awt.Component.show(Component.java:1652)
	at java.desktop@25.0.1/java.awt.Window.show(Window.java:1010)
	at java.desktop@25.0.1/sun.awt.EmbeddedFrame.show(EmbeddedFrame.java:197)
	at java.desktop@25.0.1/java.awt.Component.show(Component.java:1690)
	at java.desktop@25.0.1/java.awt.Component.setVisible(Component.java:1637)
	at java.desktop@25.0.1/java.awt.Window.setVisible(Window.java:982)
	at java.desktop@25.0.1/sun.awt.X11.XTrayIconPeer.<init>(XTrayIconPeer.java:261)
	at java.desktop@25.0.1/sun.awt.X11.XToolkit.createTrayIcon(XToolkit.java:1176)
	at java.desktop@25.0.1/java.awt.TrayIcon.addNotify(TrayIcon.java:662)
	at java.desktop@25.0.1/java.awt.SystemTray.add(SystemTray.java:262)
	at app//com.kdroid.composetray.tray.impl.AwtTrayInitializer.initialize(AwtTrayInitializer.kt:90)
	at app//com.kdroid.composetray.tray.api.NativeTray$initializeTray$1.invokeSuspend(NativeTray.kt:228)
	at app//kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:34)
	at app//kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:100)
	at app//kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:124)
	at app//kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:89)
	at app//kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:586)
	at app//kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:820)
	at app//kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:717)
	at app//kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:704)

Tested with compose multiplatform 1.11.0-alpha03 and JDK 25. Skiko itself falls back to SOFTWARE_FAST rendering.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions