@@ -44,6 +44,33 @@ AbstractStage {
4444 }
4545 }
4646
47+ onAltTabPressedChanged: {
48+ if (!spreadEnabled || !altTabEnabled) {
49+ return;
50+ }
51+ if (altTabPressed) {
52+ spreadView.snapToSpread();
53+ priv.highlightIndex = Math.min(spreadRepeater.count - 1, 1);
54+ } else {
55+ spreadView.snapTo(priv.highlightIndex)
56+ }
57+ }
58+
59+ FocusScope {
60+ focus: root.altTabPressed
61+
62+ Keys.onPressed: {
63+ switch (event.key) {
64+ case Qt.Key_Tab:
65+ priv.highlightIndex = (priv.highlightIndex + 1) % spreadRepeater.count
66+ break;
67+ case Qt.Key_Backtab:
68+ priv.highlightIndex = (priv.highlightIndex + spreadRepeater.count - 1) % spreadRepeater.count
69+ break;
70+ }
71+ }
72+ }
73+
4774 // Functions to be called from outside
4875 function updateFocusedAppOrientation() {
4976 if (spreadRepeater.count > 0) {
@@ -186,6 +213,7 @@ AbstractStage {
186213
187214 property real oldInverseProgress: 0
188215 property bool animateX: false
216+ property int highlightIndex: 0
189217
190218 onFocusedAppDelegateChanged: {
191219 if (focusedAppDelegate) {
@@ -220,6 +248,10 @@ AbstractStage {
220248 spreadView.phase = 0;
221249 spreadView.contentX = -spreadView.shift;
222250 }
251+
252+ onHighlightIndexChanged: {
253+ spreadView.contentX = highlightIndex * spreadView.contentWidth / (spreadRepeater.count + 2)
254+ }
223255 }
224256 Timer {
225257 id: fullyShowingFocusedAppUpdateTimer
@@ -287,6 +319,11 @@ AbstractStage {
287319 }
288320 }
289321
322+ Behavior on contentX {
323+ enabled: root.altTabPressed
324+ UbuntuNumberAnimation {}
325+ }
326+
290327 onShiftedContentXChanged: {
291328 if (root.beingResized) {
292329 // Flickabe.contentX wiggles during resizes. Don't react to it.
@@ -325,12 +362,17 @@ AbstractStage {
325362 } else if (shiftedContentX < positionMarker3 * width) {
326363 snapTo(1);
327364 } else if (phase < 2){
328− // Add 1 pixel to make sure we definitely hit positionMarker4 even with rounding errors of the animation.
329− snapAnimation.targetContentX = width * positionMarker4 + 1 - shift;
330− snapAnimation.start();
365+ snapToSpread();
331366 root.opened();
332367 }
333368 }
369+
370+ function snapToSpread() {
371+ // Add 1 pixel to make sure we definitely hit positionMarker4 even with rounding errors of the animation.
372+ snapAnimation.targetContentX = (root.width * spreadView.positionMarker4) + 1 - spreadView.shift;
373+ snapAnimation.start();
374+ }
375+
334376 function snapTo(index) {
335377 if (!root.altTabEnabled) {
336378 // Reset to start instead
@@ -433,6 +475,7 @@ AbstractStage {
433475 maximizedAppTopMargin: root.maximizedAppTopMargin
434476 dropShadow: spreadView.active || priv.focusedAppDelegateIsDislocated
435477 focusFirstApp: root.focusFirstApp
478+ highlightShown: root.altTabPressed && index === priv.highlightIndex
436479
437480 readonly property bool isDash: model.appId == "unity8-dash"
438481
@@ -665,9 +708,7 @@ AbstractStage {
665708 edge: Qt.RightEdge
666709
667710 onPassed: {
668− // Add 1 pixel to make sure we definitely hit positionMarker4 even with rounding errors of the animation.
669− snapAnimation.targetContentX = (root.width * spreadView.positionMarker4) + 1 - spreadView.shift;
670− snapAnimation.start();
711+ spreadView.snapToSpread();
671712 }
672713 material: Component {
673714 Item {