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.
This commit is contained in:
Jasper St. Pierre 2014-09-11 15:15:50 -06:00
parent 4f2070a7c6
commit c4922f6624
2 changed files with 45 additions and 74 deletions

View File

@ -2,6 +2,7 @@
const Clutter = imports.gi.Clutter; const Clutter = imports.gi.Clutter;
const Lang = imports.lang; const Lang = imports.lang;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk; const Gtk = imports.gi.Gtk;
const Meta = imports.gi.Meta; const Meta = imports.gi.Meta;
@ -401,18 +402,23 @@ const SearchResults = new Lang.Class({
this._highlightDefault = false; this._highlightDefault = false;
this._defaultResult = null; this._defaultResult = null;
this._startingSearch = false;
this._terms = [];
this._results = {};
this._providers = []; this._providers = [];
this._registerProvider(new AppDisplay.AppSearchProvider());
this._searchSettings = new Gio.Settings({ schema: SEARCH_PROVIDERS_SCHEMA }); this._searchSettings = new Gio.Settings({ schema: SEARCH_PROVIDERS_SCHEMA });
this._searchSettings.connect('changed::disabled', Lang.bind(this, this._reloadRemoteProviders)); 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::disable-external', Lang.bind(this, this._reloadRemoteProviders));
this._searchSettings.connect('changed::sort-order', 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._cancellable = new Gio.Cancellable();
this._registerProvider(new AppDisplay.AppSearchProvider());
this._reloadRemoteProviders();
}, },
_reloadRemoteProviders: function() { _reloadRemoteProviders: function() {
@ -446,14 +452,39 @@ const SearchResults = new Lang.Class({
this._updateResults(provider, results); this._updateResults(provider, results);
}, },
setTerms: function(terms) { _doSearch: function() {
this._startingSearch = false; 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.cancel();
this._cancellable.reset(); this._cancellable.reset();
if (!terms) if (!terms) {
if (this._searchTimeoutId > 0)
GLib.source_remove(this._searchTimeoutId);
return; return;
}
let searchString = terms.join(' '); let searchString = terms.join(' ');
let previousSearchString = this._terms.join(' '); let previousSearchString = this._terms.join(' ');
@ -465,19 +496,11 @@ const SearchResults = new Lang.Class({
isSubSearch = searchString.indexOf(previousSearchString) == 0; isSubSearch = searchString.indexOf(previousSearchString) == 0;
this._terms = terms; this._terms = terms;
this._results = {}; this._isSubSearch = isSubSearch;
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._updateSearchProgress(); this._updateSearchProgress();
if (this._searchTimeoutId == 0)
this._searchTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 150, Lang.bind(this, this._doSearch));
}, },
_onPan: function(action) { _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() { _maybeSetInitialSelection: function() {
let newDefaultResult = null; let newDefaultResult = null;
@ -601,6 +601,8 @@ const SearchResults = new Lang.Class({
}, },
activateDefault: function() { activateDefault: function() {
this._doSearch();
if (this._defaultResult) if (this._defaultResult)
this._defaultResult.activate(); this._defaultResult.activate();
}, },

View File

@ -125,7 +125,6 @@ const ViewSelector = new Lang.Class({
this._activePage = null; this._activePage = null;
this._searchActive = false; this._searchActive = false;
this._searchTimeoutId = 0;
this._entry = searchEntry; this._entry = searchEntry;
ShellEntry.addContextMenu(this._entry); ShellEntry.addContextMenu(this._entry);
@ -485,36 +484,23 @@ const ViewSelector = new Lang.Class({
_onTextChanged: function (se, prop) { _onTextChanged: function (se, prop) {
let terms = getTermsForSearchString(this._entry.get_text()); let terms = getTermsForSearchString(this._entry.get_text());
let searchPreviouslyActive = this._searchActive;
this._searchActive = (terms.length > 0); this._searchActive = (terms.length > 0);
this._searchResults.setTerms(terms);
let startSearch = this._searchActive && !searchPreviouslyActive;
if (startSearch)
this._searchResults.startingSearch();
if (this._searchActive) { if (this._searchActive) {
this._showPage(this._searchPage);
this._entry.set_secondary_icon(this._clearIcon); this._entry.set_secondary_icon(this._clearIcon);
if (this._iconClickedId == 0) if (this._iconClickedId == 0)
this._iconClickedId = this._entry.connect('secondary-icon-clicked', this._iconClickedId = this._entry.connect('secondary-icon-clicked',
Lang.bind(this, this.reset)); 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 { } else {
if (this._iconClickedId > 0) { if (this._iconClickedId > 0) {
this._entry.disconnect(this._iconClickedId); this._entry.disconnect(this._iconClickedId);
this._iconClickedId = 0; this._iconClickedId = 0;
} }
if (this._searchTimeoutId > 0) {
Mainloop.source_remove(this._searchTimeoutId);
this._searchTimeoutId = 0;
}
this._entry.set_secondary_icon(null); this._entry.set_secondary_icon(null);
this._searchCancelled(); this._searchCancelled();
} }
@ -552,12 +538,6 @@ const ViewSelector = new Lang.Class({
this._searchResults.navigateFocus(nextDirection); this._searchResults.navigateFocus(nextDirection);
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} else if (symbol == Clutter.Return || symbol == Clutter.KP_Enter) { } 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(); this._searchResults.activateDefault();
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} }
@ -580,17 +560,6 @@ const ViewSelector = new Lang.Class({
return Clutter.EVENT_PROPAGATE; 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() { getActivePage: function() {
if (this._activePage == this._workspacesPage) if (this._activePage == this._workspacesPage)
return ViewPage.WINDOWS; return ViewPage.WINDOWS;