@@ -1,1183 +0,0 @@
2− * Copyright (C) 2014-2016 Canonical, Ltd.
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
18−import Ubuntu.Components 1.3
19−import Ubuntu.Gestures 0.1
20−import Unity.Application 0.1
23−import "../Components"
30− // <tutorial-hacks> The Tutorial looks into our implementation details
31− property alias sideStageVisible: spreadView.sideStageVisible
32− property alias sideStageWidth: spreadView.sideStageWidth
33− // The stage the currently focused surface is in
34− property int stageFocusedSurface: priv.focusedAppDelegate ? priv.focusedAppDelegate.stage : ApplicationInfoInterface.MainStage
37− paintBackground: spreadView.shiftedContentX !== 0
39− // Functions to be called from outside
40− function updateFocusedAppOrientation() {
41− var mainStageIndex = root.topLevelSurfaceList.indexForId(priv.mainStageItemId);
43− if (priv.mainStageItemId && mainStageIndex >= 0 && mainStageIndex < spreadRepeater.count) {
44− spreadRepeater.itemAt(mainStageIndex).matchShellOrientation();
47− for (var i = 0; i < spreadRepeater.count; ++i) {
49− if (i === mainStageIndex) {
53− var spreadDelegate = spreadRepeater.itemAt(i);
55− var delta = spreadDelegate.appWindowOrientationAngle - root.shellOrientationAngle;
56− if (delta < 0) { delta += 360; }
59− var supportedOrientations = spreadDelegate.supportedOrientations;
60− if (supportedOrientations === Qt.PrimaryOrientation) {
61− supportedOrientations = spreadDelegate.orientations.primary;
64− if (delta === 180 && (supportedOrientations & spreadDelegate.shellOrientation)) {
65− spreadDelegate.matchShellOrientation();
69− function updateFocusedAppOrientationAnimated() {
70− var mainStageIndex = root.topLevelSurfaceList.indexForId(priv.mainStageItemId);
71− if (priv.mainStageItemId && mainStageIndex >= 0 && mainStageIndex < spreadRepeater.count) {
72− spreadRepeater.itemAt(mainStageIndex).animateToShellOrientation();
75− var sideStageIndex = root.topLevelSurfaceList.indexForId(priv.sideStageItemId);
76− if (sideStageIndex >= 0 && sideStageIndex < spreadRepeater.count) {
77− spreadRepeater.itemAt(sideStageIndex).matchShellOrientation();
81− function pushRightEdge(amount) {
82− if (spreadView.contentX == -spreadView.shift) {
83− edgeBarrier.push(amount);
87− function closeFocusedDelegate() {
88− if (priv.focusedAppDelegate && priv.focusedAppDelegate.closeable) {
89− priv.focusedAppDelegate.closed();
93− orientationChangesEnabled: priv.mainAppOrientationChangesEnabled
96− if (priv.mainStageItemId > 0) {
97− var index = root.topLevelSurfaceList.indexForId(priv.mainStageItemId);
98− return root.topLevelSurfaceList.applicationAt(index);
104− supportedOrientations: {
106− var orientations = mainApp.supportedOrientations;
107− orientations |= Qt.LandscapeOrientation | Qt.InvertedLandscapeOrientation;
108− if (priv.sideStageItemId && !spreadView.surfaceDragging) {
109− // If we have a sidestage app, support Portrait orientation
110− // so that it will switch the sidestage app to mainstage on rotate to portrait
111− orientations |= Qt.PortraitOrientation|Qt.InvertedPortraitOrientation;
113− return orientations;
115− // we just don't care
116− return Qt.PortraitOrientation |
117− Qt.LandscapeOrientation |
118− Qt.InvertedPortraitOrientation |
119− Qt.InvertedLandscapeOrientation;
123− // How far left the stage has been dragged, used externally by tutorial code
124− dragProgress: spreadRepeater.count > 0 ? spreadRepeater.itemAt(0).animatedProgress : 0
127− spreadView.selectedIndex = -1;
128− spreadView.phase = 0;
129− spreadView.contentX = -spreadView.shift;
132− onAltTabPressedChanged: {
133− if (!spreadEnabled) {
136− if (altTabPressed) {
137− priv.highlightIndex = Math.min(spreadRepeater.count - 1, 1);
138− spreadView.snapToSpread();
140− for (var i = 0; i < spreadRepeater.count; i++) {
141− if (spreadRepeater.itemAt(i).zIndex === priv.highlightIndex) {
142− spreadView.snapTo(i);
150− focus: root.altTabPressed
153− switch (event.key) {
155− priv.highlightIndex = (priv.highlightIndex + 1) % spreadRepeater.count
157− case Qt.Key_Backtab:
158− priv.highlightIndex = (priv.highlightIndex + spreadRepeater.count - 1) % spreadRepeater.count
165− target: root.topLevelSurfaceList
166− onListChanged: priv.updateMainAndSideStageIndexes()
171− objectName: "stagesPriv"
173− function updateMainAndSideStageIndexes() {
174− var choseMainStage = false;
175− var choseSideStage = false;
177− if (!root.topLevelSurfaceList)
180− for (var i = 0; i < spreadRepeater.count && (!choseMainStage || !choseSideStage); ++i) {
181− var spreadDelegate = spreadRepeater.itemAt(i);
182− if (sideStage.shown && spreadDelegate.stage == ApplicationInfoInterface.SideStage
183− && !choseSideStage) {
184− priv.sideStageDelegate = spreadDelegate
185− priv.sideStageItemId = root.topLevelSurfaceList.idAt(i);
186− priv.sideStageAppId = root.topLevelSurfaceList.applicationAt(i).appId;
187− choseSideStage = true;
188− } else if (!choseMainStage && spreadDelegate.stage == ApplicationInfoInterface.MainStage) {
189− priv.mainStageDelegate = spreadDelegate;
190− priv.mainStageItemId = root.topLevelSurfaceList.idAt(i);
191− priv.mainStageAppId = root.topLevelSurfaceList.applicationAt(i).appId;
192− choseMainStage = true;
195− if (!choseMainStage) {
196− priv.mainStageDelegate = null;
197− priv.mainStageItemId = 0;
198− priv.mainStageAppId = "";
200− if (!choseSideStage) {
201− priv.sideStageDelegate = null;
202− priv.sideStageItemId = 0;
203− priv.sideStageAppId = "";
207− property var focusedAppDelegate: null
209− property bool mainAppOrientationChangesEnabled: false
211− property real landscapeHeight: root.orientations.native_ == Qt.LandscapeOrientation ?
212− root.nativeHeight : root.nativeWidth
214− property bool shellIsLandscape: root.shellOrientation === Qt.LandscapeOrientation
215− || root.shellOrientation === Qt.InvertedLandscapeOrientation
217− property var mainStageDelegate: null
218− property var sideStageDelegate: null
220− property int mainStageItemId: 0
221− property int sideStageItemId: 0
223− property string mainStageAppId: ""
224− property string sideStageAppId: ""
226− property int oldInverseProgress: 0
228− property int highlightIndex: 0
230− property bool focusedAppDelegateIsDislocated: focusedAppDelegate &&
231− (focusedAppDelegate.dragOffset !== 0 || focusedAppDelegate.xTranslateAnimating)
232− function evaluateOneWayFlick(gesturePoints) {
233− // Need to have at least 3 points to recognize it as a flick
234− if (gesturePoints.length < 3) {
237− // Need to have a movement of at least 2 grid units to recognize it as a flick
238− if (Math.abs(gesturePoints[gesturePoints.length - 1] - gesturePoints[0]) < units.gu(2)) {
242− var oneWayFlick = true;
243− var smallestX = gesturePoints[0];
244− var leftWards = gesturePoints[1] < gesturePoints[0];
245− for (var i = 1; i < gesturePoints.length; i++) {
246− if ((leftWards && gesturePoints[i] >= smallestX)
247− || (!leftWards && gesturePoints[i] <= smallestX)) {
248− oneWayFlick = false;
251− smallestX = gesturePoints[i];
256− onHighlightIndexChanged: {
257− spreadView.contentX = highlightIndex * spreadView.contentWidth / (spreadRepeater.count + 2)
260− readonly property bool sideStageEnabled: root.shellOrientation == Qt.LandscapeOrientation ||
261− root.shellOrientation == Qt.InvertedLandscapeOrientation
265− model: root.applicationManager
266− delegate: QtObject {
267− property var stateBinding: Binding {
268− target: model.application
269− property: "requestedState"
271− // NB: the first application clause is just to ensure we never get warnings for trying to access
272− // members of a null variable.
273− value: model.application &&
274− (!root.suspended && (model.application.appId === priv.mainStageAppId
275− || model.application.appId === priv.sideStageAppId))
277− ? ApplicationInfoInterface.RequestedRunning
278− : ApplicationInfoInterface.RequestedSuspended
281− property var lifecycleBinding: Binding {
282− target: model.application
283− property: "exemptFromLifecycle"
284− value: model.application
285− ? (!model.application.isTouchApp || isExemptFromLifecycle(model.application.appId))
292− target: MirFocusController
293− property: "focusedSurface"
294− value: priv.focusedAppDelegate ? priv.focusedAppDelegate.focusedSurface : null
295− when: root.parent && !spreadRepeater.startingUp
300− objectName: "spreadView"
301− anchors.fill: parent
302− interactive: (spreadDragArea.dragging || phase > 1) && draggedDelegateCount === 0
303− contentWidth: spreadRow.width - shift
306− property int tileDistance: units.gu(20)
308− // This indicates when the spreadView is active. That means, all the animations
309− // are activated and tiles need to line up for the spread.
310− readonly property bool active: shiftedContentX > 0 || spreadDragArea.dragging
312− // The flickable needs to fill the screen in order to get touch events all over.
313− // However, we don't want to the user to be able to scroll back all the way. For
314− // that, the beginning of the gesture starts with a negative value for contentX
315− // so the flickable wants to pull it into the view already. "shift" tunes the
316− // distance where to "lock" the content.
317− readonly property real shift: width / 2
318− readonly property real shiftedContentX: contentX + shift
320− // Phase of the animation:
321− // 0: Starting from right edge, a new app (index 1) comes in from the right
322− // 1: The app has reached the first snap position.
323− // 2: The list is dragged further and snaps into the spread view when entering phase 2
326− readonly property int phase0Width: sideStageWidth
327− readonly property int phase1Width: sideStageWidth
329− // Those markers mark the various positions in the spread (ratio to screen width from right to left):
330− // 0 - 1: following finger, snap back to the beginning on release
331− readonly property real positionMarker1: 0.2
332− // 1 - 2: curved snapping movement, snap to nextInStack on release
333− readonly property real positionMarker2: sideStageWidth / spreadView.width
334− // 2 - 3: movement follows finger, snaps to phase 2 (full spread) on release
335− readonly property real positionMarker3: 0.6
336− // passing 3, we detach movement from the finger and snap to phase 2 (full spread)
337− readonly property real positionMarker4: 0.8
339− readonly property int startSnapPosition: phase0Width * 0.5
340− readonly property int endSnapPosition: phase0Width * 0.75
341− readonly property real snapPosition: 0.75
343− property int selectedIndex: -1
344− property int draggedDelegateCount: 0
345− property int closingIndex: -1
346− property var selectedDelegate: selectedIndex !== -1 ? spreadRepeater.itemAt(selectedIndex) : null
348− // <FIXME-contentX> Workaround Flickable's behavior of bringing contentX back between valid boundaries
349− // when resized. The proper way to fix this is refactoring PhoneStage so that it doesn't
350− // rely on having Flickable.contentX keeping an out-of-bounds value when it's set programatically
351− // (as opposed to having contentX reaching an out-of-bounds value through dragging, which will trigger
352− // the Flickable.boundsBehavior upon release).
353− onContentXChanged: {
354− if (!undoContentXReset()) {
355− forceItToRemainStillIfBeingResized();
358− onShiftChanged: { forceItToRemainStillIfBeingResized(); }
359− function forceItToRemainStillIfBeingResized() {
360− if (root.beingResized && contentX != -spreadView.shift) {
361− contentX = -spreadView.shift;
364− function undoContentXReset() {
365− if (contentWidth <= 0) {
366− contentWidthOnLastContentXChange = contentWidth;
367− lastContentX = contentX;
371− if (contentWidth != contentWidthOnLastContentXChange
372− && lastContentX == -shift && contentX == 0) {
373− // Flickable is resetting contentX because contentWidth has changed. Undo it.
378− contentWidthOnLastContentXChange = contentWidth;
379− lastContentX = contentX;
382− property real contentWidthOnLastContentXChange: -1
383− property real lastContentX: 0
384− // </FIXME-contentX>
386− property bool animateX: true
387− property bool beingResized: root.beingResized
388− onBeingResizedChanged: {
390− // Brace yourselves for impact!
397− property real sideStageWidth: units.gu(40)
399− property bool surfaceDragging: triGestureArea.recognisedDrag
401− readonly property bool sideStageVisible: priv.sideStageItemId != 0
403− // In case applicationManager already holds an app when starting up we're missing animations
404− // Make sure we end up in the same state
405− Component.onCompleted: {
406− spreadView.contentX = -spreadView.shift
409− property int nextInStack: {
410− var mainStageIndex = priv.mainStageDelegate ? priv.mainStageDelegate.index : -1;
411− var sideStageIndex = priv.sideStageDelegate ? priv.sideStageDelegate.index : -1;
414− if (root.topLevelSurfaceList.count > 1) {
418− case "mainAndOverlay":
419− if (root.topLevelSurfaceList.count <= 2) {
422− if (mainStageIndex == 0 || sideStageIndex == 0) {
423− if (mainStageIndex == 1 || sideStageIndex == 1) {
434− property int nextZInStack
443− State { // Side Stage only in overlay mode
446− State { // Main Stage and Side Stage in overlay mode
447− name: "mainAndOverlay"
449− State { // Main Stage and Side Stage in split mode
450− name: "mainAndSplit"
454− if ((priv.mainStageItemId && !priv.sideStageItemId) || !priv.sideStageEnabled) {
457− if (!priv.mainStageItemId && priv.sideStageItemId) {
460− if (priv.mainStageItemId && priv.sideStageItemId) {
461− return "mainAndOverlay";
466− onShiftedContentXChanged: {
467− if (root.beingResized) {
468− // Flickabe.contentX wiggles during resizes. Don't react to it.
473− // the "spreadEnabled" part is because when code does "phase = 0; contentX = -shift" to
474− // dismiss the spread because spreadEnabled went to false, for some reason, during tests,
475− // Flickable might jump in and change contentX value back, causing the code below to do
476− // "phase = 1" which will make the spread stay.
477− // It sucks that we have no control whatsoever over whether or when Flickable animates its
479− if (root.spreadEnabled && shiftedContentX > width * positionMarker2) {
484− // Do not turn to else if
485− // Sometimes the animation of shiftedContentX is very fast and we need to jump from phase 0 to 1 to 2
486− // in the same onShiftedContentXChanged
488− if (shiftedContentX < width * positionMarker2) {
490− } else if (shiftedContentX >= width * positionMarker4 && !spreadDragArea.dragging) {
497− if (shiftedContentX < phase0Width) {
498− snapAnimation.targetContentX = -shift;
499− snapAnimation.start();
500− } else if (shiftedContentX < phase1Width) {
507− function snapToSpread() {
508− // Add 1 pixel to make sure we definitely hit positionMarker4 even with rounding errors of the animation.
509− snapAnimation.targetContentX = (spreadView.width * spreadView.positionMarker4) + 1 - shift;
510− snapAnimation.start();
513− function snapTo(index) {
514− snapAnimation.stop();
515− spreadView.selectedIndex = index;
516− snapAnimation.targetContentX = -shift;
517− snapAnimation.start();
520− // We need to shuffle z ordering a bit in order to keep side stage apps above main stage apps.
521− // We don't want to really reorder them in the model because that allows us to keep track
522− // of the last focused order.
523− function indexToZIndex(index) {
524− // only shuffle when we've got a main and overlay
525− if (state !== "mainAndOverlay") return index;
527− var app = root.topLevelSurfaceList.applicationAt(index);
531− var stage = spreadRepeater.itemAt(index) ? spreadRepeater.itemAt(index).stage : ApplicationInfoInterface.MainStage;
533− // don't shuffle indexes greater than "actives or next"
534− if (index > 2) return index;
536− var mainStageIndex = root.topLevelSurfaceList.indexForId(priv.mainStageItemId);
538− if (index == mainStageIndex) {
539− // Active main stage always at 0
543− if (spreadView.nextInStack > 0) {
544− var stageOfNextInStack = spreadRepeater.itemAt(spreadView.nextInStack).stage;
546− if (index === spreadView.nextInStack) {
547− // this is the next app in stack.
549− if (stage === ApplicationInfoInterface.SideStage) {
550− // if the next app in stack is a sidestage app, it must order on top of other side stage app
551− return Math.min(2, root.topLevelSurfaceList.count-1);
555− if (stageOfNextInStack === ApplicationInfoInterface.SideStage) {
556− // if the next app in stack is a sidestage app, it must order on top of other side stage app
559− return Math.min(2, root.topLevelSurfaceList.count-1);
561− return Math.min(index+1, root.topLevelSurfaceList.count-1);
564− SequentialAnimation {
566− property int targetContentX: -spreadView.shift
568− UbuntuNumberAnimation {
570− property: "contentX"
571− to: snapAnimation.targetContentX
572− duration: UbuntuAnimation.FastDuration
577− if (spreadView.selectedIndex >= 0) {
578− var newIndex = spreadView.selectedIndex;
579− var application = root.topLevelSurfaceList.applicationAt(newIndex);
580− var spreadDelegate = spreadRepeater.itemAt(newIndex);
581− if (spreadDelegate.stage === ApplicationInfoInterface.SideStage) {
582− sideStage.showNow();
584− spreadView.selectedIndex = -1;
585− spreadDelegate.focus = true;
586− spreadView.phase = 0;
587− spreadView.contentX = -spreadView.shift;
593− Behavior on contentX {
594− enabled: root.altTabPressed
595− UbuntuNumberAnimation {}
600− x: spreadView.contentX
601− width: spreadView.width + Math.max(spreadView.width, root.topLevelSurfaceList.count * spreadView.tileDistance)
605− spreadView.snapTo(0);
609− objectName: "MainStageDropArea"
613− bottom: parent.bottom
615− width: spreadView.width - sideStage.width
616− enabled: priv.sideStageEnabled
619− drop.source.spreadDelegate.saveStage(ApplicationInfoInterface.MainStage);
620− drop.source.spreadDelegate.focus = true;
627− objectName: "sideStage"
628− height: priv.landscapeHeight
629− x: spreadView.width - width
631− if (!priv.mainStageItemId) return 0;
633− if (priv.sideStageItemId && spreadView.nextInStack > 0) {
634− var nextDelegateInStack = spreadRepeater.itemAt(spreadView.nextInStack);
636− if (nextDelegateInStack.stage === ApplicationInfoInterface.MainStage) {
637− // if the next app in stack is a main stage app, put the sidestage on top of it.
645− visible: progress != 0
646− enabled: priv.sideStageEnabled && sideStageDropArea.dropAllowed
647− opacity: priv.sideStageEnabled && !spreadView.active ? 1 : 0
648− Behavior on opacity { UbuntuNumberAnimation {} }
651− if (!shown && priv.sideStageDelegate && priv.focusedAppDelegate === priv.sideStageDelegate
652− && priv.mainStageDelegate) {
653− priv.mainStageDelegate.focus = true;
654− } else if (shown && priv.sideStageDelegate) {
655− priv.sideStageDelegate.focus = true;
660− id: sideStageDropArea
661− objectName: "SideStageDropArea"
662− anchors.fill: parent
664− property bool dropAllowed: true
667− dropAllowed = drag.keys != "Disabled";
673− if (drop.keys == "MainStage") {
674− drop.source.spreadDelegate.saveStage(ApplicationInfoInterface.SideStage);
675− drop.source.spreadDelegate.focus = true;
680− if (!sideStageDropArea.drag.source) {
688− TopLevelSurfaceRepeater {
690− objectName: "spreadRepeater"
691− model: root.topLevelSurfaceList
694− priv.updateMainAndSideStageIndexes();
695− if (spreadView.phase == 2) {
696− spreadView.snapTo(index);
701− priv.updateMainAndSideStageIndexes();
702− // Unless we're closing the app ourselves,
703− // lets make sure the spread doesn't mess up by the changing app list.
704− if (spreadView.closingIndex == -1) {
705− spreadView.phase = 0;
706− spreadView.contentX = -spreadView.shift;
710− function focusTopMostApp() {
711− if (spreadRepeater.count > 0) {
712− var topmostDelegate = spreadRepeater.itemAt(0);
713− topmostDelegate.focus = true;
717− delegate: TransformedTabletSpreadDelegate {
719− objectName: "spreadDelegate_" + model.id
721− readonly property int index: model.index
722− width: spreadView.width
723− height: spreadView.height
724− active: model.id == priv.mainStageItemId || model.id == priv.sideStageItemId
725− zIndex: selected && stage == ApplicationInfoInterface.MainStage ? 0 : spreadView.indexToZIndex(index)
727− if (spreadView.nextInStack == model.index) {
728− spreadView.nextZInStack = zIndex;
731− selected: spreadView.selectedIndex == index
732− otherSelected: spreadView.selectedIndex >= 0 && !selected
733− isInSideStage: priv.sideStageItemId == model.id
734− interactive: !spreadView.interactive && spreadView.phase === 0 && root.interactive
735− swipeToCloseEnabled: spreadView.interactive && !snapAnimation.running
736− maximizedAppTopMargin: root.maximizedAppTopMargin
737− dragOffset: model.id == priv.mainStageItemId && root.inverseProgress > 0
738− && spreadView.phase === 0 ? root.inverseProgress : 0
739− application: model.application
740− surface: model.surface
742− highlightShown: root.altTabPressed && priv.highlightIndex == zIndex
743− dropShadow: spreadView.active || priv.focusedAppDelegateIsDislocated
745− readonly property bool wantsMainStage: stage == ApplicationInfoInterface.MainStage
749− if (focus && !spreadRepeater.startingUp) {
750− priv.focusedAppDelegate = spreadTile;
751− root.topLevelSurfaceList.raiseId(model.id);
753− if (focus && priv.sideStageEnabled && stage === ApplicationInfoInterface.SideStage) {
758− target: model.surface
759− onFocusRequested: spreadTile.focus = true;
762− target: spreadTile.application
764− if (!model.surface) {
765− // when an app has no surfaces, we assume there's only one entry representing it:
767− spreadTile.focus = true;
769− // if the application has surfaces, focus request should be at surface-level.
775− if (priv.mainStageDelegate && stage === ApplicationInfoInterface.SideStage) {
776− return priv.mainStageDelegate.fullscreen;
777− } else if (surface) {
778− return surface.state == Mir.FullscreenState;
779− } else if (application) {
780− return application.fullscreen;
786− supportedOrientations: {
788− var orientations = application.supportedOrientations;
789− if (stage == ApplicationInfoInterface.MainStage) {
790− // When an app is in the mainstage, it always supports Landscape|InvertedLandscape
791− // so that we can drag it from the main stage to the side stage
792− orientations |= Qt.LandscapeOrientation | Qt.InvertedLandscapeOrientation;
794− return orientations;
796− // we just don't care
797− return Qt.PortraitOrientation |
798− Qt.LandscapeOrientation |
799− Qt.InvertedPortraitOrientation |
800− Qt.InvertedLandscapeOrientation;
804− function saveStage(newStage) {
806− WindowStateStorage.saveStage(application.appId, newStage);
809− // FIXME: A regular binding doesn't update any more after closing an app.
810− // Using a Binding for now.
814− value: (!spreadView.active && !active) ? -1 : spreadTile.zIndex
818− property real behavioredZIndex: zIndex
819− Behavior on behavioredZIndex {
820− enabled: spreadView.closingIndex >= 0
821− UbuntuNumberAnimation {}
825− onSideStageEnabledChanged: refreshStage()
828− property bool _constructing: true;
830− if (!_constructing) {
831− priv.updateMainAndSideStageIndexes();
835− Component.onCompleted: {
836− // a top level window is always the focused one when it first appears, unfocusing
837− // any preexisting one
840− _constructing = false;
843− function refreshStage() {
844− var newStage = ApplicationInfoInterface.MainStage;
845− if (priv.sideStageEnabled) { // we're in lanscape rotation.
846− if (application && application.supportedOrientations & (Qt.PortraitOrientation|Qt.InvertedPortraitOrientation)) {
847− var defaultStage = ApplicationInfoInterface.SideStage; // if application supports portrait, it defaults to sidestage.
848− if (application.supportedOrientations & (Qt.LandscapeOrientation|Qt.InvertedLandscapeOrientation)) {
849− // if it supports lanscape, it defaults to mainstage.
850− defaultStage = ApplicationInfoInterface.MainStage;
852− newStage = WindowStateStorage.getStage(application.appId, defaultStage);
860− var tileProgress = (spreadView.shiftedContentX - behavioredZIndex * spreadView.tileDistance) / spreadView.width;
861− // Some tiles (nextInStack, active) need to move directly from the beginning, normalize progress to immediately start at 0
862− if ((index == spreadView.nextInStack && spreadView.phase < 2) || (active && spreadView.phase < 1)) {
863− tileProgress += behavioredZIndex * spreadView.tileDistance / spreadView.width;
865− return tileProgress;
868− // TODO: Hiding tile when progress is such that it will be off screen.
869− property bool occluded: {
870− if (spreadView.active && !offScreen) return false;
871− else if (spreadTile.active) return false;
872− else if (xTranslateAnimating) return false;
873− else if (z <= 1 && priv.focusedAppDelegateIsDislocated) return false;
877− visible: Powerd.status == Powerd.On &&
878− !greeter.fullyShown &&
882− if (spreadView.phase == 0 && (spreadTile.active || spreadView.nextInStack == index)) {
883− if (progress < spreadView.positionMarker1) {
885− } else if (progress < spreadView.positionMarker1 + snappingCurve.period) {
886− return spreadView.positionMarker1 + snappingCurve.value * 3;
888− return spreadView.positionMarker2;
894− shellOrientationAngle: root.shellOrientationAngle
895− shellOrientation: root.shellOrientation
896− orientations: root.orientations
901− when: spreadTile.stage == ApplicationInfoInterface.MainStage
905− when: spreadTile.stage == ApplicationInfoInterface.SideStage
909− width: spreadView.sideStageWidth
910− height: priv.landscapeHeight
912− supportedOrientations: Qt.PortraitOrientation
913− shellOrientationAngle: 0
914− shellOrientation: Qt.PortraitOrientation
915− orientations: sideStageOrientations
921− id: sideStageOrientations
922− primary: Qt.PortraitOrientation
923− native_: Qt.PortraitOrientation
924− portrait: root.orientations.portrait
925− invertedPortrait: root.orientations.invertedPortrait
926− landscape: root.orientations.landscape
927− invertedLandscape: root.orientations.invertedLandscape
933− SequentialAnimation {
936− properties: "width,height,supportedOrientations,shellOrientationAngle,shellOrientation,orientations"
940− // rotate immediately.
941− spreadTile.matchShellOrientation();
942− if (priv.focusedAppDelegate === spreadTile &&
943− priv.sideStageEnabled && !sideStage.shown) {
944− // Sidestage was focused, so show the side stage.
953− SequentialAnimation {
956− if (priv.sideStageDelegate === spreadTile &&
957− mainApp && (mainApp.supportedOrientations & (Qt.PortraitOrientation|Qt.InvertedPortraitOrientation)) == 0) {
958− // The mainstage app did not natively support portrait orientation, so focus the sidestage.
959− spreadTile.focus = true;
965− properties: "width,height,supportedOrientations,shellOrientationAngle,shellOrientation,orientations"
967− ScriptAction { script: { spreadTile.matchShellOrientation(); } }
973− if (spreadView.phase == 2) {
974− spreadView.snapTo(index);
980− spreadView.draggedDelegateCount++;
982− spreadView.draggedDelegateCount--;
987− spreadView.closingIndex = index;
988− if (spreadTile.surface) {
989− spreadTile.surface.close();
990− } else if (spreadTile.application) {
991− root.applicationManager.stopApplication(spreadTile.application.appId);
993− // should never happen
994− console.warn("Can't close topLevelSurfaceList entry as it has neither"
995− + " a surface nor an application");
1001− when: model.id == priv.mainStageItemId
1002− property: "mainAppWindowOrientationAngle"
1003− value: appWindowOrientationAngle
1007− when: model.id == priv.mainStageItemId
1008− property: "mainAppOrientationChangesEnabled"
1009− value: orientationChangesEnabled
1014− type: EasingCurve.Linear
1015− period: (spreadView.positionMarker2 - spreadView.positionMarker1) / 3
1016− progress: spreadTile.progress - spreadView.positionMarker1
1019− StagedFullscreenPolicy {
1020− id: fullscreenPolicy
1021− surface: model.surface
1025− onStageAboutToBeUnloaded: fullscreenPolicy.active = false
1032− TabletSideStageTouchGesture {
1034− anchors.fill: parent
1035− enabled: priv.sideStageEnabled && !spreadView.active
1037− property Item spreadDelegate
1039− dragComponent: dragComponent
1040− dragComponentProperties: { "spreadDelegate": spreadDelegate }
1043− function matchDelegate(obj) { return String(obj.objectName).indexOf("spreadDelegate") >= 0; }
1045− var delegateAtCenter = Functions.itemAt(spreadRow, x, y, matchDelegate);
1046− if (!delegateAtCenter) return;
1048− spreadDelegate = delegateAtCenter;
1052− if (sideStage.shown) {
1060− // If we're dragging to the sidestage.
1061− if (!sideStage.shown) {
1069− property Item spreadDelegate
1071− surface: spreadDelegate ? spreadDelegate.surface : null
1073− consumesInput: false
1075− resizeSurface: false
1078− width: units.gu(40)
1079− height: units.gu(40)
1081− Drag.hotSpot.x: width/2
1082− Drag.hotSpot.y: height/2
1083− // only accept opposite stage.
1085− if (!surface) return "Disabled";
1087− if (spreadDelegate.stage === ApplicationInfo.MainStage) {
1088− if (spreadDelegate.application.supportedOrientations
1089− & (Qt.PortraitOrientation|Qt.InvertedPortraitOrientation)) {
1090− return "MainStage";
1094− return "SideStage";
1100− //eat touch events during the right edge gesture
1102− anchors.fill: parent
1103− enabled: spreadDragArea.dragging
1108− objectName: "spreadDragArea"
1109− x: parent.width - root.dragAreaWidth
1110− anchors { top: parent.top; bottom: parent.bottom }
1111− width: root.dragAreaWidth
1112− direction: Direction.Leftwards
1113− enabled: (spreadView.phase != 2 && root.spreadEnabled) || dragging
1115− property var gesturePoints: new Array()
1117− onTouchPositionChanged: {
1119− spreadView.phase = 0;
1120− spreadView.contentX = -spreadView.shift;
1124− var dragX = -touchPosition.x + spreadDragArea.width - spreadView.shift;
1125− var maxDrag = spreadView.width * spreadView.positionMarker4 - spreadView.shift;
1126− spreadView.contentX = Math.min(dragX, maxDrag);
1128− gesturePoints.push(touchPosition.x);
1131− onDraggingChanged: {
1133− // Gesture recognized. Start recording this gesture
1134− gesturePoints = [];
1136− // Ok. The user released. Find out if it was a one-way movement.
1137− var oneWayFlick = priv.evaluateOneWayFlick(gesturePoints);
1138− gesturePoints = [];
1140− if (oneWayFlick && spreadView.shiftedContentX < spreadView.positionMarker1 * spreadView.width) {
1141− // If it was a short one-way movement, do the Alt+Tab switch
1142− // no matter if we didn't cross positionMarker1 yet.
1143− spreadView.snapTo(spreadView.nextInStack);
1145− if (spreadView.shiftedContentX < spreadView.width * spreadView.positionMarker1) {
1147− } else if (spreadView.shiftedContentX < spreadView.width * spreadView.positionMarker2) {
1148− spreadView.snapTo(spreadView.nextInStack);
1150− // otherwise snap to the closest snap position we can find
1151− // (might be back to start, to app 1 or to spread)
1162− // NB: it does its own positioning according to the specified edge
1166− spreadView.snapToSpread();
1168− material: Component {
1171− width: parent.height
1172− height: parent.width
1174− anchors.centerIn: parent
1175− gradient: Gradient {
1176− GradientStop { position: 0.0; color: Qt.rgba(0.16,0.16,0.16,0.7)}
1177− GradientStop { position: 1.0; color: Qt.rgba(0.16,0.16,0.16,0)}