@@ -47,6 +47,7 @@ FocusScope {
4747 property bool oskEnabled: false
4848 property rect inputMethodRect
4949 property real rightEdgePushProgress: 0
50+ property PanelState panelState
5051
5152 // Configuration
5253 property string mode: "staged"
@@ -224,6 +225,21 @@ FocusScope {
224225 active: priv.focusedAppDelegate !== null
225226 }
226227
228+ GlobalShortcut {
229+ id: showWorkspaceSwitcherShortcutLeft
230+ shortcut: Qt.AltModifier|Qt.ControlModifier|Qt.Key_Left
231+ onTriggered: {
232+ workspaceSwitcher.left()
233+ }
234+ }
235+ GlobalShortcut {
236+ id: showWorkspaceSwitcherShortcutRight
237+ shortcut: Qt.AltModifier|Qt.ControlModifier|Qt.Key_Right
238+ onTriggered: {
239+ workspaceSwitcher.right()
240+ }
241+ }
242+
227243 QtObject {
228244 id: priv
229245 objectName: "DesktopStagePrivate"
@@ -349,23 +365,23 @@ FocusScope {
349365 readonly property real virtualKeyboardHeight: root.inputMethodRect.height
350366 }
351367
352− Component.onCompleted: priv.updateMainAndSideStageIndexes();
368+ Component.onCompleted: priv.updateMainAndSideStageIndexes()
353369
354370 Connections {
355− target: PanelState
371+ target: panelState
356372 onCloseClicked: { if (priv.focusedAppDelegate) { priv.focusedAppDelegate.close(); } }
357373 onMinimizeClicked: { if (priv.focusedAppDelegate) { priv.focusedAppDelegate.requestMinimize(); } }
358374 onRestoreClicked: { if (priv.focusedAppDelegate) { priv.focusedAppDelegate.requestRestore(); } }
359375 }
360376
361377 Binding {
362− target: PanelState
378+ target: panelState
363379 property: "decorationsVisible"
364380 value: priv.focusedAppDelegate !== null && priv.focusedAppDelegate.maximized // FIXME for Locally integrated menus
365381 }
366382
367383 Binding {
368− target: PanelState
384+ target: panelState
369385 property: "title"
370386 value: {
371387 if (priv.focusedAppDelegate !== null) {
@@ -380,7 +396,7 @@ FocusScope {
380396 }
381397
382398 Binding {
383− target: PanelState
399+ target: panelState
384400 property: "focusedPersistentSurfaceId"
385401 value: {
386402 if (priv.focusedAppDelegate !== null) {
@@ -394,21 +410,21 @@ FocusScope {
394410 }
395411
396412 Binding {
397− target: PanelState
413+ target: panelState
398414 property: "dropShadow"
399415 value: priv.focusedAppDelegate && !priv.focusedAppDelegate.maximized && priv.foregroundMaximizedAppDelegate !== null && mode == "windowed"
400416 }
401417
402418 Binding {
403− target: PanelState
419+ target: panelState
404420 property: "closeButtonShown"
405421 value: priv.focusedAppDelegate && priv.focusedAppDelegate.maximized && !priv.focusedAppDelegate.isDash
406422 }
407423
408424 Component.onDestruction: {
409− PanelState.title = "";
410− PanelState.decorationsVisible = false;
411− PanelState.dropShadow = false;
425+ panelState.title = "";
426+ panelState.decorationsVisible = false;
427+ panelState.dropShadow = false;
412428 }
413429
414430 Instantiator {
@@ -454,6 +470,7 @@ FocusScope {
454470 PropertyChanges { target: cancelSpreadMouseArea; enabled: true }
455471 PropertyChanges { target: blurLayer; visible: true; blurRadius: 32; brightness: .65; opacity: 1 }
456472 PropertyChanges { target: wallpaper; visible: false }
473+ PropertyChanges { target: screensAndWorkspaces; opacity: 1 }
457474 },
458475 State {
459476 name: "stagedRightEdge"; when: root.spreadEnabled && (rightEdgeDragArea.dragging || rightEdgePushProgress > 0) && root.mode == "staged"
@@ -502,10 +519,13 @@ FocusScope {
502519 from: "stagedRightEdge,sideStagedRightEdge,windowedRightEdge"; to: "spread"
503520 PropertyAction { target: spreadItem; property: "highlightedIndex"; value: -1 }
504521 PropertyAnimation { target: blurLayer; properties: "brightness,blurRadius"; duration: priv.animationDuration }
522+ UbuntuNumberAnimation { target: screensAndWorkspaces; property: "opacity"; duration: priv.animationDuration }
505523 },
506524 Transition {
507525 to: "spread"
508526 PropertyAction { target: spreadItem; property: "highlightedIndex"; value: appRepeater.count > 1 ? 1 : 0 }
527+ PropertyAction { target: floatingFlickable; property: "contentX"; value: 0 }
528+ UbuntuNumberAnimation { target: screensAndWorkspaces; property: "opacity"; duration: priv.animationDuration }
509529 },
510530 Transition {
511531 from: "spread"
@@ -563,10 +583,21 @@ FocusScope {
563583 visible: false
564584 }
565585
586+ ScreensAndWorkspaces {
587+ id: screensAndWorkspaces
588+ anchors { left: parent.left; top: parent.top; right: parent.right; leftMargin: root.leftMargin }
589+ height: Math.max(units.gu(30), parent.height * .3)
590+ background: root.background
591+ opacity: 0
592+ visible: opacity > 0
593+
594+ onCloseSpread: priv.goneToSpread = false;
595+ }
596+
566597 Spread {
567598 id: spreadItem
568599 objectName: "spreadItem"
569− anchors.fill: appContainer
600+ anchors { left: parent.left; bottom: parent.bottom; right: parent.right; top: screensAndWorkspaces.bottom }
570601 leftMargin: root.leftMargin
571602 model: root.topLevelSurfaceList
572603 spreadFlickable: floatingFlickable
@@ -575,6 +606,83 @@ FocusScope {
575606 onLeaveSpread: {
576607 priv.goneToSpread = false;
577608 }
609+
610+ FloatingFlickable {
611+ id: floatingFlickable
612+ objectName: "spreadFlickable"
613+ anchors.fill: parent
614+ enabled: false
615+ contentWidth: spreadItem.spreadTotalWidth
616+
617+ function snap(toIndex) {
618+ var delegate = appRepeater.itemAt(toIndex)
619+ var targetContentX = floatingFlickable.contentWidth / spreadItem.totalItemCount * toIndex;
620+ if (targetContentX - floatingFlickable.contentX > spreadItem.rightStackXPos - (spreadItem.spreadItemWidth / 2)) {
621+ var offset = (spreadItem.rightStackXPos - (spreadItem.spreadItemWidth / 2)) - (targetContentX - floatingFlickable.contentX)
622+ snapAnimation.to = floatingFlickable.contentX - offset;
623+ snapAnimation.start();
624+ } else if (targetContentX - floatingFlickable.contentX < spreadItem.leftStackXPos + units.gu(1)) {
625+ var offset = (spreadItem.leftStackXPos + units.gu(1)) - (targetContentX - floatingFlickable.contentX);
626+ snapAnimation.to = floatingFlickable.contentX - offset;
627+ snapAnimation.start();
628+ }
629+ }
630+ UbuntuNumberAnimation {id: snapAnimation; target: floatingFlickable; property: "contentX"}
631+ }
632+
633+ MouseArea {
634+ id: hoverMouseArea
635+ objectName: "hoverMouseArea"
636+ anchors.fill: parent
637+ propagateComposedEvents: true
638+ hoverEnabled: true
639+ enabled: false
640+ visible: enabled
641+
642+ property int scrollAreaWidth: width / 3
643+ property bool progressiveScrollingEnabled: false
644+
645+ onPressed: mouse.accepted = false
646+
647+ onMouseXChanged: {
648+ mouse.accepted = false
649+
650+ if (hoverMouseArea.pressed) {
651+ return;
652+ }
653+
654+ // Find the hovered item and mark it active
655+ for (var i = appRepeater.count - 1; i >= 0; i--) {
656+ var appDelegate = appRepeater.itemAt(i);
657+ var mapped = mapToItem(appDelegate, hoverMouseArea.mouseX, hoverMouseArea.mouseY)
658+ var itemUnder = appDelegate.childAt(mapped.x, mapped.y);
659+ if (itemUnder && (itemUnder.objectName === "dragArea" || itemUnder.objectName === "windowInfoItem" || itemUnder.objectName == "closeMouseArea")) {
660+ spreadItem.highlightedIndex = i;
661+ break;
662+ }
663+ }
664+
665+ if (floatingFlickable.contentWidth > floatingFlickable.width) {
666+ var margins = floatingFlickable.width * 0.05;
667+
668+ if (!progressiveScrollingEnabled && mouseX < floatingFlickable.width - scrollAreaWidth) {
669+ progressiveScrollingEnabled = true
670+ }
671+
672+ // do we need to scroll?
673+ if (mouseX < scrollAreaWidth + margins) {
674+ var progress = Math.min(1, (scrollAreaWidth + margins - mouseX) / (scrollAreaWidth - margins));
675+ var contentX = (1 - progress) * (floatingFlickable.contentWidth - floatingFlickable.width)
676+ floatingFlickable.contentX = Math.max(0, Math.min(floatingFlickable.contentX, contentX))
677+ }
678+ if (mouseX > floatingFlickable.width - scrollAreaWidth && progressiveScrollingEnabled) {
679+ var progress = Math.min(1, (mouseX - (floatingFlickable.width - scrollAreaWidth)) / (scrollAreaWidth - margins))
680+ var contentX = progress * (floatingFlickable.contentWidth - floatingFlickable.width)
681+ floatingFlickable.contentX = Math.min(floatingFlickable.contentWidth - floatingFlickable.width, Math.max(floatingFlickable.contentX, contentX))
682+ }
683+ }
684+ }
685+ }
578686 }
579687
580688 Connections {
@@ -669,10 +777,28 @@ FocusScope {
669777 }
670778 }
671779
780+ MirSurfaceItem {
781+ id: fakeDragItem
782+ property real previewScale: .5
783+ height: (screensAndWorkspaces.height - units.gu(8)) / 2
784+ // w : h = iw : ih
785+ width: implicitWidth * height / implicitHeight
786+ surfaceWidth: -1
787+ surfaceHeight: -1
788+ opacity: surface != null ? 1 : 0
789+ Behavior on opacity { UbuntuNumberAnimation {} }
790+ visible: opacity > 0
791+
792+ Drag.active: surface != null
793+ Drag.keys: ["application"]
794+
795+ z: 1000
796+ }
797+
672798 Item {
673799 id: boundariesForWindowPlacement
674800 anchors.fill: parent
675− anchors.topMargin: PanelState.panelHeight
801+ anchors.topMargin: panelState.panelHeight
676802 visible: false
677803 }
678804
@@ -704,6 +830,9 @@ FocusScope {
704830 }
705831 z: normalZ
706832
833+ opacity: fakeDragItem.surface == model.window.surface && fakeDragItem.Drag.active ? 0 : 1
834+ Behavior on opacity { UbuntuNumberAnimation {} }
835+
707836 // Normally we want x/y where the surface thinks it is. Width/height of our delegate will
708837 // match what the actual surface size is.
709838 // Don't write to those, they will be set by states
@@ -765,7 +894,7 @@ FocusScope {
765894 target: appDelegate
766895 property: "y"
767896 value: appDelegate.requestedY -
768− Math.min(appDelegate.requestedY - PanelState.panelHeight,
897+ Math.min(appDelegate.requestedY - panelState.panelHeight,
769898 Math.max(0, priv.virtualKeyboardHeight - (appContainer.height - (appDelegate.requestedY + appDelegate.height))))
770899 when: root.oskEnabled && appDelegate.focus && (appDelegate.state == "normal" || appDelegate.state == "restored")
771900 && root.inputMethodRect.height > 0
@@ -876,7 +1005,6 @@ FocusScope {
8761005 function claimFocus() {
8771006 if (root.state == "spread") {
8781007 spreadItem.highlightedIndex = index
879− priv.goneToSpread = false;
8801008 }
8811009 if (root.mode == "stagedWithSideStage") {
8821010 if (appDelegate.stage == ApplicationInfoInterface.SideStage && !sideStage.shown) {
@@ -1163,7 +1291,7 @@ FocusScope {
11631291 progress: 0
11641292 targetHeight: spreadItem.stackHeight
11651293 targetX: spreadMaths.targetX
1166− startY: appDelegate.fullscreen ? 0 : PanelState.panelHeight
1294+ startY: appDelegate.fullscreen ? 0 : panelState.panelHeight
11671295 targetY: spreadMaths.targetY
11681296 targetAngle: spreadMaths.targetAngle
11691297 targetScale: spreadMaths.targetScale
@@ -1209,8 +1337,6 @@ FocusScope {
12091337 y: spreadMaths.targetY
12101338 z: index
12111339 height: spreadItem.spreadItemHeight
1212− requestedWidth: decoratedWindow.oldRequestedWidth
1213− requestedHeight: decoratedWindow.oldRequestedHeight
12141340 visible: spreadMaths.itemVisible
12151341 }
12161342 PropertyChanges { target: dragArea; enabled: true }
@@ -1230,8 +1356,6 @@ FocusScope {
12301356 y: stagedRightEdgeMaths.animatedY
12311357 z: stagedRightEdgeMaths.animatedZ
12321358 height: stagedRightEdgeMaths.animatedHeight
1233− requestedWidth: decoratedWindow.oldRequestedWidth
1234− requestedHeight: decoratedWindow.oldRequestedHeight
12351359 visible: appDelegate.x < root.width
12361360 }
12371361 PropertyChanges {
@@ -1261,8 +1385,6 @@ FocusScope {
12611385 y: windowedRightEdgeMaths.animatedY
12621386 z: windowedRightEdgeMaths.animatedZ
12631387 height: stagedRightEdgeMaths.animatedHeight
1264− requestedWidth: decoratedWindow.oldRequestedWidth
1265− requestedHeight: decoratedWindow.oldRequestedHeight
12661388 }
12671389 PropertyChanges {
12681390 target: decoratedWindow
@@ -1284,12 +1406,16 @@ FocusScope {
12841406 PropertyChanges {
12851407 target: appDelegate
12861408 x: stageMaths.itemX
1287− y: appDelegate.fullscreen ? 0 : PanelState.panelHeight
1288− requestedWidth: appContainer.width
1289− requestedHeight: appDelegate.fullscreen ? appContainer.height : appContainer.height - PanelState.panelHeight
1409+ y: appDelegate.fullscreen ? 0 : panelState.panelHeight
12901410 visuallyMaximized: true
12911411 visible: appDelegate.x < root.width
12921412 }
1413+ PropertyChanges {
1414+ target: appDelegate
1415+ requestedWidth: appContainer.width
1416+ requestedHeight: appDelegate.fullscreen ? appContainer.height : appContainer.height - panelState.panelHeight
1417+ restoreEntryValues: false
1418+ }
12931419 PropertyChanges {
12941420 target: decoratedWindow
12951421 hasDecoration: false
@@ -1312,13 +1438,17 @@ FocusScope {
13121438 PropertyChanges {
13131439 target: appDelegate
13141440 x: stageMaths.itemX
1315− y: appDelegate.fullscreen ? 0 : PanelState.panelHeight
1441+ y: appDelegate.fullscreen ? 0 : panelState.panelHeight
13161442 z: stageMaths.itemZ
1317− requestedWidth: stageMaths.itemWidth
1318− requestedHeight: appDelegate.fullscreen ? appContainer.height : appContainer.height - PanelState.panelHeight
13191443 visuallyMaximized: true
13201444 visible: appDelegate.x < root.width
13211445 }
1446+ PropertyChanges {
1447+ target: appDelegate
1448+ requestedWidth: stageMaths.itemWidth
1449+ requestedHeight: appDelegate.fullscreen ? appContainer.height : appContainer.height - panelState.panelHeight
1450+ restoreEntryValues: false
1451+ }
13221452 PropertyChanges {
13231453 target: decoratedWindow
13241454 hasDecoration: false
@@ -1336,8 +1466,12 @@ FocusScope {
13361466 requestedY: 0;
13371467 visuallyMinimized: false;
13381468 visuallyMaximized: true
1339− requestedWidth: appContainer.width - root.leftMargin;
1340− requestedHeight: appContainer.height;
1469+ }
1470+ PropertyChanges {
1471+ target: appDelegate
1472+ requestedWidth: appContainer.width - root.leftMargin
1473+ requestedHeight: appContainer.height
1474+ restoreEntryValues: false
13411475 }
13421476 PropertyChanges { target: touchControls; enabled: true }
13431477 },
@@ -1347,8 +1481,12 @@ FocusScope {
13471481 target: appDelegate;
13481482 requestedX: 0
13491483 requestedY: 0
1350− requestedWidth: appContainer.width;
1351− requestedHeight: appContainer.height;
1484+ }
1485+ PropertyChanges {
1486+ target: appDelegate
1487+ requestedWidth: appContainer.width
1488+ requestedHeight: appContainer.height
1489+ restoreEntryValues: false
13521490 }
13531491 PropertyChanges { target: decoratedWindow; hasDecoration: false }
13541492 },
@@ -1363,6 +1501,12 @@ FocusScope {
13631501 PropertyChanges { target: touchControls; enabled: true }
13641502 PropertyChanges { target: resizeArea; enabled: true }
13651503 PropertyChanges { target: decoratedWindow; shadowOpacity: .3}
1504+ PropertyChanges {
1505+ target: appDelegate
1506+ requestedWidth: windowedWidth
1507+ requestedHeight: windowedHeight
1508+ restoreEntryValues: false
1509+ }
13661510 },
13671511 State {
13681512 name: "restored";
@@ -1380,9 +1524,9 @@ FocusScope {
13801524 PropertyChanges {
13811525 target: appDelegate
13821526 windowedX: root.leftMargin
1383− windowedY: PanelState.panelHeight
1527+ windowedY: panelState.panelHeight
13841528 windowedWidth: (appContainer.width - root.leftMargin)/2
1385− windowedHeight: appContainer.height - PanelState.panelHeight
1529+ windowedHeight: appContainer.height - panelState.panelHeight
13861530 }
13871531 },
13881532 State {
@@ -1399,9 +1543,9 @@ FocusScope {
13991543 PropertyChanges {
14001544 target: appDelegate
14011545 windowedX: root.leftMargin
1402− windowedY: PanelState.panelHeight
1546+ windowedY: panelState.panelHeight
14031547 windowedWidth: (appContainer.width - root.leftMargin)/2
1404− windowedHeight: (appContainer.height - PanelState.panelHeight)/2
1548+ windowedHeight: (appContainer.height - panelState.panelHeight)/2
14051549 }
14061550 },
14071551 State {
@@ -1418,7 +1562,7 @@ FocusScope {
14181562 PropertyChanges {
14191563 target: appDelegate
14201564 windowedX: root.leftMargin
1421− windowedY: (appContainer.height + PanelState.panelHeight)/2
1565+ windowedY: (appContainer.height + panelState.panelHeight)/2
14221566 windowedWidth: (appContainer.width - root.leftMargin)/2
14231567 windowedHeight: appContainer.height/2
14241568 }
@@ -1440,8 +1584,8 @@ FocusScope {
14401584 State {
14411585 name: "maximizedVertically"; when: appDelegate.maximizedVertically && !appDelegate.minimized
14421586 extend: "normal"
1443− PropertyChanges { target: appDelegate; windowedX: windowedX; windowedY: PanelState.panelHeight;
1444− windowedWidth: windowedWidth; windowedHeight: appContainer.height - PanelState.panelHeight }
1587+ PropertyChanges { target: appDelegate; windowedX: windowedX; windowedY: panelState.panelHeight;
1588+ windowedWidth: windowedWidth; windowedHeight: appContainer.height - panelState.panelHeight }
14451589 },
14461590 State {
14471591 name: "minimized"; when: appDelegate.minimized
@@ -1456,6 +1600,10 @@ FocusScope {
14561600 }
14571601 }
14581602 ]
1603+ onStateChanged: {
1604+ print("item", index, "state changed", state)
1605+ }
1606+
14591607 transitions: [
14601608 Transition {
14611609 from: "staged,stagedWithSideStage"
@@ -1469,6 +1617,7 @@ FocusScope {
14691617 UbuntuNumberAnimation { target: appDelegate; properties: "x,y,requestedX,requestedY,requestedWidth,requestedHeight"; duration: priv.animationDuration}
14701618 },
14711619 Transition {
1620+ from: "normal,restored,maximized,maximizedHorizontally,maximizedVertically,maximizedLeft,maximizedRight,maximizedTopLeft,maximizedBottomLeft,maximizedTopRight,maximizedBottomRight,staged,stagedWithSideStage,windowedRightEdge,stagedRightEdge";
14721621 to: "spread"
14731622 // DecoratedWindow wants the scaleToPreviewSize set before enabling scaleToPreview
14741623 PropertyAction { target: appDelegate; properties: "z,visible" }
@@ -1554,7 +1703,7 @@ FocusScope {
15541703 ]
15551704
15561705 Binding {
1557− target: PanelState
1706+ target: panelState
15581707 property: "decorationsAlwaysVisible"
15591708 value: appDelegate && appDelegate.maximized && touchControls.overlayShown
15601709 }
@@ -1575,6 +1724,7 @@ FocusScope {
15751724 borderThickness: units.gu(2)
15761725 enabled: false
15771726 visible: enabled
1727+ readyToAssesBounds: !appDelegate._constructing
15781728
15791729 onPressed: {
15801730 appDelegate.activate();
@@ -1598,16 +1748,11 @@ FocusScope {
15981748 height: implicitHeight
15991749 highlightSize: windowInfoItem.iconMargin / 2
16001750 boundsItem: boundariesForWindowPlacement
1751+ panelState: root.panelState
16011752
16021753 requestedWidth: appDelegate.requestedWidth
16031754 requestedHeight: appDelegate.requestedHeight
16041755
1605− property int oldRequestedWidth: -1
1606− property int oldRequestedHeight: -1
1607−
1608− onRequestedWidthChanged: oldRequestedWidth = requestedWidth
1609− onRequestedHeightChanged: oldRequestedHeight = requestedHeight
1610−
16111756 onCloseClicked: { appDelegate.close(); }
16121757 onMaximizeClicked: {
16131758 if (appDelegate.canBeMaximized) {
@@ -1688,6 +1833,8 @@ FocusScope {
16881833 anchors.fill: decoratedWindow
16891834 enabled: false
16901835 closeable: !appDelegate.isDash
1836+ stage: root
1837+ dragDelegate: fakeDragItem
16911838
16921839 onClicked: {
16931840 spreadItem.highlightedIndex = index;
@@ -1730,12 +1877,15 @@ FocusScope {
17301877 objectName: "closeMouseArea"
17311878 anchors { left: parent.left; top: parent.top; leftMargin: -height / 2; topMargin: -height / 2 + spreadMaths.closeIconOffset }
17321879 readonly property var mousePos: hoverMouseArea.mapToItem(appDelegate, hoverMouseArea.mouseX, hoverMouseArea.mouseY)
1733− visible: !appDelegate.isDash && dragArea.distance == 0
1880+ readonly property bool shown: !appDelegate.isDash && dragArea.distance == 0
17341881 && index == spreadItem.highlightedIndex
17351882 && mousePos.y < (decoratedWindow.height / 3)
17361883 && mousePos.y > -units.gu(4)
17371884 && mousePos.x > -units.gu(4)
17381885 && mousePos.x < (decoratedWindow.width * 2 / 3)
1886+ opacity: shown ? 1 : 0
1887+ visible: opacity > 0
1888+ Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
17391889 height: units.gu(6)
17401890 width: height
17411891
@@ -1797,83 +1947,34 @@ FocusScope {
17971947 leftMargin: root.leftMargin
17981948 appContainerWidth: appContainer.width
17991949 appContainerHeight: appContainer.height
1950+ panelState: root.panelState
18001951 }
18011952
1802− MouseArea {
1803− id: hoverMouseArea
1804− objectName: "hoverMouseArea"
1805− anchors.fill: appContainer
1806− propagateComposedEvents: true
1807− hoverEnabled: true
1808− enabled: false
1809− visible: enabled
1810−
1811− property int scrollAreaWidth: width / 3
1812− property bool progressiveScrollingEnabled: false
1813−
1814− onMouseXChanged: {
1815− mouse.accepted = false
1816−
1817− if (hoverMouseArea.pressed) {
1818− return;
1819− }
1820−
1821− // Find the hovered item and mark it active
1822− for (var i = appRepeater.count - 1; i >= 0; i--) {
1823− var appDelegate = appRepeater.itemAt(i);
1824− var mapped = mapToItem(appDelegate, hoverMouseArea.mouseX, hoverMouseArea.mouseY)
1825− var itemUnder = appDelegate.childAt(mapped.x, mapped.y);
1826− if (itemUnder && (itemUnder.objectName === "dragArea" || itemUnder.objectName === "windowInfoItem" || itemUnder.objectName == "closeMouseArea")) {
1827− spreadItem.highlightedIndex = i;
1828− break;
1829− }
1830− }
1831−
1832− if (floatingFlickable.contentWidth > floatingFlickable.width) {
1833− var margins = floatingFlickable.width * 0.05;
1834−
1835− if (!progressiveScrollingEnabled && mouseX < floatingFlickable.width - scrollAreaWidth) {
1836− progressiveScrollingEnabled = true
1837− }
1838−
1839− // do we need to scroll?
1840− if (mouseX < scrollAreaWidth + margins) {
1841− var progress = Math.min(1, (scrollAreaWidth + margins - mouseX) / (scrollAreaWidth - margins));
1842− var contentX = (1 - progress) * (floatingFlickable.contentWidth - floatingFlickable.width)
1843− floatingFlickable.contentX = Math.max(0, Math.min(floatingFlickable.contentX, contentX))
1844− }
1845− if (mouseX > floatingFlickable.width - scrollAreaWidth && progressiveScrollingEnabled) {
1846− var progress = Math.min(1, (mouseX - (floatingFlickable.width - scrollAreaWidth)) / (scrollAreaWidth - margins))
1847− var contentX = progress * (floatingFlickable.contentWidth - floatingFlickable.width)
1848− floatingFlickable.contentX = Math.min(floatingFlickable.contentWidth - floatingFlickable.width, Math.max(floatingFlickable.contentX, contentX))
1849− }
1850− }
1953+ WorkspaceSwitcher {
1954+ id: workspaceSwitcher
1955+ anchors.centerIn: parent
1956+ height: units.gu(20)
1957+ background: root.background
1958+ opacity: shown ? 1 : 0
1959+ visible: opacity > 0
1960+ Behavior on opacity { UbuntuNumberAnimation {} }
1961+ property bool shown: false
1962+ function show() {
1963+ shown = true;
1964+ hideTimer.start();
1965+ }
1966+ Timer {
1967+ id: hideTimer
1968+ interval: 3000
1969+ onTriggered: workspaceSwitcher.shown = false;
18511970 }
18521971
1853− onPressed: mouse.accepted = false
1854− }
1855−
1856− FloatingFlickable {
1857− id: floatingFlickable
1858− objectName: "spreadFlickable"
1859− anchors.fill: appContainer
1860− enabled: false
1861− contentWidth: spreadItem.spreadTotalWidth
1862−
1863− function snap(toIndex) {
1864− var delegate = appRepeater.itemAt(toIndex)
1865− var targetContentX = floatingFlickable.contentWidth / spreadItem.totalItemCount * toIndex;
1866− if (targetContentX - floatingFlickable.contentX > spreadItem.rightStackXPos - (spreadItem.spreadItemWidth / 2)) {
1867− var offset = (spreadItem.rightStackXPos - (spreadItem.spreadItemWidth / 2)) - (targetContentX - floatingFlickable.contentX)
1868− snapAnimation.to = Math.max(0, floatingFlickable.contentX - offset);
1869− snapAnimation.start();
1870− } else if (targetContentX - floatingFlickable.contentX < spreadItem.leftStackXPos + units.gu(1)) {
1871− var offset = (spreadItem.leftStackXPos + units.gu(1)) - (targetContentX - floatingFlickable.contentX);
1872− snapAnimation.to = Math.max(0, floatingFlickable.contentX - offset);
1873− snapAnimation.start();
1874− }
1972+ function left() {
1973+ show()
1974+ }
1975+ function right() {
1976+ show();
18751977 }
1876− UbuntuNumberAnimation {id: snapAnimation; target: floatingFlickable; property: "contentX"}
18771978 }
18781979
18791980 PropertyAnimation {