2011-09-28 13:16:26 +00:00
|
|
|
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
2010-11-12 17:45:29 +00:00
|
|
|
|
|
|
|
const Clutter = imports.gi.Clutter;
|
2012-10-08 16:16:55 +00:00
|
|
|
const Gio = imports.gi.Gio;
|
2013-11-29 00:45:39 +00:00
|
|
|
const GLib = imports.gi.GLib;
|
2011-02-23 19:21:47 +00:00
|
|
|
const Gtk = imports.gi.Gtk;
|
2010-11-12 17:45:29 +00:00
|
|
|
const Mainloop = imports.mainloop;
|
|
|
|
const Meta = imports.gi.Meta;
|
|
|
|
const Signals = imports.signals;
|
|
|
|
const Lang = imports.lang;
|
|
|
|
const Shell = imports.gi.Shell;
|
|
|
|
const St = imports.gi.St;
|
|
|
|
|
2012-07-28 20:06:46 +00:00
|
|
|
const AppDisplay = imports.ui.appDisplay;
|
2010-11-12 17:45:29 +00:00
|
|
|
const Main = imports.ui.main;
|
2013-01-24 06:35:19 +00:00
|
|
|
const OverviewControls = imports.ui.overviewControls;
|
2012-12-13 22:20:46 +00:00
|
|
|
const Params = imports.misc.params;
|
2010-11-12 17:45:29 +00:00
|
|
|
const Search = imports.ui.search;
|
2011-10-11 22:38:24 +00:00
|
|
|
const ShellEntry = imports.ui.shellEntry;
|
2010-11-12 17:45:29 +00:00
|
|
|
const Tweener = imports.ui.tweener;
|
2012-07-28 20:06:46 +00:00
|
|
|
const WorkspacesView = imports.ui.workspacesView;
|
2014-08-05 14:25:30 +00:00
|
|
|
const EdgeDragAction = imports.ui.edgeDragAction;
|
2010-11-12 17:45:29 +00:00
|
|
|
|
2012-10-08 16:16:55 +00:00
|
|
|
const SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings';
|
2010-11-12 17:45:29 +00:00
|
|
|
|
2013-02-13 21:13:14 +00:00
|
|
|
const ViewPage = {
|
|
|
|
WINDOWS: 1,
|
|
|
|
APPS: 2,
|
|
|
|
SEARCH: 3
|
|
|
|
};
|
|
|
|
|
2012-03-10 00:33:31 +00:00
|
|
|
const FocusTrap = new Lang.Class({
|
|
|
|
Name: 'FocusTrap',
|
|
|
|
Extends: St.Widget,
|
|
|
|
|
|
|
|
vfunc_navigate_focus: function(from, direction) {
|
|
|
|
if (direction == Gtk.DirectionType.TAB_FORWARD ||
|
|
|
|
direction == Gtk.DirectionType.TAB_BACKWARD)
|
|
|
|
return this.parent(from, direction);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2013-02-09 02:05:15 +00:00
|
|
|
function getTermsForSearchString(searchString) {
|
|
|
|
searchString = searchString.replace(/^\s+/g, '').replace(/\s+$/g, '');
|
|
|
|
if (searchString == '')
|
|
|
|
return [];
|
|
|
|
|
|
|
|
let terms = searchString.split(/\s+/);
|
|
|
|
return terms;
|
|
|
|
}
|
2012-03-10 00:33:31 +00:00
|
|
|
|
2014-06-25 16:12:04 +00:00
|
|
|
const ShowOverviewAction = new Lang.Class({
|
|
|
|
Name: 'ShowOverviewAction',
|
|
|
|
Extends: Clutter.GestureAction,
|
|
|
|
|
|
|
|
_init : function() {
|
|
|
|
this.parent();
|
|
|
|
this.set_n_touch_points(3);
|
|
|
|
|
|
|
|
global.display.connect('grab-op-begin', Lang.bind(this, function() {
|
|
|
|
this.cancel();
|
|
|
|
}));
|
|
|
|
},
|
|
|
|
|
|
|
|
vfunc_gesture_prepare : function(action, actor) {
|
|
|
|
return this.get_n_current_points() == this.get_n_touch_points();
|
|
|
|
},
|
|
|
|
|
|
|
|
_getBoundingRect : function(motion) {
|
|
|
|
let minX, minY, maxX, maxY;
|
|
|
|
|
|
|
|
for (let i = 0; i < this.get_n_current_points(); i++) {
|
|
|
|
let x, y;
|
|
|
|
|
|
|
|
if (motion == true) {
|
|
|
|
[x, y] = this.get_motion_coords(i);
|
|
|
|
} else {
|
|
|
|
[x, y] = this.get_press_coords(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i == 0) {
|
|
|
|
minX = maxX = x;
|
|
|
|
minY = maxY = y;
|
|
|
|
} else {
|
|
|
|
minX = Math.min(minX, x);
|
|
|
|
minY = Math.min(minY, y);
|
|
|
|
maxX = Math.max(maxX, x);
|
|
|
|
maxY = Math.max(maxY, y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return new Meta.Rectangle({ x: minX,
|
|
|
|
y: minY,
|
|
|
|
width: maxX - minX,
|
|
|
|
height: maxY - minY });
|
|
|
|
},
|
|
|
|
|
|
|
|
vfunc_gesture_begin : function(action, actor) {
|
|
|
|
this._initialRect = this._getBoundingRect(false);
|
|
|
|
return true;
|
|
|
|
},
|
|
|
|
|
|
|
|
vfunc_gesture_end : function(action, actor) {
|
|
|
|
let rect = this._getBoundingRect(true);
|
|
|
|
let oldArea = this._initialRect.width * this._initialRect.height;
|
|
|
|
let newArea = rect.width * rect.height;
|
|
|
|
let areaDiff = newArea / oldArea;
|
|
|
|
|
|
|
|
this.emit('activated', areaDiff);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
Signals.addSignalMethods(ShowOverviewAction.prototype);
|
|
|
|
|
2012-06-21 22:52:56 +00:00
|
|
|
const ViewSelector = new Lang.Class({
|
|
|
|
Name: 'ViewSelector',
|
|
|
|
|
|
|
|
_init : function(searchEntry, showAppsButton) {
|
2012-12-13 22:21:53 +00:00
|
|
|
this.actor = new Shell.Stack({ name: 'viewSelector' });
|
2012-06-21 22:52:56 +00:00
|
|
|
|
|
|
|
this._showAppsButton = showAppsButton;
|
2012-06-21 22:52:56 +00:00
|
|
|
this._showAppsButton.connect('notify::checked', Lang.bind(this, this._onShowAppsButtonToggled));
|
2012-06-21 22:52:56 +00:00
|
|
|
|
2012-06-21 22:52:56 +00:00
|
|
|
this._activePage = null;
|
2010-11-18 12:51:47 +00:00
|
|
|
|
2012-08-24 16:24:49 +00:00
|
|
|
this._searchActive = false;
|
2010-11-18 12:51:47 +00:00
|
|
|
this._searchTimeoutId = 0;
|
|
|
|
|
2012-07-28 20:47:55 +00:00
|
|
|
this._entry = searchEntry;
|
2011-10-11 22:38:24 +00:00
|
|
|
ShellEntry.addContextMenu(this._entry);
|
2012-06-21 22:52:56 +00:00
|
|
|
|
2011-02-16 18:20:03 +00:00
|
|
|
this._text = this._entry.clutter_text;
|
2012-06-21 22:52:56 +00:00
|
|
|
this._text.connect('text-changed', Lang.bind(this, this._onTextChanged));
|
2011-02-16 18:27:05 +00:00
|
|
|
this._text.connect('key-press-event', Lang.bind(this, this._onKeyPress));
|
2012-06-21 22:52:56 +00:00
|
|
|
this._text.connect('key-focus-in', Lang.bind(this, function() {
|
|
|
|
this._searchResults.highlightDefault(true);
|
|
|
|
}));
|
|
|
|
this._text.connect('key-focus-out', Lang.bind(this, function() {
|
|
|
|
this._searchResults.highlightDefault(false);
|
|
|
|
}));
|
|
|
|
this._entry.connect('notify::mapped', Lang.bind(this, this._onMapped));
|
|
|
|
global.stage.connect('notify::key-focus', Lang.bind(this, this._onStageKeyFocusChanged));
|
2011-02-16 18:20:03 +00:00
|
|
|
|
2013-03-03 18:56:12 +00:00
|
|
|
this._entry.set_primary_icon(new St.Icon({ style_class: 'search-entry-icon',
|
|
|
|
icon_name: 'edit-find-symbolic' }));
|
2013-08-26 22:24:26 +00:00
|
|
|
if (this._entry.get_text_direction() == Clutter.TextDirection.RTL)
|
|
|
|
this._clearIcon = new St.Icon({ style_class: 'search-entry-icon',
|
2014-06-26 22:25:22 +00:00
|
|
|
icon_name: 'edit-clear-symbolic-rtl' });
|
2013-08-26 22:24:26 +00:00
|
|
|
else
|
|
|
|
this._clearIcon = new St.Icon({ style_class: 'search-entry-icon',
|
2014-06-26 22:25:22 +00:00
|
|
|
icon_name: 'edit-clear-symbolic-ltr' });
|
2011-02-16 18:20:03 +00:00
|
|
|
|
|
|
|
this._iconClickedId = 0;
|
2012-06-21 22:52:56 +00:00
|
|
|
this._capturedEventId = 0;
|
2011-02-16 18:20:03 +00:00
|
|
|
|
2012-06-21 22:52:56 +00:00
|
|
|
this._workspacesDisplay = new WorkspacesView.WorkspacesDisplay();
|
2012-12-13 22:20:46 +00:00
|
|
|
this._workspacesPage = this._addPage(this._workspacesDisplay.actor,
|
2012-11-20 10:51:56 +00:00
|
|
|
_("Windows"), 'emblem-documents-symbolic');
|
2011-02-16 18:20:03 +00:00
|
|
|
|
2011-07-09 13:30:42 +00:00
|
|
|
this.appDisplay = new AppDisplay.AppDisplay();
|
|
|
|
this._appsPage = this._addPage(this.appDisplay.actor,
|
2012-11-20 10:51:56 +00:00
|
|
|
_("Applications"), 'view-grid-symbolic');
|
2011-02-16 18:20:03 +00:00
|
|
|
|
2013-10-30 16:38:46 +00:00
|
|
|
this._searchResults = new Search.SearchResults();
|
2012-12-13 22:20:46 +00:00
|
|
|
this._searchPage = this._addPage(this._searchResults.actor,
|
|
|
|
_("Search"), 'edit-find-symbolic',
|
|
|
|
{ a11yFocus: this._entry });
|
2011-02-16 18:20:03 +00:00
|
|
|
|
2011-11-12 04:40:56 +00:00
|
|
|
// Since the entry isn't inside the results container we install this
|
|
|
|
// dummy widget as the last results container child so that we can
|
2012-03-10 00:33:31 +00:00
|
|
|
// include the entry in the keynav tab path
|
|
|
|
this._focusTrap = new FocusTrap({ can_focus: true });
|
2011-11-12 04:40:56 +00:00
|
|
|
this._focusTrap.connect('key-focus-in', Lang.bind(this, function() {
|
|
|
|
this._entry.grab_key_focus();
|
|
|
|
}));
|
|
|
|
this._searchResults.actor.add_actor(this._focusTrap);
|
|
|
|
|
|
|
|
global.focus_manager.add_group(this._searchResults.actor);
|
2012-06-21 22:52:56 +00:00
|
|
|
|
|
|
|
this._stageKeyPressId = 0;
|
|
|
|
Main.overview.connect('showing', Lang.bind(this,
|
|
|
|
function () {
|
|
|
|
this._stageKeyPressId = global.stage.connect('key-press-event',
|
|
|
|
Lang.bind(this, this._onStageKeyPress));
|
|
|
|
}));
|
|
|
|
Main.overview.connect('hiding', Lang.bind(this,
|
|
|
|
function () {
|
|
|
|
if (this._stageKeyPressId != 0) {
|
|
|
|
global.stage.disconnect(this._stageKeyPressId);
|
|
|
|
this._stageKeyPressId = 0;
|
|
|
|
}
|
|
|
|
}));
|
2014-07-14 17:06:08 +00:00
|
|
|
Main.overview.connect('shown', Lang.bind(this,
|
|
|
|
function() {
|
|
|
|
// If we were animating from the desktop view to the
|
|
|
|
// apps page the workspace page was visible, allowing
|
|
|
|
// the windows to animate, but now we no longer want to
|
|
|
|
// show it given that we are now on the apps page or
|
|
|
|
// search page.
|
|
|
|
if (this._activePage != this._workspacesPage)
|
|
|
|
this._workspacesPage.opacity = 0;
|
|
|
|
}));
|
2012-06-21 22:52:56 +00:00
|
|
|
|
2012-08-16 12:46:23 +00:00
|
|
|
Main.wm.addKeybinding('toggle-application-view',
|
2014-06-24 19:17:09 +00:00
|
|
|
new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }),
|
2012-08-16 12:46:23 +00:00
|
|
|
Meta.KeyBindingFlags.NONE,
|
2012-12-12 13:14:13 +00:00
|
|
|
Shell.KeyBindingMode.NORMAL |
|
|
|
|
Shell.KeyBindingMode.OVERVIEW,
|
2012-08-16 12:46:23 +00:00
|
|
|
Lang.bind(this, this._toggleAppsPage));
|
2013-04-17 23:26:06 +00:00
|
|
|
|
|
|
|
Main.wm.addKeybinding('toggle-overview',
|
2014-06-24 19:17:09 +00:00
|
|
|
new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }),
|
2013-04-17 23:26:06 +00:00
|
|
|
Meta.KeyBindingFlags.NONE,
|
|
|
|
Shell.KeyBindingMode.NORMAL |
|
|
|
|
Shell.KeyBindingMode.OVERVIEW,
|
|
|
|
Lang.bind(Main.overview, Main.overview.toggle));
|
|
|
|
|
2014-06-25 16:12:04 +00:00
|
|
|
let gesture;
|
|
|
|
|
2014-08-05 14:25:30 +00:00
|
|
|
gesture = new EdgeDragAction.EdgeDragAction(St.Side.LEFT);
|
2014-06-25 15:52:19 +00:00
|
|
|
gesture.connect('activated', Lang.bind(this, function() {
|
|
|
|
if (Main.overview.visible)
|
|
|
|
Main.overview.hide();
|
|
|
|
else
|
|
|
|
this.showApps();
|
|
|
|
}));
|
|
|
|
global.stage.add_action(gesture);
|
2014-06-25 16:12:04 +00:00
|
|
|
|
|
|
|
gesture = new ShowOverviewAction();
|
|
|
|
gesture.connect('activated', Lang.bind(this, function(action, areaDiff) {
|
|
|
|
if (areaDiff < 0.7)
|
|
|
|
Main.overview.show();
|
|
|
|
}));
|
|
|
|
global.stage.add_action(gesture);
|
2012-10-08 16:16:55 +00:00
|
|
|
},
|
|
|
|
|
2012-08-16 12:46:23 +00:00
|
|
|
_toggleAppsPage: function() {
|
|
|
|
this._showAppsButton.checked = !this._showAppsButton.checked;
|
2014-07-14 17:06:08 +00:00
|
|
|
Main.overview.show();
|
2012-06-21 22:52:56 +00:00
|
|
|
},
|
|
|
|
|
2013-04-24 17:32:41 +00:00
|
|
|
showApps: function() {
|
|
|
|
this._showAppsButton.checked = true;
|
2014-07-14 17:06:08 +00:00
|
|
|
Main.overview.show();
|
2013-04-24 17:32:41 +00:00
|
|
|
},
|
|
|
|
|
2012-06-21 22:52:56 +00:00
|
|
|
show: function() {
|
2013-02-16 17:54:19 +00:00
|
|
|
this.reset();
|
2014-07-14 17:06:08 +00:00
|
|
|
this._workspacesDisplay.show(this._showAppsButton.checked);
|
2013-11-20 17:06:14 +00:00
|
|
|
this._activePage = null;
|
2014-07-14 17:06:08 +00:00
|
|
|
if (this._showAppsButton.checked)
|
|
|
|
this._showPage(this._appsPage);
|
|
|
|
else
|
|
|
|
this._showPage(this._workspacesPage);
|
2012-06-21 22:52:56 +00:00
|
|
|
|
|
|
|
if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows())
|
|
|
|
Main.overview.fadeOutDesktop();
|
|
|
|
},
|
|
|
|
|
2014-07-14 17:06:08 +00:00
|
|
|
animateFromOverview: function() {
|
|
|
|
// Make sure workspace page is fully visible to allow
|
|
|
|
// workspace.js do the animation of the windows
|
|
|
|
this._workspacesPage.opacity = 255;
|
|
|
|
|
|
|
|
this._workspacesDisplay.animateFromOverview(this._activePage != this._workspacesPage);
|
|
|
|
|
2014-07-14 16:55:34 +00:00
|
|
|
this._showAppsButton.checked = false;
|
2012-06-21 22:52:56 +00:00
|
|
|
|
|
|
|
if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows())
|
|
|
|
Main.overview.fadeInDesktop();
|
2010-11-18 12:51:47 +00:00
|
|
|
},
|
|
|
|
|
2013-02-25 23:25:27 +00:00
|
|
|
setWorkspacesFullGeometry: function(geom) {
|
|
|
|
this._workspacesDisplay.setWorkspacesFullGeometry(geom);
|
2013-02-25 23:11:59 +00:00
|
|
|
},
|
|
|
|
|
2010-11-18 12:51:47 +00:00
|
|
|
hide: function() {
|
2012-06-21 22:52:56 +00:00
|
|
|
this._workspacesDisplay.hide();
|
|
|
|
},
|
|
|
|
|
2012-12-13 22:20:46 +00:00
|
|
|
_addPage: function(actor, name, a11yIcon, params) {
|
|
|
|
params = Params.parse(params, { a11yFocus: null });
|
|
|
|
|
2012-06-21 22:52:56 +00:00
|
|
|
let page = new St.Bin({ child: actor,
|
|
|
|
x_align: St.Align.START,
|
|
|
|
y_align: St.Align.START,
|
|
|
|
x_fill: true,
|
|
|
|
y_fill: true });
|
2012-12-13 22:20:46 +00:00
|
|
|
if (params.a11yFocus)
|
|
|
|
Main.ctrlAltTabManager.addGroup(params.a11yFocus, name, a11yIcon);
|
2012-06-21 22:52:56 +00:00
|
|
|
else
|
|
|
|
Main.ctrlAltTabManager.addGroup(actor, name, a11yIcon,
|
|
|
|
{ proxy: this.actor,
|
|
|
|
focusCallback: Lang.bind(this,
|
|
|
|
function() {
|
|
|
|
this._a11yFocusPage(page);
|
|
|
|
})
|
|
|
|
});;
|
2013-11-20 17:06:14 +00:00
|
|
|
page.hide();
|
2012-12-13 22:21:53 +00:00
|
|
|
this.actor.add_actor(page);
|
2012-11-01 13:45:04 +00:00
|
|
|
return page;
|
2012-06-21 22:52:56 +00:00
|
|
|
},
|
|
|
|
|
2013-02-16 17:59:54 +00:00
|
|
|
_fadePageIn: function(oldPage) {
|
|
|
|
if (oldPage)
|
|
|
|
oldPage.hide();
|
|
|
|
|
2013-02-16 01:43:45 +00:00
|
|
|
this.emit('page-empty');
|
2014-02-19 00:44:58 +00:00
|
|
|
|
2013-01-24 06:35:19 +00:00
|
|
|
this._activePage.show();
|
|
|
|
Tweener.addTween(this._activePage,
|
|
|
|
{ opacity: 255,
|
2013-02-18 05:17:56 +00:00
|
|
|
time: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME,
|
2013-01-24 06:35:19 +00:00
|
|
|
transition: 'easeOutQuad'
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
2014-07-14 16:55:34 +00:00
|
|
|
_showPage: function(page) {
|
2014-07-14 17:06:08 +00:00
|
|
|
if (!Main.overview.visible)
|
|
|
|
return;
|
|
|
|
|
2013-01-24 21:35:11 +00:00
|
|
|
if (page == this._activePage)
|
2012-06-21 22:52:56 +00:00
|
|
|
return;
|
2012-06-21 22:52:56 +00:00
|
|
|
|
2013-01-24 21:35:11 +00:00
|
|
|
let oldPage = this._activePage;
|
2013-01-24 06:35:19 +00:00
|
|
|
this._activePage = page;
|
|
|
|
this.emit('page-changed');
|
|
|
|
|
2014-07-14 16:55:34 +00:00
|
|
|
if (oldPage)
|
2013-01-24 21:35:11 +00:00
|
|
|
Tweener.addTween(oldPage,
|
2012-06-21 22:52:56 +00:00
|
|
|
{ opacity: 0,
|
2013-02-18 05:17:56 +00:00
|
|
|
time: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME,
|
2012-06-21 22:52:56 +00:00
|
|
|
transition: 'easeOutQuad',
|
|
|
|
onComplete: Lang.bind(this,
|
|
|
|
function() {
|
2013-02-16 17:59:54 +00:00
|
|
|
this._fadePageIn(oldPage);
|
2012-06-21 22:52:56 +00:00
|
|
|
})
|
|
|
|
});
|
2013-01-24 06:35:19 +00:00
|
|
|
else
|
2014-07-14 16:55:34 +00:00
|
|
|
this._fadePageIn();
|
2012-06-21 22:52:56 +00:00
|
|
|
},
|
2012-06-21 22:52:56 +00:00
|
|
|
|
2012-06-21 22:52:56 +00:00
|
|
|
_a11yFocusPage: function(page) {
|
|
|
|
this._showAppsButton.checked = page == this._appsPage;
|
|
|
|
page.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
|
2012-06-21 22:52:56 +00:00
|
|
|
},
|
|
|
|
|
2012-06-21 22:52:56 +00:00
|
|
|
_onShowAppsButtonToggled: function() {
|
2013-02-16 17:55:59 +00:00
|
|
|
this._showPage(this._showAppsButton.checked ?
|
|
|
|
this._appsPage : this._workspacesPage);
|
2012-06-21 22:52:56 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
_onStageKeyPress: function(actor, event) {
|
2012-11-12 17:41:14 +00:00
|
|
|
// Ignore events while anything but the overview has
|
|
|
|
// pushed a modal (system modals, looking glass, ...)
|
|
|
|
if (Main.modalCount > 1)
|
2013-11-29 18:17:34 +00:00
|
|
|
return Clutter.EVENT_PROPAGATE;
|
2012-11-12 17:41:14 +00:00
|
|
|
|
2012-06-21 22:52:56 +00:00
|
|
|
let modifiers = event.get_state();
|
|
|
|
let symbol = event.get_key_symbol();
|
|
|
|
|
|
|
|
if (symbol == Clutter.Escape) {
|
2012-08-24 16:24:49 +00:00
|
|
|
if (this._searchActive)
|
2012-06-21 22:52:56 +00:00
|
|
|
this.reset();
|
2012-08-15 10:20:24 +00:00
|
|
|
else if (this._showAppsButton.checked)
|
2013-02-16 17:50:25 +00:00
|
|
|
this._showAppsButton.checked = false;
|
2012-06-21 22:52:56 +00:00
|
|
|
else
|
|
|
|
Main.overview.hide();
|
2013-11-29 18:17:34 +00:00
|
|
|
return Clutter.EVENT_STOP;
|
2013-02-22 19:56:24 +00:00
|
|
|
} else if (this._shouldTriggerSearch(symbol)) {
|
2012-06-21 22:52:56 +00:00
|
|
|
this.startSearch(event);
|
2014-05-23 15:14:20 +00:00
|
|
|
} else if (!this._searchActive && !global.stage.key_focus) {
|
2014-02-19 00:44:58 +00:00
|
|
|
if (symbol == Clutter.Tab || symbol == Clutter.Down) {
|
|
|
|
this._activePage.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
|
2014-06-10 18:25:16 +00:00
|
|
|
return Clutter.EVENT_STOP;
|
2014-02-19 00:44:58 +00:00
|
|
|
} else if (symbol == Clutter.ISO_Left_Tab) {
|
|
|
|
this._activePage.navigate_focus(null, Gtk.DirectionType.TAB_BACKWARD, false);
|
2014-06-10 18:25:16 +00:00
|
|
|
return Clutter.EVENT_STOP;
|
2014-02-19 00:44:58 +00:00
|
|
|
}
|
2012-06-21 22:52:56 +00:00
|
|
|
}
|
2013-11-29 18:17:34 +00:00
|
|
|
return Clutter.EVENT_PROPAGATE;
|
2012-06-21 22:52:56 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
_searchCancelled: function() {
|
2012-06-21 22:52:56 +00:00
|
|
|
this._showPage(this._showAppsButton.checked ? this._appsPage
|
|
|
|
: this._workspacesPage);
|
2010-11-18 12:51:47 +00:00
|
|
|
|
2011-04-07 23:10:24 +00:00
|
|
|
// Leave the entry focused when it doesn't have any text;
|
|
|
|
// when replacing a selected search term, Clutter emits
|
|
|
|
// two 'text-changed' signals, one for deleting the previous
|
|
|
|
// text and one for the new one - the second one is handled
|
|
|
|
// incorrectly when we remove focus
|
|
|
|
// (https://bugzilla.gnome.org/show_bug.cgi?id=636341) */
|
|
|
|
if (this._text.text != '')
|
2012-02-27 14:17:33 +00:00
|
|
|
this.reset();
|
2011-02-16 18:20:03 +00:00
|
|
|
},
|
|
|
|
|
2012-02-27 14:17:33 +00:00
|
|
|
reset: function () {
|
2011-02-16 18:27:05 +00:00
|
|
|
global.stage.set_key_focus(null);
|
2011-02-16 18:20:03 +00:00
|
|
|
|
2012-02-27 14:17:33 +00:00
|
|
|
this._entry.text = '';
|
|
|
|
|
2011-02-16 18:20:03 +00:00
|
|
|
this._text.set_cursor_visible(true);
|
|
|
|
this._text.set_selection(0, 0);
|
|
|
|
},
|
|
|
|
|
2012-02-27 17:43:59 +00:00
|
|
|
_onStageKeyFocusChanged: function() {
|
2011-02-16 18:20:03 +00:00
|
|
|
let focus = global.stage.get_key_focus();
|
2012-03-10 04:50:17 +00:00
|
|
|
let appearFocused = (this._entry.contains(focus) ||
|
|
|
|
this._searchResults.actor.contains(focus));
|
2012-02-27 17:43:59 +00:00
|
|
|
|
2012-03-10 04:50:17 +00:00
|
|
|
this._text.set_cursor_visible(appearFocused);
|
|
|
|
|
|
|
|
if (appearFocused)
|
|
|
|
this._entry.add_style_pseudo_class('focus');
|
|
|
|
else
|
|
|
|
this._entry.remove_style_pseudo_class('focus');
|
2011-02-16 18:20:03 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
_onMapped: function() {
|
|
|
|
if (this._entry.mapped) {
|
|
|
|
// Enable 'find-as-you-type'
|
|
|
|
this._capturedEventId = global.stage.connect('captured-event',
|
|
|
|
Lang.bind(this, this._onCapturedEvent));
|
|
|
|
this._text.set_cursor_visible(true);
|
|
|
|
this._text.set_selection(0, 0);
|
|
|
|
} else {
|
|
|
|
// Disable 'find-as-you-type'
|
|
|
|
if (this._capturedEventId > 0)
|
|
|
|
global.stage.disconnect(this._capturedEventId);
|
|
|
|
this._capturedEventId = 0;
|
|
|
|
}
|
2010-11-18 12:51:47 +00:00
|
|
|
},
|
|
|
|
|
2013-02-22 19:56:24 +00:00
|
|
|
_shouldTriggerSearch: function(symbol) {
|
|
|
|
let unicode = Clutter.keysym_to_unicode(symbol);
|
|
|
|
if (unicode == 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (getTermsForSearchString(String.fromCharCode(unicode)).length > 0)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return symbol == Clutter.BackSpace && this._searchActive;
|
|
|
|
},
|
|
|
|
|
2011-02-16 18:27:05 +00:00
|
|
|
startSearch: function(event) {
|
|
|
|
global.stage.set_key_focus(this._text);
|
2014-07-09 10:06:40 +00:00
|
|
|
|
|
|
|
let synthEvent = event.copy();
|
|
|
|
synthEvent.set_source(this._text);
|
|
|
|
this._text.event(synthEvent, true);
|
2011-02-16 18:27:05 +00:00
|
|
|
},
|
|
|
|
|
2011-02-16 18:20:03 +00:00
|
|
|
// the entry does not show the hint
|
|
|
|
_isActivated: function() {
|
|
|
|
return this._text.text == this._entry.get_text();
|
|
|
|
},
|
|
|
|
|
2010-11-18 12:51:47 +00:00
|
|
|
_onTextChanged: function (se, prop) {
|
2013-02-09 02:05:15 +00:00
|
|
|
let terms = getTermsForSearchString(this._entry.get_text());
|
|
|
|
|
2012-08-24 16:24:49 +00:00
|
|
|
let searchPreviouslyActive = this._searchActive;
|
2013-02-09 02:05:15 +00:00
|
|
|
this._searchActive = (terms.length > 0);
|
2012-08-24 16:24:49 +00:00
|
|
|
|
|
|
|
let startSearch = this._searchActive && !searchPreviouslyActive;
|
|
|
|
if (startSearch)
|
2010-11-18 12:51:47 +00:00
|
|
|
this._searchResults.startingSearch();
|
2012-08-24 16:24:49 +00:00
|
|
|
|
|
|
|
if (this._searchActive) {
|
2013-03-03 18:56:12 +00:00
|
|
|
this._entry.set_secondary_icon(this._clearIcon);
|
2011-02-16 18:20:03 +00:00
|
|
|
|
2012-08-24 16:24:49 +00:00
|
|
|
if (this._iconClickedId == 0)
|
2011-02-16 18:20:03 +00:00
|
|
|
this._iconClickedId = this._entry.connect('secondary-icon-clicked',
|
2012-08-24 16:24:49 +00:00
|
|
|
Lang.bind(this, this.reset));
|
|
|
|
|
2014-04-10 17:26:52 +00:00
|
|
|
if (this._searchTimeoutId == 0) {
|
2012-08-24 16:24:49 +00:00
|
|
|
this._searchTimeoutId = Mainloop.timeout_add(150,
|
|
|
|
Lang.bind(this, this._doSearch));
|
2014-04-10 17:26:52 +00:00
|
|
|
GLib.Source.set_name_by_id(this._searchTimeoutId, '[gnome-shell] this._doSearch');
|
|
|
|
}
|
2010-11-18 12:51:47 +00:00
|
|
|
} else {
|
2012-08-24 16:24:49 +00:00
|
|
|
if (this._iconClickedId > 0) {
|
2011-02-16 18:20:03 +00:00
|
|
|
this._entry.disconnect(this._iconClickedId);
|
2012-08-24 16:24:49 +00:00
|
|
|
this._iconClickedId = 0;
|
|
|
|
}
|
2011-02-16 18:20:03 +00:00
|
|
|
|
2010-11-18 12:51:47 +00:00
|
|
|
if (this._searchTimeoutId > 0) {
|
|
|
|
Mainloop.source_remove(this._searchTimeoutId);
|
|
|
|
this._searchTimeoutId = 0;
|
|
|
|
}
|
2012-08-24 16:24:49 +00:00
|
|
|
|
2013-03-03 18:56:12 +00:00
|
|
|
this._entry.set_secondary_icon(null);
|
2012-08-24 16:24:49 +00:00
|
|
|
this._searchCancelled();
|
2010-11-18 12:51:47 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2010-11-03 17:30:08 +00:00
|
|
|
_onKeyPress: function(entry, event) {
|
2010-11-18 12:51:47 +00:00
|
|
|
let symbol = event.get_key_symbol();
|
2011-11-14 03:13:26 +00:00
|
|
|
if (symbol == Clutter.Escape) {
|
2011-02-16 18:27:05 +00:00
|
|
|
if (this._isActivated()) {
|
2012-02-27 14:17:33 +00:00
|
|
|
this.reset();
|
2013-11-29 18:17:34 +00:00
|
|
|
return Clutter.EVENT_STOP;
|
2011-02-16 18:27:05 +00:00
|
|
|
}
|
2012-08-24 16:24:49 +00:00
|
|
|
} else if (this._searchActive) {
|
2012-03-10 02:40:46 +00:00
|
|
|
let arrowNext, nextDirection;
|
|
|
|
if (entry.get_text_direction() == Clutter.TextDirection.RTL) {
|
|
|
|
arrowNext = Clutter.Left;
|
|
|
|
nextDirection = Gtk.DirectionType.LEFT;
|
|
|
|
} else {
|
|
|
|
arrowNext = Clutter.Right;
|
|
|
|
nextDirection = Gtk.DirectionType.RIGHT;
|
|
|
|
}
|
|
|
|
|
2011-11-12 04:40:56 +00:00
|
|
|
if (symbol == Clutter.Tab) {
|
2011-11-14 03:13:26 +00:00
|
|
|
this._searchResults.navigateFocus(Gtk.DirectionType.TAB_FORWARD);
|
2013-11-29 18:17:34 +00:00
|
|
|
return Clutter.EVENT_STOP;
|
2011-11-12 04:40:56 +00:00
|
|
|
} else if (symbol == Clutter.ISO_Left_Tab) {
|
|
|
|
this._focusTrap.can_focus = false;
|
2011-11-14 03:13:26 +00:00
|
|
|
this._searchResults.navigateFocus(Gtk.DirectionType.TAB_BACKWARD);
|
2011-11-12 04:40:56 +00:00
|
|
|
this._focusTrap.can_focus = true;
|
2013-11-29 18:17:34 +00:00
|
|
|
return Clutter.EVENT_STOP;
|
2012-03-10 02:40:46 +00:00
|
|
|
} else if (symbol == Clutter.Down) {
|
|
|
|
this._searchResults.navigateFocus(Gtk.DirectionType.DOWN);
|
2013-11-29 18:17:34 +00:00
|
|
|
return Clutter.EVENT_STOP;
|
2012-03-10 02:40:46 +00:00
|
|
|
} else if (symbol == arrowNext && this._text.position == -1) {
|
|
|
|
this._searchResults.navigateFocus(nextDirection);
|
2013-11-29 18:17:34 +00:00
|
|
|
return Clutter.EVENT_STOP;
|
2013-01-27 19:00:59 +00:00
|
|
|
} 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();
|
2013-11-29 18:17:34 +00:00
|
|
|
return Clutter.EVENT_STOP;
|
2011-11-12 04:40:56 +00:00
|
|
|
}
|
2010-11-18 12:51:47 +00:00
|
|
|
}
|
2013-11-29 18:17:34 +00:00
|
|
|
return Clutter.EVENT_PROPAGATE;
|
2010-11-18 12:51:47 +00:00
|
|
|
},
|
|
|
|
|
2011-02-16 18:20:03 +00:00
|
|
|
_onCapturedEvent: function(actor, event) {
|
2011-02-16 18:27:05 +00:00
|
|
|
if (event.type() == Clutter.EventType.BUTTON_PRESS) {
|
|
|
|
let source = event.get_source();
|
2011-10-09 20:24:59 +00:00
|
|
|
if (source != this._text && this._text.text == '' &&
|
|
|
|
!Main.layoutManager.keyboardBox.contains(source)) {
|
2011-02-16 18:20:03 +00:00
|
|
|
// the user clicked outside after activating the entry, but
|
2011-10-09 20:24:59 +00:00
|
|
|
// with no search term entered and no keyboard button pressed
|
|
|
|
// - cancel the search
|
2012-02-27 14:17:33 +00:00
|
|
|
this.reset();
|
2011-02-16 18:27:05 +00:00
|
|
|
}
|
2011-02-16 18:20:03 +00:00
|
|
|
}
|
2011-02-16 18:44:03 +00:00
|
|
|
|
2013-11-29 18:17:34 +00:00
|
|
|
return Clutter.EVENT_PROPAGATE;
|
2011-02-16 18:20:03 +00:00
|
|
|
},
|
|
|
|
|
2010-11-18 12:51:47 +00:00
|
|
|
_doSearch: function () {
|
|
|
|
this._searchTimeoutId = 0;
|
|
|
|
|
2013-02-09 02:05:15 +00:00
|
|
|
let terms = getTermsForSearchString(this._entry.get_text());
|
|
|
|
|
2013-10-30 16:38:46 +00:00
|
|
|
this._searchResults.setTerms(terms);
|
2012-06-21 22:52:56 +00:00
|
|
|
this._showPage(this._searchPage);
|
2013-11-29 00:45:39 +00:00
|
|
|
|
|
|
|
return GLib.SOURCE_REMOVE;
|
2010-11-12 17:45:29 +00:00
|
|
|
},
|
|
|
|
|
2013-02-13 21:13:14 +00:00
|
|
|
getActivePage: function() {
|
|
|
|
if (this._activePage == this._workspacesPage)
|
|
|
|
return ViewPage.WINDOWS;
|
|
|
|
else if (this._activePage == this._appsPage)
|
|
|
|
return ViewPage.APPS;
|
|
|
|
else
|
|
|
|
return ViewPage.SEARCH;
|
2013-02-18 04:45:24 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
fadeIn: function() {
|
|
|
|
let actor = this._activePage;
|
|
|
|
Tweener.addTween(actor, { opacity: 255,
|
|
|
|
time: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME / 2,
|
|
|
|
transition: 'easeInQuad'
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
fadeHalf: function() {
|
|
|
|
let actor = this._activePage;
|
|
|
|
Tweener.addTween(actor, { opacity: 128,
|
|
|
|
time: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME / 2,
|
|
|
|
transition: 'easeOutQuad'
|
|
|
|
});
|
2010-11-12 17:45:29 +00:00
|
|
|
}
|
2011-11-20 17:56:27 +00:00
|
|
|
});
|
2010-11-12 17:45:29 +00:00
|
|
|
Signals.addSignalMethods(ViewSelector.prototype);
|