on xenial help sign in
drop a while lot of unused code
commit3d7a0dc31bb9ca96e9636366c996c40c3bc8bd69 authorMichael Zanetti <michael.zanetti@canonical.com> dateTue 13 Sep 2016, 13:01 (10 years ago) parent35c2d21
7 files changed−3997
qml/Stage/DesktopSpread.qml−576 qml/Stage/DesktopSpreadDelegate.qml−162 qml/Stage/PhoneStage.qml−806 qml/Stage/SpreadDelegate.qml−424 qml/Stage/TabletStage.qml−1201 qml/Stage/TransformedSpreadDelegate.qml−391 qml/Stage/TransformedTabletSpreadDelegate.qml−437
qml/Stage/DesktopSpread.qmldeleted−576
@@ -1,576 +0,0 @@
1−/*
2− * Copyright (C) 2015-2016 Canonical, Ltd.
3− *
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.
7− *
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.
12− *
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/>.
15− */
16−
17−import QtQuick 2.4
18−import QtQuick.Layouts 1.1
19−import Ubuntu.Components 1.3
20−import Ubuntu.Gestures 0.1
21−import Unity.Application 0.1
22−import "../Components"
23−import Utils 0.1
24−
25−FocusScope {
26− id: root
27−
28− property bool altTabPressed: false
29− property Item workspace: null
30−
31− readonly property alias ready: blurLayer.ready
32− readonly property alias highlightedIndex: spreadRepeater.highlightedIndex
33−
34− signal playFocusAnimation(int index)
35−
36− function show() {
37− spreadContainer.animateIn = true;
38− root.state = "altTab";
39− }
40−
41− onFocusChanged: {
42− // When the spread comes active, we want to keep focus to the input handler below
43− // Make sure nothing inside the ApplicationWindow grabs our focus!
44− if (focus) {
45− forceActiveFocus();
46− }
47− }
48−
49− Keys.onPressed: {
50− switch (event.key) {
51− case Qt.Key_Left:
52− case Qt.Key_Backtab:
53− selectPrevious(event.isAutoRepeat)
54− event.accepted = true;
55− break;
56− case Qt.Key_Right:
57− case Qt.Key_Tab:
58− selectNext(event.isAutoRepeat)
59− event.accepted = true;
60− break;
61− case Qt.Key_Escape:
62− spreadRepeater.highlightedIndex = -1
63− // Falling through intentionally
64− case Qt.Key_Enter:
65− case Qt.Key_Return:
66− case Qt.Key_Space:
67− root.state = ""
68− event.accepted = true;
69− }
70− }
71−
72− function selectNext(isAutoRepeat) {
73− if (isAutoRepeat && spreadRepeater.highlightedIndex >= topLevelSurfaceList.count -1) {
74− return; // AutoRepeat is not allowed to wrap around
75− }
76−
77− spreadRepeater.highlightedIndex = (spreadRepeater.highlightedIndex + 1) % topLevelSurfaceList.count;
78− var newContentX = ((spreadFlickable.contentWidth) / (topLevelSurfaceList.count + 1)) * Math.max(0, Math.min(topLevelSurfaceList.count - 5, spreadRepeater.highlightedIndex - 3));
79− if (spreadFlickable.contentX < newContentX || spreadRepeater.highlightedIndex == 0) {
80− spreadFlickable.snapTo(newContentX)
81− }
82− }
83−
84− function selectPrevious(isAutoRepeat) {
85− if (isAutoRepeat && spreadRepeater.highlightedIndex == 0) {
86− return; // AutoRepeat is not allowed to wrap around
87− }
88−
89− var newIndex = spreadRepeater.highlightedIndex - 1 >= 0 ? spreadRepeater.highlightedIndex - 1 : topLevelSurfaceList.count - 1;
90− spreadRepeater.highlightedIndex = newIndex;
91− var newContentX = ((spreadFlickable.contentWidth) / (topLevelSurfaceList.count + 1)) * Math.max(0, Math.min(topLevelSurfaceList.count - 5, spreadRepeater.highlightedIndex - 1));
92− if (spreadFlickable.contentX > newContentX || newIndex == topLevelSurfaceList.count -1) {
93− spreadFlickable.snapTo(newContentX)
94− }
95− }
96−
97− function focusSelected() {
98− if (spreadRepeater.highlightedIndex != -1) {
99− if (spreadContainer.visible) {
100− root.playFocusAnimation(spreadRepeater.highlightedIndex)
101− }
102− var surface = topLevelSurfaceList.surfaceAt(spreadRepeater.highlightedIndex);
103− surface.requestFocus();
104− }
105− }
106−
107− function cancel() {
108− spreadRepeater.highlightedIndex = -1;
109− state = ""
110− }
111−
112− BlurLayer {
113− id: blurLayer
114− anchors.fill: parent
115− source: root.workspace
116− visible: false
117− }
118−
119− Rectangle {
120− id: spreadBackground
121− anchors.fill: parent
122− color: "#B2000000"
123− visible: false
124− opacity: visible ? 1 : 0
125− Behavior on opacity {
126− UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration }
127− }
128− }
129−
130− MouseArea {
131− id: eventEater
132− anchors.fill: parent
133− visible: spreadBackground.visible
134− enabled: visible
135− acceptedButtons: Qt.AllButtons
136− onWheel: wheel.accepted = true;
137− }
138−
139− Item {
140− id: spreadContainer
141− objectName: "spreadContainer"
142− anchors.fill: parent
143− visible: false
144−
145− property bool animateIn: false
146−
147− Repeater {
148− id: spreadRepeater
149− objectName: "spreadRepeater"
150− model: topLevelSurfaceList
151−
152− property int highlightedIndex: -1
153− property int closingIndex: -1
154−
155− function indexOf(delegateItem) {
156− for (var i = 0; i < spreadRepeater.count; i++) {
157− if (spreadRepeater.itemAt(i) === delegateItem) {
158− return i;
159− }
160− }
161− return -1;
162− }
163−
164− delegate: Item {
165− id: spreadDelegate
166− objectName: "spreadDelegate"
167− width: units.gu(20)
168− height: units.gu(20)
169−
170− property real angle: 0
171− property real itemScale: 1
172− property int itemScaleOriginX: 0
173− property int itemScaleOriginY: 0
174−
175− readonly property string windowTitle: clippedSpreadDelegate.window.title
176−
177− Behavior on x {
178− id: closeBehavior
179− enabled: spreadRepeater.closingIndex >= 0
180− UbuntuNumberAnimation {
181− onRunningChanged: if (!running) spreadRepeater.closingIndex = -1
182− }
183− }
184−
185− DesktopSpreadDelegate {
186− id: clippedSpreadDelegate
187− objectName: "clippedSpreadDelegate"
188− anchors.left: parent.left
189− anchors.top: parent.top
190− application: model.application
191− surface: model.surface
192− width: spreadMaths.spreadHeight
193− height: spreadMaths.spreadHeight
194−
195− transform: [
196− Scale {
197− origin.x: itemScaleOriginX
198− origin.y: itemScaleOriginY
199− xScale: itemScale
200− yScale: itemScale
201− },
202− Rotation {
203− origin { x: 0; y: (clippedSpreadDelegate.height - (clippedSpreadDelegate.height * itemScale / 2)) }
204− axis { x: 0; y: 1; z: 0 }
205− angle: spreadDelegate.angle
206− }
207− ]
208−
209− MouseArea {
210− id: spreadSelectArea
211− anchors.fill: parent
212− anchors.margins: -units.gu(2)
213− enabled: false
214− onClicked: {
215− spreadRepeater.highlightedIndex = index;
216− root.state = "";
217− }
218− }
219− }
220−
221− SpreadMaths {
222− id: spreadMaths
223− flickable: spreadFlickable
224− itemIndex: index
225− totalItems: Math.max(6, topLevelSurfaceList.count)
226− sceneHeight: root.height
227− itemHeight: spreadDelegate.height
228− }
229−
230− states: [
231− State {
232− name: "altTab"; when: root.state == "altTab" && spreadContainer.visible
233− PropertyChanges {
234− target: spreadDelegate
235− x: spreadMaths.animatedX
236− y: spreadMaths.animatedY + (spreadDelegate.height - clippedSpreadDelegate.height) - units.gu(2)
237− width: spreadMaths.spreadHeight
238− height: spreadMaths.sceneHeight
239− angle: spreadMaths.animatedAngle
240− itemScale: spreadMaths.scale
241− itemScaleOriginY: clippedSpreadDelegate.height / 2;
242− z: index
243− visible: spreadMaths.itemVisible
244− }
245− PropertyChanges {
246− target: clippedSpreadDelegate
247− highlightShown: index == spreadRepeater.highlightedIndex
248− state: "transformed"
249− shadowOpacity: spreadMaths.shadowOpacity
250− anchors.topMargin: units.gu(2)
251− }
252− PropertyChanges {
253− target: tileInfo
254− visible: true
255− opacity: spreadMaths.tileInfoOpacity
256− }
257− PropertyChanges {
258− target: spreadSelectArea
259− enabled: true
260− }
261− }
262− ]
263− transitions: [
264− Transition {
265− from: ""
266− to: "altTab"
267− SequentialAnimation {
268− ParallelAnimation {
269− PropertyAction { target: spreadDelegate; properties: "y,height,width,angle,z,itemScale,itemScaleOriginY,visible" }
270− PropertyAction { target: clippedSpreadDelegate; properties: "anchors.topMargin" }
271− PropertyAnimation {
272− target: spreadDelegate; properties: "x"
273− from: root.width
274− duration: spreadContainer.animateIn ? UbuntuAnimation.FastDuration :0
275− easing: UbuntuAnimation.StandardEasing
276− }
277− UbuntuNumberAnimation { target: clippedSpreadDelegate; property: "shadowOpacity"; from: 0; to: spreadMaths.shadowOpacity; duration: spreadContainer.animateIn ? UbuntuAnimation.FastDuration : 0 }
278− UbuntuNumberAnimation { target: tileInfo; property: "opacity"; from: 0; to: spreadMaths.tileInfoOpacity; duration: spreadContainer.animateIn ? UbuntuAnimation.FastDuration : 0 }
279− }
280− PropertyAction { target: spreadSelectArea; property: "enabled" }
281− }
282− }
283− ]
284−
285− MouseArea {
286− id: tileInfo
287− objectName: "tileInfo"
288− anchors {
289− left: parent.left
290− top: clippedSpreadDelegate.bottom
291− topMargin: ((spreadMaths.sceneHeight - spreadDelegate.y) - clippedSpreadDelegate.height) * 0.2
292− }
293− property int nextItemX: spreadRepeater.count > index + 1 ? spreadRepeater.itemAt(index + 1).x : spreadDelegate.x + units.gu(30)
294− width: Math.min(units.gu(30), nextItemX - spreadDelegate.x)
295− height: titleInfoColumn.height
296− visible: false
297− hoverEnabled: true
298−
299− onContainsMouseChanged: {
300− if (containsMouse) {
301− spreadRepeater.highlightedIndex = index
302− }
303− }
304−
305− onClicked: {
306− root.state = ""
307− }
308−
309− ColumnLayout {
310− id: titleInfoColumn
311− anchors { left: parent.left; top: parent.top; right: parent.right }
312− spacing: units.gu(1)
313−
314− UbuntuShapeForItem {
315− Layout.preferredHeight: Math.min(units.gu(6), root.height * .05)
316− Layout.preferredWidth: height * 8 / 7.6
317− image: Image {
318− anchors.fill: parent
319− source: model.application.icon
320− Rectangle {
321− anchors.fill: parent
322− color: "black"
323− opacity: clippedSpreadDelegate.highlightShown ? 0 : .1
324− Behavior on opacity {
325− UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration }
326− }
327− }
328− }
329− }
330− Label {
331− Layout.fillWidth: true
332− Layout.preferredHeight: units.gu(6)
333− text: model.application ? model.application.name : spreadDelegate.windowTitle
334− wrapMode: Text.WordWrap
335− elide: Text.ElideRight
336− maximumLineCount: 2
337− }
338− }
339− }
340−
341− Image {
342− id: closeImage
343− anchors { left: parent.left; top: parent.top; leftMargin: -height / 2; topMargin: -height / 2 + spreadMaths.closeIconOffset + units.gu(2) }
344− source: "graphics/window-close.svg"
345− readonly property var mousePos: hoverMouseArea.mapToItem(spreadDelegate, hoverMouseArea.mouseX, hoverMouseArea.mouseY)
346− visible: index == spreadRepeater.highlightedIndex
347− && mousePos.y < (clippedSpreadDelegate.height / 3)
348− && mousePos.y > -units.gu(4)
349− && mousePos.x > -units.gu(4)
350− && mousePos.x < (clippedSpreadDelegate.width * 2 / 3)
351− height: units.gu(1.5)
352− width: height
353− sourceSize.width: width
354− sourceSize.height: height
355−
356− MouseArea {
357− id: closeMouseArea
358− objectName: "closeMouseArea"
359− anchors.fill: closeImage
360− anchors.margins: -units.gu(2)
361− onClicked: {
362− spreadRepeater.closingIndex = index;
363− model.surface.close();
364− }
365− }
366− }
367− }
368− }
369− }
370−
371−
372− MouseArea {
373− id: hoverMouseArea
374− objectName: "hoverMouseArea"
375− anchors.fill: spreadContainer
376− propagateComposedEvents: true
377− hoverEnabled: true
378− enabled: false
379− visible: enabled
380−
381− property int scrollAreaWidth: root.width / 3
382− property bool progressiveScrollingEnabled: false
383−
384− onMouseXChanged: {
385− mouse.accepted = false
386−
387− if (hoverMouseArea.pressed) {
388− return;
389− }
390−
391− // Find the hovered item and mark it active
392− var mapped = mapToItem(spreadContainer, hoverMouseArea.mouseX, hoverMouseArea.mouseY)
393− var itemUnder = spreadContainer.childAt(mapped.x, mapped.y)
394− if (itemUnder) {
395− mapped = mapToItem(itemUnder, hoverMouseArea.mouseX, hoverMouseArea.mouseY)
396− var delegateChild = itemUnder.childAt(mapped.x, mapped.y)
397− if (delegateChild && (delegateChild.objectName === "clippedSpreadDelegate" || delegateChild.objectName === "tileInfo")) {
398− spreadRepeater.highlightedIndex = spreadRepeater.indexOf(itemUnder)
399− }
400− }
401−
402− if (spreadFlickable.contentWidth > spreadFlickable.minContentWidth) {
403− var margins = spreadFlickable.width * 0.05;
404−
405− if (!progressiveScrollingEnabled && mouseX < spreadFlickable.width - scrollAreaWidth) {
406− progressiveScrollingEnabled = true
407− }
408−
409− // do we need to scroll?
410− if (mouseX < scrollAreaWidth + margins) {
411− var progress = Math.min(1, (scrollAreaWidth + margins - mouseX) / (scrollAreaWidth - margins));
412− var contentX = (1 - progress) * (spreadFlickable.contentWidth - spreadFlickable.width)
413− spreadFlickable.contentX = Math.max(0, Math.min(spreadFlickable.contentX, contentX))
414− }
415− if (mouseX > spreadFlickable.width - scrollAreaWidth && progressiveScrollingEnabled) {
416− var progress = Math.min(1, (mouseX - (spreadFlickable.width - scrollAreaWidth)) / (scrollAreaWidth - margins))
417− var contentX = progress * (spreadFlickable.contentWidth - spreadFlickable.width)
418− spreadFlickable.contentX = Math.min(spreadFlickable.contentWidth - spreadFlickable.width, Math.max(spreadFlickable.contentX, contentX))
419− }
420− }
421− }
422− onPressed: mouse.accepted = false
423− }
424−
425− FloatingFlickable {
426− id: spreadFlickable
427− objectName: "spreadFlickable"
428− anchors.fill: parent
429− property int minContentWidth: 6 * Math.min(height / 4, width / 5)
430− contentWidth: Math.max(6, topLevelSurfaceList.count) * Math.min(height / 4, width / 5)
431− enabled: false
432−
433− function snapTo(contentX) {
434− snapAnimation.stop();
435− snapAnimation.to = contentX
436− snapAnimation.start();
437− }
438−
439− UbuntuNumberAnimation {
440− id: snapAnimation
441− target: spreadFlickable
442− property: "contentX"
443− }
444− }
445−
446− Item {
447− id: workspaceSelector
448− anchors {
449− left: parent.left
450− top: parent.top
451− right: parent.right
452− topMargin: units.gu(3.5)
453− }
454− height: root.height * 0.25
455− visible: false
456−
457− RowLayout {
458− anchors.fill: parent
459− spacing: units.gu(1)
460− Item { Layout.fillWidth: true }
461− Repeater {
462− model: 1 // TODO: will be a workspacemodel in the future
463− Item {
464− Layout.fillHeight: true
465− Layout.preferredWidth: ((height - units.gu(6)) * root.width / root.height)
466− Image {
467− source: root.background
468− anchors {
469− left: parent.left
470− right: parent.right
471− verticalCenter: parent.verticalCenter
472− }
473− height: parent.height * 0.75
474−
475− ShaderEffect {
476− anchors.fill: parent
477−
478− property var source: ShaderEffectSource {
479− id: shaderEffectSource
480− sourceItem: root.workspace
481− }
482−
483− fragmentShader: "
484− varying highp vec2 qt_TexCoord0;
485− uniform sampler2D source;
486− void main(void)
487− {
488− highp vec4 sourceColor = texture2D(source, qt_TexCoord0);
489− gl_FragColor = sourceColor;
490− }"
491− }
492− }
493−
494− // TODO: This is the bar for the currently selected workspace
495− // Enable this once the workspace stuff is implemented
496− // Rectangle {
497− // anchors { left: parent.left; right: parent.right; bottom: parent.bottom }
498− // height: units.dp(2)
499− // color: theme.palette.normal.focus
500− // visible: index == 0 // TODO: should be active workspace index
501− // }
502− }
503−
504− }
505− // TODO: This is the "new workspace" button. Enable this once workspaces are implemented
506− // Item {
507− // Layout.fillHeight: true
508− // Layout.preferredWidth: ((height - units.gu(6)) * root.width / root.height)
509− // Rectangle {
510− // anchors {
511− // left: parent.left
512− // right: parent.right
513− // verticalCenter: parent.verticalCenter
514− // }
515− // height: parent.height * 0.75
516− // color: "#22ffffff"
517−
518− // Label {
519− // anchors.centerIn: parent
520− // font.pixelSize: parent.height / 2
521− // text: "+"
522− // }
523− // }
524− // }
525− Item { Layout.fillWidth: true }
526− }
527− }
528−
529− Label {
530− id: currentSelectedLabel
531− anchors { bottom: parent.bottom; bottomMargin: root.height * 0.625; horizontalCenter: parent.horizontalCenter }
532− text: spreadRepeater.highlightedIndex >= 0 ? spreadRepeater.itemAt(spreadRepeater.highlightedIndex).windowTitle: ""
533− visible: false
534− fontSize: "large"
535− }
536−
537− states: [
538− State {
539− name: "altTab"; when: root.altTabPressed
540− PropertyChanges { target: blurLayer; saturation: 0.8; blurRadius: 60; visible: true }
541− PropertyChanges { target: workspaceSelector; visible: true }
542− PropertyChanges { target: spreadContainer; visible: true }
543− PropertyChanges { target: spreadFlickable; enabled: spreadFlickable.contentWidth > spreadFlickable.minContentWidth }
544− PropertyChanges { target: currentSelectedLabel; visible: true }
545− PropertyChanges { target: spreadBackground; visible: true }
546− PropertyChanges { target: hoverMouseArea; enabled: true }
547− }
548− ]
549− transitions: [
550− Transition {
551− from: "*"
552− to: "altTab"
553− SequentialAnimation {
554− PropertyAction { target: spreadRepeater; property: "highlightedIndex"; value: Math.min(topLevelSurfaceList.count - 1, 1) }
555− PauseAnimation { duration: spreadContainer.animateIn ? 0 : 140 }
556− PropertyAction { target: workspaceSelector; property: "visible" }
557− PropertyAction { target: spreadContainer; property: "visible" }
558− ParallelAnimation {
559− UbuntuNumberAnimation { target: blurLayer; properties: "saturation,blurRadius"; duration: UbuntuAnimation.SnapDuration }
560− PropertyAction { target: spreadFlickable; property: "visible" }
561− PropertyAction { targets: [currentSelectedLabel,spreadBackground]; property: "visible" }
562− PropertyAction { target: spreadFlickable; property: "contentX"; value: 0 }
563− }
564− PropertyAction { target: hoverMouseArea; properties: "enabled,progressiveScrollingEnabled"; value: false }
565− }
566− },
567− Transition {
568− from: "*"
569− to: "*"
570− PropertyAnimation { property: "opacity" }
571− ScriptAction { script: { root.focusSelected() } }
572− PropertyAction { target: spreadRepeater; property: "highlightedIndex"; value: -1 }
573− PropertyAction { target: spreadContainer; property: "animateIn"; value: false }
574− }
575− ]
576−}
qml/Stage/DesktopSpreadDelegate.qmldeleted−162
@@ -1,162 +0,0 @@
1−/*
2− * Copyright (C) 2014-2016 Canonical, Ltd.
3− *
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.
7− *
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.
12− *
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/>.
15− *
16− * Authors: Michael Zanetti <michael.zanetti@canonical.com>
17− */
18−
19−import QtQuick 2.4
20−import Ubuntu.Components 1.3
21−import Unity.Application 0.1
22−
23−Item {
24− id: root
25−
26− property alias window: applicationWindow
27− property alias application: applicationWindow.application
28− property alias surface: applicationWindow.surface
29−
30− property bool highlightShown: false
31− property real shadowOpacity: 1
32−
33− property int windowWidth: surface ? surface.size.width : 0
34− property int windowHeight: surface ? surface.size.height : 0
35−
36− property alias requestedHeight: applicationWindow.requestedHeight
37− property alias requestedWidth: applicationWindow.requestedWidth
38−
39− property alias minimumWidth: applicationWindow.minimumWidth
40− property alias minimumHeight: applicationWindow.minimumHeight
41− property alias maximumWidth: applicationWindow.maximumWidth
42− property alias maximumHeight: applicationWindow.maximumHeight
43− property alias widthIncrement: applicationWindow.widthIncrement
44− property alias heightIncrement: applicationWindow.heightIncrement
45−
46− property alias fullscreen: applicationWindow.fullscreen
47− property alias title: applicationWindow.title
48− property alias showDecoration: applicationWindow.showDecoration
49− property alias active: applicationWindow.active
50−
51− signal close()
52− signal maximize()
53− signal minimize()
54− signal decorationPressed()
55−
56− state: "normal"
57− states: [
58− State {
59− name: "normal"
60− PropertyChanges {
61− target: root
62− width: windowWidth
63− height: windowHeight
64− }
65− },
66− State {
67− name: "transformed"
68− PropertyChanges {
69− target: applicationWindow
70− itemScale: Math.max(root.width / root.windowWidth, root.height / root.windowHeight)
71− interactive: false
72− showDecoration: false
73− }
74− PropertyChanges {
75− target: clipper
76− clip: true
77− }
78− }
79− ]
80−
81− scale: highlightShown ? 1.025 : 1
82− Behavior on scale {
83− UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration }
84− }
85−
86− BorderImage {
87− anchors {
88− fill: root
89− margins: -units.gu(2)
90− }
91− source: "graphics/dropshadow2gu.sci"
92− opacity: root.shadowOpacity * .3
93− }
94−
95− Rectangle {
96− id: selectionHighlight
97− anchors.fill: parent
98− anchors.margins: -units.gu(1)
99− color: "white"
100− opacity: highlightShown ? 0.55 : 0
101− antialiasing: true
102− }
103−
104− Rectangle {
105− anchors { left: selectionHighlight.left; right: selectionHighlight.right; bottom: selectionHighlight.bottom; }
106− height: units.dp(2)
107− color: theme.palette.normal.focus
108− visible: root.highlightShown
109− antialiasing: true
110− }
111−
112− Item {
113− id: clipper
114− anchors.fill: parent
115−
116− DecoratedWindow {
117− id: applicationWindow
118− objectName: "decoratedWindow"
119− anchors.left: root.left
120− anchors.top: root.top
121− active: root.focus
122− focus: true
123− showDecoration: true
124−
125− onClose: root.close()
126− onMaximize: root.maximize()
127− onMinimize: root.minimize()
128− onDecorationPressed: root.decorationPressed()
129− }
130−
131−// ApplicationWindow {
132−// id: applicationWindow
133−// objectName: application ? "appWindow_" + application.appId : "appWindow_null"
134−// anchors.top: parent.top
135−// anchors.topMargin: 0
136−// anchors.left: parent.left
137−// width: root.windowWidth
138−// height: root.windowHeight
139−// interactive: false
140−// resizeSurface: false
141−// focus: false
142−
143−// property real itemScale: 1
144−// transform: [
145−// Scale {
146−// origin.x: 0; origin.y: 0
147−// xScale: applicationWindow.itemScale
148−// yScale: applicationWindow.itemScale
149−// }
150−// ]
151−// }
152− }
153−
154− Rectangle {
155− anchors.fill: parent
156− color: "black"
157− opacity: root.highlightShown ? 0 : .1
158− Behavior on opacity {
159− UbuntuNumberAnimation { duration: UbuntuAnimation.SnapDuration }
160− }
161− }
162−}
qml/Stage/PhoneStage.qmldeleted−806
@@ -1,806 +0,0 @@
1−/*
2− * Copyright (C) 2014-2016 Canonical, Ltd.
3− *
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.
7− *
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.
12− *
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/>.
15− */
16−
17−import QtQuick 2.4
18−import Ubuntu.Components 1.3
19−import Ubuntu.Gestures 0.1
20−import Unity.Application 0.1
21−import Unity.Session 0.1
22−import Utils 0.1
23−import Powerd 0.1
24−import "../Components"
25−
26−AbstractStage {
27− id: root
28−
29− property bool focusFirstApp: true // If false, focused app will appear on right edge like other apps
30− property bool altTabEnabled: true
31− property real startScale: 1.1
32− property real endScale: 0.7
33−
34− paintBackground: spreadView.shiftedContentX !== 0
35−
36− onBeingResizedChanged: {
37− if (beingResized) {
38− // Brace yourselves for impact!
39− priv.reset();
40− }
41− }
42− onSpreadEnabledChanged: {
43− if (!spreadEnabled) {
44− priv.reset();
45− }
46− }
47−
48− onAltTabPressedChanged: {
49− if (!spreadEnabled || !altTabEnabled) {
50− return;
51− }
52− if (altTabPressed) {
53− spreadView.snapToSpread();
54− priv.highlightIndex = Math.min(spreadRepeater.count - 1, 1);
55− } else {
56− spreadView.snapTo(priv.highlightIndex)
57− }
58− }
59−
60− FocusScope {
61− focus: root.altTabPressed
62−
63− Keys.onPressed: {
64− switch (event.key) {
65− case Qt.Key_Tab:
66− priv.highlightIndex = (priv.highlightIndex + 1) % spreadRepeater.count
67− break;
68− case Qt.Key_Backtab:
69− priv.highlightIndex = (priv.highlightIndex + spreadRepeater.count - 1) % spreadRepeater.count
70− break;
71− }
72− }
73− }
74−
75− // Functions to be called from outside
76− function updateFocusedAppOrientation() {
77− if (spreadRepeater.count > 0) {
78− spreadRepeater.itemAt(0).matchShellOrientation();
79− }
80−
81− for (var i = 1; i < spreadRepeater.count; ++i) {
82−
83− var spreadDelegate = spreadRepeater.itemAt(i);
84−
85− var delta = spreadDelegate.appWindowOrientationAngle - root.shellOrientationAngle;
86− if (delta < 0) { delta += 360; }
87− delta = delta % 360;
88−
89− var supportedOrientations = spreadDelegate.application.supportedOrientations;
90− if (supportedOrientations === Qt.PrimaryOrientation) {
91− supportedOrientations = root.orientations.primary;
92− }
93−
94− if (delta === 180 && (supportedOrientations & spreadDelegate.shellOrientation)) {
95− spreadDelegate.matchShellOrientation();
96− }
97− }
98− }
99− function updateFocusedAppOrientationAnimated() {
100− if (spreadRepeater.count > 0) {
101− spreadRepeater.itemAt(0).animateToShellOrientation();
102− }
103− }
104−
105− function pushRightEdge(amount) {
106− if (spreadView.contentX == -spreadView.shift) {
107− edgeBarrier.push(amount);
108− }
109− }
110−
111− function closeFocusedDelegate() {
112− if (priv.focusedAppDelegate && priv.focusedAppDelegate.closeable) {
113− priv.focusedAppDelegate.closed();
114− }
115− }
116−
117− mainApp: priv.focusedAppDelegate ? priv.focusedAppDelegate.application : null
118−
119− orientationChangesEnabled: priv.focusedAppOrientationChangesEnabled
120− && !priv.focusedAppDelegateIsDislocated
121− && !(priv.focusedAppDelegate && priv.focusedAppDelegate.xBehavior.running)
122− && spreadView.phase === 0
123−
124− supportedOrientations: mainApp ? mainApp.supportedOrientations
125− : (Qt.PortraitOrientation | Qt.LandscapeOrientation
126− | Qt.InvertedPortraitOrientation | Qt.InvertedLandscapeOrientation)
127−
128− // How far left the stage has been dragged, used externally by tutorial code
129− dragProgress: spreadRepeater.count > 0 ? spreadRepeater.itemAt(0).animatedProgress : 0
130−
131− readonly property alias dragging: spreadDragArea.dragging
132−
133− signal opened()
134−
135− function select(appId) {
136− spreadView.snapTo(priv.indexOf(appId));
137− }
138−
139− onInverseProgressChanged: {
140− // This can't be a simple binding because that would be triggered after this handler
141− // while we need it active before doing the anition left/right
142− priv.animateX = (inverseProgress == 0)
143− if (inverseProgress == 0 && priv.oldInverseProgress > 0) {
144− // left edge drag released. Minimum distance is given by design.
145− if (priv.oldInverseProgress > units.gu(22)) {
146− applicationManager.requestFocusApplication("unity8-dash");
147− }
148− }
149− priv.oldInverseProgress = inverseProgress;
150− }
151−
152− // <FIXME-contentX> See rationale in the next comment with this tag
153− onWidthChanged: {
154− if (!root.beingResized) {
155− // we're being resized without a warning (ie, the corresponding property wasn't set
156− root.beingResized = true;
157− beingResizedTimer.start();
158− }
159− }
160− Timer {
161− id: beingResizedTimer
162− interval: 100
163− onTriggered: { root.beingResized = false; }
164− }
165−
166− QtObject {
167− id: priv
168−
169− property bool focusedAppOrientationChangesEnabled: false
170− readonly property int firstSpreadIndex: root.focusFirstApp ? 1 : 0
171− property var focusedAppDelegate
172− // NB! This may differ from applicationManager.focusedApplicationId if focusedAppDelegate
173− // contains a screenshot instead of a surface.
174− property string focusedAppId: focusedAppDelegate ? focusedAppDelegate.application.appId : ""
175−
176− property real oldInverseProgress: 0
177− property bool animateX: false
178− property int highlightIndex: 0
179−
180− property bool focusedAppDelegateIsDislocated: focusedAppDelegate ?
181− (focusedAppDelegate.x !== 0 || focusedAppDelegate.xBehavior.running)
182− : false
183−
184− function indexOf(appId) {
185− for (var i = 0; i < spreadRepeater.count; i++) {
186− if (spreadRepeater.itemAt(i).application.appId == appId) {
187− return i;
188− }
189− }
190− return -1;
191− }
192−
193− // Is more stable than "spreadView.shiftedContentX === 0" as it filters out noise caused by
194− // Flickable.contentX changing due to resizes.
195− property bool fullyShowingFocusedApp: true
196−
197− function reset() {
198− // The app that's about to go to foreground has to be focused, otherwise
199− // it would leave us in an inconsistent state.
200− if (!MirFocusController.focusedSurface && spreadRepeater.count > 0) {
201− spreadRepeater.itemAt(0).focus = true;
202− }
203−
204− spreadView.selectedIndex = -1;
205− spreadView.phase = 0;
206− spreadView.contentX = -spreadView.shift;
207− }
208−
209− onHighlightIndexChanged: {
210− spreadView.contentX = highlightIndex * spreadView.contentWidth / (spreadRepeater.count + 2)
211− }
212− }
213− Timer {
214− id: fullyShowingFocusedAppUpdateTimer
215− interval: 100
216− onTriggered: {
217− priv.fullyShowingFocusedApp = spreadView.shiftedContentX === 0;
218− }
219− }
220−
221− Instantiator {
222− model: root.applicationManager
223− delegate: QtObject {
224− property var stateBinding: Binding {
225− readonly property bool isDash: model.application ? model.application.appId == "unity8-dash" : false
226− target: model.application
227− property: "requestedState"
228− value: (isDash && root.keepDashRunning)
229− || (!root.suspended && model.application && priv.focusedAppId === model.application.appId)
230− ? ApplicationInfoInterface.RequestedRunning
231− : ApplicationInfoInterface.RequestedSuspended
232− }
233−
234− property var lifecycleBinding: Binding {
235− target: model.application
236− property: "exemptFromLifecycle"
237− value: model.application
238− ? (!model.application.isTouchApp || isExemptFromLifecycle(model.application.appId))
239− : false
240− }
241− }
242− }
243−
244− Binding {
245− target: MirFocusController
246− property: "focusedSurface"
247− value: priv.focusedAppDelegate ? priv.focusedAppDelegate.focusedSurface : null
248− when: root.parent && !spreadRepeater.startingUp
249− }
250−
251− Flickable {
252− id: spreadView
253− objectName: "spreadView"
254− anchors.fill: parent
255− interactive: (spreadDragArea.dragging || phase > 1) && draggedDelegateCount === 0
256− contentWidth: spreadRow.width - shift
257− contentX: -shift
258−
259− // This indicates when the spreadView is active. That means, all the animations
260− // are activated and tiles need to line up for the spread.
261− readonly property bool active: shiftedContentX > 0 || spreadDragArea.dragging || !root.focusFirstApp
262−
263− // The flickable needs to fill the screen in order to get touch events all over.
264− // However, we don't want to the user to be able to scroll back all the way. For
265− // that, the beginning of the gesture starts with a negative value for contentX
266− // so the flickable wants to pull it into the view already. "shift" tunes the
267− // distance where to "lock" the content.
268− readonly property real shift: width / 2
269− readonly property real shiftedContentX: contentX + shift
270−
271− property int tileDistance: width / 4
272−
273− // Those markers mark the various positions in the spread (ratio to screen width from right to left):
274− // 0 - 1: following finger, snap back to the beginning on release
275− property real positionMarker1: 0.2
276− // 1 - 2: curved snapping movement, snap to app 1 on release
277− property real positionMarker2: 0.3
278− // 2 - 3: movement follows finger, snaps back to app 1 on release
279− property real positionMarker3: 0.35
280− // passing 3, we detach movement from the finger and snap to 4
281− property real positionMarker4: 0.9
282−
283− // This is where the first app snaps to when bringing it in from the right edge.
284− property real snapPosition: 0.7
285−
286− // Phase of the animation:
287− // 0: Starting from right edge, a new app (index 1) comes in from the right
288− // 1: The app has reached the first snap position.
289− // 2: The list is dragged further and snaps into the spread view when entering phase 2
290− property int phase: 0
291−
292− property int selectedIndex: -1
293− property int draggedDelegateCount: 0
294− property int closingIndex: -1
295−
296− // <FIXME-contentX> Workaround Flickable's behavior of bringing contentX back between valid boundaries
297− // when resized. The proper way to fix this is refactoring PhoneStage so that it doesn't
298− // rely on having Flickable.contentX keeping an out-of-bounds value when it's set programatically
299− // (as opposed to having contentX reaching an out-of-bounds value through dragging, which will trigger
300− // the Flickable.boundsBehavior upon release).
301− onContentXChanged: {
302− if (!undoContentXReset()) {
303− forceItToRemainStillIfBeingResized();
304− }
305− }
306− onShiftChanged: { forceItToRemainStillIfBeingResized(); }
307− function forceItToRemainStillIfBeingResized() {
308− if (root.beingResized && contentX != -spreadView.shift) {
309− contentX = -spreadView.shift;
310− }
311− }
312− function undoContentXReset() {
313− if (contentWidth <= 0) {
314− contentWidthOnLastContentXChange = contentWidth;
315− lastContentX = contentX;
316− return false;
317− }
318−
319− if (contentWidth !== contentWidthOnLastContentXChange
320− && lastContentX === -shift && contentX === 0) {
321− // Flickable is resetting contentX because contentWidth has changed. Undo it.
322− contentX = -shift;
323− return true;
324− }
325−
326− contentWidthOnLastContentXChange = contentWidth;
327− lastContentX = contentX;
328− return false;
329− }
330− property real contentWidthOnLastContentXChange: -1
331− property real lastContentX: 0
332− // </FIXME-contentX>
333−
334− Behavior on contentX {
335− enabled: root.altTabPressed
336− UbuntuNumberAnimation {}
337− }
338−
339− onShiftedContentXChanged: {
340− if (root.beingResized) {
341− // Flickabe.contentX wiggles during resizes. Don't react to it.
342− return;
343− }
344−
345− switch (phase) {
346− case 0:
347− // the "spreadEnabled" part is because when code does "phase = 0; contentX = -shift" to
348− // dismiss the spread because spreadEnabled went to false, for some reason, during tests,
349− // Flickable might jump in and change contentX value back, causing the code below to do
350− // "phase = 1" which will make the spread stay.
351− // It sucks that we have no control whatsoever over whether or when Flickable animates its
352− // contentX.
353− if (root.spreadEnabled && shiftedContentX > width * positionMarker2) {
354− phase = 1;
355− }
356− break;
357− case 1:
358− if (shiftedContentX < width * positionMarker2) {
359− phase = 0;
360− } else if (shiftedContentX >= width * positionMarker4 && !spreadDragArea.dragging) {
361− phase = 2;
362− }
363− break;
364− }
365− fullyShowingFocusedAppUpdateTimer.restart();
366− }
367−
368− function snap() {
369− if (shiftedContentX < positionMarker1 * width) {
370− snapAnimation.targetContentX = -shift;
371− snapAnimation.start();
372− } else if (shiftedContentX < positionMarker2 * width) {
373− snapTo(1);
374− } else if (shiftedContentX < positionMarker3 * width) {
375− snapTo(1);
376− } else if (phase < 2){
377− snapToSpread();
378− root.opened();
379− }
380− }
381−
382− function snapToSpread() {
383− // Add 1 pixel to make sure we definitely hit positionMarker4 even with rounding errors of the animation.
384− snapAnimation.targetContentX = (root.width * spreadView.positionMarker4) + 1 - spreadView.shift;
385− snapAnimation.start();
386− }
387−
388− function snapTo(index) {
389− if (!root.altTabEnabled) {
390− // Reset to start instead
391− snapAnimation.targetContentX = -shift;
392− snapAnimation.start();
393− return;
394− }
395− if (topLevelSurfaceList.count <= index) {
396− // In case we're trying to snap to some non existing app, lets snap back to the first one
397− index = 0;
398− }
399− spreadView.selectedIndex = index;
400− // If we're not in full spread mode yet, always unwind to start pos
401− // otherwise unwind up to progress 0 of the selected index
402− if (spreadView.phase < 2) {
403− snapAnimation.targetContentX = -shift;
404− } else {
405− snapAnimation.targetContentX = -shift + index * spreadView.tileDistance;
406− }
407− snapAnimation.start();
408− }
409−
410− // In case the applicationManager already holds an app when starting up we're missing animations
411− // Make sure we end up in the same state
412− Component.onCompleted: {
413− spreadView.contentX = -spreadView.shift
414− priv.animateX = true;
415− snapAnimation.complete();
416− }
417−
418− SequentialAnimation {
419− id: snapAnimation
420− property int targetContentX: -spreadView.shift
421−
422− UbuntuNumberAnimation {
423− target: spreadView
424− property: "contentX"
425− to: snapAnimation.targetContentX
426− duration: UbuntuAnimation.FastDuration
427− }
428−
429− ScriptAction {
430− script: {
431− if (spreadView.selectedIndex >= 0) {
432− var delegate = spreadRepeater.itemAt(spreadView.selectedIndex)
433− delegate.focus = true;
434−
435− spreadView.selectedIndex = -1;
436− spreadView.phase = 0;
437− spreadView.contentX = -spreadView.shift;
438− }
439− }
440− }
441− }
442−
443− MouseArea {
444− id: spreadRow
445− // This width controls how much the spread can be flicked left/right. It's composed of:
446− // tileDistance * app count (with a minimum of 3 apps, in order to also allow moving 1 and 2 apps a bit)
447− // + some constant value (still scales with the screen width) which looks good and somewhat fills the screen
448− width: Math.max(3, topLevelSurfaceList.count) * spreadView.tileDistance + (spreadView.width - spreadView.tileDistance) * 1.5
449− height: parent.height
450− Behavior on width {
451− enabled: spreadView.closingIndex >= 0
452− UbuntuNumberAnimation {}
453− }
454− onWidthChanged: {
455− if (spreadView.closingIndex >= 0) {
456− spreadView.contentX = Math.min(spreadView.contentX, width - spreadView.width - spreadView.shift);
457− }
458− }
459−
460− x: spreadView.contentX
461−
462− onClicked: {
463− if (root.altTabEnabled) {
464− spreadView.snapTo(0);
465− }
466− }
467−
468− TopLevelSurfaceRepeater {
469− id: spreadRepeater
470− objectName: "spreadRepeater"
471− model: topLevelSurfaceList
472−
473− onItemRemoved: {
474− // Unless we're closing the app ourselves,
475− // lets make sure the spread doesn't mess up by the changing app list.
476− if (spreadView.closingIndex == -1) {
477− spreadView.phase = 0;
478− spreadView.contentX = -spreadView.shift;
479− }
480− focusTopMostApp();
481− }
482− function focusTopMostApp() {
483− if (spreadRepeater.count > 0) {
484− var topmostDelegate = spreadRepeater.itemAt(0);
485− topmostDelegate.focus = true;
486− }
487− }
488−
489− delegate: TransformedSpreadDelegate {
490− id: appDelegate
491− objectName: "spreadDelegate_" + model.id
492− startAngle: 45
493− endAngle: 5
494− startScale: root.startScale
495− endScale: root.endScale
496− startDistance: spreadView.tileDistance
497− endDistance: units.gu(.5)
498− width: spreadView.width
499− height: spreadView.height
500− selected: spreadView.selectedIndex == index
501− otherSelected: spreadView.selectedIndex >= 0 && !selected
502− interactive: !spreadView.interactive && spreadView.phase === 0
503− && priv.fullyShowingFocusedApp && root.interactive && focus
504− swipeToCloseEnabled: spreadView.interactive && root.interactive && !snapAnimation.running
505− maximizedAppTopMargin: root.maximizedAppTopMargin
506− dropShadow: spreadView.active || priv.focusedAppDelegateIsDislocated
507− focusFirstApp: root.focusFirstApp
508− highlightShown: root.altTabPressed && index === priv.highlightIndex
509−
510− readonly property bool isDash: model.application.appId == "unity8-dash"
511−
512− Component.onCompleted: {
513− // NB: We're differentiating if this delegate was created in response to a new entry in the model
514− // or if the Repeater is just populating itself with delegates to match the model it received.
515− if (!spreadRepeater.startingUp) {
516− // a top level window is always the focused one when it first appears, unfocusing
517− // any preexisting one
518− //
519− // new items are appended and must be manually brought to front.
520− // that's how it *must* be in order to get the animation for new
521− // surfaces working
522− claimFocus();
523− }
524− }
525−
526− onFocusChanged: {
527− if (focus && !spreadRepeater.startingUp) {
528− priv.focusedAppDelegate = appDelegate;
529− // If we're orphan (!parent) it means this stage is no longer the current one
530− // and will be deleted shortly. So we should no longer have a say over the model
531− if (root.parent) {
532− topLevelSurfaceList.raiseId(model.id);
533− }
534− }
535− }
536− function claimFocus() {
537− if (spreadView.phase > 0) {
538− spreadView.snapTo(model.index);
539− } else {
540− appDelegate.focus = true;
541− }
542− }
543− Connections {
544− target: model.surface
545− onFocusRequested: claimFocus()
546− }
547− Connections {
548− target: model.application
549− onFocusRequested: {
550− if (!model.surface) {
551− // when an app has no surfaces, we assume there's only one entry representing it:
552− // this delegate.
553− claimFocus();
554− } else {
555− // if the application has surfaces, focus request should be at surface-level.
556− }
557− }
558− }
559−
560− z: isDash && !spreadView.active ? -1 : behavioredIndex
561−
562− x: {
563− // focused app is always positioned at 0 except when following left edge drag
564− if (isFocused) {
565− if (!isDash && root.inverseProgress > 0 && spreadView.phase === 0) {
566− return root.inverseProgress;
567− }
568− return 0;
569− }
570− if (isDash && !spreadView.active && !spreadDragArea.dragging) {
571− return 0;
572− }
573−
574− // Otherwise line up for the spread
575− return spreadView.width + spreadIndex * spreadView.tileDistance;
576− }
577−
578− application: model.application
579− surface: model.surface
580− closeable: !isDash
581−
582− property real behavioredIndex: index
583− Behavior on behavioredIndex {
584− enabled: spreadView.closingIndex >= 0
585− UbuntuNumberAnimation {
586− id: appXAnimation
587− onRunningChanged: {
588− if (!running) {
589− spreadView.closingIndex = -1;
590− }
591− }
592− }
593− }
594−
595− property var xBehavior: xBehavior
596− Behavior on x {
597− enabled: root.spreadEnabled &&
598− !spreadView.active &&
599− !snapAnimation.running &&
600− !spreadDragArea.pressed &&
601− priv.animateX &&
602− !root.beingResized
603− UbuntuNumberAnimation {
604− id: xBehavior
605− duration: UbuntuAnimation.BriskDuration
606− }
607− }
608−
609− // Each tile has a different progress value running from 0 to 1.
610− // 0: means the tile is at the right edge.
611− // 1: means the tile has finished the main animation towards the left edge.
612− // >1: after the main animation has finished, tiles will continue to move very slowly to the left
613− progress: {
614− var tileProgress = (spreadView.shiftedContentX - behavioredIndex * spreadView.tileDistance) / spreadView.width;
615− // Tile 1 needs to move directly from the beginning...
616− if (root.focusFirstApp && behavioredIndex == 1 && spreadView.phase < 2) {
617− tileProgress += spreadView.tileDistance / spreadView.width;
618− }
619− // Limiting progress to ~0 and 1.7 to avoid binding calculations when tiles are not
620− // visible.
621− // < 0 : The tile is outside the screen on the right
622− // > 1.7: The tile is *very* close to the left edge and covered by other tiles now.
623− // Using 0.0001 to differentiate when a tile should still be visible (==0)
624− // or we can hide it (< 0)
625− tileProgress = Math.max(-0.0001, Math.min(1.7, tileProgress));
626− return tileProgress;
627− }
628−
629− // This mostly is the same as progress, just adds the snapping to phase 1 for tiles 0 and 1
630− animatedProgress: {
631− if (spreadView.phase == 0 && index <= priv.firstSpreadIndex) {
632− if (progress < spreadView.positionMarker1) {
633− return progress;
634− } else if (progress < spreadView.positionMarker1 + 0.05){
635− // p : 0.05 = x : pm2
636− return spreadView.positionMarker1 + (progress - spreadView.positionMarker1) * (spreadView.positionMarker2 - spreadView.positionMarker1) / 0.05
637− } else {
638− return spreadView.positionMarker2;
639− }
640− }
641− return progress;
642− }
643−
644− // Hide tile when progress is such that it will be off screen.
645− property bool occluded: {
646− if (spreadView.active && (progress >= 0 && progress < 1.7)) return false;
647− else if (!spreadView.active && isFocused) return false;
648− else if (xBehavior.running) return false;
649− else if (z <= 1 && priv.focusedAppDelegateIsDislocated) return false;
650− return true;
651− }
652−
653− visible: Powerd.status == Powerd.On &&
654− !greeter.fullyShown &&
655− !occluded
656−
657− shellOrientationAngle: root.shellOrientationAngle
658− shellOrientation: root.shellOrientation
659− orientations: root.orientations
660−
661− onClicked: {
662− if (root.altTabEnabled && spreadView.phase == 2) {
663− spreadView.snapTo(index);
664− }
665− }
666−
667− onDraggedChanged: {
668− if (dragged) {
669− spreadView.draggedDelegateCount++;
670− } else {
671− spreadView.draggedDelegateCount--;
672− }
673− }
674−
675− onClosed: {
676− spreadView.closingIndex = index;
677− if (appDelegate.surface) {
678− appDelegate.surface.close();
679− } else if (appDelegate.application) {
680− root.applicationManager.stopApplication(appDelegate.application.appId);
681− } else {
682− // should never happen
683− console.warn("Can't close topLevelSurfaceList entry as it has neither"
684− + " a surface nor an application");
685− }
686− }
687−
688− Binding {
689− target: root
690− when: index == 0
691− property: "mainAppWindowOrientationAngle"
692− value: appWindowOrientationAngle
693− }
694− Binding {
695− target: priv
696− when: index == 0
697− property: "focusedAppOrientationChangesEnabled"
698− value: orientationChangesEnabled
699− }
700−
701− StagedFullscreenPolicy {
702− id: fullscreenPolicy
703− surface: model.surface
704− }
705−
706− Connections {
707− target: root
708− onStageAboutToBeUnloaded: fullscreenPolicy.active = false
709− }
710− }
711− } // Repeater {
712− }
713− }
714−
715− //eat touch events during the right edge gesture
716− MouseArea {
717− objectName: "eventEaterArea"
718− anchors.fill: parent
719− enabled: spreadDragArea.dragging
720− }
721−
722− SwipeArea {
723− id: spreadDragArea
724− objectName: "spreadDragArea"
725− direction: Direction.Leftwards
726− enabled: (spreadView.phase != 2 && root.spreadEnabled) || dragging
727−
728− anchors { top: parent.top; right: parent.right; bottom: parent.bottom; }
729− width: root.dragAreaWidth
730−
731− property var gesturePoints: new Array()
732−
733− onTouchPositionChanged: {
734− if (dragging) {
735− // Gesture recognized. Let's move the spreadView with the finger
736− var dragX = Math.min(touchPosition.x + width, width); // Prevent dragging rightwards
737− dragX = -dragX + spreadDragArea.width - spreadView.shift;
738− // Don't allow dragging further than the animation crossing with phase2's animation
739− var maxMovement = spreadView.width * spreadView.positionMarker4 - spreadView.shift;
740−
741− spreadView.contentX = Math.min(dragX, maxMovement);
742− } else {
743− // Initial touch. Let's reset the spreadView to the starting position.
744− spreadView.phase = 0;
745− spreadView.contentX = -spreadView.shift;
746− }
747−
748− gesturePoints.push(touchPosition.x);
749− }
750−
751− onDraggingChanged: {
752− if (dragging) {
753− // A potential edge-drag gesture has started. Start recording it
754− gesturePoints = [];
755− } else {
756− // Ok. The user released. Find out if it was a one-way movement.
757− var oneWayFlick = true;
758− var smallestX = spreadDragArea.width;
759− for (var i = 0; i < gesturePoints.length; i++) {
760− if (gesturePoints[i] >= smallestX) {
761− oneWayFlick = false;
762− break;
763− }
764− smallestX = gesturePoints[i];
765− }
766− gesturePoints = [];
767−
768− if (oneWayFlick && spreadView.shiftedContentX > units.gu(2) &&
769− spreadView.shiftedContentX < spreadView.positionMarker1 * spreadView.width) {
770− // If it was a short one-way movement, do the Alt+Tab switch
771− // no matter if we didn't cross positionMarker1 yet.
772− spreadView.snapTo(1);
773− } else if (!dragging) {
774− // otherwise snap to the closest snap position we can find
775− // (might be back to start, to app 1 or to spread)
776− spreadView.snap();
777− }
778− }
779− }
780− }
781−
782− EdgeBarrier {
783− id: edgeBarrier
784−
785− // NB: it does its own positioning according to the specified edge
786− edge: Qt.RightEdge
787−
788− onPassed: {
789− spreadView.snapToSpread();
790− }
791− material: Component {
792− Item {
793− Rectangle {
794− width: parent.height
795− height: parent.width
796− rotation: 90
797− anchors.centerIn: parent
798− gradient: Gradient {
799− GradientStop { position: 0.0; color: Qt.rgba(0.16,0.16,0.16,0.7)}
800− GradientStop { position: 1.0; color: Qt.rgba(0.16,0.16,0.16,0)}
801− }
802− }
803− }
804− }
805− }
806−}
qml/Stage/SpreadDelegate.qmldeleted−424
@@ -1,424 +0,0 @@
1−/*
2− * Copyright 2014-2016 Canonical Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU Lesser General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
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 Lesser General Public License for more details.
12− *
13− * You should have received a copy of the GNU Lesser General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− *
16− * Authors: Michael Zanetti <michael.zanetti@canonical.com>
17− * Daniel d'Andrada <daniel.dandrada@canonical.com>
18− */
19−
20−import QtQuick 2.4
21−import QtQuick.Window 2.2
22−import Ubuntu.Components 1.3
23−import "../Components"
24−
25−FocusScope {
26− id: root
27−
28− // to be read from outside
29− readonly property bool dragged: dragArea.moving
30− signal clicked()
31− signal closed()
32− readonly property alias appWindowOrientationAngle: appWindowWithShadow.orientationAngle
33− readonly property alias appWindowRotation: appWindowWithShadow.rotation
34− readonly property alias orientationChangesEnabled: appWindow.orientationChangesEnabled
35− property int supportedOrientations: application ? application.supportedOrientations :
36− Qt.PortraitOrientation
37− | Qt.LandscapeOrientation
38− | Qt.InvertedPortraitOrientation
39− | Qt.InvertedLandscapeOrientation
40− readonly property alias focusedSurface: appWindow.focusedSurface
41−
42− // to be set from outside
43− property bool interactive: true
44− property bool dropShadow: true
45− property real maximizedAppTopMargin
46− property alias swipeToCloseEnabled: dragArea.enabled
47− property bool closeable
48− property alias application: appWindow.application
49− property alias surface: appWindow.surface
50− property int shellOrientationAngle
51− property int shellOrientation
52− property QtObject orientations
53− property bool highlightShown: false
54−
55− // overrideable from outside
56− property alias fullscreen: appWindow.fullscreen
57−
58− function matchShellOrientation() {
59− if (!root.application)
60− return;
61− appWindowWithShadow.orientationAngle = root.shellOrientationAngle;
62− }
63−
64− function animateToShellOrientation() {
65− if (!root.application)
66− return;
67−
68− if (root.application.rotatesWindowContents) {
69− appWindowWithShadow.orientationAngle = root.shellOrientationAngle;
70− } else {
71− orientationChangeAnimation.start();
72− }
73− }
74−
75− OrientationChangeAnimation {
76− id: orientationChangeAnimation
77− objectName: "orientationChangeAnimation"
78− spreadDelegate: root
79− background: background
80− window: appWindowWithShadow
81− screenshot: appWindowScreenshotWithShadow
82− }
83−
84− QtObject {
85− id: priv
86− objectName: "spreadDelegatePriv"
87− property bool startingUp: true
88− }
89−
90− Component.onCompleted: { finishStartUpTimer.start(); }
91− Timer { id: finishStartUpTimer; interval: 400; onTriggered: priv.startingUp = false }
92−
93− // JS version of QPlatformScreen::angleBetween C++ implementation.
94− // So don't ask me how it works because I don't know.
95− // Calling Screen.angleBetween from within a Binding component doesn't work for some reason.
96− function angleBetween(a, b) {
97− if (a == b)
98− return 0;
99−
100− var ia = Math.log(a) / Math.LN2;
101− var ib = Math.log(b) / Math.LN2;
102−
103− var delta = ia - ib;
104−
105− if (delta < 0)
106− delta = delta + 4;
107−
108− var angles = [ 0, 90, 180, 270 ];
109− return angles[delta];
110− }
111−
112− // Sets the initial orientationAngle of the window, when it first slides into view
113− // (with the splash screen likely being displayed). At that point we just try to
114− // match shell's current orientation. We need a bit of time in this state as the
115− // information we need to decide orientationAngle may take a few cycles to
116− // be set.
117− Binding {
118− target: appWindowWithShadow
119− property: "orientationAngle"
120− when: priv.startingUp
121− value: {
122− var supportedOrientations = root.supportedOrientations;
123−
124− if (supportedOrientations === Qt.PrimaryOrientation) {
125− supportedOrientations = root.orientations.primary;
126− }
127−
128− // If it doesn't support shell's current orientation
129− // then simply pick some arbitraty one that it does support
130− var chosenOrientation = 0;
131− if (supportedOrientations & root.shellOrientation) {
132− chosenOrientation = root.shellOrientation;
133− } else if (supportedOrientations & Qt.PortraitOrientation) {
134− chosenOrientation = root.orientations.portrait;
135− } else if (supportedOrientations & Qt.LandscapeOrientation) {
136− chosenOrientation = root.orientations.landscape;
137− } else if (supportedOrientations & Qt.InvertedPortraitOrientation) {
138− chosenOrientation = root.orientations.invertedPortrait;
139− } else if (supportedOrientations & Qt.InvertedLandscapeOrientation) {
140− chosenOrientation = root.orientations.invertedLandscape;
141− } else {
142− chosenOrientation = root.orientations.primary;
143− }
144−
145− return angleBetween(root.orientations.native_, chosenOrientation);
146− }
147− }
148−
149− Rectangle {
150− id: background
151− color: "black"
152− anchors.fill: parent
153− visible: false
154− }
155−
156− Item {
157− objectName: "displacedAppWindowWithShadow"
158−
159− readonly property real limit: root.height / 4
160−
161− y: root.closeable ? dragArea.distance : elastic(dragArea.distance)
162− width: parent.width
163− height: parent.height
164−
165− function elastic(distance) {
166− var k = distance < 0 ? -limit : limit
167− return k * (1 - Math.pow((k - 1) / k, distance))
168− }
169−
170− Item {
171− id: appWindowWithShadow
172− objectName: "appWindowWithShadow"
173−
174− property int orientationAngle
175−
176− property real transformRotationAngle: 0
177− property real transformOriginX
178− property real transformOriginY
179−
180− property var window: appWindow
181−
182− transform: Rotation {
183− origin.x: appWindowWithShadow.transformOriginX
184− origin.y: appWindowWithShadow.transformOriginY
185− axis { x: 0; y: 0; z: 1 }
186− angle: appWindowWithShadow.transformRotationAngle
187− }
188−
189− state: {
190− if (root.application && root.application.rotatesWindowContents) {
191− return "counterRotate";
192− } else if (orientationChangeAnimation.running) {
193− return "animatingRotation";
194− } else {
195− return "keepSceneRotation";
196− }
197− }
198−
199− // Ensures the given angle is in the form (0,90,180,270)
200− function normalizeAngle(angle) {
201− while (angle < 0) {
202− angle += 360;
203− }
204− return angle % 360;
205− }
206−
207− states: [
208− // A base state containing bindings common to others
209− // Ensures appWindowWithShadow fills the root area.
210− State {
211− name: "fillRootArea"
212− PropertyChanges {
213− target: appWindowWithShadow
214− restoreEntryValues: false
215− width: appWindowWithShadow.rotation == 0 || appWindowWithShadow.rotation == 180 ? root.width : root.height
216− height: appWindowWithShadow.rotation == 0 || appWindowWithShadow.rotation == 180 ? root.height : root.width
217− }
218− },
219− // In this state we stick to our currently set orientationAngle, which may change only due
220− // to calls made to matchShellOrientation() or animateToShellOrientation()
221− State {
222− name: "keepSceneRotation"
223− extend: "fillRootArea"
224− PropertyChanges {
225− target: appWindowWithShadow
226− restoreEntryValues: false
227− rotation: normalizeAngle(appWindowWithShadow.orientationAngle - root.shellOrientationAngle)
228− }
229− },
230− // In this state we counteract any shell rotation so that the window, in scene coordinates,
231− // remains unrotated.
232− // But the splash screen should still obey the set orientationAngle set by shell
233− State {
234− name: "counterRotate"
235− extend: "fillRootArea"
236− PropertyChanges {
237− target: appWindowWithShadow
238− rotation: normalizeAngle(-root.shellOrientationAngle)
239− }
240− PropertyChanges {
241− target: appWindow
242− surfaceOrientationAngle: appWindowWithShadow.orientationAngle
243− splashRotation: appWindowWithShadow.orientationAngle
244− }
245− },
246− // Dummy state.
247− // The animation may indiscriminately break any bindings assigned to appWindowWithShadow rotation,
248− // width or height.
249− State {
250− name: "animatingRotation"
251− }
252− ]
253−
254− anchors.centerIn: parent
255−
256− BorderImage {
257− anchors {
258− fill: appWindow
259− margins: -units.gu(2)
260− }
261− source: "graphics/dropshadow2gu.sci"
262− opacity: root.dropShadow ? .3 : 0
263− Behavior on opacity { UbuntuNumberAnimation {} }
264− }
265−
266− Rectangle {
267− id: selectionHighlight
268− objectName: "selectionHighlight"
269− anchors.fill: appWindow
270− anchors.margins: -units.gu(1)
271− color: "white"
272− opacity: root.highlightShown ? 0.15 : 0
273− antialiasing: true
274− visible: opacity > 0
275− }
276−
277− Rectangle {
278− anchors { left: selectionHighlight.left; right: selectionHighlight.right; bottom: selectionHighlight.bottom; }
279− height: units.dp(2)
280− color: theme.palette.normal.focus
281− visible: root.highlightShown
282− antialiasing: true
283− }
284−
285− ApplicationWindow {
286− id: appWindow
287− objectName: "appWindow"
288− focus: true
289− anchors {
290− fill: parent
291− topMargin: appWindow.fullscreen || (application && application.rotatesWindowContents)
292− ? 0 : maximizedAppTopMargin
293− }
294−
295− interactive: root.interactive
296− }
297− }
298− }
299−
300− Item {
301− // mimics appWindowWithShadow. Do the positioning of screenshots of non-fullscreen
302− // app windows
303− id: appWindowScreenshotWithShadow
304− visible: false
305−
306− property real transformRotationAngle: 0
307− property real transformOriginX
308− property real transformOriginY
309−
310− transform: Rotation {
311− origin.x: appWindowScreenshotWithShadow.transformOriginX
312− origin.y: appWindowScreenshotWithShadow.transformOriginY
313− axis { x: 0; y: 0; z: 1 }
314− angle: appWindowScreenshotWithShadow.transformRotationAngle
315− }
316−
317− readonly property Item window: appWindowScreenshot
318− readonly property bool ready: appWindowScreenshot.status === Image.Ready
319−
320− function take() {
321− appWindow.grabToImage(
322− function(result) {
323− appWindowScreenshot.source = result.url;
324− });
325− }
326− function discard() {
327− appWindowScreenshot.source = "";
328− }
329−
330− Image {
331− id: appWindowScreenshot
332− anchors.top: parent.top
333− }
334− }
335−
336− DraggingArea {
337− id: dragArea
338− objectName: "dragArea"
339− anchors.fill: parent
340−
341− property bool moving: false
342− property real distance: 0
343− readonly property int threshold: units.gu(2)
344− property int offset: 0
345−
346− readonly property real minSpeedToClose: units.gu(40)
347−
348− onDragValueChanged: {
349− if (!dragging) {
350− return;
351− }
352− moving = moving || Math.abs(dragValue) > threshold;
353− if (moving) {
354− distance = dragValue + offset;
355− }
356− }
357−
358− onMovingChanged: {
359− if (moving) {
360− offset = (dragValue > 0 ? -threshold: threshold)
361− } else {
362− offset = 0;
363− }
364− }
365−
366− onClicked: {
367− if (!moving) {
368− root.clicked();
369− }
370− }
371−
372− onDragEnd: {
373− if (!root.closeable) {
374− animation.animate("center")
375− return;
376− }
377−
378− // velocity and distance values specified by design prototype
379− if ((dragVelocity < -minSpeedToClose && distance < -units.gu(8)) || distance < -root.height / 2) {
380− animation.animate("up")
381− } else if ((dragVelocity > minSpeedToClose && distance > units.gu(8)) || distance > root.height / 2) {
382− animation.animate("down")
383− } else {
384− animation.animate("center")
385− }
386− }
387−
388− UbuntuNumberAnimation {
389− id: animation
390− objectName: "closeAnimation"
391− target: dragArea
392− property: "distance"
393− property bool requestClose: false
394−
395− function animate(direction) {
396− animation.from = dragArea.distance;
397− switch (direction) {
398− case "up":
399− animation.to = -root.height * 1.5;
400− requestClose = true;
401− break;
402− case "down":
403− animation.to = root.height * 1.5;
404− requestClose = true;
405− break;
406− default:
407− animation.to = 0
408− }
409− animation.start();
410− }
411−
412− onRunningChanged: {
413− if (!running) {
414− dragArea.moving = false;
415− if (requestClose) {
416− root.closed();
417− } else {
418− dragArea.distance = 0;
419− }
420− }
421− }
422− }
423− }
424−}
qml/Stage/TabletStage.qmldeleted−1201
@@ -1,1201 +0,0 @@
1−/*
2− * Copyright (C) 2014-2016 Canonical, Ltd.
3− *
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.
7− *
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.
12− *
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/>.
15− */
16−
17−import QtQuick 2.4
18−import Ubuntu.Components 1.3
19−import Ubuntu.Gestures 0.1
20−import Unity.Application 0.1
21−import Utils 0.1
22−import Powerd 0.1
23−import "../Components"
24−
25−AbstractStage {
26− id: root
27− objectName: "stages"
28− anchors.fill: parent
29−
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
35− // </tutorial-hacks>
36−
37− paintBackground: spreadView.shiftedContentX !== 0
38−
39− // Functions to be called from outside
40− function updateFocusedAppOrientation() {
41− var mainStageIndex = root.topLevelSurfaceList.indexForId(priv.mainStageItemId);
42−
43− if (priv.mainStageItemId && mainStageIndex >= 0 && mainStageIndex < spreadRepeater.count) {
44− spreadRepeater.itemAt(mainStageIndex).matchShellOrientation();
45− }
46−
47− for (var i = 0; i < spreadRepeater.count; ++i) {
48−
49− if (i === mainStageIndex) {
50− continue;
51− }
52−
53− var spreadDelegate = spreadRepeater.itemAt(i);
54−
55− var delta = spreadDelegate.appWindowOrientationAngle - root.shellOrientationAngle;
56− if (delta < 0) { delta += 360; }
57− delta = delta % 360;
58−
59− var supportedOrientations = spreadDelegate.supportedOrientations;
60− if (supportedOrientations === Qt.PrimaryOrientation) {
61− supportedOrientations = spreadDelegate.orientations.primary;
62− }
63−
64− if (delta === 180 && (supportedOrientations & spreadDelegate.shellOrientation)) {
65− spreadDelegate.matchShellOrientation();
66− }
67− }
68− }
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();
73− }
74−
75− var sideStageIndex = root.topLevelSurfaceList.indexForId(priv.sideStageItemId);
76− if (sideStageIndex >= 0 && sideStageIndex < spreadRepeater.count) {
77− spreadRepeater.itemAt(sideStageIndex).matchShellOrientation();
78− }
79− }
80−
81− function pushRightEdge(amount) {
82− if (spreadView.contentX == -spreadView.shift) {
83− edgeBarrier.push(amount);
84− }
85− }
86−
87− function closeFocusedDelegate() {
88− if (priv.focusedAppDelegate && priv.focusedAppDelegate.closeable) {
89− priv.focusedAppDelegate.closed();
90− }
91− }
92−
93− orientationChangesEnabled: priv.mainAppOrientationChangesEnabled
94−
95− mainApp: {
96− if (priv.mainStageItemId > 0) {
97− var index = root.topLevelSurfaceList.indexForId(priv.mainStageItemId);
98− return root.topLevelSurfaceList.applicationAt(index);
99− } else {
100− return null;
101− }
102− }
103−
104− supportedOrientations: {
105− if (mainApp) {
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;
112− }
113− return orientations;
114− } else {
115− // we just don't care
116− return Qt.PortraitOrientation |
117− Qt.LandscapeOrientation |
118− Qt.InvertedPortraitOrientation |
119− Qt.InvertedLandscapeOrientation;
120− }
121− }
122−
123− // How far left the stage has been dragged, used externally by tutorial code
124− dragProgress: spreadRepeater.count > 0 ? spreadRepeater.itemAt(0).animatedProgress : 0
125−
126− onWidthChanged: {
127− spreadView.selectedIndex = -1;
128− spreadView.phase = 0;
129− spreadView.contentX = -spreadView.shift;
130− }
131−
132− onInverseProgressChanged: {
133− // This can't be a simple binding because that would be triggered after this handler
134− // while we need it active before doing the anition left/right
135− spreadView.animateX = (inverseProgress == 0)
136− if (inverseProgress == 0 && priv.oldInverseProgress > 0) {
137− // left edge drag released. Minimum distance is given by design.
138− if (priv.oldInverseProgress > units.gu(22)) {
139− root.applicationManager.requestFocusApplication("unity8-dash");
140− }
141− }
142− priv.oldInverseProgress = inverseProgress;
143− }
144−
145− onAltTabPressedChanged: {
146− if (!spreadEnabled) {
147− return;
148− }
149− if (altTabPressed) {
150− priv.highlightIndex = Math.min(spreadRepeater.count - 1, 1);
151− spreadView.snapToSpread();
152− } else {
153− for (var i = 0; i < spreadRepeater.count; i++) {
154− if (spreadRepeater.itemAt(i).zIndex === priv.highlightIndex) {
155− spreadView.snapTo(i);
156− return;
157− }
158− }
159− }
160− }
161−
162− FocusScope {
163− focus: root.altTabPressed
164−
165− Keys.onPressed: {
166− switch (event.key) {
167− case Qt.Key_Tab:
168− priv.highlightIndex = (priv.highlightIndex + 1) % spreadRepeater.count
169− break;
170− case Qt.Key_Backtab:
171− priv.highlightIndex = (priv.highlightIndex + spreadRepeater.count - 1) % spreadRepeater.count
172− break;
173− }
174− }
175− }
176−
177− Connections {
178− target: root.topLevelSurfaceList
179− onListChanged: priv.updateMainAndSideStageIndexes()
180− }
181−
182− QtObject {
183− id: priv
184− objectName: "stagesPriv"
185−
186− function updateMainAndSideStageIndexes() {
187− var choseMainStage = false;
188− var choseSideStage = false;
189−
190− if (!root.topLevelSurfaceList)
191− return;
192−
193− for (var i = 0; i < spreadRepeater.count && (!choseMainStage || !choseSideStage); ++i) {
194− var spreadDelegate = spreadRepeater.itemAt(i);
195− if (sideStage.shown && spreadDelegate.stage == ApplicationInfoInterface.SideStage
196− && !choseSideStage) {
197− priv.sideStageDelegate = spreadDelegate
198− priv.sideStageItemId = root.topLevelSurfaceList.idAt(i);
199− priv.sideStageAppId = root.topLevelSurfaceList.applicationAt(i).appId;
200− choseSideStage = true;
201− } else if (!choseMainStage && spreadDelegate.stage == ApplicationInfoInterface.MainStage) {
202− priv.mainStageDelegate = spreadDelegate;
203− priv.mainStageItemId = root.topLevelSurfaceList.idAt(i);
204− priv.mainStageAppId = root.topLevelSurfaceList.applicationAt(i).appId;
205− choseMainStage = true;
206− }
207− }
208− if (!choseMainStage) {
209− priv.mainStageDelegate = null;
210− priv.mainStageItemId = 0;
211− priv.mainStageAppId = "";
212− }
213− if (!choseSideStage) {
214− priv.sideStageDelegate = null;
215− priv.sideStageItemId = 0;
216− priv.sideStageAppId = "";
217− }
218− }
219−
220− property var focusedAppDelegate: null
221−
222− property bool mainAppOrientationChangesEnabled: false
223−
224− property real landscapeHeight: root.orientations.native_ == Qt.LandscapeOrientation ?
225− root.nativeHeight : root.nativeWidth
226−
227− property bool shellIsLandscape: root.shellOrientation === Qt.LandscapeOrientation
228− || root.shellOrientation === Qt.InvertedLandscapeOrientation
229−
230− property var mainStageDelegate: null
231− property var sideStageDelegate: null
232−
233− property int mainStageItemId: 0
234− property int sideStageItemId: 0
235−
236− property string mainStageAppId: ""
237− property string sideStageAppId: ""
238−
239− property int oldInverseProgress: 0
240−
241− property int highlightIndex: 0
242−
243− property bool focusedAppDelegateIsDislocated: focusedAppDelegate &&
244− (focusedAppDelegate.dragOffset !== 0 || focusedAppDelegate.xTranslateAnimating)
245− function evaluateOneWayFlick(gesturePoints) {
246− // Need to have at least 3 points to recognize it as a flick
247− if (gesturePoints.length < 3) {
248− return false;
249− }
250− // Need to have a movement of at least 2 grid units to recognize it as a flick
251− if (Math.abs(gesturePoints[gesturePoints.length - 1] - gesturePoints[0]) < units.gu(2)) {
252− return false;
253− }
254−
255− var oneWayFlick = true;
256− var smallestX = gesturePoints[0];
257− var leftWards = gesturePoints[1] < gesturePoints[0];
258− for (var i = 1; i < gesturePoints.length; i++) {
259− if ((leftWards && gesturePoints[i] >= smallestX)
260− || (!leftWards && gesturePoints[i] <= smallestX)) {
261− oneWayFlick = false;
262− break;
263− }
264− smallestX = gesturePoints[i];
265− }
266− return oneWayFlick;
267− }
268−
269− onHighlightIndexChanged: {
270− spreadView.contentX = highlightIndex * spreadView.contentWidth / (spreadRepeater.count + 2)
271− }
272−
273− readonly property bool sideStageEnabled: root.shellOrientation == Qt.LandscapeOrientation ||
274− root.shellOrientation == Qt.InvertedLandscapeOrientation
275− }
276−
277− Instantiator {
278− model: root.applicationManager
279− delegate: QtObject {
280− property var stateBinding: Binding {
281− readonly property bool isDash: model.application ? model.application.appId == "unity8-dash" : false
282− target: model.application
283− property: "requestedState"
284−
285− // NB: the first application clause is just to ensure we never get warnings for trying to access
286− // members of a null variable.
287− value: model.application &&
288− (
289− (isDash && root.keepDashRunning)
290− || (!root.suspended && (model.application.appId === priv.mainStageAppId
291− || model.application.appId === priv.sideStageAppId))
292− )
293− ? ApplicationInfoInterface.RequestedRunning
294− : ApplicationInfoInterface.RequestedSuspended
295− }
296−
297− property var lifecycleBinding: Binding {
298− target: model.application
299− property: "exemptFromLifecycle"
300− value: model.application
301− ? (!model.application.isTouchApp || isExemptFromLifecycle(model.application.appId))
302− : false
303− }
304− }
305− }
306−
307− Binding {
308− target: MirFocusController
309− property: "focusedSurface"
310− value: priv.focusedAppDelegate ? priv.focusedAppDelegate.focusedSurface : null
311− when: root.parent && !spreadRepeater.startingUp
312− }
313−
314− Flickable {
315− id: spreadView
316− objectName: "spreadView"
317− anchors.fill: parent
318− interactive: (spreadDragArea.dragging || phase > 1) && draggedDelegateCount === 0
319− contentWidth: spreadRow.width - shift
320− contentX: -shift
321−
322− property int tileDistance: units.gu(20)
323−
324− // This indicates when the spreadView is active. That means, all the animations
325− // are activated and tiles need to line up for the spread.
326− readonly property bool active: shiftedContentX > 0 || spreadDragArea.dragging
327−
328− // The flickable needs to fill the screen in order to get touch events all over.
329− // However, we don't want to the user to be able to scroll back all the way. For
330− // that, the beginning of the gesture starts with a negative value for contentX
331− // so the flickable wants to pull it into the view already. "shift" tunes the
332− // distance where to "lock" the content.
333− readonly property real shift: width / 2
334− readonly property real shiftedContentX: contentX + shift
335−
336− // Phase of the animation:
337− // 0: Starting from right edge, a new app (index 1) comes in from the right
338− // 1: The app has reached the first snap position.
339− // 2: The list is dragged further and snaps into the spread view when entering phase 2
340− property int phase
341−
342− readonly property int phase0Width: sideStageWidth
343− readonly property int phase1Width: sideStageWidth
344−
345− // Those markers mark the various positions in the spread (ratio to screen width from right to left):
346− // 0 - 1: following finger, snap back to the beginning on release
347− readonly property real positionMarker1: 0.2
348− // 1 - 2: curved snapping movement, snap to nextInStack on release
349− readonly property real positionMarker2: sideStageWidth / spreadView.width
350− // 2 - 3: movement follows finger, snaps to phase 2 (full spread) on release
351− readonly property real positionMarker3: 0.6
352− // passing 3, we detach movement from the finger and snap to phase 2 (full spread)
353− readonly property real positionMarker4: 0.8
354−
355− readonly property int startSnapPosition: phase0Width * 0.5
356− readonly property int endSnapPosition: phase0Width * 0.75
357− readonly property real snapPosition: 0.75
358−
359− property int selectedIndex: -1
360− property int draggedDelegateCount: 0
361− property int closingIndex: -1
362− property var selectedDelegate: selectedIndex !== -1 ? spreadRepeater.itemAt(selectedIndex) : null
363−
364− // <FIXME-contentX> Workaround Flickable's behavior of bringing contentX back between valid boundaries
365− // when resized. The proper way to fix this is refactoring PhoneStage so that it doesn't
366− // rely on having Flickable.contentX keeping an out-of-bounds value when it's set programatically
367− // (as opposed to having contentX reaching an out-of-bounds value through dragging, which will trigger
368− // the Flickable.boundsBehavior upon release).
369− onContentXChanged: {
370− if (!undoContentXReset()) {
371− forceItToRemainStillIfBeingResized();
372− }
373− }
374− onShiftChanged: { forceItToRemainStillIfBeingResized(); }
375− function forceItToRemainStillIfBeingResized() {
376− if (root.beingResized && contentX != -spreadView.shift) {
377− contentX = -spreadView.shift;
378− }
379− }
380− function undoContentXReset() {
381− if (contentWidth <= 0) {
382− contentWidthOnLastContentXChange = contentWidth;
383− lastContentX = contentX;
384− return false;
385− }
386−
387− if (contentWidth != contentWidthOnLastContentXChange
388− && lastContentX == -shift && contentX == 0) {
389− // Flickable is resetting contentX because contentWidth has changed. Undo it.
390− contentX = -shift;
391− return true;
392− }
393−
394− contentWidthOnLastContentXChange = contentWidth;
395− lastContentX = contentX;
396− return false;
397− }
398− property real contentWidthOnLastContentXChange: -1
399− property real lastContentX: 0
400− // </FIXME-contentX>
401−
402− property bool animateX: true
403− property bool beingResized: root.beingResized
404− onBeingResizedChanged: {
405− if (beingResized) {
406− // Brace yourselves for impact!
407− selectedIndex = -1;
408− phase = 0;
409− contentX = -shift;
410− }
411− }
412−
413− property real sideStageWidth: units.gu(40)
414−
415− property bool surfaceDragging: triGestureArea.recognisedDrag
416−
417− readonly property bool sideStageVisible: priv.sideStageItemId != 0
418−
419− // In case applicationManager already holds an app when starting up we're missing animations
420− // Make sure we end up in the same state
421− Component.onCompleted: {
422− spreadView.contentX = -spreadView.shift
423− }
424−
425− property int nextInStack: {
426− var mainStageIndex = priv.mainStageDelegate ? priv.mainStageDelegate.index : -1;
427− var sideStageIndex = priv.sideStageDelegate ? priv.sideStageDelegate.index : -1;
428− switch (state) {
429− case "main":
430− if (root.topLevelSurfaceList.count > 1) {
431− return 1;
432− }
433− return -1;
434− case "mainAndOverlay":
435− if (root.topLevelSurfaceList.count <= 2) {
436− return -1;
437− }
438− if (mainStageIndex == 0 || sideStageIndex == 0) {
439− if (mainStageIndex == 1 || sideStageIndex == 1) {
440− return 2;
441− }
442− return 1;
443− }
444− return 0;
445− case "overlay":
446− return 1;
447− }
448− return -1;
449− }
450− property int nextZInStack
451−
452− states: [
453− State {
454− name: "empty"
455− },
456− State {
457− name: "main"
458− },
459− State { // Side Stage only in overlay mode
460− name: "overlay"
461− },
462− State { // Main Stage and Side Stage in overlay mode
463− name: "mainAndOverlay"
464− },
465− State { // Main Stage and Side Stage in split mode
466− name: "mainAndSplit"
467− }
468− ]
469− state: {
470− if ((priv.mainStageItemId && !priv.sideStageItemId) || !priv.sideStageEnabled) {
471− return "main";
472− }
473− if (!priv.mainStageItemId && priv.sideStageItemId) {
474− return "overlay";
475− }
476− if (priv.mainStageItemId && priv.sideStageItemId) {
477− return "mainAndOverlay";
478− }
479− return "empty";
480− }
481−
482− onShiftedContentXChanged: {
483− if (root.beingResized) {
484− // Flickabe.contentX wiggles during resizes. Don't react to it.
485− return;
486− }
487−
488− if (phase === 0) {
489− // the "spreadEnabled" part is because when code does "phase = 0; contentX = -shift" to
490− // dismiss the spread because spreadEnabled went to false, for some reason, during tests,
491− // Flickable might jump in and change contentX value back, causing the code below to do
492− // "phase = 1" which will make the spread stay.
493− // It sucks that we have no control whatsoever over whether or when Flickable animates its
494− // contentX.
495− if (root.spreadEnabled && shiftedContentX > width * positionMarker2) {
496− phase = 1;
497− }
498− }
499−
500− // Do not turn to else if
501− // Sometimes the animation of shiftedContentX is very fast and we need to jump from phase 0 to 1 to 2
502− // in the same onShiftedContentXChanged
503− if (phase === 1) {
504− if (shiftedContentX < width * positionMarker2) {
505− phase = 0;
506− } else if (shiftedContentX >= width * positionMarker4 && !spreadDragArea.dragging) {
507− phase = 2;
508− }
509− }
510− }
511−
512− function snap() {
513− if (shiftedContentX < phase0Width) {
514− snapAnimation.targetContentX = -shift;
515− snapAnimation.start();
516− } else if (shiftedContentX < phase1Width) {
517− snapTo(1);
518− } else {
519− snapToSpread();
520− }
521− }
522−
523− function snapToSpread() {
524− // Add 1 pixel to make sure we definitely hit positionMarker4 even with rounding errors of the animation.
525− snapAnimation.targetContentX = (spreadView.width * spreadView.positionMarker4) + 1 - shift;
526− snapAnimation.start();
527− }
528−
529− function snapTo(index) {
530− snapAnimation.stop();
531− spreadView.selectedIndex = index;
532− snapAnimation.targetContentX = -shift;
533− snapAnimation.start();
534− }
535−
536− // We need to shuffle z ordering a bit in order to keep side stage apps above main stage apps.
537− // We don't want to really reorder them in the model because that allows us to keep track
538− // of the last focused order.
539− function indexToZIndex(index) {
540− // only shuffle when we've got a main and overlay
541− if (state !== "mainAndOverlay") return index;
542−
543− var app = root.topLevelSurfaceList.applicationAt(index);
544− if (!app) {
545− return index;
546− }
547− var stage = spreadRepeater.itemAt(index) ? spreadRepeater.itemAt(index).stage : ApplicationInfoInterface.MainStage;
548−
549− // don't shuffle indexes greater than "actives or next"
550− if (index > 2) return index;
551−
552− var mainStageIndex = root.topLevelSurfaceList.indexForId(priv.mainStageItemId);
553−
554− if (index == mainStageIndex) {
555− // Active main stage always at 0
556− return 0;
557− }
558−
559− if (spreadView.nextInStack > 0) {
560− var stageOfNextInStack = spreadRepeater.itemAt(spreadView.nextInStack).stage;
561−
562− if (index === spreadView.nextInStack) {
563− // this is the next app in stack.
564−
565− if (stage === ApplicationInfoInterface.SideStage) {
566− // if the next app in stack is a sidestage app, it must order on top of other side stage app
567− return Math.min(2, root.topLevelSurfaceList.count-1);
568− }
569− return 1;
570− }
571− if (stageOfNextInStack === ApplicationInfoInterface.SideStage) {
572− // if the next app in stack is a sidestage app, it must order on top of other side stage app
573− return 1;
574− }
575− return Math.min(2, root.topLevelSurfaceList.count-1);
576− }
577− return Math.min(index+1, root.topLevelSurfaceList.count-1);
578− }
579−
580− SequentialAnimation {
581− id: snapAnimation
582− property int targetContentX: -spreadView.shift
583−
584− UbuntuNumberAnimation {
585− target: spreadView
586− property: "contentX"
587− to: snapAnimation.targetContentX
588− duration: UbuntuAnimation.FastDuration
589− }
590−
591− ScriptAction {
592− script: {
593− if (spreadView.selectedIndex >= 0) {
594− var newIndex = spreadView.selectedIndex;
595− var application = root.topLevelSurfaceList.applicationAt(newIndex);
596− var spreadDelegate = spreadRepeater.itemAt(newIndex);
597− if (spreadDelegate.stage === ApplicationInfoInterface.SideStage) {
598− sideStage.showNow();
599− }
600− spreadView.selectedIndex = -1;
601− spreadDelegate.focus = true;
602− spreadView.phase = 0;
603− spreadView.contentX = -spreadView.shift;
604− }
605− }
606− }
607− }
608−
609− Behavior on contentX {
610− enabled: root.altTabPressed
611− UbuntuNumberAnimation {}
612− }
613−
614− MouseArea {
615− id: spreadRow
616− x: spreadView.contentX
617− width: spreadView.width + Math.max(spreadView.width, root.topLevelSurfaceList.count * spreadView.tileDistance)
618− height: root.height
619−
620− onClicked: {
621− spreadView.snapTo(0);
622− }
623−
624− DropArea {
625− objectName: "MainStageDropArea"
626− anchors {
627− left: parent.left
628− top: parent.top
629− bottom: parent.bottom
630− }
631− width: spreadView.width - sideStage.width
632− enabled: priv.sideStageEnabled
633−
634− onDropped: {
635− drop.source.spreadDelegate.saveStage(ApplicationInfoInterface.MainStage);
636− drop.source.spreadDelegate.focus = true;
637− }
638− keys: "SideStage"
639− }
640−
641− SideStage {
642− id: sideStage
643− objectName: "sideStage"
644− height: priv.landscapeHeight
645− x: spreadView.width - width
646− z: {
647− if (!priv.mainStageItemId) return 0;
648−
649− if (priv.sideStageItemId && spreadView.nextInStack > 0) {
650− var nextDelegateInStack = spreadRepeater.itemAt(spreadView.nextInStack);
651−
652− if (nextDelegateInStack.stage === ApplicationInfoInterface.MainStage) {
653− // if the next app in stack is a main stage app, put the sidestage on top of it.
654− return 2;
655− }
656− return 1;
657− }
658−
659− return 1;
660− }
661− visible: progress != 0
662− enabled: priv.sideStageEnabled && sideStageDropArea.dropAllowed
663− opacity: priv.sideStageEnabled && !spreadView.active ? 1 : 0
664− Behavior on opacity { UbuntuNumberAnimation {} }
665−
666− onShownChanged: {
667− if (!shown && priv.sideStageDelegate && priv.focusedAppDelegate === priv.sideStageDelegate
668− && priv.mainStageDelegate) {
669− priv.mainStageDelegate.focus = true;
670− } else if (shown && priv.sideStageDelegate) {
671− priv.sideStageDelegate.focus = true;
672− }
673− }
674−
675− DropArea {
676− id: sideStageDropArea
677− objectName: "SideStageDropArea"
678− anchors.fill: parent
679−
680− property bool dropAllowed: true
681−
682− onEntered: {
683− dropAllowed = drag.keys != "Disabled";
684− }
685− onExited: {
686− dropAllowed = true;
687− }
688− onDropped: {
689− if (drop.keys == "MainStage") {
690− drop.source.spreadDelegate.saveStage(ApplicationInfoInterface.SideStage);
691− drop.source.spreadDelegate.focus = true;
692− }
693− }
694− drag {
695− onSourceChanged: {
696− if (!sideStageDropArea.drag.source) {
697− dropAllowed = true;
698− }
699− }
700− }
701− }
702− }
703−
704− TopLevelSurfaceRepeater {
705− id: spreadRepeater
706− objectName: "spreadRepeater"
707− model: root.topLevelSurfaceList
708−
709− onItemAdded: {
710− priv.updateMainAndSideStageIndexes();
711− if (spreadView.phase == 2) {
712− spreadView.snapTo(index);
713− }
714− }
715−
716− onItemRemoved: {
717− priv.updateMainAndSideStageIndexes();
718− // Unless we're closing the app ourselves,
719− // lets make sure the spread doesn't mess up by the changing app list.
720− if (spreadView.closingIndex == -1) {
721− spreadView.phase = 0;
722− spreadView.contentX = -spreadView.shift;
723− }
724− focusTopMostApp();
725− }
726− function focusTopMostApp() {
727− if (spreadRepeater.count > 0) {
728− var topmostDelegate = spreadRepeater.itemAt(0);
729− topmostDelegate.focus = true;
730− }
731− }
732−
733− delegate: TransformedTabletSpreadDelegate {
734− id: spreadTile
735− objectName: "spreadDelegate_" + model.id
736−
737− readonly property int index: model.index
738− width: spreadView.width
739− height: spreadView.height
740− active: model.id == priv.mainStageItemId || model.id == priv.sideStageItemId
741− zIndex: selected && stage == ApplicationInfoInterface.MainStage ? 0 : spreadView.indexToZIndex(index)
742− onZIndexChanged: {
743− if (spreadView.nextInStack == model.index) {
744− spreadView.nextZInStack = zIndex;
745− }
746− }
747− selected: spreadView.selectedIndex == index
748− otherSelected: spreadView.selectedIndex >= 0 && !selected
749− isInSideStage: priv.sideStageItemId == model.id
750− interactive: !spreadView.interactive && spreadView.phase === 0 && root.interactive
751− swipeToCloseEnabled: spreadView.interactive && !snapAnimation.running
752− maximizedAppTopMargin: root.maximizedAppTopMargin
753− dragOffset: !isDash && model.id == priv.mainStageItemId && root.inverseProgress > 0
754− && spreadView.phase === 0 ? root.inverseProgress : 0
755− application: model.application
756− surface: model.surface
757− closeable: !isDash
758− highlightShown: root.altTabPressed && priv.highlightIndex == zIndex
759− dropShadow: spreadView.active || priv.focusedAppDelegateIsDislocated
760−
761− readonly property bool wantsMainStage: stage == ApplicationInfoInterface.MainStage
762−
763− readonly property bool isDash: application.appId == "unity8-dash"
764−
765− onFocusChanged: {
766− if (focus && !spreadRepeater.startingUp) {
767− priv.focusedAppDelegate = spreadTile;
768− root.topLevelSurfaceList.raiseId(model.id);
769− }
770− if (focus && priv.sideStageEnabled && stage === ApplicationInfoInterface.SideStage) {
771− sideStage.show();
772− }
773− }
774− Connections {
775− target: model.surface
776− onFocusRequested: spreadTile.focus = true;
777− }
778− Connections {
779− target: spreadTile.application
780− onFocusRequested: {
781− if (!model.surface) {
782− // when an app has no surfaces, we assume there's only one entry representing it:
783− // this delegate.
784− spreadTile.focus = true;
785− } else {
786− // if the application has surfaces, focus request should be at surface-level.
787− }
788− }
789− }
790−
791− fullscreen: {
792− if (priv.mainStageDelegate && stage === ApplicationInfoInterface.SideStage) {
793− return priv.mainStageDelegate.fullscreen;
794− } else if (surface) {
795− return surface.state === Mir.FullscreenState;
796− } else if (application) {
797− return application.fullscreen;
798− } else {
799− return false;
800− }
801− }
802−
803− supportedOrientations: {
804− if (application) {
805− var orientations = application.supportedOrientations;
806− if (stage == ApplicationInfoInterface.MainStage) {
807− // When an app is in the mainstage, it always supports Landscape|InvertedLandscape
808− // so that we can drag it from the main stage to the side stage
809− orientations |= Qt.LandscapeOrientation | Qt.InvertedLandscapeOrientation;
810− }
811− return orientations;
812− } else {
813− // we just don't care
814− return Qt.PortraitOrientation |
815− Qt.LandscapeOrientation |
816− Qt.InvertedPortraitOrientation |
817− Qt.InvertedLandscapeOrientation;
818− }
819− }
820−
821− function saveStage(newStage) {
822− stage = newStage;
823− WindowStateStorage.saveStage(application.appId, newStage);
824− }
825−
826− // FIXME: A regular binding doesn't update any more after closing an app.
827− // Using a Binding for now.
828− Binding {
829− target: spreadTile
830− property: "z"
831− value: (!spreadView.active && isDash && !active) ? -1 : spreadTile.zIndex
832− }
833− x: spreadView.width
834−
835− property real behavioredZIndex: zIndex
836− Behavior on behavioredZIndex {
837− enabled: spreadView.closingIndex >= 0
838− UbuntuNumberAnimation {}
839− }
840− Connections {
841− target: priv
842− onSideStageEnabledChanged: refreshStage()
843− }
844−
845− property bool _constructing: true;
846− onStageChanged: {
847− if (!_constructing) {
848− priv.updateMainAndSideStageIndexes();
849− }
850− }
851−
852− Component.onCompleted: {
853− // a top level window is always the focused one when it first appears, unfocusing
854− // any preexisting one
855− focus = true;
856− refreshStage();
857− _constructing = false;
858− }
859−
860− function refreshStage() {
861− var newStage = ApplicationInfoInterface.MainStage;
862− if (priv.sideStageEnabled) { // we're in lanscape rotation.
863− if (!isDash && application && application.supportedOrientations & (Qt.PortraitOrientation|Qt.InvertedPortraitOrientation)) {
864− var defaultStage = ApplicationInfoInterface.SideStage; // if application supports portrait, it defaults to sidestage.
865− if (application.supportedOrientations & (Qt.LandscapeOrientation|Qt.InvertedLandscapeOrientation)) {
866− // if it supports lanscape, it defaults to mainstage.
867− defaultStage = ApplicationInfoInterface.MainStage;
868− }
869− newStage = WindowStateStorage.getStage(application.appId, defaultStage);
870− }
871− }
872−
873− stage = newStage;
874− }
875−
876− progress: {
877− var tileProgress = (spreadView.shiftedContentX - behavioredZIndex * spreadView.tileDistance) / spreadView.width;
878− // Some tiles (nextInStack, active) need to move directly from the beginning, normalize progress to immediately start at 0
879− if ((index == spreadView.nextInStack && spreadView.phase < 2) || (active && spreadView.phase < 1)) {
880− tileProgress += behavioredZIndex * spreadView.tileDistance / spreadView.width;
881− }
882− return tileProgress;
883− }
884−
885− // TODO: Hiding tile when progress is such that it will be off screen.
886− property bool occluded: {
887− if (spreadView.active && !offScreen) return false;
888− else if (spreadTile.active) return false;
889− else if (xTranslateAnimating) return false;
890− else if (z <= 1 && priv.focusedAppDelegateIsDislocated) return false;
891− return true;
892− }
893−
894− visible: Powerd.status == Powerd.On &&
895− !greeter.fullyShown &&
896− !occluded
897−
898− animatedProgress: {
899− if (spreadView.phase == 0 && (spreadTile.active || spreadView.nextInStack == index)) {
900− if (progress < spreadView.positionMarker1) {
901− return progress;
902− } else if (progress < spreadView.positionMarker1 + snappingCurve.period) {
903− return spreadView.positionMarker1 + snappingCurve.value * 3;
904− } else {
905− return spreadView.positionMarker2;
906− }
907− }
908− return progress;
909− }
910−
911− shellOrientationAngle: root.shellOrientationAngle
912− shellOrientation: root.shellOrientation
913− orientations: root.orientations
914−
915− states: [
916− State {
917− name: "MainStage"
918− when: spreadTile.stage == ApplicationInfoInterface.MainStage
919− },
920− State {
921− name: "SideStage"
922− when: spreadTile.stage == ApplicationInfoInterface.SideStage
923−
924− PropertyChanges {
925− target: spreadTile
926− width: spreadView.sideStageWidth
927− height: priv.landscapeHeight
928−
929− supportedOrientations: Qt.PortraitOrientation
930− shellOrientationAngle: 0
931− shellOrientation: Qt.PortraitOrientation
932− orientations: sideStageOrientations
933− }
934− }
935− ]
936−
937− Orientations {
938− id: sideStageOrientations
939− primary: Qt.PortraitOrientation
940− native_: Qt.PortraitOrientation
941− portrait: root.orientations.portrait
942− invertedPortrait: root.orientations.invertedPortrait
943− landscape: root.orientations.landscape
944− invertedLandscape: root.orientations.invertedLandscape
945− }
946−
947− transitions: [
948− Transition {
949− to: "SideStage"
950− SequentialAnimation {
951− PropertyAction {
952− target: spreadTile
953− properties: "width,height,supportedOrientations,shellOrientationAngle,shellOrientation,orientations"
954− }
955− ScriptAction {
956− script: {
957− // rotate immediately.
958− spreadTile.matchShellOrientation();
959− if (priv.focusedAppDelegate === spreadTile &&
960− priv.sideStageEnabled && !sideStage.shown) {
961− // Sidestage was focused, so show the side stage.
962− sideStage.show();
963− }
964− }
965− }
966− }
967− },
968− Transition {
969− from: "SideStage"
970− SequentialAnimation {
971− ScriptAction {
972− script: {
973− if (priv.sideStageDelegate === spreadTile &&
974− mainApp && (mainApp.supportedOrientations & (Qt.PortraitOrientation|Qt.InvertedPortraitOrientation)) == 0) {
975− // The mainstage app did not natively support portrait orientation, so focus the sidestage.
976− spreadTile.focus = true;
977− }
978− }
979− }
980− PropertyAction {
981− target: spreadTile
982− properties: "width,height,supportedOrientations,shellOrientationAngle,shellOrientation,orientations"
983− }
984− ScriptAction { script: { spreadTile.matchShellOrientation(); } }
985− }
986− }
987− ]
988−
989− onClicked: {
990− if (spreadView.phase == 2) {
991− spreadView.snapTo(index);
992− }
993− }
994−
995− onDraggedChanged: {
996− if (dragged) {
997− spreadView.draggedDelegateCount++;
998− } else {
999− spreadView.draggedDelegateCount--;
1000− }
1001− }
1002−
1003− onClosed: {
1004− spreadView.closingIndex = index;
1005− if (spreadTile.surface) {
1006− spreadTile.surface.close();
1007− } else if (spreadTile.application) {
1008− root.applicationManager.stopApplication(spreadTile.application.appId);
1009− } else {
1010− // should never happen
1011− console.warn("Can't close topLevelSurfaceList entry as it has neither"
1012− + " a surface nor an application");
1013− }
1014− }
1015−
1016− Binding {
1017− target: root
1018− when: model.id == priv.mainStageItemId
1019− property: "mainAppWindowOrientationAngle"
1020− value: appWindowOrientationAngle
1021− }
1022− Binding {
1023− target: priv
1024− when: model.id == priv.mainStageItemId
1025− property: "mainAppOrientationChangesEnabled"
1026− value: orientationChangesEnabled
1027− }
1028−
1029− EasingCurve {
1030− id: snappingCurve
1031− type: EasingCurve.Linear
1032− period: (spreadView.positionMarker2 - spreadView.positionMarker1) / 3
1033− progress: spreadTile.progress - spreadView.positionMarker1
1034− }
1035−
1036− StagedFullscreenPolicy {
1037− id: fullscreenPolicy
1038− surface: model.surface
1039− }
1040− Connections {
1041− target: root
1042− onStageAboutToBeUnloaded: fullscreenPolicy.active = false
1043− }
1044− }
1045− }
1046− }
1047− }
1048−
1049− TabletSideStageTouchGesture {
1050− id: triGestureArea
1051− anchors.fill: parent
1052− enabled: priv.sideStageEnabled && !spreadView.active
1053−
1054− property Item spreadDelegate
1055−
1056− dragComponent: dragComponent
1057− dragComponentProperties: { "spreadDelegate": spreadDelegate }
1058−
1059− onPressed: {
1060− function matchDelegate(obj) { return String(obj.objectName).indexOf("spreadDelegate") >= 0; }
1061−
1062− var delegateAtCenter = Functions.itemAt(spreadRow, x, y, matchDelegate);
1063− if (!delegateAtCenter) return;
1064−
1065− spreadDelegate = delegateAtCenter;
1066− }
1067−
1068− onClicked: {
1069− if (sideStage.shown) {
1070− sideStage.hide();
1071− } else {
1072− sideStage.show();
1073− }
1074− }
1075−
1076− onDragStarted: {
1077− // If we're dragging to the sidestage.
1078− if (!sideStage.shown) {
1079− sideStage.show();
1080− }
1081− }
1082−
1083− Component {
1084− id: dragComponent
1085− SurfaceContainer {
1086− property Item spreadDelegate
1087−
1088− surface: spreadDelegate ? spreadDelegate.surface : null
1089−
1090− consumesInput: false
1091− interactive: false
1092− resizeSurface: false
1093− focus: false
1094−
1095− width: units.gu(40)
1096− height: units.gu(40)
1097−
1098− Drag.hotSpot.x: width/2
1099− Drag.hotSpot.y: height/2
1100− // only accept opposite stage.
1101− Drag.keys: {
1102− if (!surface) return "Disabled";
1103− if (spreadDelegate.isDash) return "Disabled";
1104−
1105− if (spreadDelegate.stage === ApplicationInfo.MainStage) {
1106− if (spreadDelegate.application.supportedOrientations
1107− & (Qt.PortraitOrientation|Qt.InvertedPortraitOrientation)) {
1108− return "MainStage";
1109− }
1110− return "Disabled";
1111− }
1112− return "SideStage";
1113− }
1114− }
1115− }
1116− }
1117−
1118− //eat touch events during the right edge gesture
1119− MouseArea {
1120− anchors.fill: parent
1121− enabled: spreadDragArea.dragging
1122− }
1123−
1124− SwipeArea {
1125− id: spreadDragArea
1126− objectName: "spreadDragArea"
1127− x: parent.width - root.dragAreaWidth
1128− anchors { top: parent.top; bottom: parent.bottom }
1129− width: root.dragAreaWidth
1130− direction: Direction.Leftwards
1131− enabled: (spreadView.phase != 2 && root.spreadEnabled) || dragging
1132−
1133− property var gesturePoints: new Array()
1134−
1135− onTouchPositionChanged: {
1136− if (!dragging) {
1137− spreadView.phase = 0;
1138− spreadView.contentX = -spreadView.shift;
1139− }
1140−
1141− if (dragging) {
1142− var dragX = -touchPosition.x + spreadDragArea.width - spreadView.shift;
1143− var maxDrag = spreadView.width * spreadView.positionMarker4 - spreadView.shift;
1144− spreadView.contentX = Math.min(dragX, maxDrag);
1145− }
1146− gesturePoints.push(touchPosition.x);
1147− }
1148−
1149− onDraggingChanged: {
1150− if (dragging) {
1151− // Gesture recognized. Start recording this gesture
1152− gesturePoints = [];
1153− } else {
1154− // Ok. The user released. Find out if it was a one-way movement.
1155− var oneWayFlick = priv.evaluateOneWayFlick(gesturePoints);
1156− gesturePoints = [];
1157−
1158− if (oneWayFlick && spreadView.shiftedContentX < spreadView.positionMarker1 * spreadView.width) {
1159− // If it was a short one-way movement, do the Alt+Tab switch
1160− // no matter if we didn't cross positionMarker1 yet.
1161− spreadView.snapTo(spreadView.nextInStack);
1162− } else {
1163− if (spreadView.shiftedContentX < spreadView.width * spreadView.positionMarker1) {
1164− spreadView.snap();
1165− } else if (spreadView.shiftedContentX < spreadView.width * spreadView.positionMarker2) {
1166− spreadView.snapTo(spreadView.nextInStack);
1167− } else {
1168− // otherwise snap to the closest snap position we can find
1169− // (might be back to start, to app 1 or to spread)
1170− spreadView.snap();
1171− }
1172− }
1173− }
1174− }
1175− }
1176−
1177− EdgeBarrier {
1178− id: edgeBarrier
1179−
1180− // NB: it does its own positioning according to the specified edge
1181− edge: Qt.RightEdge
1182−
1183− onPassed: {
1184− spreadView.snapToSpread();
1185− }
1186− material: Component {
1187− Item {
1188− Rectangle {
1189− width: parent.height
1190− height: parent.width
1191− rotation: 90
1192− anchors.centerIn: parent
1193− gradient: Gradient {
1194− GradientStop { position: 0.0; color: Qt.rgba(0.16,0.16,0.16,0.7)}
1195− GradientStop { position: 1.0; color: Qt.rgba(0.16,0.16,0.16,0)}
1196− }
1197− }
1198− }
1199− }
1200− }
1201−}
qml/Stage/TransformedSpreadDelegate.qmldeleted−391
@@ -1,391 +0,0 @@
1−/*
2− * Copyright 2014,2016 Canonical Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU Lesser General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
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 Lesser General Public License for more details.
12− *
13− * You should have received a copy of the GNU Lesser General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− *
16− * Authors: Michael Zanetti <michael.zanetti@canonical.com>
17−*/
18−
19−import QtQuick 2.4
20−import Utils 0.1
21−import Ubuntu.Components 1.3
22−
23−SpreadDelegate {
24− id: root
25−
26− // Set this to true when this tile is selected in the spread. The animation will change to bring the tile to front.
27− property bool selected: false
28− // Set this to true when another tile in the spread is selected. The animation will change to fade this tile out.
29− property bool otherSelected: false
30−
31− // The progress animates the tiles. A value > 0 makes it appear from the right edge. At 1 it reaches the end position.
32− property real progress: 0
33− // This is required to snap tile 1 during phase 1 and 2.
34− property real animatedProgress: 0
35−
36− property real startAngle: 0
37− property real endAngle: 0
38−
39− property real startScale: 1
40− property real endScale: 1
41−
42− // Specific to just one tile
43− property real tile1StartScale: startScale + .4
44− property real tile0SnapAngle: 10
45−
46− property real startDistance: units.gu(5)
47− property real endDistance: units.gu(.5)
48−
49− // Whether first app is displayed entirely vs just on the spread edge
50− property bool focusFirstApp: true
51−
52− // Whether this delegate is displayed to the user outside of the spread
53− readonly property bool isFocused: focusFirstApp && index === 0
54−
55− // Adjusted index for any spread animation calculations
56− readonly property int spreadIndex: index - (focusFirstApp ? 1 : 0)
57−
58− // How far left this delegate has been translated
59− readonly property alias xTranslate: priv.xTranslate
60−
61− onSelectedChanged: {
62− if (selected) {
63− priv.snapshot();
64− }
65− priv.isSelected = selected;
66− }
67−
68− onOtherSelectedChanged: {
69− if (otherSelected) {
70− priv.snapshot();
71− }
72− priv.otherSelected = otherSelected;
73− }
74−
75− Connections {
76− target: spreadView
77− onPhaseChanged: {
78− if (root.focusFirstApp && spreadView.phase == 1) {
79− if (index === 0) {
80− priv.phase2startTranslate = priv.easingAnimation(0, spreadView.positionMarker4, 0, -spreadView.width, spreadView.positionMarker4) + spreadView.width;
81− priv.phase2startAngle = priv.easingAnimation(0, spreadView.positionMarker4, root.startAngle, root.endAngle, spreadView.positionMarker4);
82− priv.phase2startScale = priv.easingAnimation(0, spreadView.positionMarker4, root.startScale, root.endScale, spreadView.positionMarker4);
83− priv.phase2startTopMarginProgress = priv.easingAnimation(0, 1, 0, 1, spreadView.positionMarker4);
84− } else if (index == 1) {
85− // find where the main easing for Tile 1 would be when reaching phase 2
86− var phase2Progress = spreadView.positionMarker4 - spreadView.tileDistance / spreadView.width;
87− priv.phase2startTranslate = priv.easingAnimation(0, phase2Progress, 0, -spreadView.width + root.endDistance, phase2Progress);
88− priv.phase2startAngle = priv.easingAnimation(0, phase2Progress, root.startAngle, root.endAngle, phase2Progress);
89− priv.phase2startScale = priv.easingAnimation(0, phase2Progress, root.startScale, root.endScale, phase2Progress);
90− priv.phase2startTopMarginProgress = priv.easingAnimation(0, 1, 0, spreadView.positionMarker4, phase2Progress);
91− }
92− }
93− }
94− }
95−
96− QtObject {
97− id: priv
98− property bool isSelected: false
99− property bool otherSelected: false
100− property real selectedProgress
101− property real selectedXTranslate
102− property real selectedAngle
103− property real selectedScale
104− property real selectedOpacity
105− property real selectedTopMarginProgress
106−
107− // Those values are needed as target values for the end of phase 1.
108− // As they are static values, lets calculate them once when entering phase 1 instead of calculating them in each animation pass.
109− property real phase2startTranslate
110− property real phase2startAngle
111− property real phase2startScale
112− property real phase2startTopMarginProgress
113−
114− function snapshot() {
115− selectedProgress = root.progress;
116− selectedXTranslate = xTranslate;
117− selectedAngle = angle;
118− selectedScale = scale;
119− selectedOpacity = opacity;
120− selectedTopMarginProgress = topMarginProgress;
121− }
122−
123− function linearAnimation(startProgress, endProgress, startValue, endValue, progress) {
124− // progress : progressDiff = value : valueDiff => value = progress * valueDiff / progressDiff
125− return (progress - startProgress) * (endValue - startValue) / (endProgress - startProgress) + startValue;
126− }
127−
128− function easingAnimation(startProgress, endProgress, startValue, endValue, progress) {
129− helperEasingCurve.progress = progress - startProgress;
130− helperEasingCurve.period = endProgress - startProgress;
131− return helperEasingCurve.value * (endValue - startValue) + startValue;
132− }
133−
134− // The following blocks handle the animation of the tile in the spread.
135− // At the beginning, each tile is attached at the right edge, outside the screen.
136− // The progress for each tile starts at 0 and it reaches its end position at a progress of 1.
137− // The first phases are handled special for the first 2 tiles. as we do the alt-tab and snapping
138− // in there. Once we reached phase 3, the animation is the same for all tiles.
139− // When a tile is selected, the animation state is snapshotted, and the spreadView is unwound.
140− // All tiles are kept in place and faded out to 0 opacity except
141− // the selected tile, which is animated from the snapshotted position to be fullscreen.
142−
143− readonly property real xTranslate: {
144− if (!spreadView.active) {
145− return 0;
146− }
147−
148− if (otherSelected) {
149− if (spreadView.phase < 2 && root.isFocused) {
150− return linearAnimation(selectedProgress, 0, selectedXTranslate,
151− selectedXTranslate - spreadView.tileDistance, root.progress);
152− }
153−
154− return selectedXTranslate;
155− }
156−
157− if (root.focusFirstApp && index === 0) {
158− if (spreadView.phase == 0) {
159− return Math.min(0, linearAnimation(0, spreadView.positionMarker2,
160− 0, -spreadView.width * .25, root.animatedProgress));
161− } else if (spreadView.phase == 1){
162− return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4,
163− -spreadView.width * .25, priv.phase2startTranslate, root.progress);
164− } else if (!priv.isSelected){ // phase 2
165− // Apply the same animation as with the rest but add spreadView.width to align it with the others.
166− return -easingCurve.value * spreadView.width + spreadView.width;
167− } else {
168− return linearAnimation(selectedProgress, 0, selectedXTranslate, 0, root.progress);
169− }
170− } else if (root.focusFirstApp && index === 1) {
171− if (spreadView.phase == 0 && !priv.isSelected) {
172− return linearAnimation(0, spreadView.positionMarker2,
173− 0, -spreadView.width * spreadView.snapPosition, root.animatedProgress);
174− } else if (spreadView.phase == 1 && !priv.isSelected) {
175− return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4,
176− -spreadView.width * spreadView.snapPosition, priv.phase2startTranslate,
177− root.progress);
178− }
179− }
180−
181− if (priv.isSelected) {
182− // Distance to left edge
183− var targetTranslate = -spreadView.width - (root.spreadIndex * root.startDistance);
184− return linearAnimation(selectedProgress, 0,
185− selectedXTranslate, targetTranslate, root.progress);
186− }
187−
188− // Fix it at the right edge...
189− var rightEdgeOffset = -(root.spreadIndex * root.startDistance);
190− // ...and use our easing to move them to the left. Stop a bit earlier for each tile
191− var animatedEndDistance = linearAnimation(0, 2, root.endDistance, 0, root.progress);
192− return -easingCurve.value * spreadView.width + (index * animatedEndDistance) + rightEdgeOffset;
193−
194− }
195−
196− readonly property real angle: {
197− if (!spreadView.active) {
198− return 0;
199− }
200−
201− if (priv.otherSelected) {
202− return priv.selectedAngle;
203− }
204− if (priv.isSelected) {
205− return linearAnimation(selectedProgress, 0, selectedAngle, 0, root.progress);
206− }
207− if (root.focusFirstApp && index === 0) {
208− if (spreadView.phase == 0) {
209− return Math.max(0, linearAnimation(0, spreadView.positionMarker2,
210− 0, root.tile0SnapAngle, root.animatedProgress));
211− } else if (spreadView.phase == 1) {
212− return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4,
213− root.tile0SnapAngle, phase2startAngle, root.progress);
214− }
215− } else if (root.focusFirstApp && index === 1) {
216− if (spreadView.phase == 0) {
217− return linearAnimation(0, spreadView.positionMarker2, root.startAngle,
218− root.startAngle * (1-spreadView.snapPosition), root.animatedProgress);
219− } else if (spreadView.phase == 1) {
220− return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4,
221− root.startAngle * (1-spreadView.snapPosition), priv.phase2startAngle,
222− root.progress);
223− }
224− }
225− return root.startAngle - easingCurve.value * (root.startAngle - root.endAngle);
226− }
227−
228− readonly property real scale: {
229− if (!spreadView.active) {
230− return 1;
231− }
232− if (priv.otherSelected) {
233− return priv.selectedScale;
234− }
235− if (priv.isSelected) {
236− return linearAnimation(selectedProgress, 0, selectedScale, 1, root.progress);
237− }
238−
239− if (root.focusFirstApp && index === 0) {
240− if (spreadView.phase == 0) {
241− return 1;
242− } else if (spreadView.phase == 1) {
243− return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4,
244− 1, phase2startScale, root.progress);
245− }
246− } else if (root.focusFirstApp && index === 1) {
247− if (spreadView.phase == 0) {
248− var targetScale = tile1StartScale - ((tile1StartScale - 1) * spreadView.snapPosition);
249− return linearAnimation(0, spreadView.positionMarker2,
250− root.tile1StartScale, targetScale, root.animatedProgress);
251− } else if (spreadView.phase == 1) {
252− var startScale = tile1StartScale - ((tile1StartScale - 1) * spreadView.snapPosition);
253− return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4,
254− startScale, priv.phase2startScale, root.progress);
255− }
256− }
257− return root.startScale - easingCurve.value * (root.startScale - root.endScale);
258− }
259−
260− readonly property real opacity: {
261− if (priv.otherSelected) {
262− return linearAnimation (selectedProgress, Math.max(0, selectedProgress - .5),
263− selectedOpacity, 0, root.progress);
264− }
265− if (root.isFocused) {
266− switch (spreadView.phase) {
267− case 0:
268− return linearAnimation(0, spreadView.positionMarker2, 1, .7, root.animatedProgress);
269− case 1:
270− return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4,
271− .7, 1, root.animatedProgress);
272− }
273− }
274−
275− return 1;
276− }
277−
278− readonly property real topMarginProgress: {
279− if (priv.isSelected) {
280− return linearAnimation(selectedProgress, 0, selectedTopMarginProgress, 0, root.progress);
281− }
282−
283− if (root.focusFirstApp && index === 0) {
284− if (spreadView.phase == 0) {
285− return 0;
286− } else if (spreadView.phase == 1) {
287− return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4,
288− 0, priv.phase2startTopMarginProgress, root.progress);
289− }
290− } else if (root.focusFirstApp && index === 1) {
291− if (spreadView.phase == 0) {
292− return 0;
293− } else if (spreadView.phase == 1) {
294− return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4,
295− 0, priv.phase2startTopMarginProgress, root.progress);
296− }
297− }
298−
299− return easingCurve.value;
300− }
301− }
302−
303− transform: [
304− Rotation {
305− origin { x: 0; y: spreadView.height / 2 }
306− axis { x: 0; y: 1; z: 0 }
307− angle: priv.angle
308− },
309−
310− // The next two transformations are to ensure that fullscreen and rotated
311− // windows all have the same size and position as an unrotated (0 degrees)
312− // non-fullscreen window when they're stacked on top of each other on the
313− // far left of the spread.
314− Translate {
315− y: !root.fullscreen && appWindowRotation === 180
316− ? priv.topMarginProgress * maximizedAppTopMargin
317− : 0
318− },
319− Scale {
320− origin {
321− x: appWindowRotation === 270 ? spreadView.width : 0
322− y: spreadView.height
323− }
324−
325− xScale: {
326− switch (appWindowRotation) {
327− case 90:
328− case 270:
329− if (root.fullscreen) {
330− return 1;
331− } else {
332− return 1 + priv.topMarginProgress * maximizedAppTopMargin / spreadView.width;
333− }
334− break;
335− default:
336− return 1;
337− }
338− }
339−
340− yScale: {
341− switch (appWindowRotation) {
342− case 0:
343− if (root.fullscreen) {
344− return 1 - priv.topMarginProgress * maximizedAppTopMargin / spreadView.height;
345− } else {
346− return 1;
347− }
348− break;
349− case 90:
350− case 270:
351− return 1 - priv.topMarginProgress * maximizedAppTopMargin / spreadView.height;
352− break;
353− default:
354− return 1;
355− }
356− }
357− },
358−
359− Scale {
360− origin { x: 0; y: spreadView.height / 2 }
361− xScale: priv.scale
362− yScale: xScale
363− },
364− Translate {
365− x: priv.xTranslate
366− }
367− ]
368−
369− opacity: spreadView.phase == 2 ? priv.opacity : 1
370−
371− Rectangle {
372− anchors.fill: parent
373− color: "black"
374− opacity: spreadView.phase < 2 ? 1 - priv.opacity : 0
375− }
376−
377− EasingCurve {
378− id: easingCurve
379− type: EasingCurve.OutSine
380− period: 1 - spreadView.positionMarker2
381− progress: root.progress
382− }
383−
384− // This is used as a calculation helper to figure values for progress other than the current one
385− // Do not bind anything to this...
386− EasingCurve {
387− id: helperEasingCurve
388− type: easingCurve.type
389− period: easingCurve.period
390− }
391−}
qml/Stage/TransformedTabletSpreadDelegate.qmldeleted−437
@@ -1,437 +0,0 @@
1−/*
2− * Copyright 2014 Canonical Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU Lesser General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
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 Lesser General Public License for more details.
12− *
13− * You should have received a copy of the GNU Lesser General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− *
16− * Authors: Michael Zanetti <michael.zanetti@canonical.com>
17−*/
18−
19−import QtQuick 2.4
20−import Utils 0.1
21−import Ubuntu.Components 1.3
22−import Unity.Application 0.1
23−
24−SpreadDelegate {
25− id: root
26−
27− // Set this to true when this tile is selected in the spread. The animation will change to bring the tile to front.
28− property bool selected: false
29− // Set this to true when another tile in the spread is selected. The animation will change to fade this tile out.
30− property bool otherSelected: false
31− // Set this to true when this tile a currently active on either the MS or the SS.
32− property bool active: false
33−
34− property int zIndex
35− property real progress: 0
36− property real animatedProgress: 0
37−
38− property real startDistance: units.gu(5)
39− property real endDistance: units.gu(.5)
40−
41− property real startScale: 1.1
42− property real endScale: 0.7
43− property real dragStartScale: startScale + .2
44−
45− property real startAngle: 15
46− property real endAngle: 5
47−
48− property bool isInSideStage: false
49−
50− property int stage: ApplicationInfoInterface.MainStage
51−
52− property int dragOffset: 0
53− readonly property alias xTranslateAnimating: xTranslateAnimation.running
54− readonly property bool offScreen: priv.xTranslate >= 0
55−
56− dropShadow: spreadView.active ||
57− (active
58− && (root.stage == ApplicationInfoInterface.MainStage || !priv.shellIsLandscape)
59− && priv.xTranslate != 0)
60−
61− onSelectedChanged: {
62− if (selected) {
63− priv.snapshot();
64− }
65− priv.isSelected = selected;
66− }
67−
68− onOtherSelectedChanged: {
69− if (otherSelected) {
70− priv.snapshot();
71− }
72− priv.otherSelected = otherSelected;
73− }
74−
75− Connections {
76− target: spreadView
77−
78− onPhaseChanged: {
79− if (spreadView.phase == 1) {
80− var phase2Progress = spreadView.positionMarker4 - (root.zIndex * spreadView.tileDistance / spreadView.width);
81− priv.phase2StartTranslate = priv.easingAnimation(0, 1, 0, -spreadView.width + (root.zIndex * root.endDistance), phase2Progress);
82− priv.phase2StartScale = priv.easingAnimation(0, 1, root.startScale, root.endScale, phase2Progress);
83− priv.phase2StartAngle = priv.easingAnimation(0, 1, root.startAngle, root.endAngle, phase2Progress);
84− priv.phase2StartTopMarginProgress = priv.easingAnimation(0, 1, 0, 1, phase2Progress);
85− }
86− }
87− }
88−
89− // Required to be an item because we're using states on it.
90− Item {
91− id: priv
92−
93− // true if this is the next tile on the stack that comes in when dragging from the right
94− property bool nextInStack: spreadView.nextInStack == model.index
95− // true if the next tile in the stack is the nextInStack one. This one will be moved a bit to the left
96− property bool movedActive: spreadView.nextZInStack == zIndex + 1
97− property real animatedEndDistance: linearAnimation(0, 2, root.endDistance, 0, root.progress)
98−
99− property real phase2StartTranslate
100− property real phase2StartScale
101− property real phase2StartAngle
102− property real phase2StartTopMarginProgress
103−
104− property bool isSelected: false
105− property bool otherSelected: false
106− property real selectedProgress
107− property real selectedXTranslate
108− property real selectedAngle
109− property real selectedScale
110− property real selectedOpacity
111− property real selectedTopMarginProgress
112−
113− function snapshot() {
114− selectedProgress = root.progress;
115− selectedXTranslate = xTranslate;
116− selectedAngle = angle;
117− selectedScale = priv.scale;
118− selectedOpacity = priv.opacityTransform;
119− selectedTopMarginProgress = topMarginProgress;
120− }
121−
122− // This calculates how much negative progress there can be if unwinding the spread completely
123− // the progress for each tile starts at 0 when it crosses the right edge, so the later a tile comes in,
124− // the bigger its negativeProgress can be.
125− property real negativeProgress: {
126− if (nextInStack && spreadView.phase < 2) {
127− return 0;
128− }
129− return -root.zIndex * spreadView.tileDistance / spreadView.width;
130− }
131−
132− function linearAnimation(startProgress, endProgress, startValue, endValue, progress) {
133− // progress : progressDiff = value : valueDiff => value = progress * valueDiff / progressDiff
134− return (progress - startProgress) * (endValue - startValue) / (endProgress - startProgress) + startValue;
135− }
136−
137− function easingAnimation(startProgress, endProgress, startValue, endValue, progress) {
138− helperEasingCurve.progress = progress - startProgress;
139− helperEasingCurve.period = endProgress - startProgress;
140− return helperEasingCurve.value * (endValue - startValue) + startValue;
141− }
142−
143− Behavior on xTranslate {
144− enabled: !spreadView.active &&
145− !snapAnimation.running &&
146− root.application.appId !== "unity8-dash" &&
147− spreadView.animateX &&
148− !spreadView.beingResized &&
149− priv.state !== "sideStage"
150− UbuntuNumberAnimation {
151− id: xTranslateAnimation
152− duration: UbuntuAnimation.FastDuration
153− }
154− }
155−
156− property real xTranslate: {
157− var newTranslate = 0;
158−
159− // selected app or opposite stage active app.
160− if (isSelected || (otherSelected && root.active && spreadView.selectedDelegate
161− && spreadView.selectedDelegate.stage !== root.stage)) {
162− if (root.stage == ApplicationInfoInterface.MainStage) {
163− return linearAnimation(selectedProgress, negativeProgress, selectedXTranslate, -spreadView.width, root.progress);
164− } else {
165− return linearAnimation(selectedProgress, negativeProgress, selectedXTranslate, -spreadView.sideStageWidth, root.progress);
166− }
167− } else if (otherSelected) {
168− return selectedXTranslate;
169− }
170−
171− // The tile should move a bit to the left if a new one comes on top of it, but not for the Side Stage and not
172− // when we're only dragging the side stage in on top of a main stage app
173− var shouldMoveAway = spreadView.nextInStack >= 0 && priv.movedActive && root.stage === ApplicationInfoInterface.MainStage &&
174− topLevelSurfaceList.applicationAt(spreadView.nextInStack).stage === ApplicationInfoInterface.MainStage;
175−
176− if (active) {
177− newTranslate -= root.width
178− // Only do the hide animation for active apps in the mainstage, and not if we only drag the ss in
179− if (spreadView.phase == 0 && shouldMoveAway) {
180− newTranslate += linearAnimation(0, spreadView.positionMarker2, 0, -units.gu(4), root.animatedProgress);
181− }
182− newTranslate += root.dragOffset;
183− } else if (!spreadView.active && root.application.appId == "unity8-dash") {
184− newTranslate -= root.width;
185− }
186−
187− if (!spreadView.active) {
188− return newTranslate;
189− }
190−
191− var shadowOffset = units.gu(2);
192−
193− if (spreadView.phase == 0) {
194− if (nextInStack) {
195− if (root.stage == ApplicationInfoInterface.MainStage) {
196− if (spreadView.sideStageVisible && root.progress > 0) {
197− // Move it so it appears from behind the side stage immediately
198− newTranslate += -spreadView.sideStageWidth;
199− }
200− }
201−
202− if (root.stage == ApplicationInfoInterface.SideStage && !spreadView.sideStageVisible) {
203− // This is when we only drag the side stage in, without rotation or snapping
204− newTranslate = linearAnimation(0, spreadView.positionMarker2, 0, -spreadView.sideStageWidth, root.animatedProgress);
205− } else {
206− newTranslate += linearAnimation(0, spreadView.positionMarker2, 0, -spreadView.sideStageWidth * spreadView.snapPosition, root.animatedProgress);
207− }
208− } else if (!root.active) {
209− newTranslate += shadowOffset;
210− }
211− }
212−
213− if (spreadView.phase == 1) {
214− if (nextInStack) {
215− if (root.stage == ApplicationInfoInterface.MainStage) {
216− var startValue = -spreadView.sideStageWidth * spreadView.snapPosition + (spreadView.sideStageVisible ? -spreadView.sideStageWidth : 0);
217− newTranslate += linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4, startValue, priv.phase2StartTranslate, root.animatedProgress);
218− } else {
219− var endValue = -spreadView.width + spreadView.width * root.zIndex / 6;
220− if (!spreadView.sideStageVisible) {
221− newTranslate += linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4, -spreadView.sideStageWidth, priv.phase2StartTranslate, root.animatedProgress);
222− } else {
223− newTranslate += linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4, -spreadView.sideStageWidth * spreadView.snapPosition, priv.phase2StartTranslate, root.animatedProgress);
224− }
225− }
226− } else if (root.active) {
227− var startProgress = spreadView.positionMarker2 - (zIndex * spreadView.positionMarker2 / 2);
228− var endProgress = spreadView.positionMarker4 - (zIndex * spreadView.tileDistance / spreadView.width);
229− var startTranslate = -root.width + (shouldMoveAway ? -units.gu(4) : 0);
230− newTranslate = linearAnimation(startProgress, endProgress, startTranslate, priv.phase2StartTranslate, root.animatedProgress);
231− } else {
232− var startProgress = spreadView.positionMarker2 - (zIndex * spreadView.positionMarker2 / 2);
233− var endProgress = spreadView.positionMarker4 - (zIndex * spreadView.tileDistance / spreadView.width);
234− newTranslate = linearAnimation(startProgress, endProgress, shadowOffset * Math.max(0, zIndex-2), priv.phase2StartTranslate, root.animatedProgress);
235− }
236− }
237−
238− if (spreadView.phase == 2) {
239− if (easingCurve.value == 0 && !nextInStack) {
240− newTranslate = shadowOffset;
241− } else {
242− newTranslate = -easingCurve.value * (spreadView.width - root.zIndex * animatedEndDistance);
243− }
244− }
245−
246− return newTranslate;
247− }
248−
249− property real scale: {
250− if (!spreadView.active) {
251− return 1;
252− }
253−
254− // selected app or opposite stage active app.
255− if (isSelected || (otherSelected && root.active && spreadView.selectedDelegate
256− && spreadView.selectedDelegate.stage !== root.stage)) {
257− return linearAnimation(selectedProgress, negativeProgress, selectedScale, 1, root.progress);
258− } else if (otherSelected) {
259− return selectedScale;
260− }
261−
262− if (spreadView.phase == 0) {
263− if (nextInStack) {
264− if (root.stage == ApplicationInfoInterface.SideStage && !spreadView.sideStageVisible) {
265− return 1;
266− } else {
267− var targetScale = root.dragStartScale - ((root.dragStartScale - 1) * spreadView.snapPosition);
268− return linearAnimation(0, spreadView.positionMarker2, root.dragStartScale, targetScale, root.animatedProgress);
269− }
270− } else {
271− return 1;
272− }
273− }
274−
275− if (spreadView.phase == 1) {
276− if (nextInStack) {
277− var startScale = 1;
278− if (root.stage !== ApplicationInfoInterface.SideStage || spreadView.sideStageVisible) {
279− startScale = root.dragStartScale - ((root.dragStartScale - 1) * spreadView.snapPosition);
280− }
281− return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4, startScale, priv.phase2StartScale, root.animatedProgress);
282− }
283− var startProgress = spreadView.positionMarker2 - (zIndex * spreadView.positionMarker2 / 2);
284− var endProgress = spreadView.positionMarker4 - (zIndex * spreadView.tileDistance / spreadView.width);
285− return linearAnimation(startProgress, endProgress, 1, priv.phase2StartScale, root.animatedProgress);
286− }
287−
288− if (spreadView.phase == 2) {
289− return root.startScale - easingCurve.value * (root.startScale - root.endScale);
290− }
291−
292− return 1;
293− }
294−
295− property real angle: {
296− if (!spreadView.active) {
297− return 0;
298− }
299−
300− // selected app or opposite stage active app.
301− if (isSelected || (otherSelected && root.active && spreadView.selectedDelegate
302− && spreadView.selectedDelegate.stage !== root.stage)) {
303− return linearAnimation(selectedProgress, negativeProgress, selectedAngle, 0, root.progress);
304− } else if (otherSelected) {
305− return selectedAngle;
306− }
307−
308− // The tile should rotate a bit when another one comes on top, but not when only dragging the side stage in
309− var shouldMoveAway = spreadView.nextInStack == -1 ||
310− spreadView.nextInStack >= 0 && priv.movedActive &&
311− (topLevelSurfaceList.applicationAt(spreadView.nextInStack).stage === ApplicationInfoInterface.MainStage ||
312− root.stage == ApplicationInfoInterface.SideStage);
313−
314− if (spreadView.phase == 0) {
315− if (nextInStack) {
316− if (root.stage == ApplicationInfoInterface.SideStage && !spreadView.sideStageVisible) {
317− return 0;
318− } else {
319− return linearAnimation(0, spreadView.positionMarker2, root.startAngle, root.startAngle * (1-spreadView.snapPosition), root.animatedProgress);
320− }
321− }
322− if (shouldMoveAway) {
323− return linearAnimation(0, spreadView.positionMarker2, 0, root.startAngle * (1-spreadView.snapPosition), root.animatedProgress);
324− }
325− }
326− if (spreadView.phase == 1) {
327− if (nextInStack) {
328− if (root.stage == ApplicationInfoInterface.SideStage && !spreadView.sideStageVisible) {
329− return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4, 0, priv.phase2StartAngle, root.animatedProgress);
330− } else {
331− return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4, root.startAngle * (1-spreadView.snapPosition), priv.phase2StartAngle, root.animatedProgress);
332− }
333− }
334− var startProgress = spreadView.positionMarker2 - (zIndex * spreadView.positionMarker2 / 2);
335− var endProgress = spreadView.positionMarker4 - (zIndex * spreadView.tileDistance / spreadView.width);
336− var startAngle = shouldMoveAway ? root.startAngle * (1-spreadView.snapPosition) : 0;
337− return linearAnimation(startProgress, endProgress, startAngle, priv.phase2StartAngle, root.progress);
338− }
339− if (spreadView.phase == 2) {
340− return root.startAngle - easingCurve.value * (root.startAngle - root.endAngle);
341− }
342−
343− return 0;
344− }
345−
346− property real opacityTransform: {
347− // animate opacity for items not snapping into view.
348− if (spreadView.phase !== 2) return 1;
349− if (root.isSelected) return 1;
350−
351− if (otherSelected) {
352− if (root.active && spreadView.selectedDelegate
353− && spreadView.selectedDelegate.stage !== root.stage) {
354− return 1;
355− }
356− return linearAnimation(selectedProgress, negativeProgress, selectedOpacity, 0, root.progress);
357− }
358− return 1;
359− }
360−
361− property real topMarginProgress: {
362− // selected app or opposite stage active app.
363− if (isSelected || (otherSelected && root.active && spreadView.selectedDelegate
364− && spreadView.selectedDelegate.stage !== root.stage)) {
365− return linearAnimation(selectedProgress, negativeProgress, selectedTopMarginProgress, 0, root.progress);
366− }
367−
368− if (spreadView.phase == 0) {
369− return 0;
370− } else if (spreadView.phase == 1) {
371− if (nextInStack) {
372− return linearAnimation(spreadView.positionMarker2, spreadView.positionMarker4,
373− 0, 1, root.progress);
374− }
375− var startProgress = spreadView.positionMarker2 - (zIndex * spreadView.positionMarker2 / 2);
376− var endProgress = spreadView.positionMarker4 - (zIndex * spreadView.tileDistance / spreadView.width);
377− return linearAnimation(startProgress, endProgress, 0, 1, root.progress);
378− }
379− return 1;
380− }
381−
382− states: [
383− State {
384− name: "sideStage";
385− when: root.isInSideStage && spreadView.shiftedContentX == 0 && spreadView.phase == 0
386− PropertyChanges {
387− target: priv;
388− xTranslate: -spreadView.sideStageWidth + spreadView.sideStageWidth * (1-sideStage.progress)
389− }
390− }
391− ]
392− }
393−
394− transform: [
395− Rotation {
396− origin { x: 0; y: spreadView.height / 2 }
397− axis { x: 0; y: 1; z: 0 }
398− angle: priv.angle
399− },
400− Scale {
401− origin { x: 0; y: spreadView.height / 2 }
402− xScale: priv.scale
403− yScale: xScale
404− },
405− Scale {
406− origin { x: 0; y: (spreadView.height * priv.scale) + maximizedAppTopMargin * 3 }
407− xScale: 1
408− yScale: fullscreen ? 1 - priv.topMarginProgress * maximizedAppTopMargin / spreadView.height : 1
409− },
410− Translate {
411− x: priv.xTranslate
412− }
413− ]
414− opacity: priv.opacityTransform
415−
416− UbuntuNumberAnimation {
417− id: fadeBackInAnimation
418− target: root
419− property: "opacity"
420− duration: UbuntuAnimation.SlowDuration
421− from: 0
422− to: 1
423− }
424−
425− EasingCurve {
426− id: easingCurve
427− type: EasingCurve.OutSine
428− period: 1
429− progress: root.progress
430− }
431−
432− EasingCurve {
433− id: helperEasingCurve
434− type: easingCurve.type
435− period: easingCurve.period
436− }
437−}