@@ -20,6 +20,7 @@ import Unity.Launcher 0.1
2020import Utils 0.1
2121import "../Components"
2222import Qt.labs.settings 1.0
23+import GSettings 1.0
2324
2425FocusScope {
2526 id: root
@@ -47,8 +48,10 @@ FocusScope {
4748 if (event.text.trim() !== "") {
4849 focusInput();
4950 searchField.text = event.text;
50− event.accepted = true;
5151 }
52+ // Catch all presses here in case the navigation lets something through
53+ // We never want to end up in the launcher with focus
54+ event.accepted = true;
5255 }
5356
5457 Settings {
@@ -88,6 +91,9 @@ FocusScope {
8891 anchors { left: parent.left; top: parent.top; right: parent.right; margins: units.gu(1) }
8992 placeholderText: i18n.tr("Search…")
9093 focus: true
94+
95+ KeyNavigation.down: sections
96+
9197 onAccepted: {
9298 if (searchField.displayText != "" && listLoader.item && listLoader.item.currentItem) {
9399 root.applicationSelected(listLoader.item.getFirstAppId());
@@ -104,7 +110,14 @@ FocusScope {
104110
105111 Sections {
106112 id: sections
113+ objectName: "drawerSections"
107114 width: parent.width
115+
116+ KeyNavigation.up: searchField
117+ KeyNavigation.down: headerFocusScope
118+ KeyNavigation.backtab: searchField
119+ KeyNavigation.tab: headerFocusScope
120+
108121 actions: [
109122 Action {
110123 text: i18n.ctr("Apps sorted alphabetically", "A-Z")
@@ -124,9 +137,45 @@ FocusScope {
124137 }
125138 }
126139
140+ FocusScope {
141+ id: headerFocusScope
142+ objectName: "headerFocusScope"
143+ KeyNavigation.up: sections
144+ KeyNavigation.down: listLoader.item
145+ KeyNavigation.backtab: sections
146+ KeyNavigation.tab: listLoader.item
147+ activeFocusOnTab: true
148+
149+ GSettings {
150+ id: settings
151+ schema.id: "com.canonical.Unity8"
152+ }
153+
154+ Keys.onPressed: {
155+ switch (event.key) {
156+ case Qt.Key_Return:
157+ case Qt.Key_Enter:
158+ case Qt.Key_Space:
159+ trigger();
160+ event.accepted = true;
161+ }
162+ }
163+
164+ function trigger() {
165+ Qt.openUrlExternally(settings.appstoreUri)
166+ }
167+ }
168+
127169 Loader {
128170 id: listLoader
129− anchors { left: parent.left; top: sectionsContainer.bottom; right: parent.right; bottom: parent.bottom; leftMargin: units.gu(1); rightMargin: units.gu(1) }
171+ objectName: "drawerListLoader"
172+ anchors { left: parent.left; top: sectionsContainer.bottom; right: parent.right; bottom: parent.bottom }
173+
174+ KeyNavigation.up: headerFocusScope
175+ KeyNavigation.down: searchField
176+ KeyNavigation.backtab: headerFocusScope
177+ KeyNavigation.tab: searchField
178+
130179 sourceComponent: {
131180 switch (sections.selectedIndex) {
132181 case 0: return aToZComponent;
@@ -176,10 +225,13 @@ FocusScope {
176225 Component {
177226 id: mostUsedComponent
178227 DrawerListView {
228+ id: mostUsedListView
179229
180230 header: MoreAppsHeader {
181231 width: parent.width
182232 height: units.gu(6)
233+ highlighted: headerFocusScope.activeFocus
234+ onClicked: headerFocusScope.trigger();
183235 }
184236
185237 model: AppDrawerProxyModel {
@@ -189,7 +241,8 @@ FocusScope {
189241 }
190242
191243 delegate: UbuntuShape {
192− width: parent.width
244+ width: parent.width - units.gu(2)
245+ anchors.horizontalCenter: parent.horizontalCenter
193246 color: "#20ffffff"
194247 aspect: UbuntuShape.Flat
195248 // NOTE: Cannot use gridView.rows here as it would evaluate to 0 at first and only update later,
@@ -205,6 +258,9 @@ FocusScope {
205258 bottomMargin: units.gu(1)
206259 clip: true
207260
261+ interactive: true
262+ focus: index == mostUsedListView.currentIndex
263+
208264 model: sortProxyModel
209265
210266 delegateWidth: units.gu(8)
@@ -218,10 +274,13 @@ FocusScope {
218274 Component {
219275 id: aToZComponent
220276 DrawerListView {
277+ id: aToZListView
221278
222279 header: MoreAppsHeader {
223280 width: parent.width
224281 height: units.gu(6)
282+ highlighted: headerFocusScope.activeFocus
283+ onClicked: headerFocusScope.trigger();
225284 }
226285
227286 model: AppDrawerProxyModel {
@@ -231,7 +290,8 @@ FocusScope {
231290 }
232291
233292 delegate: UbuntuShape {
234− width: parent.width
293+ width: parent.width - units.gu(2)
294+ anchors.horizontalCenter: parent.horizontalCenter
235295 color: "#20ffffff"
236296 aspect: UbuntuShape.Flat
237297
@@ -253,7 +313,8 @@ FocusScope {
253313 anchors { left: parent.left; top: categoryNameLabel.bottom; right: parent.right; topMargin: units.gu(1) }
254314 height: rows * delegateHeight
255315
256− interactive: false
316+ interactive: true
317+ focus: index == aToZListView.currentIndex
257318
258319 model: AppDrawerProxyModel {
259320 id: categoryModel
@@ -272,10 +333,13 @@ FocusScope {
272333 Component {
273334 id: drawerDelegateComponent
274335 AbstractButton {
336+ id: drawerDelegate
275337 width: GridView.view.cellWidth
276338 height: units.gu(10)
277339 objectName: "drawerItem_" + model.appId
278340
341+ readonly property bool focused: index === GridView.view.currentIndex && GridView.view.activeFocus
342+
279343 onClicked: root.applicationSelected(model.appId)
280344
281345 Column {
@@ -299,6 +363,15 @@ FocusScope {
299363 source: model.icon
300364 }
301365 sourceFillMode: UbuntuShape.PreserveAspectCrop
366+
367+ StyledItem {
368+ styleName: "FocusShape"
369+ anchors.fill: parent
370+ StyleHints {
371+ visible: drawerDelegate.focused
372+ radius: units.gu(2.55)
373+ }
374+ }
302375 }
303376
304377 Label {