=== modified file 'src/bamf-legacy-screen.c'
--- src/bamf-legacy-screen.c	2012-07-30 03:00:43 +0000
+++ src/bamf-legacy-screen.c	2013-01-10 00:14:24 +0000
@@ -210,7 +210,6 @@
   BamfLegacyScreen *self;
   GList *l;
   guint xid_a, xid_b;
-  guint idx_a, idx_b;
 
   g_return_val_if_fail (BAMF_IS_LEGACY_SCREEN (data), 1);
   self = BAMF_LEGACY_SCREEN (data);
@@ -218,36 +217,18 @@
   xid_a = bamf_legacy_window_get_xid (BAMF_LEGACY_WINDOW (a));
   xid_b = bamf_legacy_window_get_xid (BAMF_LEGACY_WINDOW (b));
 
-  gboolean idx_a_found = FALSE;
-  gboolean idx_b_found = FALSE;
-  idx_a = 0;
-  idx_b = 0;
-
   for (l = wnck_screen_get_windows_stacked (self->priv->legacy_screen); l; l = l->next)
   {
     gulong legacy_xid = wnck_window_get_xid (WNCK_WINDOW (l->data));
 
-    if (!idx_a_found)
-      {
-        if (xid_a != legacy_xid)
-          idx_a++;
-        else
-          idx_a_found = TRUE;
-      }
-
-    if (!idx_b_found)
-      {
-        if (xid_b != legacy_xid)
-          idx_b++;
-        else
-          idx_b_found = TRUE;
-      }
-
-    if (idx_a_found && idx_b_found)
-      break;
+    if (legacy_xid == xid_a)
+      return -1;
+
+    if (legacy_xid == xid_b)
+      return 1;
   }
 
-  return (idx_a < idx_b) ? -1 : 1;
+  return 0;
 }
 
 static void
@@ -300,11 +281,11 @@
         }
     }
 
-  WnckWindow *legacy_window = wnck_window_get(xid);
+  WnckWindow *legacy_window = wnck_window_get (xid);
 
   if (WNCK_IS_WINDOW (legacy_window))
     {
-      handle_window_opened(NULL, legacy_window, self);
+      handle_window_opened (NULL, legacy_window, self);
     }
 }
 

=== modified file 'src/bamf-legacy-window.c'
--- src/bamf-legacy-window.c	2012-10-10 17:36:21 +0000
+++ src/bamf-legacy-window.c	2013-01-10 00:14:24 +0000
@@ -498,9 +498,9 @@
   guint xid = bamf_legacy_window_get_xid (self);
 
   /* Adding a weak ref to this object, causes to get notified after the object
-   * destruction, so once this BamfLegacyWindow has been closed and drestroyed
+   * destruction, so once this BamfLegacyWindow has been closed and destroyed
    * the handle_destroy_notify() function will be called, and that will
-   * provide to iniject another window like this one to the BamfLegacyScreen  */
+   * provide to inject another window like this one to the BamfLegacyScreen  */
   g_object_weak_ref (G_OBJECT (self), (GWeakNotify) handle_destroy_notify,
                                                     GUINT_TO_POINTER (xid));
 

=== modified file 'src/bamf-matcher-private.h'
--- src/bamf-matcher-private.h	2012-07-27 18:38:22 +0000
+++ src/bamf-matcher-private.h	2013-01-10 00:14:24 +0000
@@ -46,5 +46,6 @@
 
 BamfApplication * bamf_matcher_get_application_by_desktop_file (BamfMatcher *self, const char *desktop_file);
 BamfApplication * bamf_matcher_get_application_by_xid (BamfMatcher *self, guint xid);
+char * bamf_matcher_get_trimmed_exec (BamfMatcher *self, const char *exec);
 
 #endif

=== modified file 'src/bamf-matcher.c'
--- src/bamf-matcher.c	2012-10-10 17:36:21 +0000
+++ src/bamf-matcher.c	2013-01-10 00:14:24 +0000
@@ -48,6 +48,22 @@
 static BamfMatcher *static_matcher;
 static guint matcher_signals[LAST_SIGNAL] = { 0 };
 
+// Prefixes to be ignored in exec strings
+const gchar* EXEC_BAD_PREFIXES[] =
+{
+  "^gksu(do)?$", "^sudo$", "^su-to-root$", "^amdxdg-su$", "^java(ws)?$",
+  "^mono$", "^ruby$", "^padsp$", "^aoss$", "^python(\\d.\\d)?$", "^(ba)?sh$",
+  "^perl$", "^env$", "^xdg-open$",
+  /* javaws strings: */ "^net\\.sourceforge\\.jnlp\\.runtime\\.Boot$", "^rt.jar$"
+};
+
+// Prefixes that must be considered starting point of exec strings
+const gchar* EXEC_GOOD_PREFIXES[] =
+{
+  "^gnome-control-center$", "^libreoffice$", "^ooffice$", "^wine$", "^steam$",
+  "^sol$"
+};
+
 static void
 on_view_active_changed (BamfView *view, gboolean active, BamfMatcher *matcher)
 {
@@ -211,7 +227,8 @@
   return FALSE;
 }
 
-static void bamf_matcher_prepare_path_change (BamfMatcher *self, const gchar *desktop_file, ViewChangeType change_type)
+static void
+bamf_matcher_prepare_path_change (BamfMatcher *self, const gchar *desktop_file, ViewChangeType change_type)
 {
   BamfMatcherPrivate *priv;
   BamfApplication *app;
@@ -248,12 +265,6 @@
 }
 
 static void
