@@ -47,7 +47,7 @@ AbstractStage {
4747 property string mode: "staged"
4848
4949 // Used by TutorialRight
50− property bool spreadShown: state == "altTab"
50+ property bool spreadShown: state == "spread"
5151
5252 mainApp: priv.focusedAppDelegate ? priv.focusedAppDelegate.application : null
5353
@@ -113,6 +113,7 @@ AbstractStage {
113113 property var focusedAppDelegate: null
114114 onFocusedAppDelegateChanged: {
115115 if (focusedAppDelegate && root.state == "spread") {
116+ print("clsing spread because of focus change to", focusedAppDelegate.application.appId)
116117 goneToSpread = false;
117118 }
118119 }
@@ -121,8 +122,8 @@ AbstractStage {
121122
122123 property bool goneToSpread: false
123124 property int closingIndex: -1
124−// property int animationDuration: 4000
125− property int animationDuration: UbuntuAnimation.FastDuration
125+ property int animationDuration: 4000
126+// property int animationDuration: UbuntuAnimation.FastDuration
126127
127128 function updateForegroundMaximizedApp() {
128129 var found = false;
@@ -179,7 +180,7 @@ AbstractStage {
179180 priv.sideStageAppId = "";
180181 priv.mainStageDelegate = appRepeater.itemAt(0);
181182 priv.mainStageAppId = topLevelSurfaceList.idAt(0);
182− priv.mainStageAppId = topLevelSurfaceList.applicationAt(0).appId;
183+ priv.mainStageAppId = topLevelSurfaceList.applicationAt(0) ? topLevelSurfaceList.applicationAt(0).appId : ""
183184 return;
184185 }
185186
@@ -306,9 +307,10 @@ AbstractStage {
306307 // resume all those apps at once. We might want to avoid that.
307308 value: root.mode === "windowed"
308309 || (isDash && root.keepDashRunning)
309− || (!root.suspended && model.application && (priv.focusedAppDelegate.appId === model.application.appId ||
310− priv.mainStageAppId === model.application.appId ||
311− priv.sideStageAppId === model.application.appId))
310+ || (!root.suspended && model.application && priv.focusedAppDelegate &&
311+ (priv.focusedAppDelegate.appId === model.application.appId ||
312+ priv.mainStageAppId === model.application.appId ||
313+ priv.sideStageAppId === model.application.appId))
312314 ? ApplicationInfoInterface.RequestedRunning
313315 : ApplicationInfoInterface.RequestedSuspended
314316 }
@@ -335,6 +337,7 @@ AbstractStage {
335337 name: "spread"; when: priv.goneToSpread
336338 PropertyChanges { target: floatingFlickable; enabled: true }
337339 PropertyChanges { target: spreadItem; focus: true }
340+ PropertyChanges { target: hoverMouseArea; enabled: true }
338341 },
339342 State {
340343 name: "stagedRightEdge"; when: rightEdgeDragArea.dragging && root.mode == "staged"
@@ -376,6 +379,8 @@ AbstractStage {
376379 script: {
377380 print("hightedIndex is:", spreadItem.highlightedIndex)
378381 var item = appRepeater.itemAt(Math.max(0, spreadItem.highlightedIndex));
382+ print("playing focus animation 3 on item", spreadItem.highlightedIndex, item.application.appId)
383+
379384 item.playFocusAnimation();
380385 }
381386 }
@@ -465,6 +470,7 @@ AbstractStage {
465470 onShownChanged: {
466471 print("sidestage shown changed:", shown)
467472 if (!shown && priv.mainStageDelegate) {
473+ print("claiming focus 2")
468474 priv.mainStageDelegate.claimFocus();
469475 }
470476 }
@@ -499,6 +505,7 @@ AbstractStage {
499505 onDropped: {
500506 if (drop.keys == "MainStage") {
501507 drop.source.appDelegate.saveStage(ApplicationInfoInterface.SideStage);
508+ print("dropped on mainstage")
502509 drop.source.appDelegate.focus = true;
503510 }
504511 }
@@ -627,7 +634,7 @@ AbstractStage {
627634 readonly property bool isDash: model.application.appId == "unity8-dash"
628635
629636 function claimFocus() {
630− print("focusing app", priv.sideStageDelegate, appDelegate, sideStage.shown)
637+ print("(claimfocus) focusing app", priv.sideStageDelegate, appDelegate, sideStage.shown)
631638 if (root.mode == "windowed" && minimized) {
632639 restore(true)
633640 }
@@ -641,6 +648,7 @@ AbstractStage {
641648 onFocusRequested: {
642649 // Reset spread selection in case there is any
643650 spreadItem.highlightedIndex = -1
651+ print("claiming focus 3")
644652 claimFocus();
645653 }
646654 }
@@ -650,6 +658,7 @@ AbstractStage {
650658 if (!model.surface) {
651659 // when an app has no surfaces, we assume there's only one entry representing it:
652660 // this delegate.
661+ print("claiming focus 4")
653662 claimFocus();
654663 } else {
655664 // if the application has surfaces, focus request should be at surface-level.
@@ -683,6 +692,7 @@ AbstractStage {
683692 if (!appRepeater.startingUp) {
684693 // a top level window is always the focused one when it first appears, unfocusing
685694 // any preexisting one
695+ print("focusing because of creation")
686696 focus = true;
687697 }
688698 }
@@ -701,6 +711,7 @@ AbstractStage {
701711 for (var i = 0; i < appRepeater.count; i++) {
702712 var appDelegate = appRepeater.itemAt(i);
703713 if (appDelegate && !appDelegate.minimized && i != index) {
714+ print("focusing some other because of destruction")
704715 appDelegate.focus = true;
705716 return;
706717 }
@@ -787,6 +798,7 @@ AbstractStage {
787798 rightEdgeFocusAnimation.start()
788799 }
789800 } else if (state == "windowedRightEdge") {
801+ print("claiming focus 1")
790802 claimFocus();
791803 } else {
792804 focusAnimation.start()
@@ -805,19 +817,30 @@ AbstractStage {
805817 from: 0.98
806818 to: 1
807819 duration: UbuntuAnimation.SnapDuration
808− onStarted: topLevelSurfaceList.raiseId(model.id);
809− onStopped: appDelegate.focus = true
820+ onStarted: {
821+ print("starting focusanimation for", model.application.appId)
822+ topLevelSurfaceList.raiseId(model.id);
823+ }
824+ onStopped: {
825+ print("focusing because of normal focus animation finishing")
826+ appDelegate.focus = true
827+ }
810828 }
811829 ParallelAnimation {
812830 id: rightEdgeFocusAnimation
813831 property int targetX: 0
832+ onStarted: print("starting rightedgefocusanimation for", model.application.appId)
814833 UbuntuNumberAnimation { target: appDelegate; properties: "x"; to: rightEdgeFocusAnimation.targetX; duration: priv.animationDuration }
815834 UbuntuNumberAnimation { target: decoratedWindow; properties: "angle"; to: 0; duration: priv.animationDuration }
816835 UbuntuNumberAnimation { target: decoratedWindow; properties: "itemScale"; to: 1; duration: priv.animationDuration }
817− onStopped: appDelegate.focus = true
836+ onStopped: {
837+ print("focusing", model.application.appId, "because of right edge focus animation completion");
838+ appDelegate.focus = true
839+ }
818840 }
819841 ParallelAnimation {
820842 id: hidingAnimation
843+ onStarted: print("starting hiding animation for", model.application.appId)
821844 UbuntuNumberAnimation { target: appDelegate; property: "opacity"; to: 0; duration: priv.animationDuration }
822845 onStopped: appDelegate.opacity = 1
823846 }
@@ -1139,7 +1162,7 @@ AbstractStage {
11391162 from: "spread"; to: "*"
11401163// UbuntuNumberAnimation { target: appDelegate; properties: "x,y,height"; duration: priv.animationDuration }
11411164// UbuntuNumberAnimation { target: decoratedWindow; properties: "width,height,itemScale,angle"; duration: priv.animationDuration }
1142− ScriptAction { script: if (appDelegate.focus) appDelegate.playFocusAnimation() }
1165+// ScriptAction { script: if (appDelegate.focus) appDelegate.playFocusAnimation() }
11431166 },
11441167 Transition {
11451168 to: "minimized"
@@ -1212,16 +1235,16 @@ AbstractStage {
12121235 },
12131236 Transition {
12141237 from: "stagedRightEdge"; to: "staged"
1238+ enabled: rightEdgeDragArea.cancelled // only transition back to state if the gesture was cancelled, in the other cases we play the focusAnimations.
12151239 SequentialAnimation {
12161240 ParallelAnimation {
12171241 UbuntuNumberAnimation { target: appDelegate; properties: "x,y,height,width,scale"; duration: priv.animationDuration }
12181242 UbuntuNumberAnimation { target: decoratedWindow; properties: "width,height,itemScale,angle,scaleToPreviewProgress"; duration: priv.animationDuration }
12191243 }
1220− // // We need to release scaleToPreviewSize at last
1244+ // We need to release scaleToPreviewSize at last
12211245 PropertyAction { target: decoratedWindow; property: "scaleToPreviewSize" }
12221246 }
12231247 }
1224−
12251248 ]
12261249
12271250 Binding {
@@ -1246,6 +1269,7 @@ AbstractStage {
12461269 screenHeight: appContainer.height
12471270 leftMargin: root.leftMargin
12481271 enabled: false
1272+ visible: false
12491273
12501274 onPressed: {
12511275 print("***** focusing because of resize area press", model.application.appId)
@@ -1298,7 +1322,10 @@ AbstractStage {
12981322 onMaximizeHorizontallyClicked: appDelegate.maximizedHorizontally ? appDelegate.restoreFromMaximized() : appDelegate.maximizeHorizontally()
12991323 onMaximizeVerticallyClicked: appDelegate.maximizedVertically ? appDelegate.restoreFromMaximized() : appDelegate.maximizeVertically()
13001324 onMinimizeClicked: appDelegate.minimize()
1301− onDecorationPressed: { appDelegate.focus = true; }
1325+ onDecorationPressed: {
1326+ print("focusing because of decoration press");
1327+ appDelegate.focus = true;
1328+ }
13021329
13031330 property real angle: 0
13041331 property real itemScale: 1
@@ -1327,6 +1354,7 @@ AbstractStage {
13271354 anchors.fill: appDelegate
13281355 target: appDelegate
13291356 enabled: false
1357+ visible: enabled
13301358 }
13311359
13321360 WindowedFullscreenPolicy {
@@ -1342,22 +1370,18 @@ AbstractStage {
13421370
13431371 SpreadDelegateInputArea {
13441372 id: dragArea
1345− anchors.fill: parent
1373+ objectName: "dragArea"
1374+ anchors.fill: decoratedWindow
13461375 enabled: false
13471376 closeable: model.application.appId !== "unity8-dash"
1348− closeIconOffset: spreadMaths.closeIconOffset
13491377
13501378 onClicked: {
13511379 spreadItem.highlightedIndex = index;
1380+ print("*****************setting highlighted index to:", index, appRepeater.itemAt(index))
13521381 if (distance == 0) {
13531382 priv.goneToSpread = false;
13541383 }
13551384 }
1356− onContainsMouseChanged: {
1357− // It could happen that this triggers during the transition from spread to windowed, only actually do something
1358− // if goneToSpread is still true...
1359− if (priv.goneToSpread && containsMouse) spreadItem.highlightedIndex = index
1360− }
13611385 onClose: {
13621386 priv.closingIndex = index
13631387 model.surface.close()
@@ -1368,13 +1392,43 @@ AbstractStage {
13681392
13691393 WindowInfoItem {
13701394 id: windowInfoItem
1395+ objectName: "windowInfoItem"
13711396 anchors { left: parent.left; top: decoratedWindow.bottom; topMargin: units.gu(1) }
13721397 title: model.application.name
13731398 iconSource: model.application.icon
13741399 height: spreadItem.appInfoHeight
13751400 opacity: 0
1401+ z: 1
13761402 visible: opacity > 0
13771403 }
1404+
1405+ Image {
1406+ id: closeImage
1407+ anchors { left: parent.left; top: parent.top; leftMargin: -height / 2; topMargin: -height / 2 + spreadMaths.closeIconOffset }
1408+ source: "graphics/window-close.svg"
1409+ readonly property var mousePos: hoverMouseArea.mapToItem(appDelegate, hoverMouseArea.mouseX, hoverMouseArea.mouseY)
1410+ visible: model.application.appId !== "unity8-dash"
1411+ && index == spreadItem.highlightedIndex
1412+ && mousePos.y < (decoratedWindow.height / 3)
1413+ && mousePos.y > -units.gu(4)
1414+ && mousePos.x > -units.gu(4)
1415+ && mousePos.x < (decoratedWindow.width * 2 / 3)
1416+ height: units.gu(2)
1417+ width: height
1418+ sourceSize.width: width
1419+ sourceSize.height: height
1420+
1421+ MouseArea {
1422+ id: closeMouseArea
1423+ objectName: "closeMouseArea"
1424+ anchors.fill: closeImage
1425+ anchors.margins: -units.gu(2)
1426+ onClicked: {
1427+ priv.closingIndex = index;
1428+ model.surface.close();
1429+ }
1430+ }
1431+ }
13781432 }
13791433 }
13801434 }
@@ -1402,6 +1456,59 @@ AbstractStage {
14021456 }
14031457 }
14041458
1459+ MouseArea {
1460+ id: hoverMouseArea
1461+ objectName: "hoverMouseArea"
1462+ anchors.fill: appContainer
1463+ propagateComposedEvents: true
1464+ hoverEnabled: true
1465+ enabled: false
1466+ visible: enabled
1467+
1468+ property int scrollAreaWidth: width / 3
1469+ property bool progressiveScrollingEnabled: false
1470+
1471+ onMouseXChanged: {
1472+ mouse.accepted = false
1473+
1474+ if (hoverMouseArea.pressed) {
1475+ return;
1476+ }
1477+
1478+ // Find the hovered item and mark it active
1479+ var mapped = mapToItem(appContainer, hoverMouseArea.mouseX, hoverMouseArea.mouseY)
1480+ var itemUnder = appContainer.childAt(mapped.x, mapped.y)
1481+ if (itemUnder) {
1482+ mapped = mapToItem(itemUnder, hoverMouseArea.mouseX, hoverMouseArea.mouseY)
1483+ var delegateChild = itemUnder.childAt(mapped.x, mapped.y)
1484+ if (delegateChild && (delegateChild.objectName === "dragArea" || delegateChild.objectName === "windowInfoItem")) {
1485+ spreadItem.highlightedIndex = appRepeater.indexOf(itemUnder)
1486+ }
1487+ }
1488+
1489+ if (floatingFlickable.contentWidth > floatingFlickable.width) {
1490+ var margins = floatingFlickable.width * 0.05;
1491+
1492+ if (!progressiveScrollingEnabled && mouseX < floatingFlickable.width - scrollAreaWidth) {
1493+ progressiveScrollingEnabled = true
1494+ }
1495+
1496+ // do we need to scroll?
1497+ if (mouseX < scrollAreaWidth + margins) {
1498+ var progress = Math.min(1, (scrollAreaWidth + margins - mouseX) / (scrollAreaWidth - margins));
1499+ var contentX = (1 - progress) * (floatingFlickable.contentWidth - floatingFlickable.width)
1500+ floatingFlickable.contentX = Math.max(0, Math.min(floatingFlickable.contentX, contentX))
1501+ }
1502+ if (mouseX > floatingFlickable.width - scrollAreaWidth && progressiveScrollingEnabled) {
1503+ var progress = Math.min(1, (mouseX - (floatingFlickable.width - scrollAreaWidth)) / (scrollAreaWidth - margins))
1504+ var contentX = progress * (floatingFlickable.contentWidth - floatingFlickable.width)
1505+ floatingFlickable.contentX = Math.min(floatingFlickable.contentWidth - floatingFlickable.width, Math.max(floatingFlickable.contentX, contentX))
1506+ }
1507+ }
1508+ }
1509+ onPressed: mouse.accepted = false
1510+ }
1511+
14051512 FloatingFlickable {
14061513 id: floatingFlickable
14071514 anchors.fill: appContainer
@@ -1424,6 +1531,7 @@ AbstractStage {
14241531 width: root.dragAreaWidth
14251532
14261533 property var gesturePoints: new Array()
1534+ property bool cancelled: false
14271535
14281536 property real progress: -touchPosition.x / root.width
14291537
@@ -1439,6 +1547,7 @@ AbstractStage {
14391547 if (dragging) {
14401548 // A potential edge-drag gesture has started. Start recording it
14411549 gesturePoints = [];
1550+ cancelled = false;
14421551 } else {
14431552 // Ok. The user released. Did he drag far enough to go to full spread?
14441553 if (gesturePoints[gesturePoints.length - 1] < -spreadItem.rightEdgeBreakPoint * spreadItem.width ) {
@@ -1458,8 +1567,8 @@ AbstractStage {
14581567 if (!oneWayFlickToRight) {
14591568 // Ok, the user made it, let's go to spread!
14601569 priv.goneToSpread = true;
1461−// } else {
1462−// appRepeater.itemAt(0).playFocusAnimation();
1570+ } else {
1571+ cancelled = true;
14631572 }
14641573 } else {
14651574 // Ok, the user didn't drag far enough to cross the breakPoint
@@ -1483,9 +1592,10 @@ AbstractStage {
14831592 break;
14841593 }
14851594 }
1595+ print("playing focus animation 1")
14861596 appRepeater.itemAt(priv.nextInStack).playFocusAnimation()
14871597 } else {
1488− appRepeater.itemAt(0).playFocusAnimation();
1598+ cancelled = true;
14891599 }
14901600
14911601 gesturePoints = [];