Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong window title displayed in GNOME top bar #956

Closed
gschaffner opened this issue Aug 22, 2019 · 19 comments · Fixed by cryptomator/cryptomator-linux#20 or cryptomator/docker#4
Closed
Labels
misc:gui os:linux type:minor-bug Something minor isn't working
Milestone

Comments

@gschaffner
Copy link

Description

With GNOME 3.32.2, the wrong window title is displayed in the top bar when the Cryptomator window is focused.

System Setup

  • Operating system and version: Manjaro GNU/Linux 18.0.4 w/ GNOME 3.32
  • Cryptomator version: 1.4.15
  • Drive: FUSE

Steps to Reproduce

  1. Open Cryptomator GUI and observe the GNOME top bar.

Expected Behavior

Cryptomator will be displayed as the window's title.

Actual Behavior

org.cryptomator.launcher.Cryptomator$MainApp is displayed as the window's title.

Reproducibility

Always

Additional Information

This bug is occurring on a fresh Manjaro installation with no prior use of Cryptomator.

@gschaffner gschaffner added the type:bug Something isn't working label Aug 22, 2019
@overheadhunter overheadhunter added misc:gui os:linux type:minor-bug Something minor isn't working and removed type:bug Something isn't working labels Aug 22, 2019
@bilelmoussaoui
Copy link

It's due to a missing StartupWMClass key in the desktop file to allow GNOME Shell identify the application and display the right name.
Adding this to desktop file should fix it

StartupWMClass=skymatic-cryptomator

@overheadhunter
Copy link
Member

@bilelmoussaoui conflicts with cryptomator/cryptomator-linux#10

@bilelmoussaoui
Copy link

@overheadhunter I should have mentioned that the WMClass I used was the one from the flatpak package. Not sure if it's the correct one
CC @x80486

@dhet
Copy link

dhet commented Oct 5, 2019

I'm not sure if it's that simple. The StartupWMClass entry only provides a way to group windows of the same application together. It cannot be used to assign the WM class to an application.
One way to assign the WM class is via explicit gtk_window_set_wmclass() call (i.e. not possible from Java). I spend a few hours trying to find a way to do this with JavaFX but I couldn't find anything. Maybe the jpackager or appimagetool is worth a look?

Btw, in the current snapshot version the window title says "java" (see screenshot) and the WM class is also "java" which means that

  • window grouping as it is right now does not work
  • even if we set StartupWMClass=java, gnome will group all "java" applications under the Cryptomator icon
    (I tried plain JAR as well as AppImage)
    cryptomator-java

@tobihagemann
Copy link
Member

tobihagemann commented Oct 5, 2019

Calling native functions is within the realm of possibility. 😉 We have already done that for Windows and macOS but it wasn't needed for Linux yet. But of course, if there is another (and much simpler) way, that would definitely be preferred.

@x80486
Copy link

x80486 commented Oct 5, 2019

It's due to a missing StartupWMClass key in the desktop file to allow GNOME Shell identify the application and display the right name.
Adding this to desktop file should fix it

StartupWMClass=skymatic-cryptomator

Indeed, no problems with the Flatpak...check! 😎

Screenshot from 2019-10-05 16-30-27

@stale
Copy link

stale bot commented Jan 3, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the state:stale Issues without any activity that will be closed automatically label Jan 3, 2020
@giovannivelludo
Copy link

giovannivelludo commented Jan 24, 2020

I fixed this in my Ubuntu 18.04 PPA install by adding this line at the end of ~/.local/share/applications/Cryptomator.desktop:

StartupWMClass=org.cryptomator.launcher.Cryptomator$MainApp

@overheadhunter what's the conflict with cryptomator/cryptomator-linux#10? I'm not getting multiple icons in the dock with this fix.

@stale stale bot removed the state:stale Issues without any activity that will be closed automatically label Jan 24, 2020
@overheadhunter
Copy link
Member

overheadhunter commented Jan 24, 2020

@overheadhunter what's the conflict with cryptomator/cryptomator-linux#10? I'm not getting multiple icons in the dock with this fix.

I was referring to the fix suggested by @bilelmoussaoui, who then confirmed he used the class name from the flatpak "prototype".

For the latest 1.4.x release org.cryptomator.launcher.Cryptomator$MainApp should be correct. With 1.5.0 it will change again, which is why I will now reopen this issue immediately. 😉

@giovannivelludo
Copy link

