@@ -17,45 +17,28 @@
1717import QtQuick 2.0
1818import Ubuntu.Components 0.1
1919import Ubuntu.Gestures 0.1
20−import Unity.Application 0.1
20+import Mir.Application 0.1
2121import Utils 0.1
2222import "../Components"
2323
24−Item {
24+Rectangle {
2525 id: root
26+ color: "green"
2627
2728 // Controls to be set from outside
28− property bool shown: false
29− property bool moving: false
3029 property int dragAreaWidth
3130
31+ // FIXME: Should be registerd singleton type QAbstractItemModel.
32+ property var surfaces
33+
3234 // State information propagated to the outside
33− readonly property bool painting: mainScreenshotImage.visible || fadeInScreenshotImage.visible || appSplash.visible || spreadView.visible
3435 property bool fullscreen: priv.focusedApplication ? priv.focusedApplication.fullscreen : false
3536 property bool locked: spreadView.visible
3637
37− // Not used for PhoneStage, only useful for SideStage and similar
38− property bool overlayMode: false
39− property int overlayWidth: 0
40−
4138 function select(appId) {
4239 spreadView.snapTo(priv.indexOf(appId))
4340 }
4441
45− onMovingChanged: {
46− if (moving) {
47− if (ApplicationManager.focusedApplicationId) {
48− priv.requestNewScreenshot();
49− } else {
50− mainScreenshotImage.anchors.leftMargin = 0;
51− mainScreenshotImage.source = ApplicationManager.get(0).screenshot;
52− mainScreenshotImage.visible = true;
53− }
54− } else {
55− mainScreenshotImage.visible = false;
56− }
57− }
58−
5942 Connections {
6043 target: ApplicationManager
6144
@@ -74,7 +57,6 @@ Item {
7457 } else {
7558 var application = priv.focusedApplication;
7659 root.fullscreen = application.fullscreen;
77− mainScreenshotImage.source = application.screenshot;
7860 }
7961 } else {
8062 spreadView.selectedIndex = -1;
@@ -84,29 +66,7 @@ Item {
8466 }
8567
8668 onApplicationAdded: {
87− if (!priv.focusedApplication) {
88− mainScreenshotImage.source = "";
89− mainScreenshotImage.visible = false;
90− priv.applicationStarting = true;
91− } else {
92− mainScreenshotImage.source = "";
93− priv.newFocusedAppId = appId;
94− priv.secondApplicationStarting = true;
95− priv.requestNewScreenshot();
96− }
97−
98− if (spreadView.visible) {
99− spreadView.snapTo(0);
100− }
101− }
102−
103− onApplicationRemoved: {
104− if (ApplicationManager.count == 0) {
105− mainScreenshotImage.source = ""
106− mainScreenshotImage.visible = false;
107− } else {
108− mainScreenshotImage.source = ApplicationManager.get(0).screenshot;
109− }
69+ spreadView.snapTo(0);
11070 }
11171 }
11272
@@ -115,31 +75,12 @@ Item {
11575
11676 property string focusedAppId: ApplicationManager.focusedApplicationId
11777 property var focusedApplication: ApplicationManager.findApplication(focusedAppId)
118− property url focusedScreenshot: focusedApplication ? focusedApplication.screenshot : ""
119−
120− property bool waitingForScreenshot: false
12178
12279 property bool applicationStarting: false
12380 property bool secondApplicationStarting: false
12481
12582 property string newFocusedAppId
12683
127− onFocusedScreenshotChanged: {
128− if (root.moving && priv.waitingForScreenshot) {
129− mainScreenshotImage.anchors.leftMargin = 0;
130− mainScreenshotImage.source = priv.focusedScreenshot
131− mainScreenshotImage.visible = true;
132− } else if (priv.secondApplicationStarting && priv.waitingForScreenshot) {
133− applicationSwitchingAnimation.start();
134− }
135− waitingForScreenshot = false;
136− }
137−
138− function requestNewScreenshot() {
139− waitingForScreenshot = true;
140− ApplicationManager.updateScreenshot(focusedAppId);
141− }
142−
14384 function switchToApp(appId) {
14485 if (priv.focusedAppId) {
14586 priv.newFocusedAppId = appId;
@@ -147,6 +88,8 @@ Item {
14788 applicationSwitchingAnimation.start();
14889 } else {
14990 ApplicationManager.focusApplication(appId);
91+ // TODO: Should happen behind the schenes
92+ surfaces.move(surfaces.getIndexOfSurfaceWithAppId(appId), 0);
15093 }
15194 }
15295
@@ -161,155 +104,6 @@ Item {
161104
162105 }
163106
164− // FIXME: the signal connections seems to get lost.
165− Connections {
166− target: priv.focusedApplication
167− onScreenshotChanged: priv.focusedScreenshot = priv.focusedApplication.screenshot
168− }
169− Binding {
170− target: root
171− property: "fullscreen"
172− value: priv.focusedApplication ? priv.focusedApplication.fullscreen : false
173− }
174−
175− Timer {
176− id: appSplashTimer
177− // FIXME: We really need to show something meaningful in the app surface instead of guessing
178− // when it might be ready
179− interval: 500
180− repeat: false
181− onTriggered: {
182− priv.applicationStarting = false;
183− priv.secondApplicationStarting = false;
184− }
185− }
186−
187− SequentialAnimation {
188− id: applicationSwitchingAnimation
189− // setup
190− PropertyAction { target: mainScreenshotImage; property: "anchors.leftMargin"; value: 0 }
191− PropertyAction { target: mainScreenshotImage; property: "source"; value: priv.focusedScreenshot }
192− PropertyAction { targets: [mainScreenshotImage, fadeInScreenshotImage]; property: "visible"; value: true }
193− PropertyAction { target: fadeInScreenshotImage; property: "source"; value: {
194− var newFocusedApp = ApplicationManager.findApplication(priv.newFocusedAppId);
195− return newFocusedApp ? newFocusedApp.screenshot : "" }
196− }
197− PropertyAction { target: fadeInScreenshotImage; property: "opacity"; value: 0 }
198− PropertyAction { target: fadeInScreenshotImage; property: "scale"; value: .8 }
199−
200−
201− // The actual animation
202− ParallelAnimation {
203− UbuntuNumberAnimation { target: mainScreenshotImage; property: "anchors.leftMargin"; to: root.width; duration: UbuntuAnimation.SlowDuration }
204− UbuntuNumberAnimation { target: fadeInScreenshotImage; properties: "opacity,scale"; to: 1; duration: UbuntuAnimation.SlowDuration }
205− }
206−
207− // restore stuff
208− ScriptAction { script: ApplicationManager.focusApplication(priv.newFocusedAppId); }
209− PropertyAction { target: fadeInScreenshotImage; property: "visible"; value: false }
210− PropertyAction { target: mainScreenshotImage; property: "visible"; value: false }
211− }
212−
213− // FIXME: Drop this and make the imageprovider show a splashscreen instead
214− Rectangle {
215− id: appSplash2
216− anchors.fill: parent
217− color: "white"
218− visible: priv.secondApplicationStarting
219− }
220− Image {
221− id: fadeInScreenshotImage
222− anchors { left: parent.left; bottom: parent.bottom }
223− width: parent.width
224− scale: .7
225− visible: false
226− }
227−
228− Rectangle {
229− id: appSplash
230− anchors.fill: parent
231− color: "white"
232− visible: priv.applicationStarting
233− }
234− Image {
235− id: mainScreenshotImage
236− anchors { left: parent.left; bottom: parent.bottom }
237− width: parent.width
238− visible: false
239− }
240−
241− EdgeDragArea {
242− id: spreadDragArea
243− direction: Direction.Leftwards
244− enabled: ApplicationManager.count > 1 && spreadView.phase != 2
245−
246− anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
247− width: root.dragAreaWidth
248−
249− // Sitting at the right edge of the screen, this EdgeDragArea directly controls the spreadView when
250− // attachedToView is true. When the finger movement passes positionMarker3 we detach it from the
251− // spreadView and make the spreadView snap to positionMarker4.
252− property bool attachedToView: true
253−
254− property var gesturePoints: new Array()
255−
256− onTouchXChanged: {
257− if (!dragging && !priv.waitingForScreenshot) {
258− // Initial touch. Let's update the screenshot and reset the spreadView to the starting position.
259− priv.requestNewScreenshot();
260− spreadView.phase = 0;
261− spreadView.contentX = -spreadView.shift;
262− }
263− if (dragging && attachedToView) {
264− // Gesture recognized. Let's move the spreadView with the finger
265− spreadView.contentX = -touchX - spreadView.shift;
266− }
267− if (attachedToView && spreadView.shiftedContentX >= spreadView.width * spreadView.positionMarker3) {
268− // We passed positionMarker3. Detach from spreadView and snap it.
269− attachedToView = false;
270− spreadView.snap();
271− }
272− gesturePoints.push(touchX);
273− }
274−
275− onStatusChanged: {
276− if (status == DirectionalDragArea.Recognized) {
277− attachedToView = true;
278− }
279− }
280−
281− onDraggingChanged: {
282− if (dragging) {
283− // Gesture recognized. Start recording this gesture
284− gesturePoints = [];
285− return;
286− }
287−
288− // Ok. The user released. Find out if it was a one-way movement.
289− var oneWayFlick = true;
290− var smallestX = spreadDragArea.width;
291− for (var i = 0; i < gesturePoints.length; i++) {
292− if (gesturePoints[i] >= smallestX) {
293− oneWayFlick = false;
294− break;
295− }
296− smallestX = gesturePoints[i];
297− }
298− gesturePoints = [];
299−
300− if (oneWayFlick && spreadView.shiftedContentX > units.gu(2) &&
301− spreadView.shiftedContentX < spreadView.positionMarker1 * spreadView.width) {
302− // If it was a short one-way movement, do the Alt+Tab switch
303− // no matter if we didn't cross positionMarker1 yet.
304− spreadView.snapTo(1);
305− } else if (!dragging && attachedToView) {
306− // otherwise snap to the closest snap position we can find
307− // (might be back to start, to app 1 or to spread)
308− spreadView.snap();
309− }
310− }
311− }
312−
313107 Rectangle {
314108 id: coverFlipBackground
315109 anchors.fill: parent
@@ -317,16 +111,13 @@ Item {
317111 visible: spreadView.visible
318112 }
319113
320− InputFilterArea {
321− anchors.fill: root
322− blockInput: spreadView.visible
323− }
324114
325115 Flickable {
326116 id: spreadView
327117 objectName: "spreadView"
328118 anchors.fill: parent
329− visible: spreadDragArea.status == DirectionalDragArea.Recognized || phase > 1 || snapAnimation.running
119+// visible: spreadDragArea.status == DirectionalDragArea.Recognized || phase > 1 || snapAnimation.running
120+ interactive: spreadDragArea.status == DirectionalDragArea.Recognized || phase > 1 || snapAnimation.running
330121 contentWidth: spreadRow.width - shift
331122 contentX: -shift
332123
@@ -414,6 +205,10 @@ Item {
414205 script: {
415206 if (spreadView.selectedIndex >= 0) {
416207 ApplicationManager.focusApplication(ApplicationManager.get(spreadView.selectedIndex).appId);
208+
209+ // TODO: Should happen behind the schenes
210+ surfaces.move(spreadView.selectedIndex, 0);
211+
417212 spreadView.selectedIndex = -1
418213 spreadView.phase = 0;
419214 spreadView.contentX = -spreadView.shift;
@@ -433,7 +228,7 @@ Item {
433228
434229 Repeater {
435230 id: spreadRepeater
436− model: ApplicationManager
231+ model: root.surfaces
437232 delegate: TransformedSpreadDelegate {
438233 id: appDelegate
439234 objectName: "appDelegate" + index
@@ -447,6 +242,8 @@ Item {
447242 height: spreadView.height
448243 selected: spreadView.selectedIndex == index
449244 otherSelected: spreadView.selectedIndex >= 0 && !selected
245+ surface: model.surface
246+ interactive: !spreadView.interactive
450247
451248 z: index
452249 x: index == 0 ? 0 : spreadView.width + (index - 1) * spreadView.tileDistance
@@ -496,4 +293,76 @@ Item {
496293 }
497294 }
498295 }
296+
297+ EdgeDragArea {
298+ id: spreadDragArea
299+ direction: Direction.Leftwards
300+ enabled: ApplicationManager.count > 1 && spreadView.phase != 2
301+
302+ anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
303+ width: root.dragAreaWidth
304+
305+ // Sitting at the right edge of the screen, this EdgeDragArea directly controls the spreadView when
306+ // attachedToView is true. When the finger movement passes positionMarker3 we detach it from the
307+ // spreadView and make the spreadView snap to positionMarker4.
308+ property bool attachedToView: true
309+
310+ property var gesturePoints: new Array()
311+
312+ onTouchXChanged: {
313+ if (!dragging) {
314+ // Initial touch. Let's reset the spreadView to the starting position.
315+ spreadView.phase = 0;
316+ spreadView.contentX = -spreadView.shift;
317+ }
318+ if (dragging && attachedToView) {
319+ // Gesture recognized. Let's move the spreadView with the finger
320+ spreadView.contentX = -touchX - spreadView.shift;
321+ }
322+ if (attachedToView && spreadView.shiftedContentX >= spreadView.width * spreadView.positionMarker3) {
323+ // We passed positionMarker3. Detach from spreadView and snap it.
324+ attachedToView = false;
325+ spreadView.snap();
326+ }
327+ gesturePoints.push(touchX);
328+ }
329+
330+ onStatusChanged: {
331+ if (status == DirectionalDragArea.Recognized) {
332+ attachedToView = true;
333+ }
334+ }
335+
336+ onDraggingChanged: {
337+ if (dragging) {
338+ // Gesture recognized. Start recording this gesture
339+ gesturePoints = [];
340+ return;
341+ }
342+
343+ // Ok. The user released. Find out if it was a one-way movement.
344+ var oneWayFlick = true;
345+ var smallestX = spreadDragArea.width;
346+ for (var i = 0; i < gesturePoints.length; i++) {
347+ if (gesturePoints[i] >= smallestX) {
348+ oneWayFlick = false;
349+ break;
350+ }
351+ smallestX = gesturePoints[i];
352+ }
353+ gesturePoints = [];
354+
355+ if (oneWayFlick && spreadView.shiftedContentX > units.gu(2) &&
356+ spreadView.shiftedContentX < spreadView.positionMarker1 * spreadView.width) {
357+ // If it was a short one-way movement, do the Alt+Tab switch
358+ // no matter if we didn't cross positionMarker1 yet.
359+ spreadView.snapTo(1);
360+ } else if (!dragging && attachedToView) {
361+ // otherwise snap to the closest snap position we can find
362+ // (might be back to start, to app 1 or to spread)
363+ spreadView.snap();
364+ }
365+ }
366+ }
367+
499368}