static void
scan_startup_wm_class_to_id (ShellAppSystem *self)
{
  ShellAppSystemPrivate *priv = self->priv;
  GList *apps, *l;

  g_hash_table_remove_all (priv->startup_wm_class_to_id);

  apps = g_app_info_get_all ();
  for (l = apps; l != NULL; l = l->next)
    {
      GAppInfo *info = l->data;
      const char *startup_wm_class, *id, *old_id;

      id = g_app_info_get_id (info);
      startup_wm_class = g_desktop_app_info_get_startup_wm_class (G_DESKTOP_APP_INFO (info));

      if (startup_wm_class == NULL)
        continue;

      /* In case multiple .desktop files set the same StartupWMClass, prefer
       * the one where ID and StartupWMClass match */
      old_id = g_hash_table_lookup (priv->startup_wm_class_to_id, startup_wm_class);
      if (old_id == NULL || strcmp (id, startup_wm_class) == 0)
        g_hash_table_insert (priv->startup_wm_class_to_id,
                             g_strdup (startup_wm_class), g_strdup (id));
    }

  g_list_free_full (apps, g_object_unref);
}
Exemple #2
0
void
ephy_web_application_setup_from_desktop_file (GDesktopAppInfo *desktop_info)
{
  GAppInfo *app_info;
  const char *wm_class;
  GIcon *icon;

  g_assert (G_IS_DESKTOP_APP_INFO (desktop_info));

  app_info = G_APP_INFO (desktop_info);
  g_set_prgname (g_app_info_get_name (app_info));
  g_set_application_name (g_app_info_get_display_name (app_info));

  icon = g_app_info_get_icon (app_info);
  if (G_IS_FILE_ICON (icon)) {
    GFile *file = g_file_icon_get_file (G_FILE_ICON (icon));
    char *path = file ? g_file_get_path (file) : NULL;

    if (path) {
      gtk_window_set_default_icon_from_file (path, NULL);
      g_free (path);
    }
    g_clear_object (&file);
  } else if (G_IS_THEMED_ICON (icon)) {
    const char * const *names = g_themed_icon_get_names (G_THEMED_ICON (icon));
    if (names)
      gtk_window_set_default_icon_name (names[0]);
  }
  g_clear_object (&icon);

  /* We need to re-set this because we have already parsed the
   * options, which inits GTK+ and sets this as a side effect.
   */
  wm_class = g_desktop_app_info_get_startup_wm_class (desktop_info);
  if (wm_class)
    gdk_set_program_class (wm_class);
}
static void
on_apps_tree_changed_cb (GMenuTree *tree,
                         gpointer   user_data)
{
  CinnamonAppSystem *self = CINNAMON_APP_SYSTEM (user_data);
  GError *error = NULL;
  GHashTable *new_apps;
  GHashTableIter iter;
  gpointer key, value;
  GSList *removed_apps = NULL;
  GSList *removed_node;

  g_assert (tree == self->priv->apps_tree);

  g_slist_foreach (self->priv->known_vendor_prefixes, (GFunc)g_free, NULL);
  g_slist_free (self->priv->known_vendor_prefixes);
  self->priv->known_vendor_prefixes = NULL;

  if (!gmenu_tree_load_sync (self->priv->apps_tree, &error))
    {
      g_warning ("Failed to load apps: %s", error->message);
      return;
    }

  new_apps = get_flattened_entries_from_tree (self->priv->apps_tree);
  g_hash_table_iter_init (&iter, new_apps);
  while (g_hash_table_iter_next (&iter, &key, &value))
    {
      const char *id = key;
      GMenuTreeEntry *entry = value;
      GMenuTreeEntry *old_entry;
      char *prefix;
      CinnamonApp *app;

      GDesktopAppInfo *info;
      const char *startup_wm_class;
      
      prefix = get_prefix_for_entry (entry);
      
      if (prefix != NULL
          && !g_slist_find_custom (self->priv->known_vendor_prefixes, prefix,
                                   (GCompareFunc)g_strcmp0))
        self->priv->known_vendor_prefixes = g_slist_append (self->priv->known_vendor_prefixes,
                                                            prefix);
      else
        g_free (prefix);
      
      app = g_hash_table_lookup (self->priv->id_to_app, id);
      if (app != NULL)
        {
          /* We hold a reference to the original entry temporarily,
           * because otherwise the hash table would be referencing
           * potentially free'd memory until we replace it below with
           * the new data.
           */
          old_entry = cinnamon_app_get_tree_entry (app);
          gmenu_tree_item_ref (old_entry);
          _cinnamon_app_set_entry (app, entry);
          g_object_ref (app);  /* Extra ref, removed in _replace below */
        }
      else
        {
          old_entry = NULL;
          app = _cinnamon_app_new (entry);
        }
      /* Note that "id" is owned by app->entry.  Since we're always
       * setting a new entry, even if the app already exists in the
       * hash table we need to replace the key so that the new id
       * string is pointed to.
       */
      g_hash_table_replace (self->priv->id_to_app, (char*)id, app);
      // if (!gmenu_tree_entry_get_is_nodisplay_recurse (entry))
      //    g_hash_table_replace (self->priv->visible_id_to_app, (char*)id, app);

      if (old_entry)
        {
          GDesktopAppInfo *old_info;
          const gchar *old_startup_wm_class;

          old_info = gmenu_tree_entry_get_app_info (old_entry);
          old_startup_wm_class = g_desktop_app_info_get_startup_wm_class (old_info);

          if (old_startup_wm_class)
            g_hash_table_remove (self->priv->startup_wm_class_to_app, old_startup_wm_class);
        }

      info = gmenu_tree_entry_get_app_info (entry);
      startup_wm_class = g_desktop_app_info_get_startup_wm_class (info);
      if (startup_wm_class)
        g_hash_table_replace (self->priv->startup_wm_class_to_app,
                              (char*)startup_wm_class, g_object_ref (app));

      if (old_entry)
        gmenu_tree_item_unref (old_entry);
    }
  /* Now iterate over the apps again; we need to unreference any apps
   * which have been removed.  The JS code may still be holding a
   * reference; that's fine.
   */
  g_hash_table_iter_init (&iter, self->priv->id_to_app);
  while (g_hash_table_iter_next (&iter, &key, &value))
    {
      const char *id = key;
      
      if (!g_hash_table_lookup (new_apps, id))
        removed_apps = g_slist_prepend (removed_apps, (char*)id);
    }
  for (removed_node = removed_apps; removed_node; removed_node = removed_node->next)
    {
      const char *id = removed_node->data;
      g_hash_table_remove (self->priv->id_to_app, id);
    }
  g_slist_free (removed_apps);
      
  g_hash_table_destroy (new_apps);

  g_signal_emit (self, signals[INSTALLED_CHANGED], 0);
}