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); }
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); }