@@ -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"
@@ -349,23 +350,23 @@ FocusScope {
349350 readonly property real virtualKeyboardHeight: root.inputMethodRect.height
350351 }
351352
352− Component.onCompleted: priv.updateMainAndSideStageIndexes();
353+ Component.onCompleted: priv.updateMainAndSideStageIndexes()
353354
354355 Connections {
355− target: PanelState
356+ target: panelState
356357 onCloseClicked: { if (priv.focusedAppDelegate) { priv.focusedAppDelegate.close(); } }
357358 onMinimizeClicked: { if (priv.focusedAppDelegate) { priv.focusedAppDelegate.requestMinimize(); } }
358359 onRestoreClicked: { if (priv.focusedAppDelegate) { priv.focusedAppDelegate.requestRestore(); } }
359360 }
360361
361362 Binding {
362− target: PanelState
363+ target: panelState
363364 property: "decorationsVisible"
364365 value: priv.focusedAppDelegate !== null && priv.focusedAppDelegate.maximized // FIXME for Locally integrated menus
365366 }
366367
367368 Binding {
368− target: PanelState
369+ target: panelState
369370 property: "title"
370371 value: {
371372 if (priv.focusedAppDelegate !== null) {
@@ -380,7 +381,7 @@ FocusScope {
380381 }
381382
382383 Binding {
383− target: PanelState
384+ target: panelState
384385 property: "focusedPersistentSurfaceId"
385386 value: {
386387 if (priv.focusedAppDelegate !== null) {
@@ -394,21 +395,21 @@ FocusScope {
394395 }
395396
396397 Binding {
397− target: PanelState
398+ target: panelState
398399 property: "dropShadow"
399400 value: priv.focusedAppDelegate && !priv.focusedAppDelegate.maximized && priv.foregroundMaximizedAppDelegate !== null && mode == "windowed"
400401 }
401402
402403 Binding {
403− target: PanelState
404+ target: panelState
404405 property: "closeButtonShown"
405406 value: priv.focusedAppDelegate && priv.focusedAppDelegate.maximized && !priv.focusedAppDelegate.isDash
406407 }
407408
408409 Component.onDestruction: {
409− PanelState.title = "";
410− PanelState.decorationsVisible = false;
411− PanelState.dropShadow = false;
410+ panelState.title = "";
411+ panelState.decorationsVisible = false;
412+ panelState.dropShadow = false;
412413 }
413414
414415 Instantiator {
@@ -454,6 +455,7 @@ FocusScope {
454455 PropertyChanges { target: cancelSpreadMouseArea; enabled: true }
455456 PropertyChanges { target: blurLayer; visible: true; blurRadius: 32; brightness: .65; opacity: 1 }
456457 PropertyChanges { target: wallpaper; visible: false }
458+ PropertyChanges { target: screensAndWorkspaces; opacity: 1 }
457459 },
458460 State {
459461 name: "stagedRightEdge"; when: root.spreadEnabled && (rightEdgeDragArea.dragging || rightEdgePushProgress > 0) && root.mode == "staged"
@@ -502,10 +504,13 @@ FocusScope {
502504 from: "stagedRightEdge,sideStagedRightEdge,windowedRightEdge"; to: "spread"
503505 PropertyAction { target: spreadItem; property: "highlightedIndex"; value: -1 }
504506 PropertyAnimation { target: blurLayer; properties: "brightness,blurRadius"; duration: priv.animationDuration }
507+ UbuntuNumberAnimation { target: screensAndWorkspaces; property: "opacity"; duration: priv.animationDuration }
505508 },
506509 Transition {
507510 to: "spread"
508511 PropertyAction { target: spreadItem; property: "highlightedIndex"; value: appRepeater.count > 1 ? 1 : 0 }
512+ PropertyAction { target: floatingFlickable; property: "contentX"; value: 0 }
513+ UbuntuNumberAnimation { target: screensAndWorkspaces; property: "opacity"; duration: priv.animationDuration }
509514 },
510515 Transition {
511516 from: "spread"
@@ -563,10 +568,21 @@ FocusScope {
563568 visible: false
564569 }
565570
571+ ScreensAndWorkspaces {
572+ id: screensAndWorkspaces
573+ anchors { left: parent.left; top: parent.top; right: parent.right; leftMargin: root.leftMargin }
574+ height: Math.max(units.gu(35), parent.height * .4)
575+ background: root.background
576+ opacity: 0
577+ visible: opacity > 0
578+
579+ onCloseSpread: priv.goneToSpread = false;
580+ }
581+
566582 Spread {
567583 id: spreadItem
568584 objectName: "spreadItem"
569− anchors.fill: appContainer
585+ anchors { left: parent.left; bottom: parent.bottom; right: parent.right; top: screensAndWorkspaces.bottom }
570586 leftMargin: root.leftMargin
571587 model: root.topLevelSurfaceList
572588 spreadFlickable: floatingFlickable
@@ -575,6 +591,83 @@ FocusScope {
575591 onLeaveSpread: {
576592 priv.goneToSpread = false;
577593 }
594+
595+ FloatingFlickable {
596+ id: floatingFlickable
597+ objectName: "spreadFlickable"
598+ anchors.fill: parent
599+ enabled: false
600+ contentWidth: spreadItem.spreadTotalWidth
601+
602+ function snap(toIndex) {
603+ var delegate = appRepeater.itemAt(toIndex)
604+ var targetContentX = floatingFlickable.contentWidth / spreadItem.totalItemCount * toIndex;
605+ if (targetContentX - floatingFlickable.contentX > spreadItem.rightStackXPos - (spreadItem.spreadItemWidth / 2)) {
606+ var offset = (spreadItem.rightStackXPos - (spreadItem.spreadItemWidth / 2)) - (targetContentX - floatingFlickable.contentX)
607+ snapAnimation.to = floatingFlickable.contentX - offset;
608+ snapAnimation.start();
609+ } else if (targetContentX - floatingFlickable.contentX < spreadItem.leftStackXPos + units.gu(1)) {
610+ var offset = (spreadItem.leftStackXPos + units.gu(1)) - (targetContentX - floatingFlickable.contentX);
611+ snapAnimation.to = floatingFlickable.contentX - offset;
612+ snapAnimation.start();
613+ }
614+ }
615+ UbuntuNumberAnimation {id: snapAnimation; target: floatingFlickable; property: "contentX"}
616+ }
617+
618+ MouseArea {
619+ id: hoverMouseArea
620+ objectName: "hoverMouseArea"
621+ anchors.fill: parent
622+ propagateComposedEvents: true
623+ hoverEnabled: true
624+ enabled: false
625+ visible: enabled
626+
627+ property int scrollAreaWidth: width / 3
628+ property bool progressiveScrollingEnabled: false
629+
630+ onPressed: mouse.accepted = false
631+
632+ onMouseXChanged: {
633+ mouse.accepted = false
634+
635+ if (hoverMouseArea.pressed) {
636+ return;
637+ }
638+
639+ // Find the hovered item and mark it active
640+ for (var i = appRepeater.count - 1; i >= 0; i--) {
641+ var appDelegate = appRepeater.itemAt(i);
642+ var mapped = mapToItem(appDelegate, hoverMouseArea.mouseX, hoverMouseArea.mouseY)
643+ var itemUnder = appDelegate.childAt(mapped.x, mapped.y);
644+ if (itemUnder && (itemUnder.objectName === "dragArea" || itemUnder.objectName === "windowInfoItem" || itemUnder.objectName == "closeMouseArea")) {
645+ spreadItem.highlightedIndex = i;
646+ break;
647+ }
648+ }
649+
650+ if (floatingFlickable.contentWidth > floatingFlickable.width) {
651+ var margins = floatingFlickable.width * 0.05;
652+
653+ if (!progressiveScrollingEnabled && mouseX < floatingFlickable.width - scrollAreaWidth) {
654+ progressiveScrollingEnabled = true
655+ }
656+
657+ // do we need to scroll?
658+ if (mouseX < scrollAreaWidth + margins) {
659+ var progress = Math.min(1, (scrollAreaWidth + margins - mouseX) / (scrollAreaWidth - margins));
660+ var contentX = (1 - progress) * (floatingFlickable.contentWidth - floatingFlickable.width)
661+ floatingFlickable.contentX = Math.max(0, Math.min(floatingFlickable.contentX, contentX))
662+ }
663+ if (mouseX > floatingFlickable.width - scrollAreaWidth && progressiveScrollingEnabled) {
664+ var progress = Math.min(1, (mouseX - (floatingFlickable.width - scrollAreaWidth)) / (scrollAreaWidth - margins))
665+ var contentX = progress * (floatingFlickable.contentWidth - floatingFlickable.width)
666+ floatingFlickable.contentX = Math.min(floatingFlickable.contentWidth - floatingFlickable.width, Math.max(floatingFlickable.contentX, contentX))
667+ }
668+ }
669+ }
670+ }
578671 }
579672
580673 Connections {
@@ -669,10 +762,28 @@ FocusScope {
669762 }
670763 }
671764
765+ MirSurfaceItem {
766+ id: fakeDragItem
767+ property real previewScale: .5
768+ height: (screensAndWorkspaces.height - units.gu(8)) / 2
769+ // w : h = iw : ih
770+ width: implicitWidth * height / implicitHeight
771+ surfaceWidth: -1
772+ surfaceHeight: -1
773+ opacity: surface != null ? 1 : 0
774+ Behavior on opacity { UbuntuNumberAnimation {} }
775+ visible: opacity > 0
776+
777+ Drag.active: surface != null
778+ Drag.keys: ["application"]
779+
780+ z: 1000
781+ }
782+
672783 Item {
673784 id: boundariesForWindowPlacement
674785 anchors.fill: parent
675− anchors.topMargin: PanelState.panelHeight
786+ anchors.topMargin: panelState.panelHeight
676787 visible: false
677788 }
678789
@@ -704,6 +815,9 @@ FocusScope {
704815 }
705816 z: normalZ
706817
818+ opacity: fakeDragItem.surface == model.window.surface && fakeDragItem.Drag.active ? 0 : 1
819+ Behavior on opacity { UbuntuNumberAnimation {} }
820+
707821 // Normally we want x/y where the surface thinks it is. Width/height of our delegate will
708822 // match what the actual surface size is.
709823 // Don't write to those, they will be set by states
@@ -765,7 +879,7 @@ FocusScope {
765879 target: appDelegate
766880 property: "y"
767881 value: appDelegate.requestedY -
768− Math.min(appDelegate.requestedY - PanelState.panelHeight,
882+ Math.min(appDelegate.requestedY - panelState.panelHeight,
769883 Math.max(0, priv.virtualKeyboardHeight - (appContainer.height - (appDelegate.requestedY + appDelegate.height))))
770884 when: root.oskEnabled && appDelegate.focus && (appDelegate.state == "normal" || appDelegate.state == "restored")
771885 && root.inputMethodRect.height > 0
@@ -876,7 +990,6 @@ FocusScope {
876990 function claimFocus() {
877991 if (root.state == "spread") {
878992 spreadItem.highlightedIndex = index
879− priv.goneToSpread = false;
880993 }
881994 if (root.mode == "stagedWithSideStage") {
882995 if (appDelegate.stage == ApplicationInfoInterface.SideStage && !sideStage.shown) {
@@ -1163,7 +1276,7 @@ FocusScope {
11631276 progress: 0
11641277 targetHeight: spreadItem.stackHeight
11651278 targetX: spreadMaths.targetX
1166− startY: appDelegate.fullscreen ? 0 : PanelState.panelHeight
1279+ startY: appDelegate.fullscreen ? 0 : panelState.panelHeight
11671280 targetY: spreadMaths.targetY
11681281 targetAngle: spreadMaths.targetAngle
11691282 targetScale: spreadMaths.targetScale
@@ -1284,9 +1397,9 @@ FocusScope {
12841397 PropertyChanges {
12851398 target: appDelegate
12861399 x: stageMaths.itemX
1287− y: appDelegate.fullscreen ? 0 : PanelState.panelHeight
1400+ y: appDelegate.fullscreen ? 0 : panelState.panelHeight
12881401 requestedWidth: appContainer.width
1289− requestedHeight: appDelegate.fullscreen ? appContainer.height : appContainer.height - PanelState.panelHeight
1402+ requestedHeight: appDelegate.fullscreen ? appContainer.height : appContainer.height - panelState.panelHeight
12901403 visuallyMaximized: true
12911404 visible: appDelegate.x < root.width
12921405 }
@@ -1312,10 +1425,10 @@ FocusScope {
13121425 PropertyChanges {
13131426 target: appDelegate
13141427 x: stageMaths.itemX
1315− y: appDelegate.fullscreen ? 0 : PanelState.panelHeight
1428+ y: appDelegate.fullscreen ? 0 : panelState.panelHeight
13161429 z: stageMaths.itemZ
13171430 requestedWidth: stageMaths.itemWidth
1318− requestedHeight: appDelegate.fullscreen ? appContainer.height : appContainer.height - PanelState.panelHeight
1431+ requestedHeight: appDelegate.fullscreen ? appContainer.height : appContainer.height - panelState.panelHeight
13191432 visuallyMaximized: true
13201433 visible: appDelegate.x < root.width
13211434 }
@@ -1380,9 +1493,9 @@ FocusScope {
13801493 PropertyChanges {
13811494 target: appDelegate
13821495 windowedX: root.leftMargin
1383− windowedY: PanelState.panelHeight
1496+ windowedY: panelState.panelHeight
13841497 windowedWidth: (appContainer.width - root.leftMargin)/2
1385− windowedHeight: appContainer.height - PanelState.panelHeight
1498+ windowedHeight: appContainer.height - panelState.panelHeight
13861499 }
13871500 },
13881501 State {
@@ -1399,9 +1512,9 @@ FocusScope {
13991512 PropertyChanges {
14001513 target: appDelegate
14011514 windowedX: root.leftMargin
1402− windowedY: PanelState.panelHeight
1515+ windowedY: panelState.panelHeight
14031516 windowedWidth: (appContainer.width - root.leftMargin)/2
1404− windowedHeight: (appContainer.height - PanelState.panelHeight)/2
1517+ windowedHeight: (appContainer.height - panelState.panelHeight)/2
14051518 }
14061519 },
14071520 State {
@@ -1418,7 +1531,7 @@ FocusScope {
14181531 PropertyChanges {
14191532 target: appDelegate
14201533 windowedX: root.leftMargin
1421− windowedY: (appContainer.height + PanelState.panelHeight)/2
1534+ windowedY: (appContainer.height + panelState.panelHeight)/2
14221535 windowedWidth: (appContainer.width - root.leftMargin)/2
14231536 windowedHeight: appContainer.height/2
14241537 }
@@ -1440,8 +1553,8 @@ FocusScope {
14401553 State {
14411554 name: "maximizedVertically"; when: appDelegate.maximizedVertically && !appDelegate.minimized
14421555 extend: "normal"
1443− PropertyChanges { target: appDelegate; windowedX: windowedX; windowedY: PanelState.panelHeight;
1444− windowedWidth: windowedWidth; windowedHeight: appContainer.height - PanelState.panelHeight }
1556+ PropertyChanges { target: appDelegate; windowedX: windowedX; windowedY: panelState.panelHeight;
1557+ windowedWidth: windowedWidth; windowedHeight: appContainer.height - panelState.panelHeight }
14451558 },
14461559 State {
14471560 name: "minimized"; when: appDelegate.minimized
@@ -1456,6 +1569,10 @@ FocusScope {
14561569 }
14571570 }
14581571 ]
1572+ onStateChanged: {
1573+ print("item", index, "state changed", state)
1574+ }
1575+
14591576 transitions: [
14601577 Transition {
14611578 from: "staged,stagedWithSideStage"
@@ -1469,6 +1586,7 @@ FocusScope {
14691586 UbuntuNumberAnimation { target: appDelegate; properties: "x,y,requestedX,requestedY,requestedWidth,requestedHeight"; duration: priv.animationDuration}
14701587 },
14711588 Transition {
1589+ from: "normal,restored,maximized,maximizedHorizontally,maximizedVertically,maximizedLeft,maximizedRight,maximizedTopLeft,maximizedBottomLeft,maximizedTopRight,maximizedBottomRight,staged,stagedWithSideStage,windowedRightEdge,stagedRightEdge";
14721590 to: "spread"
14731591 // DecoratedWindow wants the scaleToPreviewSize set before enabling scaleToPreview
14741592 PropertyAction { target: appDelegate; properties: "z,visible" }
@@ -1554,7 +1672,7 @@ FocusScope {
15541672 ]
15551673
15561674 Binding {
1557− target: PanelState
1675+ target: panelState
15581676 property: "decorationsAlwaysVisible"
15591677 value: appDelegate && appDelegate.maximized && touchControls.overlayShown
15601678 }
@@ -1730,12 +1848,15 @@ FocusScope {
17301848 objectName: "closeMouseArea"
17311849 anchors { left: parent.left; top: parent.top; leftMargin: -height / 2; topMargin: -height / 2 + spreadMaths.closeIconOffset }
17321850 readonly property var mousePos: hoverMouseArea.mapToItem(appDelegate, hoverMouseArea.mouseX, hoverMouseArea.mouseY)
1733− visible: !appDelegate.isDash && dragArea.distance == 0
1851+ readonly property bool shown: !appDelegate.isDash && dragArea.distance == 0
17341852 && index == spreadItem.highlightedIndex
17351853 && mousePos.y < (decoratedWindow.height / 3)
17361854 && mousePos.y > -units.gu(4)
17371855 && mousePos.x > -units.gu(4)
17381856 && mousePos.x < (decoratedWindow.width * 2 / 3)
1857+ opacity: shown ? 1 : 0
1858+ visible: opacity > 0
1859+ Behavior on opacity { UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration } }
17391860 height: units.gu(6)
17401861 width: height
17411862
@@ -1797,83 +1918,7 @@ FocusScope {
17971918 leftMargin: root.leftMargin
17981919 appContainerWidth: appContainer.width
17991920 appContainerHeight: appContainer.height
1800− }
1801−
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− }
1851− }
1852−
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− }
1875− }
1876− UbuntuNumberAnimation {id: snapAnimation; target: floatingFlickable; property: "contentX"}
1921+ panelState: root.panelState
18771922 }
18781923
18791924 PropertyAnimation {