105
102
transition: 'easeOutQuad' });
108
setFilter: function(filter) {
109
this._filterApp = filter;
110
for (let i = 0; i < this._apps.length; i++)
111
this._apps[i].actor.visible = filter(this._apps[i]._appInfo);
114
// Create actors for the applications in an idle to avoid blocking
115
// for too long; see bug 647778
116
_addPendingApps: function() {
118
let startTimeMillis = new Date().getTime();
119
for (i = 0; i < this._pendingAppIds.length; i++) {
120
let id = this._pendingAppIds[i];
121
this._addApp(this._pendingApps[id]);
123
let currentTimeMillis = new Date().getTime();
124
if (currentTimeMillis - startTimeMillis > MAX_APPLICATION_WORK_MILLIS)
127
this._pendingAppIds.splice(0, i + 1);
128
if (this._pendingAppIds.length > 0) {
105
setVisibleApps: function(apps) {
106
if (apps == null) { // null implies "all"
107
for (var id in this._appIcons) {
108
var icon = this._appIcons[id];
109
icon.actor.visible = true;
131
this._pendingAppLaterId = 0;
132
this._pendingAppIds = null;
133
this._pendingApps = null;
112
// Set everything to not-visible, then set to visible what we should see
113
for (var id in this._appIcons) {
114
var icon = this._appIcons[id];
115
icon.actor.visible = false;
117
for (var i = 0; i < apps.length; i++) {
119
var id = app.get_id();
120
var icon = this._appIcons[id];
121
icon.actor.visible = true;
138
refresh: function(apps) {
142
ids.sort(function(a, b) {
143
return apps[a].get_name().localeCompare(apps[b].get_name());
126
setAppList: function(apps) {
146
127
this._removeAll();
148
this._pendingAppIds = ids;
149
this._pendingApps = apps;
150
if (this._pendingAppLaterId)
151
Meta.later_remove(this._pendingAppLaterId);
152
this._pendingAppLaterId = Meta.later_add(Meta.LaterType.BEFORE_REDRAW,
153
Lang.bind(this, this._addPendingApps));
128
for (var i = 0; i < apps.length; i++) {
171
149
// -2 is a flag to indicate that nothing is selected
172
150
// (used only before the actor is mapped the first time)
173
151
this._currentCategory = -2;
174
this._filters = new St.BoxLayout({ vertical: true, reactive: true });
175
this._filtersBox = new St.ScrollView({ x_fill: false,
177
style_class: 'vfade' });
178
this._filtersBox.add_actor(this._filters);
152
this._categories = [];
155
this._categoryBox = new St.BoxLayout({ vertical: true, reactive: true });
156
this._categoryScroll = new St.ScrollView({ x_fill: false,
158
style_class: 'vfade' });
159
this._categoryScroll.add_actor(this._categoryBox);
179
160
this.actor.add(this._view.actor, { expand: true, x_fill: true, y_fill: true });
180
this.actor.add(this._filtersBox, { expand: false, y_fill: false, y_align: St.Align.START });
161
this.actor.add(this._categoryScroll, { expand: false, y_fill: false, y_align: St.Align.START });
182
163
// Always select the "All" filter when switching to the app view
183
164
this.actor.connect('notify::mapped', Lang.bind(this,
185
if (this.actor.mapped && this._allFilter)
166
if (this.actor.mapped && this._allCategoryButton)
186
167
this._selectCategory(-1);
191
170
// We need a dummy actor to catch the keyboard focus if the
192
171
// user Ctrl-Alt-Tabs here before the deferred work creates
193
172
// our real contents
202
181
this._currentCategory = num;
205
this._allFilter.remove_style_pseudo_class('selected');
207
this._allFilter.add_style_pseudo_class('selected');
209
this._view.setFilter(Lang.bind(this, function(app) {
212
return this._sections[num].name == app.get_section();
215
for (let i = 0; i < this._sections.length; i++) {
184
var category = this._categories[num];
185
this._allCategoryButton.remove_style_pseudo_class('selected');
186
this._view.setVisibleApps(category.apps);
188
this._allCategoryButton.add_style_pseudo_class('selected');
189
this._view.setVisibleApps(null);
192
for (var i = 0; i < this._categories.length; i++) {
217
this._sections[i].filterActor.add_style_pseudo_class('selected');
194
this._categories[i].button.add_style_pseudo_class('selected');
219
this._sections[i].filterActor.remove_style_pseudo_class('selected');
223
_addFilter: function(name, num) {
196
this._categories[i].button.remove_style_pseudo_class('selected');
200
// Recursively load a GMenuTreeDirectory; we could put this in ShellAppSystem too
201
_loadCategory: function(dir, appList) {
202
var iter = dir.iter();
204
while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) {
205
if (nextType == GMenu.TreeItemType.ENTRY) {
206
var entry = iter.get_entry();
207
var app = this._appSystem.lookup_app_by_tree_entry(entry);
208
if (!entry.get_app_info().get_nodisplay())
210
} else if (nextType == GMenu.TreeItemType.DIRECTORY) {
211
this._loadCategory(iter.get_directory(), appList);
216
_addCategory: function(name, index, dir, allApps) {
224
217
let button = new St.Button({ label: GLib.markup_escape_text (name, -1),
225
218
style_class: 'app-filter',
226
219
x_align: St.Align.START,
227
220
can_focus: true });
228
this._filters.add(button, { expand: true, x_fill: true, y_fill: false });
229
221
button.connect('clicked', Lang.bind(this, function() {
230
this._selectCategory(num);
222
this._selectCategory(index);
234
this._sections[num] = { filterActor: button,
237
this._allFilter = button;
228
this._allCategoryButton = button;
231
this._loadCategory(dir, apps);
232
this._categories.push({ apps: apps,
237
this._categoryBox.add(button, { expand: true, x_fill: true, y_fill: false });
240
240
_removeAll: function() {
242
this._filters.destroy_children();
241
this._categories = [];
242
this._categoryBox.destroy_children();
245
refresh: function(apps) {
245
refresh: function() {
246
246
this._removeAll();
248
let sections = this._appSystem.get_sections();
248
var allApps = Shell.AppSystem.get_default().get_all();
249
allApps.sort(function(a, b) {
250
return a.compare_by_name(b);
251
253
/* Translators: Filter to display all applications */
252
this._addFilter(_("All"), -1);
257
for (let i = 0; i < sections.length; i++)
258
this._addFilter(sections[i], i);
254
this._addCategory(_("All"), -1, null, allApps);
256
var tree = this._appSystem.get_tree();
257
var root = tree.get_root_directory();
259
var iter = root.iter();
262
while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) {
263
if (nextType == GMenu.TreeItemType.DIRECTORY) {
264
var dir = iter.get_directory();
265
this._addCategory(dir.get_name(), i, dir);
270
this._view.setAppList(allApps);
260
271
this._selectCategory(-1);
261
this._view.refresh(apps);
263
273
if (this._focusDummy) {
264
274
let focused = this._focusDummy.has_key_focus();
293
303
_redisplay: function() {
294
let apps = this._appSystem.get_flattened_apps().filter(function(app) {
295
return !app.get_is_nodisplay();
298
this._appView.refresh(apps);
304
this._appView.refresh();
302
function BaseAppSearchProvider() {
308
function AppSearchProvider() {
306
BaseAppSearchProvider.prototype = {
312
AppSearchProvider.prototype = {
307
313
__proto__: Search.SearchProvider.prototype,
309
_init: function(name) {
310
Search.SearchProvider.prototype._init.call(this, name);
316
Search.SearchProvider.prototype._init.call(this, _("APPLICATIONS"));
311
317
this._appSys = Shell.AppSystem.get_default();
314
getResultMeta: function(resultId) {
315
let app = this._appSys.get_app(resultId);
318
return { 'id': resultId,
320
getResultMeta: function(app) {
319
322
'name': app.get_name(),
320
323
'createIcon': function(size) {
321
324
return app.create_icon_texture(size);
326
activateResult: function(id, params) {
327
params = Params.parse(params, { workspace: null,
330
let workspace = params.workspace ? params.workspace.index() : -1;
329
getInitialResultSet: function(terms) {
330
return this._appSys.initial_search(terms);
333
getSubsearchResultSet: function(previousResults, terms) {
334
return this._appSys.subsearch(previousResults, terms);
337
activateResult: function(app, params) {
338
params = Params.parse(params, { workspace: -1,
331
341
let event = Clutter.get_current_event();
332
342
let modifiers = event ? Shell.get_event_state(event) : 0;
333
343
let openNewWindow = modifiers & Clutter.ModifierType.CONTROL_MASK;
335
let app = this._appSys.get_app(id);
336
345
if (openNewWindow)
337
app.open_new_window(workspace);
346
app.open_new_window(params.workspace);
339
app.activate(workspace);
348
app.activate_full(params.workspace, params.timestamp);
342
351
dragActivateResult: function(id, params) {
343
params = Params.parse(params, { workspace: null,
346
let app = this._appSys.get_app(id);
347
app.open_new_window(params.workspace ? params.workspace.index() : -1);
351
function AppSearchProvider() {
355
AppSearchProvider.prototype = {
356
__proto__: BaseAppSearchProvider.prototype,
359
BaseAppSearchProvider.prototype._init.call(this, _("APPLICATIONS"));
362
getInitialResultSet: function(terms) {
363
return this._appSys.initial_search(false, terms);
366
getSubsearchResultSet: function(previousResults, terms) {
367
return this._appSys.subsearch(false, previousResults, terms);
370
createResultActor: function (resultMeta, terms) {
371
let app = this._appSys.get_app(resultMeta['id']);
372
let icon = new AppWellIcon(app);
377
function PrefsSearchProvider() {
381
PrefsSearchProvider.prototype = {
382
__proto__: BaseAppSearchProvider.prototype,
385
BaseAppSearchProvider.prototype._init.call(this, _("SETTINGS"));
388
getInitialResultSet: function(terms) {
389
return this._appSys.initial_search(true, terms);
392
getSubsearchResultSet: function(previousResults, terms) {
393
return this._appSys.subsearch(true, previousResults, terms);
352
params = Params.parse(params, { workspace: -1,
355
let app = this._appSys.lookup_app(id);
356
app.open_new_window(workspace);
359
createResultActor: function (resultMeta, terms) {
360
let app = resultMeta['id'];
361
let icon = new AppWellIcon(app);
366
function SettingsSearchProvider() {
370
SettingsSearchProvider.prototype = {
371
__proto__: Search.SearchProvider.prototype,
374
Search.SearchProvider.prototype._init.call(this, _("SETTINGS"));
375
this._appSys = Shell.AppSystem.get_default();
376
this._gnomecc = this._appSys.lookup_app('gnome-control-center.desktop');
379
getResultMeta: function(pref) {
381
'name': pref.get_name(),
382
'createIcon': function(size) {
383
return pref.create_icon_texture(size);
388
getInitialResultSet: function(terms) {
389
return this._appSys.search_settings(terms);
392
getSubsearchResultSet: function(previousResults, terms) {
393
return this._appSys.search_settings(terms);
396
activateResult: function(pref, params) {
397
params = Params.parse(params, { workspace: -1,
400
pref.activate_full(params.workspace, params.timestamp);
403
dragActivateResult: function(pref, params) {
404
this.activateResult(pref, params);
407
createResultActor: function (resultMeta, terms) {
408
let app = resultMeta['id'];
409
let icon = new AppWellIcon(app);
569
588
this.emit('launching');
570
589
let modifiers = Shell.get_event_state(event);
572
if (modifiers & Clutter.ModifierType.CONTROL_MASK
573
&& this.app.state == Shell.AppState.RUNNING) {
574
this.app.open_new_window(-1);
591
if (this._onActivateOverride) {
592
this._onActivateOverride(event);
576
this.app.activate(-1);
594
if (modifiers & Clutter.ModifierType.CONTROL_MASK
595
&& this.app.state == Shell.AppState.RUNNING) {
596
this.app.open_new_window(-1);
578
601
Main.overview.hide();
581
604
shellWorkspaceLaunch : function(params) {
582
params = Params.parse(params, { workspace: null,
605
params = Params.parse(params, { workspace: -1,
585
this.app.open_new_window(params.workspace ? params.workspace.index() : -1);
608
this.app.open_new_window(params.workspace);
588
611
getDragActor: function() {
589
return this.app.create_icon_texture(Main.overview.dash.iconSize);
612
return this.app.create_icon_texture(Main.overview.dashIconSize);
592
615
// Returns the original actor that should align with the actor