-on_view_closed (BamfView *view, BamfMatcher *self)
-{
-  bamf_matcher_unregister_view (self, view);
-}
-
-static void
 bamf_matcher_register_view_stealing_ref (BamfMatcher *self, BamfView *view)
 {
   const char *path, *type;
@@ -264,8 +275,8 @@
   path = bamf_view_export_on_bus (view, connection);
   type = bamf_view_get_view_type (view);
 
-  g_signal_connect (G_OBJECT (view), "closed-internal",
-                    (GCallback) on_view_closed, self);
+  g_signal_connect_swapped (G_OBJECT (view), "closed-internal",
+                            (GCallback) bamf_matcher_unregister_view, self);
   g_signal_connect (G_OBJECT (view), "active-changed",
                     (GCallback) on_view_active_changed, self);
 
@@ -296,7 +307,7 @@
 
   g_signal_emit_by_name (self, "view-closed", path, type);
 
-  g_signal_handlers_disconnect_by_func (G_OBJECT (view), on_view_closed, self);
+  g_signal_handlers_disconnect_by_func (G_OBJECT (view), bamf_matcher_unregister_view, self);
   g_signal_handlers_disconnect_by_func (G_OBJECT (view), on_view_active_changed, self);
 
   if (BAMF_IS_APPLICATION (view))
@@ -348,7 +359,7 @@
   else if (g_str_has_suffix (name, "LibreOffice Calc"))
     {
       binary = "libreoffice";
-       parameter = "calc";
+      parameter = "calc";
     }
   else if (g_str_has_suffix (name, "LibreOffice Impress"))
     {
@@ -466,60 +477,72 @@
   if (!binary)
     return NULL;
 
-  const char *sufix = NULL;
-
-  if (g_strcmp0 (binary, "libreoffice") == 0)
-    sufix = " %U";
-  else if (g_strcmp0 (binary, "ooffice") == 0)
-    sufix = " %F";
-
-  GList *l;
-  if (!parameter)
-    exec = g_strconcat (binary, sufix, NULL);
-  else
-    exec = g_strconcat (binary, " --", parameter, sufix, NULL);
-
-  l = g_hash_table_lookup (self->priv->desktop_file_table, exec);
-  g_free (exec);
-
-  if (!l && parameter)
+  GList *l = NULL;
+
+  if (parameter)
     {
-      exec = g_strconcat (binary, " -", parameter, sufix, NULL);
-
+      exec = g_strconcat (binary, " --", parameter, NULL);
       l = g_hash_table_lookup (self->priv->desktop_file_table, exec);
       g_free (exec);
+
+      if (!l)
+        {
+          exec = g_strconcat (binary, " -", parameter, NULL);
+          l = g_hash_table_lookup (self->priv->desktop_file_table, exec);
+          g_free (exec);
+
+          if (!l)
+            {
+              exec = g_strconcat (binary, "-", parameter, NULL);
+              l = g_hash_table_lookup (self->priv->desktop_id_table, exec);
+              g_free (exec);
+            }
+        }
+    }
+  else
+    {
+      l = g_hash_table_lookup (self->priv->desktop_file_table, binary);
     }
 
   return (l ? (char *) l->data : NULL);
 }
 
 /* Attempts to return the binary name for a particular execution string */
-static char *
-trim_exec_string (BamfMatcher * self, char * execString)
+char *
+bamf_matcher_get_trimmed_exec (BamfMatcher * self, const char * exec_string)
 {
-  gchar *result = NULL, *exec = NULL, *part = NULL, *tmp = NULL;
+  gchar *result = NULL, *part, *tmp;
   gchar **parts;
-  gint i, j;
-  gboolean regexFail;
-  gboolean goodPrefix = FALSE;
+  gint i, j, parts_size;
+  gboolean bad_prefix;
+  gboolean good_prefix = FALSE;
+  gboolean double_parsed = FALSE;
   GRegex *regex;
 
-  if (!execString || (execString && execString[0] == '\0'))
+  if (!exec_string || exec_string[0] == '\0')
     return NULL;
 
-  exec = g_utf8_casefold (execString, -1);
-  parts = g_strsplit (exec, " ", 0);
+  if (!g_shell_parse_argv (exec_string, &parts_size, &parts, NULL))
+    return g_strdup (exec_string);
 
-  i = 0;
-  while (parts[i] != NULL)
+  for (i = 0; i < parts_size; ++i)
     {
       part = parts[i];
+      if (*part == '%' || g_utf8_strrchr (part, -1, '='))
+        continue;
 
-      if (part[0] != '-')
+      if (*part != '-' || good_prefix)
         {
-          if (goodPrefix)
-            {
-              gchar *tmp = g_strconcat (result, " ", part, NULL);
+          if (!result)
+            {
+              tmp = g_utf8_strrchr (part, -1, G_DIR_SEPARATOR);
+              if (tmp)
+                part = tmp + 1;
+            }
+
+          if (good_prefix)
+            {
+              tmp = g_strconcat (result, " ", part, NULL);
               g_free (result);
               result = tmp;
             }
@@ -530,113 +553,81 @@
                   regex = g_array_index (self->priv->good_prefixes, GRegex *, j);
                   if (g_regex_match (regex, part, 0, NULL))
                     {
-                      goodPrefix = TRUE;
-                      result = g_strdup (part);
+                      good_prefix = TRUE;
+                      result = g_ascii_strdown (part, -1);
                       break;
                     }
                 }
-            }
-
-          if (!goodPrefix)
-            {
-              tmp = g_utf8_strrchr (part, -1, G_DIR_SEPARATOR);
-              if (tmp)
-                part = tmp + 1;
-
-              regexFail = FALSE;
+
+              if (good_prefix)
+                continue;
+
+              bad_prefix = FALSE;
               for (j = 0; j < self->priv->bad_prefixes->len; j++)
                 {
                   regex = g_array_index (self->priv->bad_prefixes, GRegex *, j);
                   if (g_regex_match (regex, part, 0, NULL))
                     {
-                      regexFail = TRUE;
+                      bad_prefix = TRUE;
                       break;
                     }
                 }
 
-              if (!regexFail)
+              if (!bad_prefix)
                 {
-                  result = g_strdup (part);
+                  if (!double_parsed && g_utf8_strrchr (part, -1, ' '))
+                  {
+                    /* If the current exec_string has an empty char,
+                     * we double check it again to parse scripts:
+                     * For example strings like 'sh -c "foo || bar"' */
+                    gchar **old_parts = parts;
+
+                    if (g_shell_parse_argv (part, &parts_size, &parts, NULL))
+                      {
+                        // Make the loop to restart!
+                        g_strfreev (old_parts);
+                        i = -1;
+                        continue;
+                      }
+
+                    double_parsed = TRUE;
+                  }
+
+                  result = g_ascii_strdown (part, -1);
                   break;
                 }
             }
         }
-      else if (goodPrefix)
-        {
-          break;
-        }
-
-      i++;
     }
 
   if (!result)
     {
-      result = g_strdup (execString);
+      if (parts_size > 0)
+        {
+          tmp = g_utf8_strrchr (parts[0], -1, G_DIR_SEPARATOR);
+          if (tmp)
+            exec_string = tmp + 1;
+        }
+
+      result = g_strdup (exec_string);
     }
   else
     {
       tmp = result;
-      
-      regex = g_regex_new ("((\\.|-)bin|\\.py)$", 0, 0, NULL);
+
+      regex = g_regex_new ("(\\.bin|\\.py|\\.pl)$", 0, 0, NULL);
       result = g_regex_replace_literal (regex, result, -1, 0, "", 0, NULL);
-      
+
       g_free (tmp);
       g_regex_unref (regex);
     }
 
-  g_free (exec);
   g_strfreev (parts);
 
   return result;
 }
 
 static GArray *
