@@ -46,7 +46,7 @@ AbstractStage {
46 if (delta < 0) { delta += 360; }
46 if (delta < 0) { delta += 360; }
47 delta = delta % 360;
47 delta = delta % 360;
49− var supportedOrientations = spreadDelegate.application.supportedOrientations;
49+ var supportedOrientations = spreadDelegate.supportedOrientations;
50 if (supportedOrientations === Qt.PrimaryOrientation) {
50 if (supportedOrientations === Qt.PrimaryOrientation) {
51 supportedOrientations = spreadDelegate.orientations.primary;
51 supportedOrientations = spreadDelegate.orientations.primary;
@@ -78,9 +78,24 @@ AbstractStage {
79 orientationChangesEnabled: priv.mainAppOrientationChangesEnabled
79 orientationChangesEnabled: priv.mainAppOrientationChangesEnabled
81+ supportedOrientations: {
81− supportedOrientations: mainApp ? mainApp.supportedOrientations
83+ var orientations = mainApp.supportedOrientations;
84+ orientations |= Qt.LandscapeOrientation | Qt.InvertedLandscapeOrientation;
85+ if (priv.sideStageAppId && !spreadView.surfaceDragging) {
86+ // If we have a sidestage app, support Portrait orientation
87+ // so that it will switch the sidestage app to mainstage on rotate
82− : (Qt.PortraitOrientation | Qt.LandscapeOrientation
88+ orientations |= Qt.PortraitOrientation|Qt.InvertedPortraitOrientation;
92+ // we just don't care
93+ return Qt.PortraitOrientation |
94+ Qt.LandscapeOrientation |
95+ Qt.InvertedPortraitOrientation |
83− | Qt.InvertedPortraitOrientation | Qt.InvertedLandscapeOrientation)
96+ Qt.InvertedLandscapeOrientation;
85 onWidthChanged: {
100 onWidthChanged: {
86 spreadView.selectedIndex = -1;
101 spreadView.selectedIndex = -1;
@@ -88,13 +103,6 @@ AbstractStage {
88 spreadView.contentX = -spreadView.shift;
103 spreadView.contentX = -spreadView.shift;
91− onShellOrientationChanged: {
92− if (shellOrientation == Qt.PortraitOrientation || shellOrientation == Qt.InvertedPortraitOrientation) {
93− ApplicationManager.focusApplication(priv.mainStageAppId);
94− priv.sideStageAppId = "";
98 onInverseProgressChanged: {
106 onInverseProgressChanged: {
99 // This can't be a simple binding because that would be triggered after this handler
107 // This can't be a simple binding because that would be triggered after this handler
100 // while we need it active before doing the anition left/right
108 // while we need it active before doing the anition left/right
@@ -170,20 +178,7 @@ AbstractStage {
171 property int highlightIndex: 0
179 property int highlightIndex: 0
173− onFocusedAppIdChanged: {
181+ onFocusedAppIdChanged: updateStageApps()
174− if (priv.focusedAppId.length > 0) {
175− var focusedApp = ApplicationManager.findApplication(focusedAppId);
176− if (focusedApp.stage == ApplicationInfoInterface.SideStage) {
177− priv.sideStageAppId = focusedAppId;
179− priv.mainStageAppId = focusedAppId;
180− root.mainApp = focusedApp;
184− appId0 = ApplicationManager.count >= 1 ? ApplicationManager.get(0).appId : "";
185− appId1 = ApplicationManager.count > 1 ? ApplicationManager.get(1).appId : "";
188 onFocusedAppDelegateChanged: {
183 onFocusedAppDelegateChanged: {
189 if (focusedAppDelegate) {
184 if (focusedAppDelegate) {
@@ -229,6 +224,46 @@ AbstractStage {
229 onHighlightIndexChanged: {
224 onHighlightIndexChanged: {
230 spreadView.contentX = highlightIndex * spreadView.contentWidth / (spreadRepeater.count + 2)
225 spreadView.contentX = highlightIndex * spreadView.contentWidth / (spreadRepeater.count + 2)
228+ function getTopApp(stage) {
229+ for (var i = 0; i < ApplicationManager.count; i++) {
230+ var app = ApplicationManager.get(i)
231+ if (app.stage === stage) {
238+ function setAppStage(appId, stage, save) {
239+ var app = ApplicationManager.findApplication(appId);
243+ WindowStateStorage.saveStage(appId, stage);
248+ function updateStageApps() {
249+ var app = priv.getTopApp(ApplicationInfoInterface.MainStage);
250+ priv.mainStageAppId = app ? app.appId : ""
253+ if (sideStage.shown) {
254+ app = priv.getTopApp(ApplicationInfoInterface.SideStage);
255+ priv.sideStageAppId = app ? app.appId : ""
257+ priv.sideStageAppId = "";
260+ appId0 = ApplicationManager.count >= 1 ? ApplicationManager.get(0).appId : "";
261+ appId1 = ApplicationManager.count > 1 ? ApplicationManager.get(1).appId : "";
264+ readonly property bool sideStageEnabled: root.shellOrientation == Qt.LandscapeOrientation ||
265+ root.shellOrientation == Qt.InvertedLandscapeOrientation
266+ Component.onCompleted: updateStageApps();
234 Connections {
269 Connections {
@@ -256,7 +291,8 @@ AbstractStage {
256 ApplicationManager.focusApplication("unity8-dash")
291 ApplicationManager.focusApplication("unity8-dash")
258 if (priv.sideStageAppId == appId) {
293 if (priv.sideStageAppId == appId) {
294+ var app = priv.getTopApp(ApplicationInfoInterface.SideStage);
259− priv.sideStageAppId = "";
295+ priv.sideStageAppId = app === null ? "" : app.appId;
262 if (ApplicationManager.count == 0) {
298 if (ApplicationManager.count == 0) {
@@ -267,6 +303,7 @@ AbstractStage {
267 // lets make sure the spread doesn't mess up by the changing app list.
303 // lets make sure the spread doesn't mess up by the changing app list.
268 spreadView.phase = 0;
304 spreadView.phase = 0;
269 spreadView.contentX = -spreadView.shift;
305 spreadView.contentX = -spreadView.shift;
270 ApplicationManager.focusApplication(ApplicationManager.get(0).appId);
307 ApplicationManager.focusApplication(ApplicationManager.get(0).appId);
@@ -322,6 +359,7 @@ AbstractStage {
322 property int selectedIndex: -1
359 property int selectedIndex: -1
323 property int draggedDelegateCount: 0
360 property int draggedDelegateCount: 0
324 property int closingIndex: -1
361 property int closingIndex: -1
362+ property var selectedApplication: selectedIndex !== -1 ? ApplicationManager.get(selectedIndex) : null
326 // FIXME: Workaround Flickable's not keepping its contentX still when resized
364 // FIXME: Workaround Flickable's not keepping its contentX still when resized
327 onContentXChanged: { forceItToRemainStillIfBeingResized(); }
365 onContentXChanged: { forceItToRemainStillIfBeingResized(); }
@@ -343,15 +381,8 @@ AbstractStage {
346− property bool sideStageDragging: sideStageDragHandle.dragging
347− property real sideStageDragProgress: sideStageDragHandle.progress
384+ property real sideStageDragProgress: sideStage.progress
348−
385+ property bool surfaceDragging: triGestureArea.recognisedDrag
349− onSideStageDragProgressChanged: {
350− if (sideStageDragProgress == 1) {
351− ApplicationManager.focusApplication(priv.mainStageAppId);
352− priv.sideStageAppId = "";
356 // In case the ApplicationManager already holds an app when starting up we're missing animations
387 // In case the ApplicationManager already holds an app when starting up we're missing animations
357 // Make sure we end up in the same state
388 // Make sure we end up in the same state
@@ -402,7 +433,7 @@ AbstractStage {
405− if (priv.mainStageAppId && !priv.sideStageAppId) {
436+ if ((priv.mainStageAppId && !priv.sideStageAppId) || !priv.sideStageEnabled) {
406 return "main";
437 return "main";
408 if (!priv.mainStageAppId && priv.sideStageAppId) {
439 if (!priv.mainStageAppId && priv.sideStageAppId) {
@@ -419,12 +450,26 @@ AbstractStage {
419 // Flickabe.contentX wiggles during resizes. Don't react to it.
450 // Flickabe.contentX wiggles during resizes. Don't react to it.
456+ // the "spreadEnabled" part is because when code does "phase = 0; contentX = -shift" to
457+ // dismiss the spread because spreadEnabled went to false, for some reason, during tests,
458+ // Flickable might jump in and change contentX value back, causing the code below to do
459+ // "phase = 1" which will make the spread stay.
460+ // It sucks that we have no control whatsoever over whether or when Flickable animates its
422− if (spreadView.phase == 0 && spreadView.shiftedContentX > spreadView.width * spreadView.positionMarker2) {
462+ if (root.spreadEnabled && shiftedContentX > width * positionMarker2) {
423− spreadView.phase = 1;
463+ phase = 1;
467+ if (shiftedContentX < width * positionMarker2) {
424− } else if (spreadView.phase == 1 && spreadView.shiftedContentX > spreadView.width * spreadView.positionMarker4) {
469+ } else if (shiftedContentX >= width * positionMarker4 && !spreadDragArea.dragging) {
425− spreadView.phase = 2;
470+ phase = 2;
426− } else if (spreadView.phase == 1 && spreadView.shiftedContentX < spreadView.width * spreadView.positionMarker2) {
471+ }
427− spreadView.phase = 0;
472+ break;
@@ -446,6 +491,7 @@ AbstractStage {
448 function snapTo(index) {
493 function snapTo(index) {
494+ snapAnimation.stop();
449 spreadView.selectedIndex = index;
495 spreadView.selectedIndex = index;
450 snapAnimation.targetContentX = -shift;
496 snapAnimation.targetContentX = -shift;
451 snapAnimation.start();
497 snapAnimation.start();
@@ -455,55 +501,41 @@ AbstractStage {
455 // We don't want to really reorder them in the model because that allows us to keep track
501 // We don't want to really reorder them in the model because that allows us to keep track
456 // of the last focused order.
502 // of the last focused order.
457 function indexToZIndex(index) {
503 function indexToZIndex(index) {
504+ // only shuffle when we've got a main and overlay
505+ if (state !== "mainAndOverlay") return index;
458 var app = ApplicationManager.get(index);
507 var app = ApplicationManager.get(index);
459 if (!app) {
508 if (!app) {
460 return index;
509 return index;
512+ // don't shuffle indexes greater than "actives or next"
513+ if (index > 2) return index;
463− var active = app.appId == priv.mainStageAppId || app.appId == priv.sideStageAppId;
515+ if (app.appId === priv.mainStageAppId) {
464− if (active && app.stage == ApplicationInfoInterface.MainStage) {
516+ // Active main stage always at 0
465− // if this app is active, and its the MainStage, always put it to index 0
466 return 0;
517 return 0;
468− if (active && app.stage == ApplicationInfoInterface.SideStage) {
469− if (!priv.mainStageAppId) {
470− // Only have SS apps running. Put the active one at 0
474− // Precondition now: There's an active MS app and this is SS app:
520+ if (spreadView.nextInStack > 0) {
475− if (spreadView.nextInStack >= 0 && ApplicationManager.get(spreadView.nextInStack).stage == ApplicationInfoInterface.MainStage) {
521+ var nextAppInStack = ApplicationManager.get(spreadView.nextInStack);
476− // If the next app coming from the right is a MS app, we need to elevate this SS ap above it.
522+
477− // Put it to at least level 2, or higher if there's more apps coming in before this one.
523+ if (index === spreadView.nextInStack) {
478− return Math.max(index, 2);
524+ // this is the next app in stack.
480− // if this is no next app to come in from the right, place this one at index 1, just on top the active MS app.
526+ if (app.stage === ApplicationInfoInterface.SideStage) {
527+ // if the next app in stack is a sidestage app, it must order on top of other side stage app
528+ return Math.min(2, ApplicationManager.count-1);
481 return 1;
530 return 1;
484− if (index <= 2 && app.stage == ApplicationInfoInterface.MainStage && priv.sideStageAppId) {
485− // Ok, this is an inactive MS app. If there's an active SS app around, we need to place this one
486− // in between the active MS app and the active SS app, so that it comes in from there when dragging from the right.
487− // If there's now active SS app, just leave it where it is.
488− return priv.indexOf(priv.sideStageAppId) < index ? index - 1 : index;
490− if (index == spreadView.nextInStack && app.stage == ApplicationInfoInterface.SideStage) {
532+ if (nextAppInStack.stage === ApplicationInfoInterface.SideStage) {
491− // This is a SS app and the next one to come in from the right:
533+ // if the next app in stack is a sidestage app, it must order on top of other side stage app
492− if (priv.sideStageAppId && priv.mainStageAppId) {
493− // If there's both, an active MS and an active SS app, put this one right on top of that
494− return 2;
534+ return 1;
496− // Or if there's only one other active app, put it on top of that.
536+ return Math.min(2, ApplicationManager.count-1);
497− // The case that there isn't any other active app is already handled above.
500− if (index == 2 && spreadView.nextInStack == 1 && priv.sideStageAppId) {
501− // If its index 2 but not the next one to come in, it means
502− // we've pulled another one down to index 2. Move this one up to 2 instead.
505− // don't touch all others... (mostly index > 3 + simple cases where the above doesn't shuffle much)
538+ return Math.min(index+1, ApplicationManager.count-1);
509 SequentialAnimation {
541 SequentialAnimation {
@@ -521,8 +553,12 @@ AbstractStage {
521 script: {
553 script: {
522 if (spreadView.selectedIndex >= 0) {
554 if (spreadView.selectedIndex >= 0) {
523 var newIndex = spreadView.selectedIndex;
555 var newIndex = spreadView.selectedIndex;
556+ var application = ApplicationManager.get(newIndex);
557+ if (application.stage === ApplicationInfoInterface.SideStage) {
558+ sideStage.showNow();
524 spreadView.selectedIndex = -1;
560 spreadView.selectedIndex = -1;
525− ApplicationManager.focusApplication(ApplicationManager.get(newIndex).appId);
561+ ApplicationManager.focusApplication(application.appId);
526 spreadView.phase = 0;
562 spreadView.phase = 0;
527 spreadView.contentX = -spreadView.shift;
563 spreadView.contentX = -spreadView.shift;
@@ -545,87 +581,82 @@ AbstractStage {
545 spreadView.snapTo(0);
581 spreadView.snapTo(0);
548− Rectangle {
584+ DropArea {
549− id: sideStageBackground
585+ objectName: "MainStageDropArea"
550− color: "black"
586+ anchors {
551− width: spreadView.sideStageWidth * (1 - sideStageDragHandle.progress)
587+ left: parent.left
552− height: priv.landscapeHeight
588+ top: parent.top
589+ bottom: parent.bottom
553− x: spreadView.width - width
591+ width: spreadView.width - sideStage.width
554− z: spreadView.indexToZIndex(priv.indexOf(priv.sideStageAppId))
592+ enabled: priv.sideStageEnabled
555− opacity: spreadView.phase == 0 ? 1 : 0
593+
556− Behavior on opacity { UbuntuNumberAnimation {} }
594+ onDropped: {
595+ priv.setAppStage(drag.source.appId, ApplicationInfoInterface.MainStage, true);
596+ ApplicationManager.focusApplication(drag.source.appId);
559− Item {
601+ SideStage {
560− id: sideStageDragHandle
602+ id: sideStage
561− anchors.right: sideStageBackground.left
603+ objectName: "sideStage"
562− anchors.top: sideStageBackground.top
564 height: priv.landscapeHeight
604 height: priv.landscapeHeight
565− z: sideStageBackground.z
605+ x: spreadView.width - width
566− opacity: spreadView.phase <= 0 && spreadView.sideStageVisible ? 1 : 0
606+ z: {
567− property real progress: 0
607+ if (!priv.mainStageAppId) return 0;
568− property bool dragging: false
570− Behavior on opacity { UbuntuNumberAnimation {} }
609+ if (priv.sideStageAppId && spreadView.nextInStack > 0) {
610+ var nextAppInStack = ApplicationManager.get(spreadView.nextInStack);
572− Connections {
612+ if (nextAppInStack.stage === ApplicationInfoInterface.MainStage) {
573− target: spreadView
613+ // if the next app in stack is a main stage app, put the sidestage on top of it.
574− onSideStageVisibleChanged: {
614+ return 2;
575− if (spreadView.sideStageVisible) {
576− sideStageDragHandle.progress = 0;
621+ visible: progress != 0
622+ enabled: priv.sideStageEnabled && sideStageDropArea.dropAllowed
623+ opacity: priv.sideStageEnabled && !spreadView.active ? 1 : 0
624+ Behavior on opacity { UbuntuNumberAnimation {} }
581− Image {
626+ onShownChanged: {
582− anchors.centerIn: parent
627+ if (!shown && ApplicationManager.focusedApplicationId == priv.sideStageAppId) {
583− width: sideStageDragHandleMouseArea.pressed ? parent.width * 2 : parent.width
628+ ApplicationManager.requestFocusApplication(priv.mainStageAppId);
584− height: parent.height
629+ }
585− source: "graphics/sidestage_handle@20.png"
630+ priv.updateStageApps();
586− Behavior on width { UbuntuNumberAnimation {} }
631+ if (shown && priv.sideStageAppId) {
632+ ApplicationManager.requestFocusApplication(priv.sideStageAppId);
589− MouseArea {
636+ DropArea {
590− id: sideStageDragHandleMouseArea
637+ id: sideStageDropArea
638+ objectName: "SideStageDropArea"
591 anchors.fill: parent
639 anchors.fill: parent
592− enabled: spreadView.shiftedContentX == 0
640+
593− property int startX
641+ property bool dropAllowed: true
594− property var gesturePoints: new Array()
642+
595− property real totalDiff
643+ onEntered: {
596−
644+ dropAllowed = drag.keys != "Disabled";
601− sideStageDragHandle.progress = 0;
602− sideStageDragHandle.dragging = true;
605− totalDiff += mouseX - startX;
606− if (priv.mainStageAppId) {
607− sideStageDragHandle.progress = Math.max(0, totalDiff / spreadView.sideStageWidth);
609− gesturePoints.push(mouseX);
611− onReleased: {
646+ onExited: {
612− if (priv.mainStageAppId) {
647+ dropAllowed = true;
613− var oneWayFlick = priv.evaluateOneWayFlick(gesturePoints);
648+ }
614− sideStageDragSnapAnimation.to = sideStageDragHandle.progress > 0.5 || oneWayFlick ? 1 : 0;
649+ onDropped: {
615− sideStageDragSnapAnimation.start();
650+ if (drop.keys == "MainStage") {
616− } else {
651+ priv.setAppStage(drop.source.appId, ApplicationInfoInterface.SideStage, true);
617− sideStageDragHandle.dragging = false;
652+ ApplicationManager.requestFocusApplication(drop.source.appId);
621− UbuntuNumberAnimation {
656+ onSourceChanged: {
622− id: sideStageDragSnapAnimation
657+ if (!sideStageDropArea.drag.source) {
623− target: sideStageDragHandle
658+ dropAllowed = true;
624− property: "progress"
659+ }
628− sideStageDragHandle.dragging = false;
@@ -640,29 +671,17 @@ AbstractStage {
640 id: spreadTile
671 id: spreadTile
641 objectName: model.appId ? "tabletSpreadDelegate_" + model.appId
672 objectName: model.appId ? "tabletSpreadDelegate_" + model.appId
642 : "tabletSpreadDelegate_null";
673 : "tabletSpreadDelegate_null";
644− if (wantsMainStage) {
645− return spreadView.width;
674+ width: spreadView.width
647− return spreadView.sideStageWidth;
651− if (wantsMainStage) {
652− return spreadView.height;
675+ height: spreadView.height
654− return priv.landscapeHeight;
657− active: model.appId == priv.mainStageAppId || model.appId == priv.sideStageAppId
676+ active: appId == priv.mainStageAppId || appId == priv.sideStageAppId
658− zIndex: spreadView.indexToZIndex(index)
677+ zIndex: selected && stage == ApplicationInfoInterface.MainStage ? 0 : spreadView.indexToZIndex(index)
659 selected: spreadView.selectedIndex == index
678 selected: spreadView.selectedIndex == index
660 otherSelected: spreadView.selectedIndex >= 0 && !selected
679 otherSelected: spreadView.selectedIndex >= 0 && !selected
661− isInSideStage: priv.sideStageAppId == model.appId
680+ isInSideStage: priv.sideStageAppId === appId
662 interactive: !spreadView.interactive && spreadView.phase === 0 && root.interactive
681 interactive: !spreadView.interactive && spreadView.phase === 0 && root.interactive
663 swipeToCloseEnabled: spreadView.interactive && !snapAnimation.running
682 swipeToCloseEnabled: spreadView.interactive && !snapAnimation.running
664 maximizedAppTopMargin: root.maximizedAppTopMargin
683 maximizedAppTopMargin: root.maximizedAppTopMargin
665− dragOffset: !isDash && model.appId == priv.mainStageAppId && root.inverseProgress > 0 && spreadView.phase === 0 ? root.inverseProgress : 0
684+ dragOffset: !isDash && appId == priv.mainStageAppId && root.inverseProgress > 0 && spreadView.phase === 0 ? root.inverseProgress : 0
666 application: ApplicationManager.get(index)
685 application: ApplicationManager.get(index)
667 closeable: !isDash
686 closeable: !isDash
668 highlightShown: root.altTabPressed && priv.highlightIndex == zIndex
687 highlightShown: root.altTabPressed && priv.highlightIndex == zIndex
@@ -671,6 +690,35 @@ AbstractStage {
672 readonly property bool isDash: model.appId == "unity8-dash"
691 readonly property bool isDash: model.appId == "unity8-dash"
695+ if (mainApp && stage === ApplicationInfoInterface.SideStage) {
696+ return mainApp.fullscreen;
698+ return application ? application.fullscreen : false;
701+ supportedOrientations: {
703+ var orientations = application.supportedOrientations;
704+ if (stage == ApplicationInfoInterface.MainStage) {
705+ // When an app is in the mainstage, it always supports Landscape|InvertedLandscape
706+ // so that we can drag it from the main stage to the side stage
707+ orientations |= Qt.LandscapeOrientation | Qt.InvertedLandscapeOrientation;
709+ return orientations;
711+ // we just don't care
712+ return Qt.PortraitOrientation |
713+ Qt.LandscapeOrientation |
714+ Qt.InvertedPortraitOrientation |
715+ Qt.InvertedLandscapeOrientation;
719+ readonly property string appId: model.appId
720+ readonly property bool isDash: appId == "unity8-dash"
674 Binding {
722 Binding {
675 target: spreadTile.application
723 target: spreadTile.application
676 property: "exemptFromLifecycle"
724 property: "exemptFromLifecycle"
@@ -701,6 +749,28 @@ AbstractStage {
701 enabled: spreadView.closingIndex >= 0
749 enabled: spreadView.closingIndex >= 0
702 UbuntuNumberAnimation {}
750 UbuntuNumberAnimation {}
754+ onSideStageEnabledChanged: refreshStage()
757+ Component.onCompleted: {
759+ stageChanged.connect(priv.updateStageApps);
762+ function refreshStage() {
763+ var stage = ApplicationInfoInterface.MainStage;
764+ if (priv.sideStageEnabled) {
765+ if (application && application.supportedOrientations & (Qt.PortraitOrientation|Qt.InvertedPortraitOrientation)) {
766+ stage = WindowStateStorage.getStage(appId);
770+ if (model.stage !== stage) {
771+ priv.setAppStage(appId, stage, false);
705 // This is required because none of the bindings are triggered in some cases:
775 // This is required because none of the bindings are triggered in some cases:
706 // When an app is closed, it might happen that ApplicationManager.get(nextInStack)
776 // When an app is closed, it might happen that ApplicationManager.get(nextInStack)
@@ -725,7 +795,7 @@ AbstractStage {
726 // TODO: Hiding tile when progress is such that it will be off screen.
796 // TODO: Hiding tile when progress is such that it will be off screen.
727 property bool occluded: {
797 property bool occluded: {
728− if (spreadView.active) return false;
798+ if (spreadView.active && !offScreen) return false;
729 else if (spreadTile.active) return false;
799 else if (spreadTile.active) return false;
730 else if (xTranslateAnimating) return false;
800 else if (xTranslateAnimating) return false;
731 else if (z <= 1 && priv.focusedAppDelegateIsDislocated) return false;
801 else if (z <= 1 && priv.focusedAppDelegateIsDislocated) return false;
@@ -749,17 +819,87 @@ AbstractStage {
749 return progress;
819 return progress;
752− shellOrientationAngle: wantsMainStage ? root.shellOrientationAngle : 0
822+ shellOrientationAngle: root.shellOrientationAngle
823+ shellOrientation: root.shellOrientation
824+ orientations: root.orientations
829+ when: spreadTile.stage == ApplicationInfoInterface.MainStage
833+ when: spreadTile.stage == ApplicationInfoInterface.SideStage
837+ width: spreadView.sideStageWidth
838+ height: priv.landscapeHeight
840+ supportedOrientations: Qt.PortraitOrientation
841+ shellOrientationAngle: 0
753− shellOrientation: wantsMainStage ? root.shellOrientation : Qt.PortraitOrientation
842+ shellOrientation: Qt.PortraitOrientation
843+ orientations: sideStageOrientations
754− orientations: Orientations {
848+ Orientations {
849+ id: sideStageOrientations
755− primary: spreadTile.wantsMainStage ? root.orientations.primary : Qt.PortraitOrientation
850+ primary: Qt.PortraitOrientation
756− native_: spreadTile.wantsMainStage ? root.orientations.native_ : Qt.PortraitOrientation
851+ native_: Qt.PortraitOrientation
757 portrait: root.orientations.portrait
852 portrait: root.orientations.portrait
758 invertedPortrait: root.orientations.invertedPortrait
853 invertedPortrait: root.orientations.invertedPortrait
759 landscape: root.orientations.landscape
854 landscape: root.orientations.landscape
760 invertedLandscape: root.orientations.invertedLandscape
855 invertedLandscape: root.orientations.invertedLandscape
861+ SequentialAnimation {
864+ properties: "width,height,supportedOrientations,shellOrientationAngle,shellOrientation,orientations"
868+ // rotate immediately.
869+ spreadTile.matchShellOrientation();
870+ if (ApplicationManager.focusedApplicationId === spreadTile.appId &&
871+ priv.sideStageEnabled && !sideStage.shown) {
872+ // Sidestage was focused, so show the side stage.
874+ // if we've switched to a main app which doesnt support portrait, hide the side stage.
875+ } else if (mainApp && (mainApp.supportedOrientations & (Qt.PortraitOrientation|Qt.InvertedPortraitOrientation)) == 0) {
876+ sideStage.hideNow();
884+ SequentialAnimation {
887+ if (priv.sideStageAppId === spreadTile.appId &&
888+ mainApp && (mainApp.supportedOrientations & (Qt.PortraitOrientation|Qt.InvertedPortraitOrientation)) == 0) {
889+ // The mainstage app did not natively support portrait orientation, so focus the sidestage.
890+ ApplicationManager.requestFocusApplication(spreadTile.appId);
896+ properties: "width,height,supportedOrientations,shellOrientationAngle,shellOrientation,orientations"
898+ ScriptAction { script: { spreadTile.matchShellOrientation(); } }
763 onClicked: {
903 onClicked: {
764 if (spreadView.phase == 2) {
904 if (spreadView.phase == 2) {
765 spreadView.snapTo(index);
905 spreadView.snapTo(index);
@@ -779,6 +919,16 @@ AbstractStage {
779 ApplicationManager.stopApplication(ApplicationManager.get(index).appId);
919 ApplicationManager.stopApplication(ApplicationManager.get(index).appId);
923+ if (focus && ApplicationManager.focusedApplicationId !== appId) {
924+ ApplicationManager.focusApplication(appId);
927+ if (focus && priv.sideStageEnabled && stage === ApplicationInfoInterface.SideStage) {
782 Binding {
932 Binding {
783 target: root
933 target: root
784 when: model.appId == priv.mainStageAppId
934 when: model.appId == priv.mainStageAppId
@@ -803,6 +953,71 @@ AbstractStage {
956+ TabletSideStageTouchGesture {
958+ anchors.fill: parent
959+ enabled: priv.sideStageEnabled && !spreadView.active
960+ property var dragObject: null
961+ property string appId: ""
962+ dragComponent: dragComponent
963+ dragComponentProperties: { "appId": appId }
966+ function matchDelegate(obj) { return String(obj.objectName).indexOf("tabletSpreadDelegate") >= 0; }
968+ var delegateAtCenter = Functions.itemAt(spreadRow, x, y, matchDelegate);
969+ if (!delegateAtCenter) return;
971+ appId = delegateAtCenter.appId;
975+ if (sideStage.shown) {
983+ // If we're dragging to the sidestage.
984+ if (!sideStage.shown) {
992+ property string appId: ""
993+ property var application: ApplicationManager.findApplication(appId)
995+ session: application ? application.session : null
997+ resizeSurface: false
1000+ width: units.gu(40)
1001+ height: units.gu(40)
1003+ Drag.hotSpot.x: width/2
1004+ Drag.hotSpot.y: height/2
1005+ // only accept opposite stage.
1007+ if (!application) return "Disabled";
1009+ if (application.stage === ApplicationInfo.MainStage) {
1010+ if (application.supportedOrientations & (Qt.PortraitOrientation|Qt.InvertedPortraitOrientation)) {
1011+ return "MainStage";
1015+ return "SideStage";
806 //eat touch events during the right edge gesture
1021 //eat touch events during the right edge gesture
807 MouseArea {
1022 MouseArea {
808 anchors.fill: parent
1023 anchors.fill: parent
@@ -812,7 +1027,8 @@ AbstractStage {
812 DirectionalDragArea {
1027 DirectionalDragArea {
813 id: spreadDragArea
1028 id: spreadDragArea
814 objectName: "spreadDragArea"
1029 objectName: "spreadDragArea"
1030+ x: parent.width - root.dragAreaWidth
815− anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
1031+ anchors { top: parent.top; bottom: parent.bottom }
816 width: root.dragAreaWidth
1032 width: root.dragAreaWidth
817 direction: Direction.Leftwards
1033 direction: Direction.Leftwards
818 enabled: (spreadView.phase != 2 && root.spreadEnabled) || dragging
1034 enabled: (spreadView.phase != 2 && root.spreadEnabled) || dragging