I submitted a pull request on Cryptomator's AUR to fix this issue there too.

@stale stale bot added the state:stale Issues without any activity that will be closed automatically label Jul 25, 2020
@cryptomator cryptomator deleted a comment from stale bot Jul 26, 2020
@stale stale bot removed the state:stale Issues without any activity that will be closed automatically label Jul 26, 2020
@swiesend
Copy link
Contributor

swiesend commented Feb 26, 2021

Hey, the current

$ xprop WM_CLASS
WM_CLASS(STRING) = "java", "java"

for 1.5.x (used 1.5.13 via ppa on Ubuntu 20.04.1) isn't very useful. I also noticed this when testing @purejava's KeepassXC integration, as cryptomator was only listed on the built-in Secret Service daemon as application: java.

So currently one has to set StartupWMClass=java on a .desktop entry.

Whats also annoying, is, that one can't add the application to the gnome dock, unless the StartupWMClass matches the WM_CLASS (I guess the first value of both, there seems to be an heuristic for that).

StartupWMClass=org-cryptomator-launcher-Cryptomator StartupWMClass=java
Cryptomator-no-favorites Cryptomator-add-favorites

@overheadhunter
Copy link
Member

overheadhunter commented Feb 26, 2021

@swiesend If you fixed this for the PPA, do you think it can be fixed for the AppImage (see desktop file) as well? If so, would you mind submitting a PR to cryptomator/cryptomator-linux and explain your findings a bit more?

@swiesend
Copy link
Contributor

I'll check.

@swiesend
Copy link
Contributor

swiesend commented Feb 27, 2021

Well I spent a lot of time to find a nice solution for the AppImage, but did not succeed.

I think the easiest, but dirties solution is to just change the StartupWMClass=java in the AppImage .desktop file, but that comes at the price to also catch other applications which run under the WM_CLASS(STRING) = "java", "java".

The idea IDE e.g. stores a startupWMClass in an *.appdata.xml, but I am not sure if that value is actually read and used at runtime or just generated at compile time and put there.

Some sites I've been to:

gtk_window_set_wmclass has been deprecated since version 3.22 and should not be used in newly-written code.

https://wiki.gnome.org/HowDoI/GtkApplication
https://developer.gnome.org/gtk3//3.2/GtkApplication.html#GtkApplication.object-hierarchy
https://developer.gnome.org/gtk3/3.24/GtkApplication.html
https://developer.gnome.org/gtk3/3.24/GtkApplicationWindow.html
https://developer.gnome.org/gtk3/3.24/GtkWindow.html
https://developer.gnome.org/gtk3/3.24/GtkWindow.html#gtk-window-set-wmclass

$ ./launcher-linux.sh 
Exception in thread "main" java.lang.NoClassDefFoundError: org/objectweb/asm/ClassAdapter
	at java.base/java.lang.ClassLoader.defineClass1(Native Method)
	at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1017)
	at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:151)
	at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:821)
	at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:719)
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:642)
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:600)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
	at java.base/java.lang.Class.getDeclaredMethods0(Native Method)
	at java.base/java.lang.Class.privateGetDeclaredMethods(Class.java:3244)
	at java.base/java.lang.Class.getDeclaredMethod(Class.java:2551)
	at java.instrument/sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:454)
	at java.instrument/sun.instrument.InstrumentationImpl.loadClassAndCallPremain(InstrumentationImpl.java:525)
Caused by: java.lang.ClassNotFoundException: org.objectweb.asm.ClassAdapter
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:602)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
	... 14 more
*** java.lang.instrument ASSERTION FAILED ***: "result" with message agent load/premain call failed at ./src/java.instrument/share/native/libinstrument/JPLISAgent.c line: 422
FATAL ERROR in native method: processing of -javaagent failed, processJavaStart failed
Aborted (core dumped)
  • I tried the awt app approach from this gist in combination with this sample JavaFX app, but did not succeed. I still wonder why the correct fully qualified class-path is not provided in the current Cryptomator setup, as it was before with the org.cryptomator.launcher.Cryptomator$MainApp.

  • I also tried to manipulate the Cryptomator window title on the primary stage, before calling .show(), but that doesn't help at all. I tried it here with stage.setTitle("Cryptomator").

  • And there is more:

http://java-gnome.sourceforge.net/

https://stackoverflow.com/a/50119254/4992066

https://stackoverflow.com/a/39319003/4992066
awesomeWM/awesome#977