-bad_prefix_strings (void)
-{
-  GArray *arr = g_array_new (FALSE, TRUE, sizeof (char *));
-
-  char *str = "^gksu(do)?$";
-  g_array_append_val (arr, str);
-
-  str = "^sudo$";
-  g_array_append_val (arr, str);
-
-  str = "^java$";
-  g_array_append_val (arr, str);
-
-  str = "^mono$";
-  g_array_append_val (arr, str);
-
-  str = "^ruby$";
-  g_array_append_val (arr, str);
-
-  str = "^padsp$";
-  g_array_append_val (arr, str);
-
-  str = "^aoss$";
-  g_array_append_val (arr, str);
-
-  str = "^python(\\d.\\d)?$";
-  g_array_append_val (arr, str);
-
-  str = "^(ba)?sh$";
-  g_array_append_val (arr, str);
-
-  return arr;
-}
-
-static GArray *
-good_prefix_strings (void)
-{
-  GArray *arr = g_array_new (FALSE, TRUE, sizeof (char *));
-
-  char *str = "^gnome-control-center$";
-  g_array_append_val (arr, str);
-
-  return arr;
-}
-
-static GArray *
 pid_parent_tree (BamfMatcher *self, gint pid)
 {
   BamfMatcherPrivate *priv;
@@ -678,15 +669,6 @@
 }
 
 static gboolean
-exec_string_should_be_processed (const char *exec)
-{
-  if (!exec)
-    return TRUE;
-
-  return !g_str_has_prefix (exec, "ooffice") && !g_str_has_prefix (exec, "libreoffice");
-}
-
-static gboolean
 is_desktop_folder_item (const char *desktop_file_path, gssize max_len)
 {
   gsize len;
@@ -850,18 +832,15 @@
       return;
     }
 
-  if (exec_string_should_be_processed (exec))
-    {
-      /**
-       * Set of nasty hacks which should be removed some day. We wish to keep the full exec
-       * strings so we can do nasty matching hacks later. A very very evil thing indeed. However this
-       * helps hack around applications that run in the same process cross radically different instances.
-       * A better solution needs to be thought up, however at this time it is not known.
-       **/
-      char *tmp = trim_exec_string (self, exec);
-      g_free (exec);
-      exec = tmp;
-    }
+  /**
+   * Set of nasty hacks which should be removed some day. We wish to keep the full exec
+   * strings so we can do nasty matching hacks later. A very very evil thing indeed. However this
+   * helps hack around applications that run in the same process cross radically different instances.
+   * A better solution needs to be thought up, however at this time it is not known.
+   **/
+  char *tmp = bamf_matcher_get_trimmed_exec (self, exec);
+  g_free (exec);
+  exec = tmp;
 
   path = g_path_get_basename (file);
   desktop_id = g_string_new (path);
