diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js index c683cc2ba..4785c9981 100644 --- a/js/ui/appDisplay.js +++ b/js/ui/appDisplay.js @@ -889,11 +889,24 @@ const AppSearchProvider = new Lang.Class({ }, getInitialResultSet: function(terms, callback, cancellable) { - callback(this._appSys.initial_search(terms)); + let query = terms.join(' '); + let groups = Gio.DesktopAppInfo.search(query); + let usage = Shell.AppUsage.get_default(); + let results = []; + groups.forEach(function(group) { + group = group.filter(function(appID) { + let app = Gio.DesktopAppInfo.new(appID); + return app && app.should_show(); + }); + results = results.concat(group.sort(function(a, b) { + return usage.compare('', a, b); + })); + }); + callback(results); }, getSubsearchResultSet: function(previousResults, terms, callback, cancellable) { - callback(this._appSys.subsearch(previousResults, terms)); + this.getInitialResultSet(terms, callback, cancellable); }, activateResult: function(result) { diff --git a/src/shell-app-private.h b/src/shell-app-private.h index 407e75f20..020abd432 100644 --- a/src/shell-app-private.h +++ b/src/shell-app-private.h @@ -22,11 +22,6 @@ void _shell_app_add_window (ShellApp *app, MetaWindow *window); void _shell_app_remove_window (ShellApp *app, MetaWindow *window); -void _shell_app_do_match (ShellApp *app, - GSList *terms, - GSList **prefix_results, - GSList **substring_results); - G_END_DECLS #endif /* __SHELL_APP_PRIVATE_H__ */ diff --git a/src/shell-app-system.c b/src/shell-app-system.c index feca09cf8..3a3170925 100644 --- a/src/shell-app-system.c +++ b/src/shell-app-system.c @@ -348,143 +348,3 @@ shell_app_system_get_running (ShellAppSystem *self) return ret; } - - -static gint -compare_apps_by_usage (gconstpointer a, - gconstpointer b, - gpointer data) -{ - ShellAppUsage *usage = shell_app_usage_get_default (); - - ShellApp *app_a = (ShellApp*)a; - ShellApp *app_b = (ShellApp*)b; - - return shell_app_usage_compare (usage, "", app_a, app_b); -} - -static GSList * -sort_and_concat_results (ShellAppSystem *system, - GSList *prefix_matches, - GSList *substring_matches) -{ - GSList *matches = NULL; - GSList *l; - - prefix_matches = g_slist_sort_with_data (prefix_matches, - compare_apps_by_usage, - system); - substring_matches = g_slist_sort_with_data (substring_matches, - compare_apps_by_usage, - system); - - for (l = substring_matches; l != NULL; l = l->next) - matches = g_slist_prepend (matches, (char *) shell_app_get_id (SHELL_APP (l->data))); - for (l = prefix_matches; l != NULL; l = l->next) - matches = g_slist_prepend (matches, (char *) shell_app_get_id (SHELL_APP (l->data))); - - return g_slist_reverse (matches); -} - -/** - * normalize_terms: - * @terms: (element-type utf8): Input search terms - * - * Returns: (element-type utf8) (transfer full): Unicode-normalized and lowercased terms - */ -static GSList * -normalize_terms (GSList *terms) -{ - GSList *normalized_terms = NULL; - GSList *iter; - for (iter = terms; iter; iter = iter->next) - { - const char *term = iter->data; - normalized_terms = g_slist_prepend (normalized_terms, - shell_util_normalize_casefold_and_unaccent (term)); - } - return normalized_terms; -} - -static GSList * -search_tree (ShellAppSystem *self, - GSList *terms, - GHashTable *apps) -{ - GSList *prefix_results = NULL; - GSList *substring_results = NULL; - GSList *normalized_terms; - GHashTableIter iter; - gpointer key, value; - - normalized_terms = normalize_terms (terms); - - g_hash_table_iter_init (&iter, apps); - while (g_hash_table_iter_next (&iter, &key, &value)) - { - ShellApp *app = value; - _shell_app_do_match (app, normalized_terms, - &prefix_results, - &substring_results); - } - g_slist_free_full (normalized_terms, g_free); - - return sort_and_concat_results (self, prefix_results, substring_results); -} - -/** - * shell_app_system_initial_search: - * @system: A #ShellAppSystem - * @terms: (element-type utf8): List of terms, logical AND - * - * Search through applications for the given search terms. - * - * Returns: (transfer container) (element-type utf8): List of applications - */ -GSList * -shell_app_system_initial_search (ShellAppSystem *self, - GSList *terms) -{ - return search_tree (self, terms, self->priv->id_to_app); -} - -/** - * shell_app_system_subsearch: - * @system: A #ShellAppSystem - * @previous_results: (element-type utf8): List of previous results - * @terms: (element-type utf8): List of terms, logical AND - * - * Search through a previous result set; for more information, see - * js/ui/search.js. Note that returned strings are only valid until - * a return to the main loop. - * - * Returns: (transfer container) (element-type utf8): List of application identifiers - */ -GSList * -shell_app_system_subsearch (ShellAppSystem *system, - GSList *previous_results, - GSList *terms) -{ - GSList *iter; - GSList *prefix_results = NULL; - GSList *substring_results = NULL; - GSList *normalized_terms = normalize_terms (terms); - - previous_results = g_slist_reverse (previous_results); - - for (iter = previous_results; iter; iter = iter->next) - { - ShellApp *app = shell_app_system_lookup_app (system, iter->data); - - _shell_app_do_match (app, normalized_terms, - &prefix_results, - &substring_results); - } - g_slist_free_full (normalized_terms, g_free); - - /* Note that a shorter term might have matched as a prefix, but - when extended only as a substring, so we have to redo the - sort rather than reusing the existing ordering */ - return sort_and_concat_results (system, prefix_results, substring_results); -} - diff --git a/src/shell-app-system.h b/src/shell-app-system.h index 6f9344925..c0c501ad7 100644 --- a/src/shell-app-system.h +++ b/src/shell-app-system.h @@ -49,10 +49,4 @@ ShellApp *shell_app_system_lookup_desktop_wmclass (ShellAppSystem *s GSList *shell_app_system_get_running (ShellAppSystem *self); -GSList *shell_app_system_initial_search (ShellAppSystem *system, - GSList *terms); -GSList *shell_app_system_subsearch (ShellAppSystem *system, - GSList *previous_results, - GSList *terms); - #endif /* __SHELL_APP_SYSTEM_H__ */ diff --git a/src/shell-app-usage.c b/src/shell-app-usage.c index 31e7f85c2..c733ce4c5 100644 --- a/src/shell-app-usage.c +++ b/src/shell-app-usage.c @@ -527,19 +527,19 @@ shell_app_usage_get_most_used (ShellAppUsage *self, * shell_app_usage_compare: * @self: the usage instance to request * @context: Activity identifier - * @app_a: First app - * @app_b: Second app + * @id_a: ID of first app + * @id_b: ID of second app * - * Compare @app_a and @app_b based on frequency of use. + * Compare @id_a and @id_b based on frequency of use. * - * Returns: -1 if @app_a ranks higher than @app_b, 1 if @app_b ranks higher - * than @app_a, and 0 if both rank equally. + * Returns: -1 if @id_a ranks higher than @id_b, 1 if @id_b ranks higher + * than @id_a, and 0 if both rank equally. */ int shell_app_usage_compare (ShellAppUsage *self, const char *context, - ShellApp *app_a, - ShellApp *app_b) + const char *id_a, + const char *id_b) { GHashTable *usages; UsageData *usage_a, *usage_b; @@ -548,8 +548,8 @@ shell_app_usage_compare (ShellAppUsage *self, if (usages == NULL) return 0; - usage_a = g_hash_table_lookup (usages, shell_app_get_id (app_a)); - usage_b = g_hash_table_lookup (usages, shell_app_get_id (app_b)); + usage_a = g_hash_table_lookup (usages, id_a); + usage_b = g_hash_table_lookup (usages, id_b); if (usage_a == NULL && usage_b == NULL) return 0; diff --git a/src/shell-app-usage.h b/src/shell-app-usage.h index 4016b58c5..4afdbb3ec 100644 --- a/src/shell-app-usage.h +++ b/src/shell-app-usage.h @@ -31,8 +31,8 @@ GSList *shell_app_usage_get_most_used (ShellAppUsage *usage, const char *context); int shell_app_usage_compare (ShellAppUsage *self, const char *context, - ShellApp *app_a, - ShellApp *app_b); + const char *id_a, + const char *id_b); G_END_DECLS diff --git a/src/shell-app.c b/src/shell-app.c index 6904b6b6b..487268d1f 100644 --- a/src/shell-app.c +++ b/src/shell-app.c @@ -81,12 +81,7 @@ struct _ShellApp ShellAppRunningState *running_state; char *window_id_string; - - char *casefolded_name; - char *casefolded_generic_name; char *name_collation_key; - char *casefolded_exec; - char **casefolded_keywords; }; enum { @@ -1360,49 +1355,6 @@ trim_exec_line (const char *str) return g_strndup (start, end - start); } -static void -shell_app_init_search_data (ShellApp *app) -{ - const char *name; - const char *generic_name; - const char *exec; - const char * const *keywords; - char *normalized_exec; - - name = g_app_info_get_name (G_APP_INFO (app->info)); - app->casefolded_name = shell_util_normalize_casefold_and_unaccent (name); - - generic_name = g_desktop_app_info_get_generic_name (app->info); - if (generic_name) - app->casefolded_generic_name = shell_util_normalize_casefold_and_unaccent (generic_name); - else - app->casefolded_generic_name = NULL; - - exec = g_app_info_get_executable (G_APP_INFO (app->info)); - normalized_exec = shell_util_normalize_casefold_and_unaccent (exec); - app->casefolded_exec = trim_exec_line (normalized_exec); - g_free (normalized_exec); - - keywords = g_desktop_app_info_get_keywords (app->info); - - if (keywords) - { - int i; - - app->casefolded_keywords = g_new0 (char*, g_strv_length ((char **)keywords) + 1); - - i = 0; - while (keywords[i]) - { - app->casefolded_keywords[i] = shell_util_normalize_casefold_and_unaccent (keywords[i]); - ++i; - } - app->casefolded_keywords[i] = NULL; - } - else - app->casefolded_keywords = NULL; -} - /** * shell_app_compare_by_name: * @app: One app @@ -1419,116 +1371,6 @@ shell_app_compare_by_name (ShellApp *app, ShellApp *other) return strcmp (app->name_collation_key, other->name_collation_key); } -static ShellAppSearchMatch -_shell_app_match_search_terms (ShellApp *app, - GSList *terms) -{ - GSList *iter; - ShellAppSearchMatch match; - - if (G_UNLIKELY (!app->casefolded_name)) - shell_app_init_search_data (app); - - match = MATCH_NONE; - for (iter = terms; iter; iter = iter->next) - { - ShellAppSearchMatch current_match; - const char *term = iter->data; - const char *p; - - current_match = MATCH_NONE; - - p = strstr (app->casefolded_name, term); - if (p != NULL) - { - if (p == app->casefolded_name || *(p - 1) == ' ') - current_match = MATCH_PREFIX; - else - current_match = MATCH_SUBSTRING; - } - - if (app->casefolded_generic_name) - { - p = strstr (app->casefolded_generic_name, term); - if (p != NULL) - { - if (p == app->casefolded_generic_name || *(p - 1) == ' ') - current_match = MATCH_PREFIX; - else if (current_match < MATCH_PREFIX) - current_match = MATCH_SUBSTRING; - } - } - - if (app->casefolded_exec) - { - p = strstr (app->casefolded_exec, term); - if (p != NULL) - { - if (p == app->casefolded_exec || *(p - 1) == '-') - current_match = MATCH_PREFIX; - else if (current_match < MATCH_PREFIX) - current_match = MATCH_SUBSTRING; - } - } - - if (app->casefolded_keywords) - { - int i = 0; - while (app->casefolded_keywords[i] && current_match < MATCH_PREFIX) - { - p = strstr (app->casefolded_keywords[i], term); - if (p != NULL) - { - if (p == app->casefolded_keywords[i]) - current_match = MATCH_PREFIX; - else - current_match = MATCH_SUBSTRING; - } - ++i; - } - } - - if (current_match == MATCH_NONE) - return current_match; - - if (current_match > match) - match = current_match; - } - return match; -} - -void -_shell_app_do_match (ShellApp *app, - GSList *terms, - GSList **prefix_results, - GSList **substring_results) -{ - ShellAppSearchMatch match; - - g_assert (app != NULL); - - /* Skip window-backed apps */ - if (app->info == NULL) - return; - /* Skip not-visible apps */ - if (!g_app_info_should_show (G_APP_INFO (app->info))) - return; - - match = _shell_app_match_search_terms (app, terms); - switch (match) - { - case MATCH_NONE: - break; - case MATCH_PREFIX: - *prefix_results = g_slist_prepend (*prefix_results, app); - break; - case MATCH_SUBSTRING: - *substring_results = g_slist_prepend (*substring_results, app); - break; - } -} - - static void shell_app_init (ShellApp *self) { @@ -1561,11 +1403,7 @@ shell_app_finalize (GObject *object) g_free (app->window_id_string); - g_free (app->casefolded_name); - g_free (app->casefolded_generic_name); g_free (app->name_collation_key); - g_free (app->casefolded_exec); - g_strfreev (app->casefolded_keywords); G_OBJECT_CLASS(shell_app_parent_class)->finalize (object); } diff --git a/src/shell-util.c b/src/shell-util.c index 92fc3dad6..bbbb86fcb 100644 --- a/src/shell-util.c +++ b/src/shell-util.c @@ -111,98 +111,6 @@ shell_util_get_transformed_allocation (ClutterActor *actor, box->y2 = y_max; } -char * -shell_util_normalize_and_casefold (const char *str) -{ - char *normalized, *result; - - if (str == NULL) - return NULL; - - /* NOTE: 'ALL' is equivalent to 'NFKD'. If this is ever updated, please - * update the unaccenting mechanism as well. */ - normalized = g_utf8_normalize (str, -1, G_NORMALIZE_ALL); - result = g_utf8_casefold (normalized, -1); - g_free (normalized); - return result; -} - -/* Combining diacritical mark? - * Basic range: [0x0300,0x036F] - * Supplement: [0x1DC0,0x1DFF] - * For Symbols: [0x20D0,0x20FF] - * Half marks: [0xFE20,0xFE2F] - */ -#define IS_CDM_UCS4(c) (((c) >= 0x0300 && (c) <= 0x036F) || \ - ((c) >= 0x1DC0 && (c) <= 0x1DFF) || \ - ((c) >= 0x20D0 && (c) <= 0x20FF) || \ - ((c) >= 0xFE20 && (c) <= 0xFE2F)) - -/* Copied from tracker/src/libtracker-fts/tracker-parser-glib.c under the GPL - * Originally written by Aleksander Morgado - */ -char * -shell_util_normalize_casefold_and_unaccent (const char *str) -{ - char *tmp; - gsize i = 0, j = 0, ilen; - - if (str == NULL) - return NULL; - - /* Get the NFKD-normalized and casefolded string */ - tmp = shell_util_normalize_and_casefold (str); - ilen = strlen (tmp); - - while (i < ilen) - { - gunichar unichar; - gchar *next_utf8; - gint utf8_len; - - /* Get next character of the word as UCS4 */ - unichar = g_utf8_get_char_validated (&tmp[i], -1); - - /* Invalid UTF-8 character or end of original string. */ - if (unichar == (gunichar) -1 || - unichar == (gunichar) -2) - { - break; - } - - /* Find next UTF-8 character */ - next_utf8 = g_utf8_next_char (&tmp[i]); - utf8_len = next_utf8 - &tmp[i]; - - if (IS_CDM_UCS4 ((guint32) unichar)) - { - /* If the given unichar is a combining diacritical mark, - * just update the original index, not the output one */ - i += utf8_len; - continue; - } - - /* If already found a previous combining - * diacritical mark, indexes are different so - * need to copy characters. As output and input - * buffers may overlap, need to use memmove - * instead of memcpy */ - if (i != j) - { - memmove (&tmp[j], &tmp[i], utf8_len); - } - - /* Update both indexes */ - i += utf8_len; - j += utf8_len; - } - - /* Force proper string end */ - tmp[j] = '\0'; - - return tmp; -} - /** * shell_util_format_date: * @format: a strftime-style string format, as parsed by diff --git a/src/shell-util.h b/src/shell-util.h index 95271d05a..fdaec560a 100644 --- a/src/shell-util.h +++ b/src/shell-util.h @@ -19,10 +19,6 @@ void shell_util_get_transformed_allocation (ClutterActor *actor, int shell_util_get_week_start (void); -char *shell_util_normalize_and_casefold (const char *str); - -char *shell_util_normalize_casefold_and_unaccent (const char *str); - char *shell_util_format_date (const char *format, gint64 time_ms);