@swiesend
Copy link
Contributor

swiesend commented Feb 27, 2021

I found the setName() method. I was confused between the javafx.application.Application and the com.sun.glass.ui.Application.

There seem to be two javafx.application.Application.launch() methods. I guess one wants to use the launch method which already provides the correct appClass, as the other tries to figure the name. Both set the name only if the default name is not yet overwritten: DEFAULT_NAME.equals(this.name).

Or one could manipulate the com.sun.glass.ui.Application and set the DEFAULT_NAME to whatever one wants, if calling the .launch() method is no option.

package javafx.application;

public abstract class Application {

    public static void launch(Class<? extends Application> appClass, String... args) {
        LauncherImpl.launchApplication(appClass, args);
    }
...
    public static void launch(String... args) {
...
        try {
            Class theClass = Class.forName(callingClassName, false,
                               Thread.currentThread().getContextClassLoader());
            if (Application.class.isAssignableFrom(theClass)) {
                Class<? extends Application> appClass = theClass;
                LauncherImpl.launchApplication(appClass, args);
            } else {
                throw new RuntimeException("Error: " + theClass
                        + " is not a subclass of javafx.application.Application");
            }
        } catch (RuntimeException ex) {
            throw ex;
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
...
package com.sun.javafx.application;

public class LauncherImpl {
...
    private static void launchApplication1(final Class<? extends Application> appClass,
            final Class<? extends Preloader> preloaderClass,
            final String[] args) throws Exception {
...
                PlatformImpl.runAndWait(() -> {
                    try {
                        Constructor<? extends Application> c = appClass.getConstructor();
                        app.set(c.newInstance());
                        // Set startup parameters
                        ParametersImpl.registerParameters(app.get(), new ParametersImpl(args));
                        PlatformImpl.setApplicationName(appClass);
                    } catch (Throwable t) {
                        System.err.println("Exception in Application constructor");
                        constructorError = t;
                        error = true;
                    }
                });
package com.sun.javafx.application;

public class PlatformImpl {
    /**
     * Sets the name of the this application based on the Application class.
     * This method is called by the launcher, and is not
     * called from the FX Application Thread, so we need to do it in a runLater.
     * We do not need to wait for the result since it will complete before the
     * Application start() method is called regardless.
     *
     * @param appClass the Application class.
     */
    public static void setApplicationName(final Class appClass) {
        runLater(() -> com.sun.glass.ui.Application.GetApplication().setName(appClass.getName()));
    }
...
package com.sun.glass.ui;

public abstract class Application {

    private final static String DEFAULT_NAME = "java";
    protected String name = DEFAULT_NAME;
...
    /**
     * Sets the name for the application.  The application name may
     * be used to identify the application in the user interface or
     * as part of the platform specific path used to store application
     * data.
     *
     * The name could be set only once. All subsequent calls are ignored.
     *
     * This is a hint and may not be used on some platforms.
     *
     * @param name the new application name
     */
    public void setName(String name) {
        checkEventThread();
        if (name != null && DEFAULT_NAME.equals(this.name)) {
            this.name = name;
        }
    }

@overheadhunter
Copy link
Member

Wow thanks for that intensive research!

I still wonder why the correct fully qualified class-path is not provided in the current Cryptomator setup, as it was before with the org.cryptomator.launcher.Cryptomator$MainApp.

Well Cryptomator doesn't use the "traditional" JavaFX launch. Instead it first launches a "normal" headless java process and checks if it should start "hidden". The JavaFX application itself is launched lazily (if at all). If one chooses to have a tray icon, AWT will initialize before JavaFX does. So there is no clear "main" entry point from a window manager's perspective.

Maybe by disabling the tray icon you will get different results?

@stale
Copy link

stale bot commented Apr 16, 2022

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the state:stale Issues without any activity that will be closed automatically label Apr 16, 2022
@overheadhunter
Copy link
Member

With #2139 merged, the WM_CLASS should now be org.cryptomator.launcher.Cryptomator$MainApp again.

@stale stale bot removed the state:stale Issues without any activity that will be closed automatically label Apr 18, 2022
@overheadhunter overheadhunter added this to the 1.6.9 milestone Apr 18, 2022
@infeo
Copy link
Member

infeo commented Apr 27, 2022

I tested this on a Ubuntu 22.04 VM and it works as expected 🙂

@infeo infeo closed this as completed Apr 27, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
misc:gui os:linux type:minor-bug Something minor isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants