@@ -47,7 +47,7 @@ AbstractStage {
47 property string mode: "staged"
47 property string mode: "staged"
49 // Used by TutorialRight
49 // Used by TutorialRight
50− property bool spreadShown: state == "altTab"
50+ property bool spreadShown: state == "spread"
52 mainApp: priv.focusedAppDelegate ? priv.focusedAppDelegate.application : null
52 mainApp: priv.focusedAppDelegate ? priv.focusedAppDelegate.application : null
@@ -113,6 +113,7 @@ AbstractStage {
113 property var focusedAppDelegate: null
113 property var focusedAppDelegate: null
114 onFocusedAppDelegateChanged: {
114 onFocusedAppDelegateChanged: {
115 if (focusedAppDelegate && root.state == "spread") {
115 if (focusedAppDelegate && root.state == "spread") {
116+ print("clsing spread because of focus change to", focusedAppDelegate.application.appId)
116 goneToSpread = false;
117 goneToSpread = false;
@@ -121,8 +122,8 @@ AbstractStage {
122 property bool goneToSpread: false
123 property bool goneToSpread: false
123 property int closingIndex: -1
124 property int closingIndex: -1
124−// property int animationDuration: 4000
125+ property int animationDuration: 4000
125− property int animationDuration: UbuntuAnimation.FastDuration
126+// property int animationDuration: UbuntuAnimation.FastDuration
127 function updateForegroundMaximizedApp() {
128 function updateForegroundMaximizedApp() {
128 var found = false;
129 var found = false;
@@ -179,7 +180,7 @@ AbstractStage {
179 priv.sideStageAppId = "";
180 priv.sideStageAppId = "";
180 priv.mainStageDelegate = appRepeater.itemAt(0);
181 priv.mainStageDelegate = appRepeater.itemAt(0);
181 priv.mainStageAppId = topLevelSurfaceList.idAt(0);
182 priv.mainStageAppId = topLevelSurfaceList.idAt(0);
182− priv.mainStageAppId = topLevelSurfaceList.applicationAt(0).appId;
183+ priv.mainStageAppId = topLevelSurfaceList.applicationAt(0) ? topLevelSurfaceList.applicationAt(0).appId : ""
@@ -306,9 +307,10 @@ AbstractStage {
306 // resume all those apps at once. We might want to avoid that.
307 // resume all those apps at once. We might want to avoid that.
307 value: root.mode === "windowed"
308 value: root.mode === "windowed"
308 || (isDash && root.keepDashRunning)
309 || (isDash && root.keepDashRunning)
310+ || (!root.suspended && model.application && priv.focusedAppDelegate &&
309− || (!root.suspended && model.application && (priv.focusedAppDelegate.appId === model.application.appId ||
311+ (priv.focusedAppDelegate.appId === model.application.appId ||
310− priv.mainStageAppId === model.application.appId ||
312+ priv.mainStageAppId === model.application.appId ||
311− priv.sideStageAppId === model.application.appId))
313+ priv.sideStageAppId === model.application.appId))
312 ? ApplicationInfoInterface.RequestedRunning
314 ? ApplicationInfoInterface.RequestedRunning
313 : ApplicationInfoInterface.RequestedSuspended
315 : ApplicationInfoInterface.RequestedSuspended
@@ -335,6 +337,7 @@ AbstractStage {
335 name: "spread"; when: priv.goneToSpread
337 name: "spread"; when: priv.goneToSpread
336 PropertyChanges { target: floatingFlickable; enabled: true }
338 PropertyChanges { target: floatingFlickable; enabled: true }
337 PropertyChanges { target: spreadItem; focus: true }
339 PropertyChanges { target: spreadItem; focus: true }
340+ PropertyChanges { target: hoverMouseArea; enabled: true }
340 name: "stagedRightEdge"; when: rightEdgeDragArea.dragging && root.mode == "staged"
343 name: "stagedRightEdge"; when: rightEdgeDragArea.dragging && root.mode == "staged"
@@ -376,6 +379,8 @@ AbstractStage {
376 script: {
379 script: {
377 print("hightedIndex is:", spreadItem.highlightedIndex)
380 print("hightedIndex is:", spreadItem.highlightedIndex)
378 var item = appRepeater.itemAt(Math.max(0, spreadItem.highlightedIndex));
381 var item = appRepeater.itemAt(Math.max(0, spreadItem.highlightedIndex));
382+ print("playing focus animation 3 on item", spreadItem.highlightedIndex, item.application.appId)
379 item.playFocusAnimation();
384 item.playFocusAnimation();
@@ -465,6 +470,7 @@ AbstractStage {
465 onShownChanged: {
470 onShownChanged: {
466 print("sidestage shown changed:", shown)
471 print("sidestage shown changed:", shown)
467 if (!shown && priv.mainStageDelegate) {
472 if (!shown && priv.mainStageDelegate) {
473+ print("claiming focus 2")
468 priv.mainStageDelegate.claimFocus();
474 priv.mainStageDelegate.claimFocus();
@@ -499,6 +505,7 @@ AbstractStage {
499 onDropped: {
505 onDropped: {
500 if (drop.keys == "MainStage") {
506 if (drop.keys == "MainStage") {
501 drop.source.appDelegate.saveStage(ApplicationInfoInterface.SideStage);
507 drop.source.appDelegate.saveStage(ApplicationInfoInterface.SideStage);
508+ print("dropped on mainstage")
502 drop.source.appDelegate.focus = true;
509 drop.source.appDelegate.focus = true;
@@ -627,7 +634,7 @@ AbstractStage {
627 readonly property bool isDash: model.application.appId == "unity8-dash"
634 readonly property bool isDash: model.application.appId == "unity8-dash"
629 function claimFocus() {
636 function claimFocus() {
630− print("focusing app", priv.sideStageDelegate, appDelegate, sideStage.shown)
637+ print("(claimfocus) focusing app", priv.sideStageDelegate, appDelegate, sideStage.shown)
631 if (root.mode == "windowed" && minimized) {
638 if (root.mode == "windowed" && minimized) {
632 restore(true)
639 restore(true)
@@ -641,6 +648,7 @@ AbstractStage {
641 onFocusRequested: {
648 onFocusRequested: {
642 // Reset spread selection in case there is any
649 // Reset spread selection in case there is any
643 spreadItem.highlightedIndex = -1
650 spreadItem.highlightedIndex = -1
651+ print("claiming focus 3")
644 claimFocus();
652 claimFocus();
@@ -650,6 +658,7 @@ AbstractStage {
650 if (!model.surface) {
658 if (!model.surface) {
651 // when an app has no surfaces, we assume there's only one entry representing it:
659 // when an app has no surfaces, we assume there's only one entry representing it:
652 // this delegate.
660 // this delegate.
661+ print("claiming focus 4")
653 claimFocus();
662 claimFocus();
655 // if the application has surfaces, focus request should be at surface-level.
664 // if the application has surfaces, focus request should be at surface-level.
@@ -683,6 +692,7 @@ AbstractStage {
683 if (!appRepeater.startingUp) {
692 if (!appRepeater.startingUp) {
684 // a top level window is always the focused one when it first appears, unfocusing
693 // a top level window is always the focused one when it first appears, unfocusing
685 // any preexisting one
694 // any preexisting one
695+ print("focusing because of creation")
686 focus = true;
696 focus = true;
@@ -701,6 +711,7 @@ AbstractStage {
701 for (var i = 0; i < appRepeater.count; i++) {
711 for (var i = 0; i < appRepeater.count; i++) {
702 var appDelegate = appRepeater.itemAt(i);
712 var appDelegate = appRepeater.itemAt(i);
703 if (appDelegate && !appDelegate.minimized && i != index) {
713 if (appDelegate && !appDelegate.minimized && i != index) {
714+ print("focusing some other because of destruction")
704 appDelegate.focus = true;
715 appDelegate.focus = true;
@@ -787,6 +798,7 @@ AbstractStage {
787 rightEdgeFocusAnimation.start()
798 rightEdgeFocusAnimation.start()
789 } else if (state == "windowedRightEdge") {
800 } else if (state == "windowedRightEdge") {
801+ print("claiming focus 1")
790 claimFocus();
802 claimFocus();
792 focusAnimation.start()
804 focusAnimation.start()
@@ -805,19 +817,30 @@ AbstractStage {
805 from: 0.98
817 from: 0.98
807 duration: UbuntuAnimation.SnapDuration
819 duration: UbuntuAnimation.SnapDuration
821+ print("starting focusanimation for", model.application.appId)
808− onStarted: topLevelSurfaceList.raiseId(model.id);
822+ topLevelSurfaceList.raiseId(model.id);
825+ print("focusing because of normal focus animation finishing")
809− onStopped: appDelegate.focus = true
826+ appDelegate.focus = true
811 ParallelAnimation {
829 ParallelAnimation {
812 id: rightEdgeFocusAnimation
830 id: rightEdgeFocusAnimation
813 property int targetX: 0
831 property int targetX: 0
832+ onStarted: print("starting rightedgefocusanimation for", model.application.appId)
814 UbuntuNumberAnimation { target: appDelegate; properties: "x"; to: rightEdgeFocusAnimation.targetX; duration: priv.animationDuration }
833 UbuntuNumberAnimation { target: appDelegate; properties: "x"; to: rightEdgeFocusAnimation.targetX; duration: priv.animationDuration }
815 UbuntuNumberAnimation { target: decoratedWindow; properties: "angle"; to: 0; duration: priv.animationDuration }
834 UbuntuNumberAnimation { target: decoratedWindow; properties: "angle"; to: 0; duration: priv.animationDuration }
816 UbuntuNumberAnimation { target: decoratedWindow; properties: "itemScale"; to: 1; duration: priv.animationDuration }
835 UbuntuNumberAnimation { target: decoratedWindow; properties: "itemScale"; to: 1; duration: priv.animationDuration }
837+ print("focusing", model.application.appId, "because of right edge focus animation completion");
817− onStopped: appDelegate.focus = true
838+ appDelegate.focus = true
819 ParallelAnimation {
841 ParallelAnimation {
820 id: hidingAnimation
842 id: hidingAnimation
843+ onStarted: print("starting hiding animation for", model.application.appId)
821 UbuntuNumberAnimation { target: appDelegate; property: "opacity"; to: 0; duration: priv.animationDuration }
844 UbuntuNumberAnimation { target: appDelegate; property: "opacity"; to: 0; duration: priv.animationDuration }
822 onStopped: appDelegate.opacity = 1
845 onStopped: appDelegate.opacity = 1
@@ -1139,7 +1162,7 @@ AbstractStage {
1139 from: "spread"; to: "*"
1162 from: "spread"; to: "*"
1140// UbuntuNumberAnimation { target: appDelegate; properties: "x,y,height"; duration: priv.animationDuration }
1163// UbuntuNumberAnimation { target: appDelegate; properties: "x,y,height"; duration: priv.animationDuration }
1141// UbuntuNumberAnimation { target: decoratedWindow; properties: "width,height,itemScale,angle"; duration: priv.animationDuration }
1164// 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() }
1144 Transition {
1167 Transition {
1145 to: "minimized"
1168 to: "minimized"
@@ -1212,16 +1235,16 @@ AbstractStage {
1213 Transition {
1236 Transition {
1214 from: "stagedRightEdge"; to: "staged"
1237 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.
1215 SequentialAnimation {
1239 SequentialAnimation {
1216 ParallelAnimation {
1240 ParallelAnimation {
1217 UbuntuNumberAnimation { target: appDelegate; properties: "x,y,height,width,scale"; duration: priv.animationDuration }
1241 UbuntuNumberAnimation { target: appDelegate; properties: "x,y,height,width,scale"; duration: priv.animationDuration }
1218 UbuntuNumberAnimation { target: decoratedWindow; properties: "width,height,itemScale,angle,scaleToPreviewProgress"; duration: priv.animationDuration }
1242 UbuntuNumberAnimation { target: decoratedWindow; properties: "width,height,itemScale,angle,scaleToPreviewProgress"; duration: priv.animationDuration }
1220− // // We need to release scaleToPreviewSize at last
1244+ // We need to release scaleToPreviewSize at last
1221 PropertyAction { target: decoratedWindow; property: "scaleToPreviewSize" }
1245 PropertyAction { target: decoratedWindow; property: "scaleToPreviewSize" }
1227 Binding {
1250 Binding {
@@ -1246,6 +1269,7 @@ AbstractStage {
1246 screenHeight: appContainer.height
1269 screenHeight: appContainer.height
1247 leftMargin: root.leftMargin
1270 leftMargin: root.leftMargin
1248 enabled: false
1271 enabled: false
1250 onPressed: {
1274 onPressed: {
1251 print("***** focusing because of resize area press", model.application.appId)
1275 print("***** focusing because of resize area press", model.application.appId)
@@ -1298,7 +1322,10 @@ AbstractStage {
1298 onMaximizeHorizontallyClicked: appDelegate.maximizedHorizontally ? appDelegate.restoreFromMaximized() : appDelegate.maximizeHorizontally()
1322 onMaximizeHorizontallyClicked: appDelegate.maximizedHorizontally ? appDelegate.restoreFromMaximized() : appDelegate.maximizeHorizontally()
1299 onMaximizeVerticallyClicked: appDelegate.maximizedVertically ? appDelegate.restoreFromMaximized() : appDelegate.maximizeVertically()
1323 onMaximizeVerticallyClicked: appDelegate.maximizedVertically ? appDelegate.restoreFromMaximized() : appDelegate.maximizeVertically()
1300 onMinimizeClicked: appDelegate.minimize()
1324 onMinimizeClicked: appDelegate.minimize()
1325+ onDecorationPressed: {
1326+ print("focusing because of decoration press");
1301− onDecorationPressed: { appDelegate.focus = true; }
1327+ appDelegate.focus = true;
1303 property real angle: 0
1330 property real angle: 0
1304 property real itemScale: 1
1331 property real itemScale: 1
@@ -1327,6 +1354,7 @@ AbstractStage {
1327 anchors.fill: appDelegate
1354 anchors.fill: appDelegate
1328 target: appDelegate
1355 target: appDelegate
1329 enabled: false
1356 enabled: false
1332 WindowedFullscreenPolicy {
1360 WindowedFullscreenPolicy {
@@ -1342,22 +1370,18 @@ AbstractStage {
1343 SpreadDelegateInputArea {
1371 SpreadDelegateInputArea {
1344 id: dragArea
1372 id: dragArea
1373+ objectName: "dragArea"
1345− anchors.fill: parent
1374+ anchors.fill: decoratedWindow
1346 enabled: false
1375 enabled: false
1347 closeable: model.application.appId !== "unity8-dash"
1376 closeable: model.application.appId !== "unity8-dash"
1348− closeIconOffset: spreadMaths.closeIconOffset
1350 onClicked: {
1378 onClicked: {
1351 spreadItem.highlightedIndex = index;
1379 spreadItem.highlightedIndex = index;
1380+ print("*****************setting highlighted index to:", index, appRepeater.itemAt(index))
1352 if (distance == 0) {
1381 if (distance == 0) {
1353 priv.goneToSpread = false;
1382 priv.goneToSpread = false;
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
1361 onClose: {
1385 onClose: {
1362 priv.closingIndex = index
1386 priv.closingIndex = index
1363 model.surface.close()
1387 model.surface.close()
@@ -1368,13 +1392,43 @@ AbstractStage {
1369 WindowInfoItem {
1393 WindowInfoItem {
1370 id: windowInfoItem
1394 id: windowInfoItem
1395+ objectName: "windowInfoItem"
1371 anchors { left: parent.left; top: decoratedWindow.bottom; topMargin: units.gu(1) }
1396 anchors { left: parent.left; top: decoratedWindow.bottom; topMargin: units.gu(1) }
1372 title: model.application.name
1397 title: model.application.name
1373 iconSource: model.application.icon
1398 iconSource: model.application.icon
1374 height: spreadItem.appInfoHeight
1399 height: spreadItem.appInfoHeight
1375 opacity: 0
1400 opacity: 0
1376 visible: opacity > 0
1402 visible: opacity > 0
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)
1418+ sourceSize.width: width
1419+ sourceSize.height: height
1423+ objectName: "closeMouseArea"
1424+ anchors.fill: closeImage
1425+ anchors.margins: -units.gu(2)
1427+ priv.closingIndex = index;
1428+ model.surface.close();
@@ -1402,6 +1456,59 @@ AbstractStage {
1461+ objectName: "hoverMouseArea"
1462+ anchors.fill: appContainer
1463+ propagateComposedEvents: true
1468+ property int scrollAreaWidth: width / 3
1469+ property bool progressiveScrollingEnabled: false
1472+ mouse.accepted = false
1474+ if (hoverMouseArea.pressed) {
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)
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)
1489+ if (floatingFlickable.contentWidth > floatingFlickable.width) {
1490+ var margins = floatingFlickable.width * 0.05;
1492+ if (!progressiveScrollingEnabled && mouseX < floatingFlickable.width - scrollAreaWidth) {
1493+ progressiveScrollingEnabled = true
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))
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))
1509+ onPressed: mouse.accepted = false
1405 FloatingFlickable {
1512 FloatingFlickable {
1406 id: floatingFlickable
1513 id: floatingFlickable
1407 anchors.fill: appContainer
1514 anchors.fill: appContainer
@@ -1424,6 +1531,7 @@ AbstractStage {
1424 width: root.dragAreaWidth
1531 width: root.dragAreaWidth
1426 property var gesturePoints: new Array()
1533 property var gesturePoints: new Array()
1534+ property bool cancelled: false
1428 property real progress: -touchPosition.x / root.width
1536 property real progress: -touchPosition.x / root.width
@@ -1439,6 +1547,7 @@ AbstractStage {
1439 if (dragging) {
1547 if (dragging) {
1440 // A potential edge-drag gesture has started. Start recording it
1548 // A potential edge-drag gesture has started. Start recording it
1441 gesturePoints = [];
1549 gesturePoints = [];
1442 } else {
1551 } else {
1443 // Ok. The user released. Did he drag far enough to go to full spread?
1552 // Ok. The user released. Did he drag far enough to go to full spread?
1444 if (gesturePoints[gesturePoints.length - 1] < -spreadItem.rightEdgeBreakPoint * spreadItem.width ) {
1553 if (gesturePoints[gesturePoints.length - 1] < -spreadItem.rightEdgeBreakPoint * spreadItem.width ) {
@@ -1458,8 +1567,8 @@ AbstractStage {
1458 if (!oneWayFlickToRight) {
1567 if (!oneWayFlickToRight) {
1459 // Ok, the user made it, let's go to spread!
1568 // Ok, the user made it, let's go to spread!
1460 priv.goneToSpread = true;
1569 priv.goneToSpread = true;
1461−// } else {
1570+ } else {
1462−// appRepeater.itemAt(0).playFocusAnimation();
1571+ cancelled = true;
1464 } else {
1573 } else {
1465 // Ok, the user didn't drag far enough to cross the breakPoint
1574 // Ok, the user didn't drag far enough to cross the breakPoint
@@ -1483,9 +1592,10 @@ AbstractStage {
1595+ print("playing focus animation 1")
1486 appRepeater.itemAt(priv.nextInStack).playFocusAnimation()
1596 appRepeater.itemAt(priv.nextInStack).playFocusAnimation()
1487 } else {
1597 } else {
1488− appRepeater.itemAt(0).playFocusAnimation();
1598+ cancelled = true;
1491 gesturePoints = [];
1601 gesturePoints = [];