@@ -958,16 +937,12 @@
       GString *desktop_id;
 
       gchar **parts = g_strsplit (line, "\t", 3);
+
+      char *tmp = bamf_matcher_get_trimmed_exec (self, parts[1]);
+      g_free (parts[1]);
+      parts[1] = tmp;
       exec = parts[1];
 
-      if (exec_string_should_be_processed (exec))
-        {
-          char *tmp = trim_exec_string (self, exec);
-          g_free (parts[1]);
-          parts[1] = tmp;
-          exec = parts[1];
-        }
-
       filename = g_build_filename (directory, parts[0], NULL);
 
       desktop_id = g_string_new (parts[0]);
@@ -1172,7 +1147,7 @@
                   free_func (l->data);
 
                 /* If the target is the first element of the list (and thanks to
--                * the previous check we're also sure that it's not the only one),
+                 * the previous check we're also sure that it's not the only one),
                  * simply switch it with its follower, not to change the first
                  * pointer and the hash table value for key
                  */
@@ -1301,15 +1276,25 @@
 }
 
 static void
-bamf_add_new_monitored_directory (BamfMatcher * self, const gchar *directory)
+bamf_matcher_add_new_monitored_directory (BamfMatcher * self, const gchar *directory)
 {
   g_return_if_fail (BAMF_IS_MATCHER (self));
 
   GFile *file;
   GFileMonitor *monitor;
+  GError *error = NULL;
 
   file = g_file_new_for_path (directory);
-  monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL);
+  monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, &error);
+
+  if (error)
+    {
+      g_warning ("Error monitoring %s: %s\n", directory, error->message);
+      g_error_free (error);
+      g_object_unref (file);
+      return;
+    }
+
   g_file_monitor_set_rate_limit (monitor, 1000);
   g_object_set_data_full (G_OBJECT (monitor), "root", g_strdup (directory), g_free);
   g_signal_connect (monitor, "changed", (GCallback) on_monitor_changed, self);
@@ -1338,7 +1323,7 @@
       if (!g_file_test (directory, G_FILE_TEST_IS_DIR))
         continue;
 
-      bamf_add_new_monitored_directory (self, directory);
+      bamf_matcher_add_new_monitored_directory (self, directory);
 
       bamf_file = g_build_filename (directory, "bamf.index", NULL);
 
