Skip to content

Linux: allow setting the Wayland app_id (JVM/dev runs get "java", so the shell can't match the .desktop entry) #577

Description

@rocketraman

⚠️ 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

  1. Configure nativeDistributions.linux { packageName = "myapp"; startupWMClass = "MyApp" }.
  2. ./gradlew run on a Wayland session.
  3. Inspect the window's app_id (KWin's window-info overlay, or
    qdbus org.kde.KWin /KWin queryWindowInfo) — it reports java.
  4. 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.classapp.idnucleus.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?

  • Yes
  • No

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions