From: VMware, Inc <> Date: Tue, 28 Jun 2011 19:53:24 +0000 (-0700) Subject: Unity/X11: More dirty hacks to match executables to .desktop files. X-Git-Tag: 2011.06.27-437995~9 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fd84640555671d85d65ba0cae472fe593233d539;p=thirdparty%2Fopen-vm-tools.git Unity/X11: More dirty hacks to match executables to .desktop files. Summary: o Now recognizing "gnome-" prefix for .desktop entries. o Matching Firefox and Thunderbird to mozilla-{firefox,thunderbird}. o All pattern matching stuff is setup once in WindowPathFactory's constructor. Details: Unity/X11 wasn't returning icons for Firefox, Nautilus, and GNOME's calculator. Turns out what RHEL packaged some GNOME apps with their .desktop files including a gnome- prefix. This is similar to the kde4- prefix we saw with OpenSUSE. The Mozilla apps were packaged with mozilla- prefixes. This change tosses in a few hacks to accommodate. Signed-off-by: Marcelo Vanzin --- diff --git a/open-vm-tools/services/plugins/unity/unitylib/vmware/tools/unity/windowPathFactory.hh b/open-vm-tools/services/plugins/unity/unitylib/vmware/tools/unity/windowPathFactory.hh index 5bd7f2f45..016caf455 100644 --- a/open-vm-tools/services/plugins/unity/unitylib/vmware/tools/unity/windowPathFactory.hh +++ b/open-vm-tools/services/plugins/unity/unitylib/vmware/tools/unity/windowPathFactory.hh @@ -55,6 +55,7 @@ public: private: typedef std::tr1::unordered_map > ExecMap; + typedef std::pair, std::string> ExecPattern; Glib::ustring CanonicalizeAppName(const Glib::ustring& appName, const Glib::ustring& cwd); @@ -67,6 +68,8 @@ private: Display* mDpy; ExecMap mExecMap; + std::vector mEnvPrefixes; + std::vector mExecPatterns; Glib::RefPtr mSkipPatterns; }; diff --git a/open-vm-tools/services/plugins/unity/unitylib/windowPathFactory.cc b/open-vm-tools/services/plugins/unity/unitylib/windowPathFactory.cc index b0eacc128..b439211e4 100644 --- a/open-vm-tools/services/plugins/unity/unitylib/windowPathFactory.cc +++ b/open-vm-tools/services/plugins/unity/unitylib/windowPathFactory.cc @@ -74,6 +74,39 @@ namespace unity { WindowPathFactory::WindowPathFactory(Display* dpy) : mDpy(dpy) { + /* + * PR631378 - see + * http://standards.freedesktop.org/menu-spec/latest/ar01s04.html#menu-file-elements + * + * With OpenSUSE 11.2, apps under /usr/share/applications/kde4 are referred + * to as kde4-$app, not just $app. + */ + mEnvPrefixes.push_back(""); + mEnvPrefixes.push_back("gnome-"); + mEnvPrefixes.push_back("kde4-"); + + /* + * There isn't always a direct correspondance between an application's executable's + * path and its .desktop file. For example on Ubuntu 10.10 Mozilla Firefox has a + * firefox.desktop which launches "firefox". However "firefox" is just a symlink to + * a wrapper around the actual Firefox executable, firefox-bin. It's the latter + * which Unity/X11 will encounter and use as a starting point to find the app's + * .desktop file. + * + * Below are pairs of regular expressions and candidate application names. If an + * executable name matches pair.first(), we'll check for a pair.second()+".desktop". + */ + // XXX Keep this in an external file. +#define WPFADDMATCH(pattern, target) \ + mExecPatterns.push_back(std::make_pair(Glib::Regex::create(pattern), target)) + WPFADDMATCH("acroread$", "AdobeReader"); + WPFADDMATCH("firefox(-bin|$)", "firefox"); + WPFADDMATCH("firefox(-bin|$)", "mozilla-firefox"); + WPFADDMATCH("thunderbird(-bin|$)", "thunderbird"); + WPFADDMATCH("thunderbird(-bin|$)", "mozilla-thunderbird"); + WPFADDMATCH("soffice", "openoffice.org-base"); +#undef WPFADDMATCH + // XXX Keep this in an external file. mSkipPatterns = Glib::Regex::create("^(sh|bash)-?|(perl|python)(-|\\d|$)"); } @@ -262,62 +295,35 @@ WindowPathFactory::FindByArgv(const Glib::ustring& cwd, // IN */ Glib::ustring testString = Glib::path_get_basename(*arg); - bool guessed = false; - /* - * PR631378 - see - * http://standards.freedesktop.org/menu-spec/latest/ar01s04.html#menu-file-elements - * - * With OpenSUSE 11.2, apps under /usr/share/applications/kde4 are referred - * to as kde4-$app, not just $app. - * - * XXX Prefixes should be discovered at runtime when analyzing .menu files. - */ - std::vector prefixes; - prefixes.push_back(""); - prefixes.push_back("kde4-"); - -tryagain: - for (std::vector::iterator i = prefixes.begin(); - i != prefixes.end(); - ++i) { - - /* Try for a DesktopAppInfo identified by arg. */ - Glib::ustring desktopId = Glib::ustring::compose("%1%2.desktop", *i, testString); - Glib::RefPtr desktopApp = - Gio::DesktopAppInfo::create(desktopId); - if (desktopApp) { - GDesktopAppInfo* gobj = desktopApp->gobj(); - pathPair.second = g_desktop_app_info_get_filename(gobj); - mExecMap[*arg] = pathPair; - return true; + std::vector candidates; + candidates.push_back(testString); + + for (std::vector::iterator pattern = mExecPatterns.begin(); + pattern != mExecPatterns.end(); + ++pattern) { + if (pattern->first->match(testString)) { + candidates.push_back(pattern->second); } } - /* Attempt #2: Get our static map on. */ - if (!guessed) { - static struct { - const gchar *pattern; - const gchar *exec; - } fudgePatterns[] = { - /* - * XXX Worth compiling once? Consider placing in an external filter - * file to allow users to update it themselves easily. - */ - { "*acroread", "AdobeReader" }, - { "*firefox*-bin", "firefox" }, - { "*thunderbird*-bin", "thunderbird" }, - { "*soffice*", "openoffice.org-base" } - }; - unsigned int i; - - guessed = true; - - for (i = 0; i < ARRAYSIZE(fudgePatterns); i++) { - if (g_pattern_match_simple(fudgePatterns[i].pattern, - testString.c_str())) { - testString = fudgePatterns[i].exec; - goto tryagain; + for (std::vector::iterator candidate = candidates.begin(); + candidate != candidates.end(); + ++candidate) + { + for (std::vector::iterator i = mEnvPrefixes.begin(); + i != mEnvPrefixes.end(); + ++i) { + /* Try for a DesktopAppInfo identified by arg. */ + Glib::ustring desktopId = + Glib::ustring::compose("%1%2.desktop", *i, *candidate); + Glib::RefPtr desktopApp = + Gio::DesktopAppInfo::create(desktopId); + if (desktopApp) { + GDesktopAppInfo* gobj = desktopApp->gobj(); + pathPair.second = g_desktop_app_info_get_filename(gobj); + mExecMap[*arg] = pathPair; + return true; } } }