@@ -1492,8 +1477,7 @@
   
   if (exec_string)
     {
-      trimmed = trim_exec_string (self, exec_string);
-      
+      trimmed = bamf_matcher_get_trimmed_exec (self, exec_string);
       if (trimmed)
         {
           if (trimmed[0] != '\0')
@@ -1882,6 +1866,7 @@
       /* secondary matching */
       GList *a;
       BamfView *view;
+
       const gchar *app_desktop_class;
 
       for (a = self->priv->views; a; a = a->next)
@@ -1892,10 +1877,41 @@
             continue;
 
           app = BAMF_APPLICATION (view);
-          app_desktop_class = bamf_application_get_wmclass (app);
 
           if (bamf_application_contains_similar_to_window (app, bamf_window))
             {
+              char *exec_string = bamf_legacy_window_get_exec_string (window);
+              char *trimmed_exec = bamf_matcher_get_trimmed_exec (self, exec_string);
+              g_free (exec_string);
+
+              GList *ll;
+              gboolean found_exec = FALSE;
+              for (ll = bamf_view_get_children (BAMF_VIEW (app)); ll && !found_exec; ll = ll->next)
+                {
+                  if (!BAMF_IS_WINDOW (ll->data))
+                    continue;
+
+                  BamfLegacyWindow *w = bamf_window_get_window (BAMF_WINDOW (ll->data));
+                  char *wexec = bamf_legacy_window_get_exec_string (w);
+                  char *wtrimmed = bamf_matcher_get_trimmed_exec (self, wexec);
+                  g_free (wexec);
+
+                  if (g_strcmp0 (trimmed_exec, wtrimmed) == 0)
+                    {
+                      best = BAMF_APPLICATION (view);
+                      found_exec = TRUE;
+                    }
+
+                  g_free (wtrimmed);
+                }
+
+              g_free (trimmed_exec);
+
+              if (!found_exec)
+                continue;
+
+              app_desktop_class = bamf_application_get_wmclass (app);
+
               if (target_class && g_strcmp0 (target_class, app_desktop_class) == 0)
                 {
                   best = app;
@@ -2068,26 +2084,26 @@
 get_gnome_control_center_window_hint (BamfMatcher * self, BamfLegacyWindow * window)
 {
   gchar *role;
-  gchar *exec;
-  GHashTable *desktopFileTable;
   GList *list;
 
   g_return_val_if_fail (BAMF_IS_MATCHER (self), NULL);
   g_return_val_if_fail (BAMF_IS_LEGACY_WINDOW (window), NULL);
 
+  list = NULL;
   role = bamf_legacy_window_get_hint (window, WM_WINDOW_ROLE);
-  exec = g_strconcat ("gnome-control-center", (role ? " " : NULL), role, NULL);
-
-  desktopFileTable = self->priv->desktop_file_table;
-  list = g_hash_table_lookup (desktopFileTable, exec);
-
-  if (!list && g_strcmp0 ("gnome-control-center", exec) != 0)
-    {
-      list = g_hash_table_lookup (desktopFileTable, "gnome-control-center");
-    }
-
-  g_free (exec);
-  g_free (role);
+
+  if (role)
+    {
+      gchar *exec = g_strconcat ("gnome-control-center ", role, NULL);
+      list = g_hash_table_lookup (self->priv->desktop_file_table, exec);
+      g_free (exec);
+      g_free (role);
+    }
+
+  if (!role || !list)
+    {
+      list = g_hash_table_lookup (self->priv->desktop_id_table, "gnome-control-center");
+    }
 
   return (list ? (char *) list->data : NULL);
 }
@@ -2125,7 +2141,8 @@
   g_return_if_fail (BAMF_IS_MATCHER (self));
   g_return_if_fail (BAMF_IS_LEGACY_WINDOW (window));
 
-  if (bamf_legacy_window_get_window_type (window) == BAMF_WINDOW_DESKTOP)
+  BamfWindowType win_type = bamf_legacy_window_get_window_type (window);
+  if (win_type == BAMF_WINDOW_DESKTOP)
     {
       BamfWindow *bamfwindow = bamf_window_new (window);
       bamf_matcher_register_view_stealing_ref (self, BAMF_VIEW (bamfwindow));
@@ -2135,8 +2152,6 @@
 
   if (is_open_office_window (self, window))
     {
-      BamfWindowType win_type = bamf_legacy_window_get_window_type (window);
-
       if (win_type == BAMF_WINDOW_SPLASHSCREEN || win_type == BAMF_WINDOW_TOOLBAR)
         {
           return;
@@ -2895,34 +2910,29 @@
   BamfMatcherPrivate *priv;
   BamfLegacyScreen *screen;
   BamfIndicatorSource *approver;
-  GArray *prefixstrings;
   int i;
 
   priv = self->priv = BAMF_MATCHER_GET_PRIVATE (self);
 
   priv->known_pids = g_array_new (FALSE, TRUE, sizeof (gint));
-  priv->bad_prefixes = g_array_new (FALSE, TRUE, sizeof (GRegex *));
-  priv->good_prefixes = g_array_new (FALSE, TRUE, sizeof (GRegex *));
+  priv->bad_prefixes = g_array_sized_new (FALSE, TRUE, sizeof (GRegex *),
+                                          G_N_ELEMENTS (EXEC_BAD_PREFIXES));
+  priv->good_prefixes = g_array_sized_new (FALSE, TRUE, sizeof (GRegex *),
+                                           G_N_ELEMENTS (EXEC_GOOD_PREFIXES));
   priv->registered_pids = g_hash_table_new_full (g_direct_hash, g_direct_equal,
                                                  NULL, g_free);
 
-  prefixstrings = bad_prefix_strings ();
-  for (i = 0; i < prefixstrings->len; i++)
+  for (i = 0; i < G_N_ELEMENTS (EXEC_BAD_PREFIXES); ++i)
     {
-      char *str = g_array_index (prefixstrings, char *, i);
-      GRegex *regex = g_regex_new (str, G_REGEX_OPTIMIZE, 0, NULL);
+      GRegex *regex = g_regex_new (EXEC_BAD_PREFIXES[i], G_REGEX_OPTIMIZE, 0, NULL);
       g_array_append_val (priv->bad_prefixes, regex);
     }
-  g_array_free (prefixstrings, TRUE);
 
-  prefixstrings = good_prefix_strings ();
-  for (i = 0; i < prefixstrings->len; i++)
+  for (i = 0; i < G_N_ELEMENTS (EXEC_GOOD_PREFIXES); ++i)
     {
-      char *str = g_array_index (prefixstrings, char *, i);
-      GRegex *regex = g_regex_new (str, G_REGEX_OPTIMIZE, 0, NULL);
+      GRegex *regex = g_regex_new (EXEC_GOOD_PREFIXES[i], G_REGEX_OPTIMIZE, 0, NULL);
       g_array_append_val (priv->good_prefixes, regex);
     }
-  g_array_free (prefixstrings, TRUE);
 
   create_desktop_file_table (self, &(priv->desktop_file_table),
                              &(priv->desktop_id_table),
@@ -3046,6 +3056,7 @@
       g_signal_handlers_disconnect_by_func (G_OBJECT (l->data), 
                                             (GCallback) on_monitor_changed, self);
     }
+
   g_list_free_full (priv->monitors, g_object_unref);
   priv->monitors = NULL;
 

=== modified file 'tests/bamfdaemon/Makefile.am'
--- tests/bamfdaemon/Makefile.am	2012-11-28 12:16:12 +0000
+++ tests/bamfdaemon/Makefile.am	2013-01-10 00:14:24 +0000
@@ -119,6 +119,7 @@
 	export LOG_PATH=$(LOG_PATH); \
 	export XVFB_PATH=$(XVFB); \
 	export DISPLAY=""; \
+	export XDG_CURRENT_DESKTOP="Unity"; \
 	source $(XVFB_RUN); \
 	\
 	$(DBUS_LAUNCH) > $(LOG_PATH)/sessionbus.sh; \

=== added file 'tests/bamfdaemon/data/gnome-control-center.desktop'
--- tests/bamfdaemon/data/gnome-control-center.desktop	1970-01-01 00:00:00 +0000
+++ tests/bamfdaemon/data/gnome-control-center.desktop	2013-01-10 00:14:24 +0000
@@ -0,0 +1,9 @@
+[Desktop Entry]
+Name=System Settings
+Icon=preferences-system
+Exec=gnome-control-center --overview
+Terminal=false
+Type=Application
+StartupNotify=true
+Categories=GNOME;GTK;System;
+OnlyShowIn=GNOME;Unity;

=== added file 'tests/bamfdaemon/data/gnome-display-panel.desktop'
--- tests/bamfdaemon/data/gnome-display-panel.desktop	1970-01-01 00:00:00 +0000
+++ tests/bamfdaemon/data/gnome-display-panel.desktop	2013-01-10 00:14:24 +0000
@@ -0,0 +1,10 @@
+[Desktop Entry]
+Name=Displays
+Comment=Change resolution and position of monitors and projectors
+Exec=gnome-control-center display
+Icon=preferences-desktop-display
+Terminal=false
+Type=Application
+StartupNotify=true
+Categories=GNOME;GTK;Settings;HardwareSettings;X-GNOME-Settings-Panel;
+OnlyShowIn=GNOME;Unity;

=== added file 'tests/bamfdaemon/data/gnome-mouse-panel.desktop'
--- tests/bamfdaemon/data/gnome-mouse-panel.desktop	1970-01-01 00:00:00 +0000
+++ tests/bamfdaemon/data/gnome-mouse-panel.desktop	2013-01-10 00:14:24 +0000
@@ -0,0 +1,10 @@
+[Desktop Entry]
+Name=Mouse and Touchpad
+Comment=Set your mouse and touchpad preferences
+Exec=gnome-control-center mouse
+Icon=input-mouse
+Terminal=false
+Type=Application
+StartupNotify=true
+Categories=GNOME;GTK;Settings;HardwareSettings;X-GNOME-Settings-Panel;
+OnlyShowIn=GNOME;Unity;

=== modified file 'tests/bamfdaemon/test-matcher.c'
--- tests/bamfdaemon/test-matcher.c	2012-10-10 17:36:21 +0000
+++ tests/bamfdaemon/test-matcher.c	2013-01-10 00:14:24 +0000
@@ -32,7 +32,10 @@
 static void test_match_desktopless_application (void);
 static void test_match_desktop_application (void);
 static void test_match_libreoffice_windows (void);
+static void test_match_gnome_control_center_panels (void);
+static void test_match_javaws_windows (void);
 static void test_new_desktop_matches_unmatched_windows (void);
+static void test_trim_exec_string (void);
 
 static GDBusConnection *gdbus_connection = NULL;
 
@@ -51,7 +54,10 @@
   g_test_add_func (DOMAIN"/Matching/Application/DesktopLess", test_match_desktopless_application);
   g_test_add_func (DOMAIN"/Matching/Application/Desktop", test_match_desktop_application);
   g_test_add_func (DOMAIN"/Matching/Application/LibreOffice", test_match_libreoffice_windows);
+  g_test_add_func (DOMAIN"/Matching/Application/GnomeControlCenter", test_match_gnome_control_center_panels);
+  g_test_add_func (DOMAIN"/Matching/Application/JavaWebStart", test_match_javaws_windows);
   g_test_add_func (DOMAIN"/Matching/Windows/UnmatchedOnNewDesktop", test_new_desktop_matches_unmatched_windows);
+  g_test_add_func (DOMAIN"/ExecStringTrimming", test_trim_exec_string);
 }
 
 static void
@@ -480,3 +486,211 @@
   g_object_unref (screen);
 }
 
+static void
+test_match_gnome_control_center_panels (void)
+{
+  BamfMatcher *matcher;
+  BamfWindow *window;
+  BamfLegacyScreen *screen;
+  BamfLegacyWindowTest *test_win;
+  BamfApplication *app;
+  char *hint;
+
+  screen = bamf_legacy_screen_get_default ();
+  matcher = bamf_matcher_get_default ();
+  guint xid = g_random_int ();
+  const char *exec = "gnome-control-center";
+  const char *class_name = "Gnome-control-center";
+  const char *class_instance = "gnome-control-center";
+
+  cleanup_matcher_tables (matcher);
+  export_matcher_on_bus (matcher);
+
+  bamf_matcher_load_desktop_file (matcher, DATA_DIR"/gnome-control-center.desktop");
+  bamf_matcher_load_desktop_file (matcher, DATA_DIR"/gnome-display-panel.desktop");
+  bamf_matcher_load_desktop_file (matcher, DATA_DIR"/gnome-mouse-panel.desktop");
+
+  test_win = bamf_legacy_window_test_new (xid, "System Settings", NULL, exec);
+  bamf_legacy_window_test_set_wmclass (test_win, class_name, class_instance);
+  bamf_legacy_window_set_hint (BAMF_LEGACY_WINDOW (test_win), WM_WINDOW_ROLE, NULL);
+  _bamf_legacy_screen_open_test_window (screen, test_win);
+
+  hint = bamf_legacy_window_get_hint (BAMF_LEGACY_WINDOW (test_win), _NET_WM_DESKTOP_FILE);
+  g_assert_cmpstr (hint, ==, DATA_DIR"/gnome-control-center.desktop");
+  g_free (hint);
+  app = bamf_matcher_get_application_by_desktop_file (matcher, DATA_DIR"/gnome-control-center.desktop");
+  g_assert (find_window_in_app (app, BAMF_LEGACY_WINDOW (test_win)));
+
+  bamf_legacy_window_set_hint (BAMF_LEGACY_WINDOW (test_win), WM_WINDOW_ROLE, "display");
+  bamf_legacy_window_test_set_name (test_win, "Displays");
+  g_assert (!bamf_matcher_get_application_by_desktop_file (matcher, DATA_DIR"/gnome-control-center.desktop"));
+  app = bamf_matcher_get_application_by_desktop_file (matcher, DATA_DIR"/gnome-display-panel.desktop");
+  g_assert (app);
+  window = BAMF_WINDOW (bamf_view_get_children (BAMF_VIEW (app))->data);
+  test_win = BAMF_LEGACY_WINDOW_TEST (bamf_window_get_window (window));
+  hint = bamf_legacy_window_get_hint (BAMF_LEGACY_WINDOW (test_win), _NET_WM_DESKTOP_FILE);
+  g_assert_cmpstr (hint, ==, DATA_DIR"/gnome-display-panel.desktop");
+  g_free (hint);
+
+  bamf_legacy_window_set_hint (BAMF_LEGACY_WINDOW (test_win), WM_WINDOW_ROLE, "mouse");
+  bamf_legacy_window_test_set_name (test_win, "Mouse and Touchpad");
+  g_assert (!bamf_matcher_get_application_by_desktop_file (matcher, DATA_DIR"/gnome-display-panel.desktop"));
+  app = bamf_matcher_get_application_by_desktop_file (matcher, DATA_DIR"/gnome-mouse-panel.desktop");
+  g_assert (app);
+  window = BAMF_WINDOW (bamf_view_get_children (BAMF_VIEW (app))->data);
+  test_win = BAMF_LEGACY_WINDOW_TEST (bamf_window_get_window (window));
+  hint = bamf_legacy_window_get_hint (BAMF_LEGACY_WINDOW (test_win), _NET_WM_DESKTOP_FILE);
+  g_assert_cmpstr (hint, ==, DATA_DIR"/gnome-mouse-panel.desktop");
+  g_free (hint);
+
+  bamf_legacy_window_set_hint (BAMF_LEGACY_WINDOW (test_win), WM_WINDOW_ROLE, "invalid-role");
+  bamf_legacy_window_test_set_name (test_win, "Invalid Panel");
+  g_assert (!bamf_matcher_get_application_by_desktop_file (matcher, DATA_DIR"/gnome-mouse-panel.desktop"));
+  app = bamf_matcher_get_application_by_desktop_file (matcher, DATA_DIR"/gnome-control-center.desktop");
+  g_assert (app);
+  window = BAMF_WINDOW (bamf_view_get_children (BAMF_VIEW (app))->data);
+  test_win = BAMF_LEGACY_WINDOW_TEST (bamf_window_get_window (window));
+  hint = bamf_legacy_window_get_hint (BAMF_LEGACY_WINDOW (test_win), _NET_WM_DESKTOP_FILE);
+  g_assert_cmpstr (hint, ==, DATA_DIR"/gnome-control-center.desktop");
+  g_free (hint);
+
+  g_object_unref (matcher);
+  g_object_unref (screen);
+}
+
+static void
+test_match_javaws_windows (void)
+{
+  BamfMatcher *matcher;
+  BamfLegacyScreen *screen;
+  BamfLegacyWindowTest *test_win;
+  BamfApplication *app1, *app2, *app3;
+  GList *app_children;
+
+  screen = bamf_legacy_screen_get_default ();
+  matcher = bamf_matcher_get_default ();
+  const char *exec_prefix = "/usr/lib/jvm/java-6-openjdk-amd64/jre/bin/java " \
+                            "-Xbootclasspath/a:/usr/share/icedtea-web/netx.jar " \
+                            "-Xms8m -Djava.security.manager " \
+                            "-Djava.security.policy=/etc/icedtea-web/javaws.policy " \
+                            "-classpath /usr/lib/jvm/java-6-openjdk-amd64/jre/lib/rt.jar " \
+                            "-Dicedtea-web.bin.name=javaws " \
+                            "-Dicedtea-web.bin.location=/usr/bin/javaws "\
+                            "net.sourceforge.jnlp.runtime.Boot";
+  const char *class_name = "sun-awt-X11-XFramePeer";
+  const char *class_instance = "net-sourceforge-jnlp-runtime-Boot";
+
+  cleanup_matcher_tables (matcher);
+  export_matcher_on_bus (matcher);
+
+  guint xid = g_random_int ();
+  char *exec = g_strconcat (exec_prefix, " Notepad.jnlp", NULL);
+  test_win = bamf_legacy_window_test_new (xid, "Notepad", NULL, exec);
+  bamf_legacy_window_test_set_wmclass (test_win, class_name, class_instance);
+  _bamf_legacy_screen_open_test_window (screen, test_win);
+  g_free (exec);
+  app1 = bamf_matcher_get_application_by_xid (matcher, xid);
+  g_assert (BAMF_IS_APPLICATION (app1));
+  app_children = bamf_view_get_children (BAMF_VIEW (app1));
+  g_assert_cmpuint (g_list_length (app_children), ==, 1);
+  g_assert (find_window_in_app (app1, BAMF_LEGACY_WINDOW (test_win)));
+
+  xid = g_random_int ();
+  exec = g_strconcat (exec_prefix, " Draw.jnlp", NULL);
+  test_win = bamf_legacy_window_test_new (xid, "Draw", NULL, exec);
+  bamf_legacy_window_test_set_wmclass (test_win, class_name, class_instance);
+  _bamf_legacy_screen_open_test_window (screen, test_win);
+  g_free (exec);
+  app2 = bamf_matcher_get_application_by_xid (matcher, xid);
+  g_assert (BAMF_IS_APPLICATION (app2));
+  g_assert (app1 != app2);
+  app_children = bamf_view_get_children (BAMF_VIEW (app2));
+  g_assert_cmpuint (g_list_length (app_children), ==, 1);
+  g_assert (find_window_in_app (app2, BAMF_LEGACY_WINDOW (test_win)));
+
+  xid = g_random_int ();
+  exec = g_strconcat (exec_prefix, " Notepad.jnlp", NULL);
+  test_win = bamf_legacy_window_test_new (xid, "Notepad Subwin", NULL, exec);
+  bamf_legacy_window_test_set_wmclass (test_win, class_name, class_instance);
+  _bamf_legacy_screen_open_test_window (screen, test_win);
+  g_free (exec);
+  app3 = bamf_matcher_get_application_by_xid (matcher, xid);
+  g_assert (app3 == app1);
+  g_assert (BAMF_IS_APPLICATION (app3));
+  app_children = bamf_view_get_children (BAMF_VIEW (app3));
+  g_assert_cmpuint (g_list_length (app_children), ==, 2);
+  g_assert (find_window_in_app (app3, BAMF_LEGACY_WINDOW (test_win)));
+
+  g_object_unref (matcher);
+  g_object_unref (screen);
+}
+
+static void
+test_trim_exec_string (void)
+{
+  BamfMatcher *matcher;
+  char *trimmed;
+
+  matcher = bamf_matcher_get_default ();
+
+  // Bad prefixes
+  trimmed = bamf_matcher_get_trimmed_exec (matcher, "gksudo bad-prefix-bin");
+  g_assert_cmpstr (trimmed, ==, "bad-prefix-bin");
+  g_free (trimmed);
+
+  trimmed = bamf_matcher_get_trimmed_exec (matcher, "sudo --opt val=X /usr/bin/bad-prefix-bin");
+  g_assert_cmpstr (trimmed, ==, "bad-prefix-bin");
+  g_free (trimmed);
+
+  trimmed = bamf_matcher_get_trimmed_exec (matcher, "python2.7 /home/foo/bad-prefix-script.py");
+  g_assert_cmpstr (trimmed, ==, "bad-prefix-script");
+  g_free (trimmed);
+
+  trimmed = bamf_matcher_get_trimmed_exec (matcher, "/usr/bin/python3.1");
+  g_assert_cmpstr (trimmed, ==, "python3.1");
+  g_free (trimmed);
+
+  trimmed = bamf_matcher_get_trimmed_exec (matcher, "/usr/bin/python %u --option val=/path");
+  g_assert_cmpstr (trimmed, ==, "python");
+  g_free (trimmed);
+
+  trimmed = bamf_matcher_get_trimmed_exec (matcher, "sh -c \"binary --option --value %U || exec binary\"");
+  g_assert_cmpstr (trimmed, ==, "binary");
+  g_free (trimmed);
+
+  // Good prefixes
+  trimmed = bamf_matcher_get_trimmed_exec (matcher, "/usr/bin/libreoffice --writer %U");
+  g_assert_cmpstr (trimmed, ==, "libreoffice --writer");
+  g_free (trimmed);
+
+  trimmed = bamf_matcher_get_trimmed_exec (matcher, "/usr/bin/gnome-control-center");
+  g_assert_cmpstr (trimmed, ==, "gnome-control-center");
+  g_free (trimmed);
+
+  trimmed = bamf_matcher_get_trimmed_exec (matcher, "gnome-control-center foo-panel");
+  g_assert_cmpstr (trimmed, ==, "gnome-control-center foo-panel");
+  g_free (trimmed);
+
+  // Other exec strings
+  trimmed = bamf_matcher_get_trimmed_exec (matcher, "env FOOVAR=\"bar\" myprog");
+  g_assert_cmpstr (trimmed, ==, "myprog");
+  g_free (trimmed);
+
+  trimmed = bamf_matcher_get_trimmed_exec (matcher, "/opt/path/bin/myprog --option %U --foo=daa");
+  g_assert_cmpstr (trimmed, ==, "myprog");
+  g_free (trimmed);
+
+  const char *exec = "/usr/lib/jvm/java-6-openjdk-amd64/jre/bin/java " \
+                     "-Xbootclasspath/a:/usr/share/icedtea-web/netx.jar " \
+                     "-Xms8m -Djava.security.manager " \
+                     "-Djava.security.policy=/etc/icedtea-web/javaws.policy " \
+                     "-classpath /usr/lib/jvm/java-6-openjdk-amd64/jre/lib/rt.jar " \
+                     "-Dicedtea-web.bin.name=javaws " \
+                     "-Dicedtea-web.bin.location=/usr/bin/javaws "\
+                     "net.sourceforge.jnlp.runtime.Boot Notepad.jnlp";
+  trimmed = bamf_matcher_get_trimmed_exec (matcher, exec);
+  g_assert_cmpstr (trimmed, ==, "notepad.jnlp");
+  g_free (trimmed);
+
+  g_object_unref (matcher);
+}

