From c4922f6624bb950e00b2b8b61ec08f374adcb9e6 Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Thu, 11 Sep 2014 15:15:50 -0600 Subject: [PATCH] search: Move the timeout for searching into setTerms This lets us considerably clean up the event flow here and change how things are structured. It also makes sure that we never show "No Results" -- search.js not being aware of the timeout means that it might not think that any work was being done when we show the page. --- js/ui/search.js | 82 ++++++++++++++++++++++--------------------- js/ui/viewSelector.js | 37 ++----------------- 2 files changed, 45 insertions(+), 74 deletions(-) diff --git a/js/ui/search.js b/js/ui/search.js index 832fe1ce4..3f6e0ed39 100644 --- a/js/ui/search.js +++ b/js/ui/search.js @@ -2,6 +2,7 @@ const Clutter = imports.gi.Clutter; const Lang = imports.lang; +const GLib = imports.gi.GLib; const Gio = imports.gi.Gio; const Gtk = imports.gi.Gtk; const Meta = imports.gi.Meta; @@ -401,18 +402,23 @@ const SearchResults = new Lang.Class({ this._highlightDefault = false; this._defaultResult = null; + this._startingSearch = false; + + this._terms = []; + this._results = {}; this._providers = []; - this._registerProvider(new AppDisplay.AppSearchProvider()); this._searchSettings = new Gio.Settings({ schema: SEARCH_PROVIDERS_SCHEMA }); this._searchSettings.connect('changed::disabled', Lang.bind(this, this._reloadRemoteProviders)); this._searchSettings.connect('changed::disable-external', Lang.bind(this, this._reloadRemoteProviders)); this._searchSettings.connect('changed::sort-order', Lang.bind(this, this._reloadRemoteProviders)); - this._reloadRemoteProviders(); - + this._searchTimeoutId = 0; this._cancellable = new Gio.Cancellable(); + + this._registerProvider(new AppDisplay.AppSearchProvider()); + this._reloadRemoteProviders(); }, _reloadRemoteProviders: function() { @@ -446,14 +452,39 @@ const SearchResults = new Lang.Class({ this._updateResults(provider, results); }, - setTerms: function(terms) { + _doSearch: function() { this._startingSearch = false; + let previousResults = this._results; + this._results = {}; + + this._providers.forEach(Lang.bind(this, function(provider) { + provider.searchInProgress = true; + + let previousProviderResults = previousResults[provider.id]; + if (this._isSubSearch && previousProviderResults) + provider.getSubsearchResultSet(previousProviderResults, this._terms, Lang.bind(this, this._gotResults, provider), this._cancellable); + else + provider.getInitialResultSet(this._terms, Lang.bind(this, this._gotResults, provider), this._cancellable); + })); + + this._updateSearchProgress(); + + this._searchTimeoutId = 0; + return GLib.SOURCE_REMOVE; + }, + + setTerms: function(terms) { + this._startingSearch = true; + this._cancellable.cancel(); this._cancellable.reset(); - if (!terms) + if (!terms) { + if (this._searchTimeoutId > 0) + GLib.source_remove(this._searchTimeoutId); return; + } let searchString = terms.join(' '); let previousSearchString = this._terms.join(' '); @@ -465,19 +496,11 @@ const SearchResults = new Lang.Class({ isSubSearch = searchString.indexOf(previousSearchString) == 0; this._terms = terms; - this._results = {}; - - this._providers.forEach(Lang.bind(this, function(provider) { - provider.searchInProgress = true; - - let previousProviderResults = previousResults[provider.id]; - if (isSubSearch && previousProviderResults) - provider.getSubsearchResultSet(previousProviderResults, terms, Lang.bind(this, this._gotResults, provider), this._cancellable); - else - provider.getInitialResultSet(terms, Lang.bind(this, this._gotResults, provider), this._cancellable); - })); - + this._isSubSearch = isSubSearch; this._updateSearchProgress(); + + if (this._searchTimeoutId == 0) + this._searchTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 150, Lang.bind(this, this._doSearch)); }, _onPan: function(action) { @@ -512,29 +535,6 @@ const SearchResults = new Lang.Class({ }); }, - reset: function() { - this._terms = []; - this._results = {}; - this._clearDisplay(); - this._defaultResult = null; - this._startingSearch = false; - - this._updateSearchProgress(); - }, - - startingSearch: function() { - this.reset(); - - // We don't call setTerms and do the actual search until - // a timeout a little while later, but we don't want to - // show "No Results" because we think there's no work - // being done, so we keep this flag to know that there's - // "pending work". This is cleared in setTerms. - this._startingSearch = true; - - this._updateSearchProgress(); - }, - _maybeSetInitialSelection: function() { let newDefaultResult = null; @@ -601,6 +601,8 @@ const SearchResults = new Lang.Class({ }, activateDefault: function() { + this._doSearch(); + if (this._defaultResult) this._defaultResult.activate(); }, diff --git a/js/ui/viewSelector.js b/js/ui/viewSelector.js index e97627d19..e82dfb3ff 100644 --- a/js/ui/viewSelector.js +++ b/js/ui/viewSelector.js @@ -125,7 +125,6 @@ const ViewSelector = new Lang.Class({ this._activePage = null; this._searchActive = false; - this._searchTimeoutId = 0; this._entry = searchEntry; ShellEntry.addContextMenu(this._entry); @@ -485,36 +484,23 @@ const ViewSelector = new Lang.Class({ _onTextChanged: function (se, prop) { let terms = getTermsForSearchString(this._entry.get_text()); - let searchPreviouslyActive = this._searchActive; this._searchActive = (terms.length > 0); - - let startSearch = this._searchActive && !searchPreviouslyActive; - if (startSearch) - this._searchResults.startingSearch(); + this._searchResults.setTerms(terms); if (this._searchActive) { + this._showPage(this._searchPage); + this._entry.set_secondary_icon(this._clearIcon); if (this._iconClickedId == 0) this._iconClickedId = this._entry.connect('secondary-icon-clicked', Lang.bind(this, this.reset)); - - if (this._searchTimeoutId == 0) { - this._searchTimeoutId = Mainloop.timeout_add(150, - Lang.bind(this, this._doSearch)); - GLib.Source.set_name_by_id(this._searchTimeoutId, '[gnome-shell] this._doSearch'); - } } else { if (this._iconClickedId > 0) { this._entry.disconnect(this._iconClickedId); this._iconClickedId = 0; } - if (this._searchTimeoutId > 0) { - Mainloop.source_remove(this._searchTimeoutId); - this._searchTimeoutId = 0; - } - this._entry.set_secondary_icon(null); this._searchCancelled(); } @@ -552,12 +538,6 @@ const ViewSelector = new Lang.Class({ this._searchResults.navigateFocus(nextDirection); return Clutter.EVENT_STOP; } else if (symbol == Clutter.Return || symbol == Clutter.KP_Enter) { - // We can't connect to 'activate' here because search providers - // might want to do something with the modifiers in activateDefault. - if (this._searchTimeoutId > 0) { - Mainloop.source_remove(this._searchTimeoutId); - this._doSearch(); - } this._searchResults.activateDefault(); return Clutter.EVENT_STOP; } @@ -580,17 +560,6 @@ const ViewSelector = new Lang.Class({ return Clutter.EVENT_PROPAGATE; }, - _doSearch: function () { - this._searchTimeoutId = 0; - - let terms = getTermsForSearchString(this._entry.get_text()); - - this._searchResults.setTerms(terms); - this._showPage(this._searchPage); - - return GLib.SOURCE_REMOVE; - }, - getActivePage: function() { if (this._activePage == this._workspacesPage) return ViewPage.WINDOWS;