on xenial help sign in
make right edge animation work, dropping all the screenshot crazyness
commit80737c6e9708ff6f15631c4e56f9176c3bac529c authorMichael Zanetti <michael.zanetti@canonical.com> dateMon 19 May 2014, 10:08 (12 years ago) parent6f37b4c
3 files changed+127−240
plugins/Unity/Launcher/launchermodel.cpp+6 qml/Stages/PhoneStage.qml+90−221 qml/Stages/SpreadDelegate.qml+31−19
plugins/Unity/Launcher/launchermodel.cpp+6
@@ -23,6 +23,8 @@
2323
2424#include <unity/shell/application/ApplicationInfoInterface.h>
2525
26+#include <QDebug>
27+
2628using namespace unity::shell::application;
2729
2830LauncherModel::LauncherModel(QObject *parent):
@@ -291,6 +293,10 @@ void LauncherModel::applicationAdded(const QModelIndex &parent, int row)
291293 Q_UNUSED(parent);
292294
293295 ApplicationInfoInterface *app = m_appManager->get(row);
296+ if (!app) {
297+ qDebug() << "Huh? Can't get newly added Application from ApplicationManager... Ignoring this app...";
298+ return;
299+ }
294300
295301 bool found = false;
296302 Q_FOREACH(LauncherItem *item, m_list) {
qml/Stages/PhoneStage.qml+90−221
@@ -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}
qml/Stages/SpreadDelegate.qml+31−19
@@ -22,34 +22,46 @@ Item {
2222 id: root
2323
2424 signal clicked()
25−
2625 property real topMarginProgress
26+ property bool interactive: true
2727
28− QtObject {
29− id: priv
30− property real heightDifference: root.height - appImage.implicitHeight
28+ // FIXME: This really should be invisible to QML code.
29+ // e.g. Create a SurfaceItem {} in C++ which we just use without any imperative hacks.
30+ property var surface
31+ onSurfaceChanged: {
32+ if (surface) {
33+ root.width = surface.implicitWidth;
34+ root.height = surface.implicitHeight;
35+ surface.parent = root;
36+ surface.anchors.fill = root;
37+ surface.enabled = root.interactive;
38+ surface.z = 1;
39+ }
40+ }
41+
42+ Component.onDestruction: {
43+ if (surface) {
44+ surface.release();
45+ }
3146 }
3247
33− Image {
48+ BorderImage {
3449 id: dropShadow
35− anchors.fill: appImage
50+ anchors.fill: root
3651 anchors.margins: -units.gu(2)
3752 source: "graphics/dropshadow.png"
3853 opacity: .4
54+ border { left: 50; right: 50; top: 50; bottom: 50 }
3955 }
40− Image {
41− id: appImage
42− anchors {
43− left: parent.left;
44− bottom: parent.bottom;
45− top: parent.top;
46− topMargin: priv.heightDifference * Math.max(0, 1 - root.topMarginProgress)
47− }
48− source: model.screenshot
49− antialiasing: true
50− }
56+
57+ // This is used to get clicked events on the whole app. e.g. when in spreadView.
58+ // It's only enabled when the surface is !interactive
5159 MouseArea {
52− anchors.fill: appImage
53− onClicked: root.clicked()
60+ anchors.fill: parent
61+ z: 2
62+ enabled: !root.interactive
63+ onClicked: {
64+ root.clicked()
65+ }
5466 }
5567}