⚠️ Is your feature request related to a problem? Please describe
On Linux, a Nucleus app launched any way other than through the packaged launcher binary gets
the Wayland app_id java, so the desktop shell can't match the window to its .desktop
entry and the taskbar falls back to a generic icon.
Launching via the Gradle run task, the app_id is the GTK program name, which is java for
any JVM process. The compositor matches windows to .desktop entries by
app_id/StartupWMClass, so nothing matches. The packaged .deb/.rpm is fine — there the
launcher binary is named after the package, so the app_id matches the generated
StartupWMClass. run, java -jar and IDE run configurations are all affected.
Setting icon = painterResource(...) on the window doesn't help: Wayland has no per-window
icon that the shell uses.
Reported downstream as rocketraman/gitvantage#10 — a contributor
running from source sees a generic taskbar icon, while the packaged build is correct.
Environment: Nucleus 2.4.0, JVM (Temurin 25), Fedora 44, KDE Plasma 6 (Wayland), Tao
decorated-window backend.
Steps to reproduce
- Configure
nativeDistributions.linux { packageName = "myapp"; startupWMClass = "MyApp" }.
./gradlew run on a Wayland session.
- Inspect the window's
app_id (KWin's window-info overlay, or
qdbus org.kde.KWin /KWin queryWindowInfo) — it reports java.
- Install the
.rpm/.deb and launch it from the app menu — app_id is MyApp and the
icon resolves correctly.
💡 Describe the solution you'd like
On Linux, have the Tao backend set the GTK program name before the first window is realized —
e.g. g_set_prgname(), which is what GDK derives the Wayland app_id from — resolved from
the values Nucleus already computes.
Most of this already exists in the framework; it just isn't applied on the JVM/Tao path:
- The
run task already injects -Dnucleus.app.id=<resolved id>
(configureJvmApplication.kt, JVM args for the run exec).
generateAppProperties writes nucleus/nucleus-app.properties (app.id,
startup.wm.class) into a resources srcDir of the main source set, so both keys are on the
classpath during a dev run, not only in packaged builds.
AppNameResolver (in nucleus.graalvm-runtime) already implements the desired resolution
order — startup.wm.class → app.id → nucleus.app.id → executable name — but it is only
wired into a GraalVM substitution for AWT's XToolkit, so it never runs for JVM + Tao.
- macOS dev runs already get equivalent treatment (
-Dapple.awt.application.name,
-Xdock:icon). Linux has no counterpart.
It would also help to expose an explicit override — a nucleus.app.wm-class-style system
property, or a parameter on the window API — for apps that need a value different from the
packaged one.
Two smaller notes:
- Prefer
startup.wm.class over app.id when both are present. They legitimately differ:
Debian policy wants a lowercase packageName (gitvantage), while the .desktop
StartupWMClass matches the launcher binary (GitVantage). AppNameResolver already
prefers the former.
- Once this is set at runtime,
startupWMClass in the Gradle DSL and the actual app_id can
no longer drift apart, which today is a silent failure that varies by launch method.
🤚 Do you want to develop this feature yourself?
On Linux, a Nucleus app launched any way other than through the packaged launcher binary gets
the Wayland
app_idjava, so the desktop shell can't match the window to its.desktopentry and the taskbar falls back to a generic icon.
Launching via the Gradle
runtask, theapp_idis the GTK program name, which isjavaforany JVM process. The compositor matches windows to
.desktopentries byapp_id/StartupWMClass, so nothing matches. The packaged.deb/.rpmis fine — there thelauncher binary is named after the package, so the
app_idmatches the generatedStartupWMClass.run,java -jarand IDE run configurations are all affected.Setting
icon = painterResource(...)on the window doesn't help: Wayland has no per-windowicon that the shell uses.
Reported downstream as rocketraman/gitvantage#10 — a contributor
running from source sees a generic taskbar icon, while the packaged build is correct.
Environment: Nucleus 2.4.0, JVM (Temurin 25), Fedora 44, KDE Plasma 6 (Wayland), Tao
decorated-window backend.
Steps to reproduce
nativeDistributions.linux { packageName = "myapp"; startupWMClass = "MyApp" }../gradlew runon a Wayland session.app_id(KWin's window-info overlay, orqdbus org.kde.KWin /KWin queryWindowInfo) — it reportsjava..rpm/.deband launch it from the app menu —app_idisMyAppand theicon resolves correctly.
💡 Describe the solution you'd like
On Linux, have the Tao backend set the GTK program name before the first window is realized —
e.g.
g_set_prgname(), which is what GDK derives the Waylandapp_idfrom — resolved fromthe values Nucleus already computes.
Most of this already exists in the framework; it just isn't applied on the JVM/Tao path:
runtask already injects-Dnucleus.app.id=<resolved id>(
configureJvmApplication.kt, JVM args for the run exec).generateAppPropertieswritesnucleus/nucleus-app.properties(app.id,startup.wm.class) into a resources srcDir of the main source set, so both keys are on theclasspath during a dev run, not only in packaged builds.
AppNameResolver(innucleus.graalvm-runtime) already implements the desired resolutionorder —
startup.wm.class→app.id→nucleus.app.id→ executable name — but it is onlywired into a GraalVM substitution for AWT's
XToolkit, so it never runs for JVM + Tao.-Dapple.awt.application.name,-Xdock:icon). Linux has no counterpart.It would also help to expose an explicit override — a
nucleus.app.wm-class-style systemproperty, or a parameter on the window API — for apps that need a value different from the
packaged one.
Two smaller notes:
startup.wm.classoverapp.idwhen both are present. They legitimately differ:Debian policy wants a lowercase
packageName(gitvantage), while the.desktopStartupWMClassmatches the launcher binary (GitVantage).AppNameResolveralreadyprefers the former.
startupWMClassin the Gradle DSL and the actualapp_idcanno longer drift apart, which today is a silent failure that varies by launch method.
🤚 Do you want to develop this feature yourself?