viewSelector: add Applications pane and search entry to Ctrl-Alt-Tab

Add Ctrl-Alt-Tab support to ViewTab, and fix the Applications pane to
scroll to track the keyboard focus.

The Windows pane can be switched to, but navigation within the pane is
not yet implemented.

https://bugzilla.gnome.org/show_bug.cgi?id=618887
This commit is contained in:
Dan Winship 2011-02-23 14:21:47 -05:00
parent 7aa326a836
commit 0cccf1d4cc
5 changed files with 76 additions and 15 deletions

View File

@ -576,6 +576,10 @@ StTooltip StLabel {
background-position: 10px 10px;
}
.app-filter:focus {
outline: 1px solid #aaa;
}
.dash-item-container > .app-well-app {
padding: 4px 8px;
}

View File

@ -23,6 +23,7 @@ const Workspace = imports.ui.workspace;
const Params = imports.misc.params;
const MENU_POPUP_TIMEOUT = 600;
const SCROLL_TIME = 0.1;
function AlphabeticalView() {
this._init();
@ -67,6 +68,7 @@ AlphabeticalView.prototype = {
let appIcon = new AppWellIcon(this._appSystem.get_app(appInfo.get_id()));
this._grid.addItem(appIcon.actor);
appIcon.actor.connect('key-focus-in', Lang.bind(this, this._ensureIconVisible));
appIcon._appInfo = appInfo;
if (this._filterApp && !this._filterApp(appInfo))
@ -75,6 +77,28 @@ AlphabeticalView.prototype = {
this._apps.push(appIcon);
},
_ensureIconVisible: function(icon) {
let adjustment = this.actor.vscroll.adjustment;
let [value, lower, upper, stepIncrement, pageIncrement, pageSize] = adjustment.get_values();
let offset = 0;
let vfade = this.actor.get_effect("vfade");
if (vfade)
offset = vfade.fade_offset;
if (icon.y < value + offset)
value = Math.max(0, icon.y - offset);
else if (icon.y + icon.height > value + pageSize - offset)
value = Math.min(upper, icon.y + icon.height + offset - pageSize);
else
return;
Tweener.addTween(adjustment,
{ value: value,
time: SCROLL_TIME,
transition: 'easeOutQuad' });
},
setFilter: function(filter) {
this._filterApp = filter;
for (let i = 0; i < this._apps.length; i++)
@ -128,6 +152,12 @@ ViewByCategories.prototype = {
}));
this._sections = [];
// We need a dummy actor to catch the keyboard focus if the
// user Ctrl-Alt-Tabs here before the deferred work creates
// our real contents
this._focusDummy = new St.Bin({ can_focus: true });
this.actor.add(this._focusDummy);
},
_scrollFilter: function(actor, event) {
@ -166,7 +196,8 @@ ViewByCategories.prototype = {
_addFilter: function(name, num) {
let button = new St.Button({ label: GLib.markup_escape_text (name, -1),
style_class: 'app-filter',
x_align: St.Align.START });
x_align: St.Align.START,
can_focus: true });
this._filters.add(button, { expand: true, x_fill: true, y_fill: false });
button.connect('clicked', Lang.bind(this, function() {
this._selectCategory(num);
@ -201,6 +232,14 @@ ViewByCategories.prototype = {
this._addFilter(sections[i], i);
this._selectCategory(-1);
if (this._focusDummy) {
let focused = this._focusDummy.has_key_focus();
this._focusDummy.destroy();
this._focusDummy = null;
if (focused)
this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
}
}
};

View File

@ -180,10 +180,10 @@ Overview.prototype = {
this._group.add_actor(this.viewSelector.actor);
this._workspacesDisplay = new WorkspacesView.WorkspacesDisplay();
this.viewSelector.addViewTab(_("Windows"), this._workspacesDisplay.actor);
this.viewSelector.addViewTab(_("Windows"), this._workspacesDisplay.actor, 'text-x-generic');
let appView = new AppDisplay.AllAppDisplay();
this.viewSelector.addViewTab(_("Applications"), appView.actor);
this.viewSelector.addViewTab(_("Applications"), appView.actor, 'system-run');
// Default search providers
this.viewSelector.addSearchProvider(new AppDisplay.AppSearchProvider());

View File

@ -1,6 +1,7 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Clutter = imports.gi.Clutter;
const Gtk = imports.gi.Gtk;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
const Signals = imports.signals;
@ -15,12 +16,12 @@ const Search = imports.ui.search;
const SearchDisplay = imports.ui.searchDisplay;
const Tweener = imports.ui.tweener;
function BaseTab(titleActor, pageActor) {
this._init(titleActor, pageActor);
function BaseTab(titleActor, pageActor, name, a11yIcon) {
this._init(titleActor, pageActor, name, a11yIcon);
}
BaseTab.prototype = {
_init: function(titleActor, pageActor) {
_init: function(titleActor, pageActor, name, a11yIcon) {
this.title = titleActor;
this.page = new St.Bin({ child: pageActor,
x_align: St.Align.START,
@ -29,6 +30,14 @@ BaseTab.prototype = {
y_fill: true,
style_class: 'view-tab-page' });
if (this.title.can_focus) {
Main.ctrlAltTabManager.addGroup(this.title, name, a11yIcon);
} else {
Main.ctrlAltTabManager.addGroup(this.page, name, a11yIcon,
{ proxy: this.title,
focusCallback: Lang.bind(this, this._a11yFocus) });
}
this.visible = false;
},
@ -56,6 +65,11 @@ BaseTab.prototype = {
});
},
_a11yFocus: function() {
this._activate();
this.page.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
},
_activate: function() {
this.emit('activated');
}
@ -63,19 +77,19 @@ BaseTab.prototype = {
Signals.addSignalMethods(BaseTab.prototype);
function ViewTab(label, pageActor) {
this._init(label, pageActor);
function ViewTab(label, pageActor, a11yIcon) {
this._init(label, pageActor, a11yIcon);
}
ViewTab.prototype = {
__proto__: BaseTab.prototype,
_init: function(label, pageActor) {
_init: function(label, pageActor, a11yIcon) {
let titleActor = new St.Button({ label: label,
style_class: 'view-tab-title' });
titleActor.connect('clicked', Lang.bind(this, this._activate));
BaseTab.prototype._init.call(this, titleActor, pageActor);
BaseTab.prototype._init.call(this, titleActor, pageActor, label, a11yIcon);
}
};
@ -101,7 +115,8 @@ SearchTab.prototype = {
active; it should not exceed ~30
characters. */
hint_text: _("Type to search..."),
track_hover: true });
track_hover: true,
can_focus: true });
this._text = this._entry.clutter_text;
this._text.connect('key-press-event', Lang.bind(this, this._onKeyPress));
@ -118,7 +133,9 @@ SearchTab.prototype = {
this._searchResults = new SearchDisplay.SearchResults(this._searchSystem, this._openSearchSystem);
BaseTab.prototype._init.call(this,
this._entry,
this._searchResults.actor);
this._searchResults.actor,
_("Search"),
'edit-find');
this._text.connect('text-changed', Lang.bind(this, this._onTextChanged));
this._text.connect('activate', Lang.bind(this, function (se) {
@ -366,8 +383,8 @@ ViewSelector.prototype = {
}));
},
addViewTab: function(title, pageActor) {
let viewTab = new ViewTab(title, pageActor);
addViewTab: function(title, pageActor, a11yIcon) {
let viewTab = new ViewTab(title, pageActor, a11yIcon);
this._tabs.push(viewTab);
this._tabBox.add(viewTab.title);
this._addTab(viewTab);

View File

@ -176,7 +176,8 @@ st_scroll_view_set_vfade (StScrollView *self,
if (priv->vfade_effect == NULL)
priv->vfade_effect = g_object_new (ST_TYPE_SCROLL_VIEW_FADE, NULL);
clutter_actor_add_effect (CLUTTER_ACTOR (self), CLUTTER_EFFECT (priv->vfade_effect));
clutter_actor_add_effect_with_name (CLUTTER_ACTOR (self), "vfade",
CLUTTER_EFFECT (priv->vfade_effect));
}
else
{