on xenial help sign in
parent animation
c25c21eNick Dedekind
qml/Stages/SpreadDelegate.qml+11−12
@@ -30,7 +30,7 @@ Item {
30 property real maximizedAppTopMargin
30 property real maximizedAppTopMargin
31 property alias swipeToCloseEnabled: dragArea.enabled
31 property alias swipeToCloseEnabled: dragArea.enabled
32
32
33− readonly property bool isFullscreen: surface !== null && surfaceContainer.surface.anchors.topMargin == 0
33+ readonly property bool isFullscreen: surface !== null && surfaceContainer.surfaceArea.anchors.topMargin == 0
34
34
35 signal clicked()
35 signal clicked()
36 signal closed()
36 signal closed()
@@ -47,15 +47,6 @@ Item {
47 surface.visible = false; // hide until splash screen removed
47 surface.visible = false; // hide until splash screen removed
48 appHasCreatedASurface = true;
48 appHasCreatedASurface = true;
49 }
49 }
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;
59 }
50 }
60 }
51 }
61
52
@@ -64,6 +55,15 @@ Item {
64 splashLoader.source = "";
55 splashLoader.source = "";
65 }
56 }
66
57
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+
67 Binding {
67 Binding {
68 target: surface
68 target: surface
69 property: "enabled"
69 property: "enabled"
@@ -83,7 +83,6 @@ Item {
83
83
84 Connections {
84 Connections {
85 target: surface
85 target: surface
86− onStateChanged: surfaceContainer.checkFullscreen(surface);
87 // FIXME: I would rather not need to do this, but currently it doesn't get
86 // FIXME: I would rather not need to do this, but currently it doesn't get
88 // active focus without it and I don't know why.
87 // active focus without it and I don't know why.
89 onFocusChanged: forceSurfaceActiveFocusIfReady();
88 onFocusChanged: forceSurfaceActiveFocusIfReady();
@@ -103,7 +102,7 @@ Item {
103 leftMargin: -units.gu(2)
102 leftMargin: -units.gu(2)
104 rightMargin: -units.gu(2)
103 rightMargin: -units.gu(2)
105 bottomMargin: -units.gu(2)
104 bottomMargin: -units.gu(2)
106− topMargin: -units.gu(2) + (root.isFullscreen ? 0 : maximizedAppTopMargin)
105+ topMargin: -units.gu(2)// + (root.isFullscreen ? 0 : maximizedAppTopMargin)
107 }
106 }
108 source: "graphics/dropshadow.png"
107 source: "graphics/dropshadow.png"
109 border { left: 50; right: 50; top: 50; bottom: 50 }
108 border { left: 50; right: 50; top: 50; bottom: 50 }
qml/Stages/SurfaceContainer.qml+105−23
@@ -19,14 +19,30 @@ import QtQuick 2.0
19Item {
19Item {
20 id: container
20 id: container
21 property Item surface: null
21 property Item surface: null
22− property string animation
22+ readonly property alias surfaceArea: _surfaceArea
23− property bool show: false
23+ property bool removing: false
24
24
25 onSurfaceChanged: {
25 onSurfaceChanged: {
26 if (surface) {
26 if (surface) {
27 surface.parent = container;
27 surface.parent = container;
28− surface.anchors.fill = container;
29 surface.z = 1;
28 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();
30 }
46 }
31 }
47 }
32
48
@@ -35,60 +51,126 @@ Item {
35
51
36 delegate: Loader {
52 delegate: Loader {
37 z: 2
53 z: 2
38− anchors.fill: surface
54+ anchors.fill: surfaceArea
39
55
40 // Only way to do recursive qml items.
56 // Only way to do recursive qml items.
41 source: Qt.resolvedUrl("SurfaceContainer.qml")
57 source: Qt.resolvedUrl("SurfaceContainer.qml")
42 onLoaded: {
58 onLoaded: {
43− item.parent = container.surface;
44 item.surface = modelData;
59 item.surface = modelData;
45− item.animation = "overlaySwipeBottom"
60+ item.animateIn("swipeFromBottom");
46− item.show = true;
61+ container.animateIn("swipeUp");
47 }
62 }
48 }
63 }
49 }
64 }
50
65
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+
51 states: [
95 states: [
96+ State {
97+ name: "initial"
98+ PropertyChanges { target: surface; anchors.fill: surfaceArea }
99+ },
100+
52 State {
101 State {
53 name: "baseAnimation"
102 name: "baseAnimation"
54 PropertyChanges { target: surface; anchors.fill: undefined }
103 PropertyChanges { target: surface; anchors.fill: undefined }
55 },
104 },
56
105
57 State {
106 State {
58− name: "overlaySwipeBottom-out"
107+ name: "swipeFromBottom-prep"
59 extend: "baseAnimation"
108 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 }
62 },
110 },
63 State {
111 State {
64− name: "overlaySwipeBottom-in"
112+ name: "swipeFromBottom-out"
113+ extend: "swipeFromBottom-prep"
114+ },
115+ State {
116+ name: "swipeFromBottom-in"
65 extend: "baseAnimation"
117 extend: "baseAnimation"
66− when: surface && animation === "overlaySwipeBottom" && show
67− AnchorChanges { target: surface; anchors.top: surface.parent.top }
118+ AnchorChanges { target: surface; anchors.top: surfaceArea.top }
68− }
119+ },
69
120
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+ }
70 // TODO: more animations!
134 // TODO: more animations!
71− // Surface needs to stick around so that we can dimiss them with animation.
72 ]
135 ]
73
136
74 transitions: [
137 transitions: [
75 Transition {
138 Transition {
76− from: "overlaySwipeBottom-out"
139+ to: "swipeFromBottom-in"
77− to: "overlaySwipeBottom-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"
78 SequentialAnimation {
148 SequentialAnimation {
79− PropertyAction { target: surface.parent; property: "clip"; value: true}
149+ PropertyAction { target: surface.parent; property: "clip"; value: true }
80 AnchorAnimation { easing.type: Easing.InOutQuad; duration: 400 }
150 AnchorAnimation { easing.type: Easing.InOutQuad; duration: 400 }
151+ PropertyAction { target: surface; property: "visible"; value: !removing }
81− PropertyAction { target: surface.parent; property: "clip"; value: false}
152+ PropertyAction { target: surface.parent; property: "clip"; value: false }
153+ ScriptAction { script: { if (container.removing) surface.release() } }
82 }
154 }
83 },
155 },
156+
84 Transition {
157 Transition {
85− from: "overlaySwipeBottom-in"
158+ to: "swipeUp-in"
86− to: "overlaySwipeBottom-out"
87 SequentialAnimation {
159 SequentialAnimation {
88− PropertyAction { target: surface.parent; property: "clip"; value: true}
160+ PropertyAction { target: surface.parent; property: "clip"; value: true }
89 AnchorAnimation { easing.type: Easing.InOutQuad; duration: 400 }
161 AnchorAnimation { easing.type: Easing.InOutQuad; duration: 400 }
90 PropertyAction { target: surface; property: "visible"; value: false}
162 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() } }
92 }
174 }
93 }
175 }
94 ]
176 ]
tests/mocks/Unity/Application/ApplicationDBusAdaptor.cpp+30−5
@@ -28,11 +28,31 @@ ApplicationDBusAdaptor::ApplicationDBusAdaptor(ApplicationManager* applicationMa
28{
28{
29}
29}
30
30
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+
31quint32 ApplicationDBusAdaptor::addChildSurface(const QString &appId, const QString &surfaceImage)
49quint32 ApplicationDBusAdaptor::addChildSurface(const QString &appId, const QString &surfaceImage)
32{
50{
51+ qDebug() << "ApplicationDBusAdaptor::addChildSurface - " << appId;
52+
33 ApplicationInfo* application = m_applicationManager->findApplication(appId);
53 ApplicationInfo* application = m_applicationManager->findApplication(appId);
34 if (!application) {
54 if (!application) {
35− qDebug() << "ApplicationDBusAdaptor::addChildSurface - No application for " << appId;
55+ qDebug() << "ApplicationDBusAdaptor::addChildSurface - No application found for " << appId;
36 return ~0;
56 return ~0;
37 }
57 }
38 quint32 surfaceId = ++nextId;
58 quint32 surfaceId = ++nextId;
@@ -41,13 +61,18 @@ quint32 ApplicationDBusAdaptor::addChildSurface(const QString &appId, const QStr
41 MirSurfaceItem::Maximized,
61 MirSurfaceItem::Maximized,
42 QUrl(surfaceImage));
62 QUrl(surfaceImage));
43 m_childItems[surfaceId] = surface;
63 m_childItems[surfaceId] = surface;
44− surface->setParentSurface(application->surface());
64+ surface->setParentSurface(topSurface(application->surface()));
45 return surfaceId;
65 return surfaceId;
46}
66}
47
67
48void ApplicationDBusAdaptor::removeChildSurface(int surfaceId)
68void ApplicationDBusAdaptor::removeChildSurface(int surfaceId)
49{
69{
70+ qDebug() << "ApplicationDBusAdaptor::removeChildSurface - " << surfaceId;
71+
50− if (!m_childItems.contains(surfaceId)) return;
72+ if (!m_childItems.contains(surfaceId)) {
73+ qDebug() << "ApplicationDBusAdaptor::removeChildSurface - No added surface for " << surfaceId;
74+ return;
75+ }
51− MirSurfaceItem* surface = m_childItems[surfaceId];
76+ MirSurfaceItem* surface = m_childItems.take(surfaceId);
52− surface->setParentSurface(nullptr);
77+ Q_EMIT surface->removed();
53}
78}
tests/mocks/Unity/Application/ApplicationInfo.cpp+19−12
@@ -72,7 +72,7 @@ void ApplicationInfo::onStateChanged(State state)
72 if (state == ApplicationInfo::Running) {
72 if (state == ApplicationInfo::Running) {
73 QTimer::singleShot(1000, this, SLOT(createSurface()));
73 QTimer::singleShot(1000, this, SLOT(createSurface()));
74 } else if (state == ApplicationInfo::Stopped) {
74 } else if (state == ApplicationInfo::Stopped) {
75− destroySurface();
75+ setSurface(nullptr);
76 }
76 }
77}
77}
78
78
@@ -80,23 +80,30 @@ void ApplicationInfo::createSurface()
80{
80{
81 if (m_surface || state() == ApplicationInfo::Stopped) return;
81 if (m_surface || state() == ApplicationInfo::Stopped) return;
82
82
83− m_surface = new MirSurfaceItem(name(),
83+ setSurface(new MirSurfaceItem(name(),
84 MirSurfaceItem::Normal,
84 MirSurfaceItem::Normal,
85 fullscreen() ? MirSurfaceItem::Fullscreen : MirSurfaceItem::Maximized,
85 fullscreen() ? MirSurfaceItem::Fullscreen : MirSurfaceItem::Maximized,
86− screenshot());
86+ screenshot()));
87− Q_EMIT surfaceChanged(m_surface);
88− Q_EMIT SurfaceManager::singleton()->surfaceCreated(m_surface);
89}
87}
90
88
91−void ApplicationInfo::destroySurface()
89+void ApplicationInfo::setSurface(MirSurfaceItem* surface)
92{
90{
93− if (!m_surface) return;
91+ if (m_surface == surface)
94− MirSurfaceItem* oldSurface = m_surface;
92+ return;
93+
94+ if (m_surface) {
95+ m_surface->setApplication(nullptr);
95− m_surface = nullptr;
96+ m_surface->setParent(nullptr);
97+ }
96
98
99+ m_surface = surface;
100+
101+ if (m_surface) {
102+ m_surface->setApplication(this);
103+ m_surface->setParent(this);
104+ }
105+
97− Q_EMIT surfaceChanged(nullptr);
106+ Q_EMIT surfaceChanged(m_surface);
98− Q_EMIT SurfaceManager::singleton()->surfaceDestroyed(oldSurface);
99− oldSurface->deleteLater();
100}
107}
101
108
102void ApplicationInfo::createWindowComponent()
109void ApplicationInfo::createWindowComponent()
tests/mocks/Unity/Application/ApplicationInfo.h+1−1
@@ -82,6 +82,7 @@ public:
82 #undef IMPLEMENT_PROPERTY
82 #undef IMPLEMENT_PROPERTY
83
83
84public:
84public:
85+ void setSurface(MirSurfaceItem* surface);
85 MirSurfaceItem* surface() const { return m_surface; }
86 MirSurfaceItem* surface() const { return m_surface; }
86
87
87Q_SIGNALS:
88Q_SIGNALS:
@@ -96,7 +97,6 @@ private Q_SLOTS:
96 void onStateChanged(State state);
97 void onStateChanged(State state);
97
98
98 void createSurface();
99 void createSurface();
99− void destroySurface();
100
100
101private:
101private:
102 void createWindowItem();
102 void createWindowItem();
tests/mocks/Unity/Application/ApplicationManager.cpp+4
@@ -303,6 +303,7 @@ bool ApplicationManager::focusApplication(const QString &appId)
303 if (app->focused() && app->stage() == ApplicationInfo::MainStage) {
303 if (app->focused() && app->stage() == ApplicationInfo::MainStage) {
304 app->setFocused(false);
304 app->setFocused(false);
305 app->hideWindow();
305 app->hideWindow();
306+ app->setState(ApplicationInfo::Suspended);
306 }
307 }
307 }
308 }
308
309
@@ -310,6 +311,7 @@ bool ApplicationManager::focusApplication(const QString &appId)
310 application->setFocused(true);
311 application->setFocused(true);
311 if (!m_mainStage)
312 if (!m_mainStage)
312 createMainStage();
313 createMainStage();
314+ application->setState(ApplicationInfo::Running);
313 application->showWindow(m_mainStage);
315 application->showWindow(m_mainStage);
314 m_mainStage->setZ(-1000);
316 m_mainStage->setZ(-1000);
315 if (m_sideStage)
317 if (m_sideStage)
@@ -320,6 +322,7 @@ bool ApplicationManager::focusApplication(const QString &appId)
320 if (app->focused() && app->stage() == ApplicationInfo::SideStage) {
322 if (app->focused() && app->stage() == ApplicationInfo::SideStage) {
321 app->setFocused(false);
323 app->setFocused(false);
322 app->hideWindow();
324 app->hideWindow();
325+ app->setState(ApplicationInfo::Suspended);
323 }
326 }
324 }
327 }
325
328
@@ -327,6 +330,7 @@ bool ApplicationManager::focusApplication(const QString &appId)
327 application->setFocused(true);
330 application->setFocused(true);
328 if (!m_sideStage)
331 if (!m_sideStage)
329 createSideStage();
332 createSideStage();
333+ application->setState(ApplicationInfo::Running);
330 application->showWindow(m_sideStage);
334 application->showWindow(m_sideStage);
331 m_sideStage->setZ(-1000);
335 m_sideStage->setZ(-1000);
332 if (m_mainStage)
336 if (m_mainStage)
tests/mocks/Unity/Application/MirSurfaceItem.cpp+25
@@ -15,8 +15,10 @@
15 */
15 */
16
16
17#include "MirSurfaceItem.h"
17#include "MirSurfaceItem.h"
18+#include "ApplicationInfo.h"
18
19
19#include <QPainter>
20#include <QPainter>
21+#include <QQmlEngine>
20
22
21MirSurfaceItem::MirSurfaceItem(const QString& name,
23MirSurfaceItem::MirSurfaceItem(const QString& name,
22 MirSurfaceItem::Type type,
24 MirSurfaceItem::Type type,
@@ -24,12 +26,15 @@ MirSurfaceItem::MirSurfaceItem(const QString& name,
24 const QUrl& screenshot,
26 const QUrl& screenshot,
25 QQuickItem *parent)
27 QQuickItem *parent)
26 : QQuickPaintedItem(parent)
28 : QQuickPaintedItem(parent)
29+ , m_application(nullptr)
27 , m_name(name)
30 , m_name(name)
28 , m_type(type)
31 , m_type(type)
29 , m_state(state)
32 , m_state(state)
30 , m_img(screenshot.isLocalFile() ? screenshot.toLocalFile() : screenshot.toString())
33 , m_img(screenshot.isLocalFile() ? screenshot.toLocalFile() : screenshot.toString())
31 , m_parentSurface(nullptr)
34 , m_parentSurface(nullptr)
32{
35{
36+ QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
37+
33 setFillColor(Qt::white);
38 setFillColor(Qt::white);
34}
39}
35
40
@@ -41,6 +46,9 @@ MirSurfaceItem::~MirSurfaceItem()
41 }
46 }
42 if (m_parentSurface)
47 if (m_parentSurface)
43 m_parentSurface->removeChildSurface(this);
48 m_parentSurface->removeChildSurface(this);
49+
50+ if (m_application)
51+ m_application->setSurface(nullptr);
44}
52}
45
53
46void MirSurfaceItem::paint(QPainter * painter)
54void MirSurfaceItem::paint(QPainter * painter)
@@ -50,6 +58,23 @@ void MirSurfaceItem::paint(QPainter * painter)
50 }
58 }
51}
59}
52
60
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+
53void MirSurfaceItem::setParentSurface(MirSurfaceItem* surface)
78void MirSurfaceItem::setParentSurface(MirSurfaceItem* surface)
54{
79{
55 if (m_parentSurface == surface || surface == this)
80 if (m_parentSurface == surface || surface == this)
tests/mocks/Unity/Application/MirSurfaceItem.h+8−1
@@ -20,6 +20,8 @@
20#include <QQuickPaintedItem>
20#include <QQuickPaintedItem>
21#include <QImage>
21#include <QImage>
22
22
23+class ApplicationInfo;
24+
23class MirSurfaceItem : public QQuickPaintedItem
25class MirSurfaceItem : public QQuickPaintedItem
24{
26{
25 Q_OBJECT
27 Q_OBJECT
@@ -61,16 +63,18 @@ public:
61 ~MirSurfaceItem();
63 ~MirSurfaceItem();
62
64
63 //getters
65 //getters
66+ ApplicationInfo* application() const { return m_application; }
64 Type type() const { return m_type; }
67 Type type() const { return m_type; }
65 State state() const { return m_state; }
68 State state() const { return m_state; }
66 QString name() const { return m_name; }
69 QString name() const { return m_name; }
67 MirSurfaceItem* parentSurface() const { return m_parentSurface; }
70 MirSurfaceItem* parentSurface() const { return m_parentSurface; }
68 QList<QObject*> childSurfaces() const;
71 QList<QObject*> childSurfaces() const;
69
72
70− Q_INVOKABLE void release() {}
73+ Q_INVOKABLE void release();
71
74
72 void paint(QPainter * painter) override;
75 void paint(QPainter * painter) override;
73
76
77+ void setApplication(ApplicationInfo* item);
74 void setParentSurface(MirSurfaceItem* item);
78 void setParentSurface(MirSurfaceItem* item);
75
79
76Q_SIGNALS:
80Q_SIGNALS:
@@ -80,10 +84,13 @@ Q_SIGNALS:
80 void parentSurfaceChanged(MirSurfaceItem*);
84 void parentSurfaceChanged(MirSurfaceItem*);
81 void childSurfacesChanged();
85 void childSurfacesChanged();
82
86
87+ void removed();
88+
83private:
89private:
84 void addChildSurface(MirSurfaceItem* surface);
90 void addChildSurface(MirSurfaceItem* surface);
85 void removeChildSurface(MirSurfaceItem* surface);
91 void removeChildSurface(MirSurfaceItem* surface);
86
92
93+ ApplicationInfo* m_application;
87 const QString m_name;
94 const QString m_name;
88 const Type m_type;
95 const Type m_type;
89 const State m_state;
96 const State m_state;