on xenial help sign in
parent animation
commitc25c21ec48b989a157f55920bdd12d049b0e1873 authorNick Dedekind <nicholas.dedekind@gmail.com> dateMon 21 Jul 2014, 10:17 (12 years ago) parent2abb1f0
8 files changed+203−54
qml/Stages/SpreadDelegate.qml+11−12 qml/Stages/SurfaceContainer.qml+105−23 tests/mocks/Unity/Application/ApplicationDBusAdaptor.cpp+30−5 tests/mocks/Unity/Application/ApplicationInfo.cpp+19−12 tests/mocks/Unity/Application/ApplicationInfo.h+1−1 tests/mocks/Unity/Application/ApplicationManager.cpp+4 tests/mocks/Unity/Application/MirSurfaceItem.cpp+25 tests/mocks/Unity/Application/MirSurfaceItem.h+8−1
qml/Stages/SpreadDelegate.qml+11−12
@@ -30,7 +30,7 @@ Item {
3030 property real maximizedAppTopMargin
3131 property alias swipeToCloseEnabled: dragArea.enabled
3232
33− readonly property bool isFullscreen: surface !== null && surfaceContainer.surface.anchors.topMargin == 0
33+ readonly property bool isFullscreen: surface !== null && surfaceContainer.surfaceArea.anchors.topMargin == 0
3434
3535 signal clicked()
3636 signal closed()
@@ -47,15 +47,6 @@ Item {
4747 surface.visible = false; // hide until splash screen removed
4848 appHasCreatedASurface = true;
4949 }
50− surfaceContainer.checkFullscreen(surface);
51− }
52− }
53−
54− function checkFullscreen(surface) {
55− if (surface.state === MirSurfaceItem.Fullscreen) {
56− surface.anchors.topMargin = 0;
57− } else {
58− surface.anchors.topMargin = maximizedAppTopMargin;
5950 }
6051 }
6152
@@ -64,6 +55,15 @@ Item {
6455 splashLoader.source = "";
6556 }
6657
58+ Binding {
59+ target: surfaceContainer.surfaceArea
60+ property: "anchors.topMargin"
61+ value: {
62+ if (!surfaceContainer.surface) return 0;
63+ return surfaceContainer.surface.state === MirSurfaceItem.Fullscreen ? 0 : maximizedAppTopMargin;
64+ }
65+ }
66+
6767 Binding {
6868 target: surface
6969 property: "enabled"
@@ -83,7 +83,6 @@ Item {
8383
8484 Connections {
8585 target: surface
86− onStateChanged: surfaceContainer.checkFullscreen(surface);
8786 // FIXME: I would rather not need to do this, but currently it doesn't get
8887 // active focus without it and I don't know why.
8988 onFocusChanged: forceSurfaceActiveFocusIfReady();
@@ -103,7 +102,7 @@ Item {
103102 leftMargin: -units.gu(2)
104103 rightMargin: -units.gu(2)
105104 bottomMargin: -units.gu(2)
106− topMargin: -units.gu(2) + (root.isFullscreen ? 0 : maximizedAppTopMargin)
105+ topMargin: -units.gu(2)// + (root.isFullscreen ? 0 : maximizedAppTopMargin)
107106 }
108107 source: "graphics/dropshadow.png"
109108 border { left: 50; right: 50; top: 50; bottom: 50 }
qml/Stages/SurfaceContainer.qml+105−23
@@ -19,14 +19,30 @@ import QtQuick 2.0
1919Item {
2020 id: container
2121 property Item surface: null
22− property string animation
23− property bool show: false
22+ readonly property alias surfaceArea: _surfaceArea
23+ property bool removing: false
2424
2525 onSurfaceChanged: {
2626 if (surface) {
2727 surface.parent = container;
28− surface.anchors.fill = container;
2928 surface.z = 1;
29+ state = "initial"
30+ }
31+ }
32+
33+ Item {
34+ id: _surfaceArea
35+ anchors.fill: parent
36+ }
37+
38+ Connections {
39+ target: surface
40+ onRemoved: {
41+ if (surface.parentSurface) {
42+ surface.parentSurface.parent.animateOut();
43+ }
44+ container.removing = true;
45+ animateOut();
3046 }
3147 }
3248
@@ -35,60 +51,126 @@ Item {
3551
3652 delegate: Loader {
3753 z: 2
38− anchors.fill: surface
54+ anchors.fill: surfaceArea
3955
4056 // Only way to do recursive qml items.
4157 source: Qt.resolvedUrl("SurfaceContainer.qml")
4258 onLoaded: {
43− item.parent = container.surface;
4459 item.surface = modelData;
45− item.animation = "overlaySwipeBottom"
46− item.show = true;
60+ item.animateIn("swipeFromBottom");
61+ container.animateIn("swipeUp");
4762 }
4863 }
4964 }
5065
66+ function animateIn(type) {
67+ var tmp = d.animations;
68+ tmp.push(type);
69+ d.animations = tmp;
70+
71+ container.state = d.currentAnimation + "-prep";
72+ container.state = d.currentAnimation + "-in";
73+ }
74+
75+ function animateOut() {
76+ if (d.animations.length > 0) {
77+ var tmp = d.animations;
78+ var popped = tmp.pop();
79+ d.animations = tmp;
80+ container.state = popped + "-out";
81+ if (d.currentAnimation !== "") {
82+ container.state = d.currentAnimation + "-in";
83+ }
84+ } else {
85+ container.state = "initial";
86+ }
87+ }
88+
89+ QtObject {
90+ id: d
91+ property variant animations: []
92+ property string currentAnimation: animations.length > 0 ? animations[animations.length-1] : ""
93+ }
94+
5195 states: [
96+ State {
97+ name: "initial"
98+ PropertyChanges { target: surface; anchors.fill: surfaceArea }
99+ },
100+
52101 State {
53102 name: "baseAnimation"
54103 PropertyChanges { target: surface; anchors.fill: undefined }
55104 },
56105
57106 State {
58− name: "overlaySwipeBottom-out"
107+ name: "swipeFromBottom-prep"
59108 extend: "baseAnimation"
60− when: surface && animation === "overlaySwipeBottom" && !show
61− AnchorChanges { target: surface; anchors.top: surface.parent.bottom }
109+ AnchorChanges { target: surface; anchors.top: surfaceArea.bottom }
62110 },
63111 State {
64− name: "overlaySwipeBottom-in"
112+ name: "swipeFromBottom-out"
113+ extend: "swipeFromBottom-prep"
114+ },
115+ State {
116+ name: "swipeFromBottom-in"
65117 extend: "baseAnimation"
66− when: surface && animation === "overlaySwipeBottom" && show
67− AnchorChanges { target: surface; anchors.top: surface.parent.top }
68− }
118+ AnchorChanges { target: surface; anchors.top: surfaceArea.top }
119+ },
69120
121+ State {
122+ name: "swipeUp-prep"
123+ extend: "baseAnimation"
124+ },
125+ State {
126+ name: "swipeUp-out"
127+ extend: "swipeUp-prep"
128+ },
129+ State {
130+ name: "swipeUp-in"
131+ extend: "baseAnimation"
132+ AnchorChanges { target: surface; anchors.bottom: surfaceArea.top }
133+ }
70134 // TODO: more animations!
71− // Surface needs to stick around so that we can dimiss them with animation.
72135 ]
73136
74137 transitions: [
75138 Transition {
76− from: "overlaySwipeBottom-out"
77− to: "overlaySwipeBottom-in"
139+ to: "swipeFromBottom-in"
140+ SequentialAnimation {
141+ PropertyAction { target: surface.parent; property: "clip"; value: true }
142+ AnchorAnimation { easing.type: Easing.InOutQuad; duration: 400 }
143+ PropertyAction { target: surface.parent; property: "clip"; value: false }
144+ }
145+ },
146+ Transition {
147+ to: "swipeFromBottom-out"
78148 SequentialAnimation {
79− PropertyAction { target: surface.parent; property: "clip"; value: true}
149+ PropertyAction { target: surface.parent; property: "clip"; value: true }
80150 AnchorAnimation { easing.type: Easing.InOutQuad; duration: 400 }
81− PropertyAction { target: surface.parent; property: "clip"; value: false}
151+ PropertyAction { target: surface; property: "visible"; value: !removing }
152+ PropertyAction { target: surface.parent; property: "clip"; value: false }
153+ ScriptAction { script: { if (container.removing) surface.release() } }
82154 }
83155 },
156+
84157 Transition {
85− from: "overlaySwipeBottom-in"
86− to: "overlaySwipeBottom-out"
158+ to: "swipeUp-in"
87159 SequentialAnimation {
88− PropertyAction { target: surface.parent; property: "clip"; value: true}
160+ PropertyAction { target: surface.parent; property: "clip"; value: true }
89161 AnchorAnimation { easing.type: Easing.InOutQuad; duration: 400 }
90162 PropertyAction { target: surface; property: "visible"; value: false}
91− PropertyAction { target: surface.parent; property: "clip"; value: false}
163+ PropertyAction { target: surface.parent; property: "clip"; value: false }
164+ }
165+ },
166+ Transition {
167+ to: "swipeUp-out"
168+ SequentialAnimation {
169+ PropertyAction { target: surface.parent; property: "clip"; value: true }
170+ PropertyAction { target: surface; property: "visible"; value: true }
171+ AnchorAnimation { easing.type: Easing.InOutQuad; duration: 400 }
172+ PropertyAction { target: surface.parent; property: "clip"; value: false }
173+ ScriptAction { script: { if (container.removing) surface.release() } }
92174 }
93175 }
94176 ]
tests/mocks/Unity/Application/ApplicationDBusAdaptor.cpp+30−5
@@ -28,11 +28,31 @@ ApplicationDBusAdaptor::ApplicationDBusAdaptor(ApplicationManager* applicationMa
2828{
2929}
3030
31+MirSurfaceItem* topSurface(MirSurfaceItem* surface)
32+{
33+ if (!surface)
34+ return nullptr;
35+
36+ QList<QObject*> children = surface->childSurfaces();
37+ if (children.count() > 0) {
38+ MirSurfaceItem* child = nullptr;
39+ int i = 0;
40+ while(!child && i < children.count()) {
41+ child = qobject_cast<MirSurfaceItem*>(children[i++]);
42+ }
43+ if (child)
44+ return topSurface(child);
45+ }
46+ return surface;
47+}
48+
3149quint32 ApplicationDBusAdaptor::addChildSurface(const QString &appId, const QString &surfaceImage)
3250{
51+ qDebug() << "ApplicationDBusAdaptor::addChildSurface - " << appId;
52+
3353 ApplicationInfo* application = m_applicationManager->findApplication(appId);
3454 if (!application) {
35− qDebug() << "ApplicationDBusAdaptor::addChildSurface - No application for " << appId;
55+ qDebug() << "ApplicationDBusAdaptor::addChildSurface - No application found for " << appId;
3656 return ~0;
3757 }
3858 quint32 surfaceId = ++nextId;
@@ -41,13 +61,18 @@ quint32 ApplicationDBusAdaptor::addChildSurface(const QString &appId, const QStr
4161 MirSurfaceItem::Maximized,
4262 QUrl(surfaceImage));
4363 m_childItems[surfaceId] = surface;
44− surface->setParentSurface(application->surface());
64+ surface->setParentSurface(topSurface(application->surface()));
4565 return surfaceId;
4666}
4767
4868void ApplicationDBusAdaptor::removeChildSurface(int surfaceId)
4969{
50− if (!m_childItems.contains(surfaceId)) return;
51− MirSurfaceItem* surface = m_childItems[surfaceId];
52− surface->setParentSurface(nullptr);
70+ qDebug() << "ApplicationDBusAdaptor::removeChildSurface - " << surfaceId;
71+
72+ if (!m_childItems.contains(surfaceId)) {
73+ qDebug() << "ApplicationDBusAdaptor::removeChildSurface - No added surface for " << surfaceId;
74+ return;
75+ }
76+ MirSurfaceItem* surface = m_childItems.take(surfaceId);
77+ Q_EMIT surface->removed();
5378}
tests/mocks/Unity/Application/ApplicationInfo.cpp+19−12
@@ -72,7 +72,7 @@ void ApplicationInfo::onStateChanged(State state)
7272 if (state == ApplicationInfo::Running) {
7373 QTimer::singleShot(1000, this, SLOT(createSurface()));
7474 } else if (state == ApplicationInfo::Stopped) {
75− destroySurface();
75+ setSurface(nullptr);
7676 }
7777}
7878
@@ -80,23 +80,30 @@ void ApplicationInfo::createSurface()
8080{
8181 if (m_surface || state() == ApplicationInfo::Stopped) return;
8282
83− m_surface = new MirSurfaceItem(name(),
83+ setSurface(new MirSurfaceItem(name(),
8484 MirSurfaceItem::Normal,
8585 fullscreen() ? MirSurfaceItem::Fullscreen : MirSurfaceItem::Maximized,
86− screenshot());
87− Q_EMIT surfaceChanged(m_surface);
88− Q_EMIT SurfaceManager::singleton()->surfaceCreated(m_surface);
86+ screenshot()));
8987}
9088
91−void ApplicationInfo::destroySurface()
89+void ApplicationInfo::setSurface(MirSurfaceItem* surface)
9290{
93− if (!m_surface) return;
94− MirSurfaceItem* oldSurface = m_surface;
95− m_surface = nullptr;
91+ if (m_surface == surface)
92+ return;
93+
94+ if (m_surface) {
95+ m_surface->setApplication(nullptr);
96+ m_surface->setParent(nullptr);
97+ }
9698
97− Q_EMIT surfaceChanged(nullptr);
98− Q_EMIT SurfaceManager::singleton()->surfaceDestroyed(oldSurface);
99− oldSurface->deleteLater();
99+ m_surface = surface;
100+
101+ if (m_surface) {
102+ m_surface->setApplication(this);
103+ m_surface->setParent(this);
104+ }
105+
106+ Q_EMIT surfaceChanged(m_surface);
100107}
101108
102109void ApplicationInfo::createWindowComponent()
tests/mocks/Unity/Application/ApplicationInfo.h+1−1
@@ -82,6 +82,7 @@ public:
8282 #undef IMPLEMENT_PROPERTY
8383
8484public:
85+ void setSurface(MirSurfaceItem* surface);
8586 MirSurfaceItem* surface() const { return m_surface; }
8687
8788Q_SIGNALS:
@@ -96,7 +97,6 @@ private Q_SLOTS:
9697 void onStateChanged(State state);
9798
9899 void createSurface();
99− void destroySurface();
100100
101101private:
102102 void createWindowItem();
tests/mocks/Unity/Application/ApplicationManager.cpp+4
@@ -303,6 +303,7 @@ bool ApplicationManager::focusApplication(const QString &appId)
303303 if (app->focused() && app->stage() == ApplicationInfo::MainStage) {
304304 app->setFocused(false);
305305 app->hideWindow();
306+ app->setState(ApplicationInfo::Suspended);
306307 }
307308 }
308309
@@ -310,6 +311,7 @@ bool ApplicationManager::focusApplication(const QString &appId)
310311 application->setFocused(true);
311312 if (!m_mainStage)
312313 createMainStage();
314+ application->setState(ApplicationInfo::Running);
313315 application->showWindow(m_mainStage);
314316 m_mainStage->setZ(-1000);
315317 if (m_sideStage)
@@ -320,6 +322,7 @@ bool ApplicationManager::focusApplication(const QString &appId)
320322 if (app->focused() && app->stage() == ApplicationInfo::SideStage) {
321323 app->setFocused(false);
322324 app->hideWindow();
325+ app->setState(ApplicationInfo::Suspended);
323326 }
324327 }
325328
@@ -327,6 +330,7 @@ bool ApplicationManager::focusApplication(const QString &appId)
327330 application->setFocused(true);
328331 if (!m_sideStage)
329332 createSideStage();
333+ application->setState(ApplicationInfo::Running);
330334 application->showWindow(m_sideStage);
331335 m_sideStage->setZ(-1000);
332336 if (m_mainStage)
tests/mocks/Unity/Application/MirSurfaceItem.cpp+25
@@ -15,8 +15,10 @@
1515 */
1616
1717#include "MirSurfaceItem.h"
18+#include "ApplicationInfo.h"
1819
1920#include <QPainter>
21+#include <QQmlEngine>
2022
2123MirSurfaceItem::MirSurfaceItem(const QString& name,
2224 MirSurfaceItem::Type type,
@@ -24,12 +26,15 @@ MirSurfaceItem::MirSurfaceItem(const QString& name,
2426 const QUrl& screenshot,
2527 QQuickItem *parent)
2628 : QQuickPaintedItem(parent)
29+ , m_application(nullptr)
2730 , m_name(name)
2831 , m_type(type)
2932 , m_state(state)
3033 , m_img(screenshot.isLocalFile() ? screenshot.toLocalFile() : screenshot.toString())
3134 , m_parentSurface(nullptr)
3235{
36+ QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
37+
3338 setFillColor(Qt::white);
3439}
3540
@@ -41,6 +46,9 @@ MirSurfaceItem::~MirSurfaceItem()
4146 }
4247 if (m_parentSurface)
4348 m_parentSurface->removeChildSurface(this);
49+
50+ if (m_application)
51+ m_application->setSurface(nullptr);
4452}
4553
4654void MirSurfaceItem::paint(QPainter * painter)
@@ -50,6 +58,23 @@ void MirSurfaceItem::paint(QPainter * painter)
5058 }
5159}
5260
61+void MirSurfaceItem::release()
62+{
63+ QList<MirSurfaceItem*> children(m_children);
64+ for (MirSurfaceItem* child : children) {
65+ child->release();
66+ }
67+
68+ if (m_application)
69+ m_application->setSurface(nullptr);
70+ this->deleteLater();
71+}
72+
73+void MirSurfaceItem::setApplication(ApplicationInfo* application)
74+{
75+ m_application = application;
76+}
77+
5378void MirSurfaceItem::setParentSurface(MirSurfaceItem* surface)
5479{
5580 if (m_parentSurface == surface || surface == this)
tests/mocks/Unity/Application/MirSurfaceItem.h+8−1
@@ -20,6 +20,8 @@
2020#include <QQuickPaintedItem>
2121#include <QImage>
2222
23+class ApplicationInfo;
24+
2325class MirSurfaceItem : public QQuickPaintedItem
2426{
2527 Q_OBJECT
@@ -61,16 +63,18 @@ public:
6163 ~MirSurfaceItem();
6264
6365 //getters
66+ ApplicationInfo* application() const { return m_application; }
6467 Type type() const { return m_type; }
6568 State state() const { return m_state; }
6669 QString name() const { return m_name; }
6770 MirSurfaceItem* parentSurface() const { return m_parentSurface; }
6871 QList<QObject*> childSurfaces() const;
6972
70− Q_INVOKABLE void release() {}
73+ Q_INVOKABLE void release();
7174
7275 void paint(QPainter * painter) override;
7376
77+ void setApplication(ApplicationInfo* item);
7478 void setParentSurface(MirSurfaceItem* item);
7579
7680Q_SIGNALS:
@@ -80,10 +84,13 @@ Q_SIGNALS:
8084 void parentSurfaceChanged(MirSurfaceItem*);
8185 void childSurfacesChanged();
8286
87+ void removed();
88+
8389private:
8490 void addChildSurface(MirSurfaceItem* surface);
8591 void removeChildSurface(MirSurfaceItem* surface);
8692
93+ ApplicationInfo* m_application;
8794 const QString m_name;
8895 const Type m_type;
8996 const State m_state;