GNOME Bugzilla – Bug 673657
Use StartupWMClass for application matching
Last modified: 2013-09-07 01:42:28 UTC
From time to time, we see complaints from developers and users that their applications are not recognized by the shell, because they set StartupWMClass to a valid value, but then keep invalid filenames. This especially happens with Chrome web apps, Wine apps and Java apps.
Created attachment 211502 [details] [review] Use StartupWMClass to associate window and applications Some applications (such as most Java, Wine and Chrome Web apps) ship with desktop files that have the wrong name, but whose StartupWMClass field contains the right value. Therefore first check that key, against both the class and instance part of WM_CLASS, and only use the filename if nothing else works.
Created attachment 211514 [details] [review] Use StartupWMClass to associate window and applications Some applications (such as most Java, Wine and Chrome Web apps) ship with desktop files that have the wrong name, but whose StartupWMClass field contains the right value. Therefore first check that key, against both the class and instance part of WM_CLASS, and only use the filename if nothing else works.
Did you forget to attach a patch (or dep on a bug) to gio? I don't have g_desktop_app_info_get_startup_wm_class.
Review of attachment 211514 [details] [review]: Yeah, I've been considering this for a little while as well. Let's do this. ::: src/shell-app-system.c @@ +385,3 @@ g_hash_table_replace (self->priv->id_to_app, (char*)id, app); + if (old_entry) { Bad style. ::: src/shell-window-tracker.c @@ +231,3 @@ + } + + /* then try a match from unmodifidied WM_CLASS (instance part) unmodified @@ +232,3 @@ + + /* then try a match from unmodifidied WM_CLASS (instance part) + to StartupWMClass */ Needs a '*' at the start. @@ +242,3 @@ + + /* then try to turn the WM_CLASS into something that resembles + a desktop file name, and look up that */ Missing *
Created attachment 211518 [details] [review] Use StartupWMClass to associate window and applications Some applications (such as most Java, Wine and Chrome Web apps) ship with desktop files that have the wrong name, but whose StartupWMClass field contains the right value. Therefore first check that key, against both the class and instance part of WM_CLASS, and only use the filename if nothing else works.
Review of attachment 211518 [details] [review]: ::: src/shell-window-tracker.c @@ +244,3 @@ + * a desktop file name, and look up that */ + appid = get_appid_from_window (window); + if (!appid) If we want to land this for 3.4.1, how about we put the startup_wm_class matching after the normal app matching so there can't possibly be a regression? I can imagine a case where somebody has a dumb StartupWMClass, and we'll regress.
Is it possible to land this 3.4.1, with g_desktop_app_info_get_startup_wm_class only in glib master? Also, is it possible that both the filename and the StartupWMClass match, and the former is correct? That is a very unlikely possibility, considering that most apps have no StartupWMClass field.
(In reply to comment #7) > Is it possible to land this 3.4.1, with g_desktop_app_info_get_startup_wm_class > only in glib master? If you push the g_desktop_app_info_get_startup_wm_class change to the gnome-3.4 branch, then sure. This seems like it would be worthwhile for 3.4.1 (it's a long-standing bug that's mainly been unfulfilled do to missing patches), but ask owen/mclasen first. > Also, is it possible that both the filename and the StartupWMClass match, and > the former is correct? That is a very unlikely possibility, considering that > most apps have no StartupWMClass field. Yeah, that doesn't make sense. Now that I think of it, the more likely regression that may happen is that a dumb application may cause false positive failures for other applications. A Java app might add StartupWMClass=java-awt-Frame to their .desktop file, breaking every other Java application...
The 3.4 boat has sailed, but is it possible to have this in 3.6? The rebased patch comes next.
Created attachment 217229 [details] [review] Use StartupWMClass to associate window and applications Some applications (such as most Java, Wine and Chrome Web apps) ship with desktop files that have the wrong name, but whose StartupWMClass field contains the right value. Therefore first check that key, against both the class and instance part of WM_CLASS, and only use the filename if nothing else works.
Review of attachment 217229 [details] [review]: We should update https://live.gnome.org/GnomeShell/ApplicationBased after this lands. So I don't see anything wrong with the code. It'd be helpful though to have a concrete example of an application that would be helped by this. You mention Java/Wine/Chrome but those are all frameworks, not apps. Is there a package in e.g. Fedora to install?
Hi. I'm the Chromium developer responsible for integrating Chrome apps with Linux shells. I'd like to know what the status of this patch is. We currently set StartupWMClass for application matching, but this does not work on Gnome Shell. Here is our bug on this issue: https://code.google.com/p/chromium/issues/detail?id=174794 Colin: You asked for examples of applications (not frameworks). I don't know of one. I think this feature is more appropriate for frameworks because that is where you will see windows that belong to the same binary, but represent conceptually different applications. To reproduce this on Gnome Shell: 1. Install Chromium / Chrome 27 or higher. 2. Install a Chrome app (https://chrome.google.com/webstore/category/packaged_apps). 3. Confirm that a shortcut has been created. It should be in ~/.local/share/applications/chrome-APPID.desktop. This file should contain "StartupWMClass=crx_APPID". 4. Run the app. Expected behaviour: Gnome Shell displays the app title and icon in the title bar, and the task switcher groups the app's window(s) separately from the browser. This is the current behaviour on Unity. Actual behaviour: Gnome Shell displays "Chromium" in the title bar, and the task switcher groups the app into the browser category. We could potentially change the WM_CLASS and .desktop file name in Chromium to match each other, but this will require migrations and other headaches, and we would very much prefer if Gnome Shell were to honour the StartupWMClass attribute in the .desktop file.
The problem here is as follows: WM_CLASS has two strings, instance and class. Currently gnome-shell looks only at the class part, and tries to match that to a .desktop file. It doesn't look at StartupWMClass. Giovani's patch makes two changes: - Makes gnome-shell look for a matching StartupWMClass before trying to match to a .desktop file. This would remove the current requirement of WM_CLASS and .desktop file being similar, which e.g. chrome doesn't follow. - Makes gnome-shell fall back to WM_CLASS' instance if WM_CLASS' class can't be matched. However, this wouldn't help in Chrome's case, and may or many not help in others. Currently chrome sets WM_CLASS as follows (the first string is the 'instance', the second one is the 'class': For the normal browser: WM_CLASS(STRING) = "chromium", "Chromium" For a bookmarked page (through 'Tools -> Create application shortcuts') WM_CLASS(STRING) = "wiki.gnome.org__GnomeShell_ApplicationBased", "Chromium" For an application from the chrome store (with a .desktop file created through right click, "Create shortcuts" from Chrome's apps overview) WM_CLASS(STRING) = "crx_blpcfgokakmgnkcojhhkbfbldkacnbeo", "Chromium" The .desktop file has a matching StartupWMClass, but the name differs, e.g. for the store app (youtube) there is .local/share/applications/chrome-blpcfgokakmgnkcojhhkbfbldkacnbeo-Default.desktop with StartupWMClass=crx_blpcfgokakmgnkcojhhkbfbldkacnbeo So what currently happens is that gnome-shell sees WM_CLASS' class as 'Chromium', and looks for a matching .desktop file. It finds chromium.desktop and groups the window together with chromium, with the issues that has. With Giovanni's patch, gnome-shell sees WM_CLASS' class as 'Chromium' and looks for a .desktop file with StartupWMClass=Chromium -> finds chromium.desktop. Note that if chromium.desktop didn't have StartupWMClass=Chromium, it would look for a .desktop file named 'chromium.desktop' and would find it as well. It wouldn't fall back to looking for WM_CLASS' instance (crx_blpcfgokakmgnkcojhhkbfbldkacnbeo) unless the above failed, which doesn't. We could find a heuristic that worked (e.g. looking for WM_CLASS' instance in StartupWMClass, then WM_CLASS' class in StartupWMClass, and only then falling back to matching .desktop file and process name). (Apparently Unity has a working heuristic so we could check that as well, I haven't checked it yet). But before we do anything like that, we should have a clear definition of how WM_CLASS' class and instance would affect window matching / grouping, and how StartupWMClass affects this all. What I have found is http://standards.freedesktop.org/desktop-entry-spec/latest/ar01s05.html which mentions both class and instance without a clear definition, pointing to http://standards.freedesktop.org/startup-notification-spec/startup-notification-latest.txt which doesn't show the spec. I have found http://standards.freedesktop.org/startup-notification-spec/startup-notification-latest.txt but all it says is "StartupWMClass=STRING If specified, it is KNOWN that the application will map at least one window with the given string as its WM class or WM name hint." Also note that chrome made WM_CLASS' class match StartupWMClass, and then reverted the change, see https://code.google.com/p/chromium/issues/detail?id=20587 comment #64 (and following).
Hi Emilio, Thanks for your detailed response. It's a very confusing issue and I didn't realise the Chrome history on this goes back so far (the discussion you referenced ended in 2011; I started working on this in 2013 and when I found it it was broken for both Unity and Gnome Shell). > We could find a heuristic that worked (e.g. looking for WM_CLASS' instance > in StartupWMClass, then WM_CLASS' class in StartupWMClass, and only then > falling back to matching .desktop file and process name). I believe this is the heuristic used by Unity, and it works for our use case at least. (We have had correct window matching for Chrome apps on Unity working since Chrome 26 in March 2013.) It seems like the currently proposed algorithm here is to look for the WM_CLASS class, THEN match the .desktop filename, THEN match the WM_CLASS instance. It seems like it wouldn't break anything to swap the second and third steps, so you are looking for the WM_CLASS class, then WM_CLASS instance, and lastly falling back to the .desktop filename. (It doesn't matter, for our purposes, whether you match the class or instance first.) This approach seems consistent with the FreeDesktop specification that "the application will map at least one window with the given string as its WM class or WM name hint." I don't see any specification that says that there should be any relationship between the .desktop filename and the WM_CLASS, which is why I think that matching those two should be the last resort. > But before we do anything like that, we should have a clear definition of > how WM_CLASS' class and instance would affect window matching / grouping, > and how StartupWMClass affects this all. I haven't found any detailed spec on this (and as you say, FreeDesktop spec is frustratingly vague). There are only two major FreeDesktop-based window managers that I know of that group windows into applications based on .desktop files: Unity and Gnome Shell. It seems like the path of least resistance would be to change Gnome Shell to prioritize StartupWMClass over the .desktop filename. Surely any app that sets StartupWMClass will do so in an attempt to match against either the WM_CLASS class or instance, as Chromium does? An app that does not set StartupWMClass won't notice the difference. The Unity code to do window matching is here: http://bazaar.launchpad.net/~unity-team/bamf/trunk/view/head:/src/bamf-matcher.c#L1760 bamf_matcher_get_application_for_window
Created attachment 251037 [details] [review] Use StartupWMClass to associate window and applications Some applications (such as most Java apps, as well as Chrome Web apps) ship with desktop files that have the wrong name, but whose StartupWMClass field contains the right value. Therefore first check that key, against both the class and instance part of WM_CLASS, and only use the filename if nothing else works. This implements almost the proposed algorithm, and it works as expected for chrome packaged web apps and java apps.
Let me say that this patch (and this approach) will also help me matching Wolfram Mathematica. This app sets a blank WM_CLASS (yes, no idea why), but has a "matchable" WM_CLASS instance. If we also match the instance value, I can add that string to Wolfram Alpha .desktop file as StartupWMclass and be an happy camper.
Review of attachment 251037 [details] [review]: This looks right to me, just really minor docs comments. ::: src/shell-app-system.c @@ +545,3 @@ * + * Find a valid application whose .desktop file, without the extension + * and properly canonicalized, matches @wmclass Should end with '.'. @@ +582,3 @@ + * + * Find a valid application whose .desktop file contains a + * StartupWMClass entry matching @wmclass Ditto.
Attachment 251037 [details] pushed as db75734 - Use StartupWMClass to associate window and applications
Created attachment 251064 [details] [review] Match WM_CLASS' instance against StartupWMClass first (In reply to comment #14) > It seems like the currently proposed algorithm here is to look for the WM_CLASS > class, THEN match the .desktop filename, THEN match the WM_CLASS instance. It > seems like it wouldn't break anything to swap the second and third steps, so > you are looking for the WM_CLASS class, then WM_CLASS instance, and lastly > falling back to the .desktop filename. (It doesn't matter, for our purposes, > whether you match the class or instance first.) Actually it does matter, as I said in my comment: (In reply to comment #13) > With Giovanni's patch, gnome-shell sees WM_CLASS' class as 'Chromium' and looks > for a .desktop file with StartupWMClass=Chromium -> finds chromium.desktop. So checking for WM_CLASS' class first doesn't fix this bug for Chromium, as gnome-shell will match every chromium app to chromium.desktop. This is what happens with the current patch. A simple change like the attached, checking for WM_CLASS' instance first, then checking for WM_CLASS' class fixes this for Chromium, *but* I understand that can have regressions for other apps and may not be how things are meant to be. Perhaps the final fix for this is to make Chrome swap WM_CLASS' instance and class. But given the lack of a clear definition in the fdo specs, I can't say if that's the case...
Created attachment 251081 [details] screenshot of crash Also, this patch is what broke the integrationtest - it looks like we need to handle windows without WM_CLASS?
> So checking for WM_CLASS' class first doesn't fix this bug for Chromium, > as gnome-shell will match every chromium app to chromium.desktop. This > is what happens with the current patch. First, ignoring the Chromium .desktop file and looking at the general case: I think it is important to get the order (class first or instance first) right. To go to the specs, I think the best source is actually the X Consortium Inter-Client Communication Conventions Manual: http://tronche.com/gui/x/icccm/sec-4.html#WM_CLASS The WM_CLASS instance is "a string that names the particular instance of the application to which the client that owns this window belongs." The WM_CLASS class is "a string that names the general class of applications to which the client that owns this window belongs." These definitions are still pretty vague, but what is fairly clear is that the instance is *more specific* than the class. Therefore, I believe that a correct algorithm to match StartupWMClass should look at the instance first, then the class (so that you can have a generic .desktop file for all windows of a given class, and then provide specialised .desktop files for windows with a specific instance name). So for Chromium, we definitely want the instance name to be the app ID, and the class name to be general (we don't want to swap them). The Unity algorithm is to check instance first. See bamf_matcher_possible_applications_for_window: http://bazaar.launchpad.net/~unity-team/bamf/trunk/view/head:/src/bamf-matcher.c#L1616 (Note: They actually have a special case for Chrome/Chromium, where they ignore the class entirely, but it is a legacy special case from before we fixed WM_CLASS in Chrome, and I don't think it matters here.) Lastly (somewhat of an aside), I don't think that chromium.desktop should include a StartupWMClass line at all. There is no need for it, because the .desktop file name already matches the WM_CLASS class. The .desktop file we supply with Chromium does not include this line: https://code.google.com/p/chromium/codesearch#chromium/src/chrome/installer/linux/common/desktop.template So I'm not sure where you got your chromium.desktop file -- perhaps your distro has a custom one.
Created attachment 251124 [details] [review] ShellWindowTracker: complete WM_CLASS fix Chromium (but not google-chrome) has a StartupWMClass in the desktop file, so we must match the instance part first to have chrome web apps working. Also, we must take care of apps without a wm_class or instance at all. Ok, let's fix everything once and for all.
Review of attachment 251124 [details] [review]: Looks right.
This problem has been fixed in the development version. The fix will be available in the next major software release. Thank you for your bug report.
Hi Giovanni, Thanks very much for fixing this! I'm looking forward to using Chrome apps with proper titles and icons on Gnome Shell. Is there any way I can test this patch out before the next release without building all of Gnome Shell? (For instance, is there an individual library with this functionality I can build and replace my system library?) I just wanted to note that the comment about Chrome in the patch is misleading: "Note that chromium (but not google-chrome!) includes a StartupWMClass=chromium in their .desktop file, so we must match the instance first." As I said above, the .desktop file we supply with Chromium does NOT have StartupWMClass. This is our .desktop file: https://code.google.com/p/chromium/codesearch#chromium/src/chrome/installer/linux/common/desktop.template This is not a Chromium issue, but an issue with some distributions' packaging of Chromium. I think a more appropriate comment is more general than Chromium: the WM_CLASS instance name is more specific than the class name, so we match the instance name against StartupWMClass before the class name.
Nice to hear that, as always, it's distributions screwing up :D And sorry, I have chrome, not chromium, so I just listened to the other comments. Anyway, I'm afraid there is no way to try this without rebuilding gnome-shell, and the preferred method to do so is jhbuild. If you really don't want rebuilding, you can try the pre-built ostree images.
Thanks. I will try jhbuild. It doesn't look to complicated :)
Has the looking glass been updated to show both entries in a window's WMCLASS?
*** Bug 654661 has been marked as a duplicate of this bug. ***