on xenial help sign in
Merge overlay
630d245Albert Astals Cid
CMakeLists.txt+1−1
@@ -56,7 +56,7 @@ find_package(Qt5DBus 5.2 REQUIRED)
56find_package(Qt5Concurrent 5.2 REQUIRED)
56find_package(Qt5Concurrent 5.2 REQUIRED)
57find_package(Qt5Sql 5.2 REQUIRED)
57find_package(Qt5Sql 5.2 REQUIRED)
58
58
59−pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=7)
59+pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=8)
60
60
61# Standard install paths
61# Standard install paths
62include(GNUInstallDirs)
62include(GNUInstallDirs)
debian/changelog+8
@@ -1,3 +1,11 @@
1+unity8 (8.11+15.04.20150827.1-0ubuntu1) vivid; urgency=medium
2+
3+ [ Daniel d'Andrada ]
4+ * MirSurfaceItem is now a view+controller instantiated from QML (LP:
5+ #1483752)
6+
7+ -- CI Train Bot <ci-train-bot@canonical.com> Thu, 27 Aug 2015 14:00:05 +0000
8+
1unity8 (8.11+15.04.20150821-0ubuntu1) vivid; urgency=medium
9unity8 (8.11+15.04.20150821-0ubuntu1) vivid; urgency=medium
2
10
3 [ Michael Terry ]
11 [ Michael Terry ]
debian/control+1−1
@@ -28,7 +28,7 @@ Build-Depends: cmake,
28 libqt5xmlpatterns5-dev,
28 libqt5xmlpatterns5-dev,
29 libsystemsettings-dev,
29 libsystemsettings-dev,
30 libudev-dev,
30 libudev-dev,
31− libunity-api-dev (>= 7.99),
31+ libunity-api-dev (>= 7.100),
32 libusermetricsoutput1-dev,
32 libusermetricsoutput1-dev,
33 libxcb1-dev,
33 libxcb1-dev,
34 pkg-config,
34 pkg-config,
qml/Components/InputMethod.qml+26−21
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2014 Canonical, Ltd.
2+ * Copyright (C) 2014,2015 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU General Public License as published by
@@ -22,24 +22,44 @@ import Ubuntu.Gestures 0.1
22Item {
22Item {
23 id: root
23 id: root
24
24
25− property var surface: null
25+ Connections {
26+ target: SurfaceManager
27+ onSurfaceCreated: {
28+ if (surface.type == Mir.InputMethodType) {
29+ surfaceItem.surface = surface;
30+ }
31+ }
32+ }
26
33
27 property int transitionDuration: UbuntuAnimation.FastDuration
34 property int transitionDuration: UbuntuAnimation.FastDuration
28
35
29− Binding { target: surface; property: "z"; value: 0 }
36+ MirSurfaceItem {
37+ id: surfaceItem
38+ anchors.fill: parent
39+
40+ consumesInput: true
41+
42+ surfaceWidth: width
43+ surfaceHeight: height
44+
45+ onLiveChanged: {
46+ if (surface !== null && !live) {
47+ surface = null;
48+ }
49+ }
50+ }
30
51
31 TouchGate {
52 TouchGate {
32 x: UbuntuKeyboardInfo.x
53 x: UbuntuKeyboardInfo.x
33 y: UbuntuKeyboardInfo.y
54 y: UbuntuKeyboardInfo.y
34− z: 1
35 width: UbuntuKeyboardInfo.width
55 width: UbuntuKeyboardInfo.width
36 height: UbuntuKeyboardInfo.height
56 height: UbuntuKeyboardInfo.height
37
57
38− targetItem: root.surface
58+ targetItem: surfaceItem
39 }
59 }
40
60
41 state: {
61 state: {
42− if (surface && surface.state != MirSurfaceItem.Minimized) {
62+ if (surfaceItem.surface && surfaceItem.surfaceState != Mir.MinimizedState) {
43 return "shown";
63 return "shown";
44 } else {
64 } else {
45 return "hidden";
65 return "hidden";
@@ -74,19 +94,4 @@ Item {
74 UbuntuNumberAnimation { property: "y"; duration: transitionDuration }
94 UbuntuNumberAnimation { property: "y"; duration: transitionDuration }
75 }
95 }
76 ]
96 ]
77−
78− onSurfaceChanged: {
79− if (surface) {
80− surface.parent = root;
81− surface.anchors.fill = root;
82− }
83− }
84−
85− Component.onDestruction: {
86− if (surface) {
87− surface.parent = null;
88− surface.release();
89− surface = null;
90− }
91− }
92}
97}
qml/Shell.qml−19
@@ -395,25 +395,6 @@ Item {
395 z: notifications.useModal || panel.indicators.shown || wizard.active ? overlay.z + 1 : overlay.z - 1
395 z: notifications.useModal || panel.indicators.shown || wizard.active ? overlay.z + 1 : overlay.z - 1
396 }
396 }
397
397
398− Connections {
399− target: SurfaceManager
400− onSurfaceCreated: {
401− if (surface.type == MirSurfaceItem.InputMethod) {
402− inputMethod.surface = surface;
403− }
404− }
405−
406− onSurfaceDestroyed: {
407− if (inputMethod.surface == surface) {
408− inputMethod.surface = null;
409− surface.parent = null;
410− }
411− if (!surface.parent) {
412− // there's no one displaying it. delete it right away
413− surface.release();
414− }
415− }
416− }
417 Connections {
398 Connections {
418 target: SessionManager
399 target: SessionManager
419 onSessionStopping: {
400 onSessionStopping: {
qml/Stages/ApplicationWindow.qml+2−1
@@ -50,7 +50,8 @@ FocusScope {
50 property bool hadSurface: sessionContainer.surfaceContainer.hadSurface
50 property bool hadSurface: sessionContainer.surfaceContainer.hadSurface
51
51
52 property bool needToTakeScreenshot:
52 property bool needToTakeScreenshot:
53− sessionContainer.surface && d.surfaceInitialized && screenshotImage.status === Image.Null
53+ ((sessionContainer.surface && d.surfaceInitialized) || d.hadSurface)
54+ && screenshotImage.status === Image.Null
54 && d.applicationState === ApplicationInfoInterface.Stopped
55 && d.applicationState === ApplicationInfoInterface.Stopped
55 onNeedToTakeScreenshotChanged: {
56 onNeedToTakeScreenshotChanged: {
56 if (needToTakeScreenshot) {
57 if (needToTakeScreenshot) {
qml/Stages/SurfaceContainer.qml+38−21
@@ -18,34 +18,26 @@ import QtQuick 2.0
18import Ubuntu.Components 1.1
18import Ubuntu.Components 1.1
19import Ubuntu.Gestures 0.1 // For TouchGate
19import Ubuntu.Gestures 0.1 // For TouchGate
20import Utils 0.1 // for InputWatcher
20import Utils 0.1 // for InputWatcher
21+import Unity.Application 0.1 // for MirSurfaceItem
21
22
22FocusScope {
23FocusScope {
23 id: root
24 id: root
24 objectName: "surfaceContainer"
25 objectName: "surfaceContainer"
26+
25− property Item surface: null
27+ property var surface: null
26 property bool hadSurface: false
28 property bool hadSurface: false
27 property bool interactive
29 property bool interactive
28 property int surfaceOrientationAngle: 0
30 property int surfaceOrientationAngle: 0
29
31
30 onSurfaceChanged: {
32 onSurfaceChanged: {
31 if (surface) {
33 if (surface) {
32− // Set the surface focus *after* it is added to the scene to
34+ surfaceItem.surface = surface;
33− // ensure an update to the scene's active focus.
34− surface.focus = false;
35− surface.parent = root;
36− surface.focus = true;
37− } else {
38− hadSurface = true;
35+ root.hadSurface = false;
39 }
36 }
40 }
37 }
41− Binding { target: surface; property: "anchors.fill"; value: root }
42− Binding { target: surface; property: "z"; value: 1 }
43− Binding { target: surface; property: "enabled"; value: root.interactive; when: surface }
44− Binding { target: surface; property: "antialiasing"; value: !root.interactive; when: surface }
45− Binding { target: surface; property: "orientationAngle"; value: root.surfaceOrientationAngle; when: surface }
46
38
47 InputWatcher {
39 InputWatcher {
48− target: root.surface
40+ target: surfaceItem
49 onTargetPressedChanged: {
41 onTargetPressedChanged: {
50 if (targetPressed && root.interactive) {
42 if (targetPressed && root.interactive) {
51 root.focus = true;
43 root.focus = true;
@@ -54,28 +46,53 @@ FocusScope {
54 }
46 }
55 }
47 }
56
48
49+ MirSurfaceItem {
50+ id: surfaceItem
51+ objectName: "surfaceItem"
52+
53+ consumesInput: true
54+
55+ surfaceWidth: width
56+ surfaceHeight: height
57+
58+ anchors.fill: root
59+ enabled: root.interactive
60+ focus: true
61+ antialiasing: !root.interactive
62+ orientationAngle: root.surfaceOrientationAngle
63+ }
64+
57 TouchGate {
65 TouchGate {
58− targetItem: surface
66+ targetItem: surfaceItem
59 anchors.fill: root
67 anchors.fill: root
60− enabled: root.surface ? root.surface.enabled : false
68+ enabled: surfaceItem.enabled
61− z: 2
62 }
69 }
63
70
64 states: [
71 states: [
65 State {
72 State {
66 name: "zombie"
73 name: "zombie"
67− when: surface && !surface.live
74+ when: surfaceItem.surface && !surfaceItem.live
68 }
75 }
69 ]
76 ]
70 transitions: [
77 transitions: [
71 Transition {
78 Transition {
72 from: ""; to: "zombie"
79 from: ""; to: "zombie"
73 SequentialAnimation {
80 SequentialAnimation {
74− UbuntuNumberAnimation { target: surface; property: "opacity"; to: 0.0
81+ UbuntuNumberAnimation { target: surfaceItem; property: "opacity"; to: 0.0
75 duration: UbuntuAnimation.BriskDuration }
82 duration: UbuntuAnimation.BriskDuration }
76− PropertyAction { target: surface; property: "visible"; value: false }
83+ PropertyAction { target: surfaceItem; property: "visible"; value: false }
77− ScriptAction { script: { if (root.surface) { root.surface.release(); } } }
84+ ScriptAction { script: {
85+ surfaceItem.surface = null;
86+ root.hadSurface = true;
87+ } }
78 }
88 }
89+ },
90+ Transition {
91+ from: "zombie"; to: ""
92+ ScriptAction { script: {
93+ surfaceItem.opacity = 1.0;
94+ surfaceItem.visible = true;
95+ } }
79 }
96 }
80 ]
97 ]
81}
98}
tests/mocks/Unity/Application/ApplicationInfo.cpp+9−1
@@ -15,6 +15,7 @@
15 */
15 */
16
16
17#include "ApplicationInfo.h"
17#include "ApplicationInfo.h"
18+#include "MirSurface.h"
18#include "Session.h"
19#include "Session.h"
19#include "SessionManager.h"
20#include "SessionManager.h"
20
21
@@ -74,6 +75,13 @@ void ApplicationInfo::createSession()
74 setSession(SessionManager::singleton()->createSession(appId(), screenshotUrl));
75 setSession(SessionManager::singleton()->createSession(appId(), screenshotUrl));
75}
76}
76
77
78+void ApplicationInfo::destroySession()
79+{
80+ Session *session = this->session();
81+ setSession(nullptr);
82+ delete session;
83+}
84+
77void ApplicationInfo::setSession(Session* session)
85void ApplicationInfo::setSession(Session* session)
78{
86{
79 if (m_session == session)
87 if (m_session == session)
@@ -237,7 +245,7 @@ void ApplicationInfo::setRequestedState(RequestedState value)
237 }
245 }
238}
246}
239
247
240−void ApplicationInfo::onSessionSurfaceChanged(MirSurfaceItem* surface)
248+void ApplicationInfo::onSessionSurfaceChanged(MirSurface* surface)
241{
249{
242 if (surface != nullptr && m_state == Starting) {
250 if (surface != nullptr && m_state == Starting) {
243 if (m_requestedState == RequestedRunning) {
251 if (m_requestedState == RequestedRunning) {
tests/mocks/Unity/Application/ApplicationInfo.h+4−6
@@ -17,13 +17,10 @@
17#ifndef APPLICATION_H
17#ifndef APPLICATION_H
18#define APPLICATION_H
18#define APPLICATION_H
19
19
20−#include "SurfaceManager.h"
21−#include "MirSurfaceItemModel.h"
22−
23#include <QObject>
20#include <QObject>
24
21
25−class QQuickItem;
22+class MirSurface;
26−class MirSurfaceItem;
23+class Session;
27
24
28// unity-api
25// unity-api
29#include <unity/shell/application/ApplicationInfoInterface.h>
26#include <unity/shell/application/ApplicationInfoInterface.h>
@@ -103,9 +100,10 @@ Q_SIGNALS:
103
100
104public Q_SLOTS:
101public Q_SLOTS:
105 Q_INVOKABLE void createSession();
102 Q_INVOKABLE void createSession();
103+ Q_INVOKABLE void destroySession();
106
104
107private Q_SLOTS:
105private Q_SLOTS:
108− void onSessionSurfaceChanged(MirSurfaceItem*);
106+ void onSessionSurfaceChanged(MirSurface*);
109
107
110private:
108private:
111 void setIcon(const QUrl &value);
109 void setIcon(const QUrl &value);
tests/mocks/Unity/Application/ApplicationTestInterface.cpp+3−3
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2014 Canonical, Ltd.
2+ * Copyright (C) 2014,2015 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU General Public License as published by
@@ -20,7 +20,7 @@
20#include "SessionManager.h"
20#include "SessionManager.h"
21#include "SurfaceManager.h"
21#include "SurfaceManager.h"
22#include "Session.h"
22#include "Session.h"
23−#include "MirSurfaceItem.h"
23+#include "MirSurface.h"
24
24
25#include <paths.h>
25#include <paths.h>
26
26
@@ -62,7 +62,7 @@ void ApplicationTestInterface::removeSession(Session* existingSession)
62 existingSession->setLive(false);
62 existingSession->setLive(false);
63}
63}
64
64
65−void ApplicationTestInterface::removeSurface(MirSurfaceItem* existingSurface)
65+void ApplicationTestInterface::removeSurface(MirSurface* existingSurface)
66{
66{
67 qDebug() << "ApplicationTestInterface::removeSurface - " << existingSurface;
67 qDebug() << "ApplicationTestInterface::removeSurface - " << existingSurface;
68
68
tests/mocks/Unity/Application/ApplicationTestInterface.h+3−3
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2014 Canonical, Ltd.
2+ * Copyright (C) 2014,2015 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU General Public License as published by
@@ -21,7 +21,7 @@
21
21
22class ApplicationManager;
22class ApplicationManager;
23class Session;
23class Session;
24−class MirSurfaceItem;
24+class MirSurface;
25
25
26class ApplicationTestInterface : public QDBusAbstractAdaptor
26class ApplicationTestInterface : public QDBusAbstractAdaptor
27{
27{
@@ -32,7 +32,7 @@ public:
32
32
33 Q_INVOKABLE Session* addChildSession(Session* existingSession, const QString& surfaceImage);
33 Q_INVOKABLE Session* addChildSession(Session* existingSession, const QString& surfaceImage);
34 Q_INVOKABLE void removeSession(Session* existingSession);
34 Q_INVOKABLE void removeSession(Session* existingSession);
35− Q_INVOKABLE void removeSurface(MirSurfaceItem* existingSurface);
35+ Q_INVOKABLE void removeSurface(MirSurface* existingSurface);
36
36
37public Q_SLOTS:
37public Q_SLOTS:
38 quint32 addChildSession(const QString& appId, quint32 existingSessionId, const QString& surfaceImage);
38 quint32 addChildSession(const QString& appId, quint32 existingSessionId, const QString& surfaceImage);
tests/mocks/Unity/Application/CMakeLists.txt+4−1
@@ -4,8 +4,8 @@ set(FakeUnityApplicationQml_SOURCES
4 ApplicationManager.cpp
4 ApplicationManager.cpp
5 ApplicationScreenshotProvider.cpp
5 ApplicationScreenshotProvider.cpp
6 ApplicationTestInterface.cpp
6 ApplicationTestInterface.cpp
7+ MirSurface.cpp
7 MirSurfaceItem.cpp
8 MirSurfaceItem.cpp
8− MirSurfaceItemModel.h
9 ObjectListModel.h
9 ObjectListModel.h
10 Session.cpp
10 Session.cpp
11 SessionManager.cpp
11 SessionManager.cpp
@@ -15,6 +15,9 @@ set(FakeUnityApplicationQml_SOURCES
15 VirtualKeyboard.cpp
15 VirtualKeyboard.cpp
16 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
16 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
17 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationManagerInterface.h
17 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationManagerInterface.h
18+ ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/Mir.h
19+ ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceInterface.h
20+ ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceItemInterface.h
18)
21)
19
22
20add_library(FakeUnityApplicationQml MODULE ${FakeUnityApplicationQml_SOURCES})
23add_library(FakeUnityApplicationQml MODULE ${FakeUnityApplicationQml_SOURCES})
tests/mocks/Unity/Application/MirSurface.cppnew file+182
@@ -0,0 +1,182 @@
1+/*
2+ * Copyright (C) 2015 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+#include "MirSurface.h"
18+
19+#include <QDebug>
20+
21+MirSurface::MirSurface(const QString& name,
22+ Mir::Type type,
23+ Mir::State state,
24+ const QUrl& screenshot,
25+ const QString &qmlFilePath)
26+ : unity::shell::application::MirSurfaceInterface(nullptr)
27+ , m_name(name)
28+ , m_type(type)
29+ , m_state(state)
30+ , m_orientationAngle(Mir::Angle0)
31+ , m_screenshotUrl(screenshot)
32+ , m_qmlFilePath(qmlFilePath)
33+ , m_live(true)
34+ , m_viewCount(0)
35+ , m_activeFocus(false)
36+ , m_width(-1)
37+ , m_height(-1)
38+{
39+ qDebug() << "MirSurface::MirSurface() " << name;
40+}
41+
42+MirSurface::~MirSurface()
43+{
44+ qDebug() << "MirSurface::~MirSurface() " << name();
45+}
46+
47+QString MirSurface::name() const
48+{
49+ return m_name;
50+}
51+
52+Mir::Type MirSurface::type() const
53+{
54+ return m_type;
55+}
56+
57+Mir::State MirSurface::state() const
58+{
59+ return m_state;
60+}
61+
62+void MirSurface::setState(Mir::State state)
63+{
64+ if (state == m_state)
65+ return;
66+
67+ m_state = state;
68+ Q_EMIT stateChanged(state);
69+}
70+
71+bool MirSurface::live() const
72+{
73+ return m_live;
74+}
75+
76+void MirSurface::setLive(bool live)
77+{
78+ qDebug().nospace() << "MirSurface::setLive("<<live<<") " << name();
79+ if (live == m_live)
80+ return;
81+
82+ m_live = live;
83+ Q_EMIT liveChanged(live);
84+
85+ if (!m_live && m_viewCount == 0) {
86+ deleteLater();
87+ }
88+}
89+
90+QString MirSurface::qmlFilePath() const
91+{
92+ return m_qmlFilePath;
93+}
94+
95+QUrl MirSurface::screenshotUrl() const
96+{
97+ return m_screenshotUrl;
98+}
99+
100+void MirSurface::setScreenshotUrl(QUrl screenshotUrl)
101+{
102+ if (screenshotUrl == m_screenshotUrl)
103+ return;
104+
105+ m_screenshotUrl = screenshotUrl;
106+ Q_EMIT screenshotUrlChanged(screenshotUrl);
107+}
108+
109+Mir::OrientationAngle MirSurface::orientationAngle() const
110+{
111+ return m_orientationAngle;
112+}
113+
114+void MirSurface::setOrientationAngle(Mir::OrientationAngle angle)
115+{
116+ if (angle == m_orientationAngle)
117+ return;
118+
119+ m_orientationAngle = angle;
120+ Q_EMIT orientationAngleChanged(angle);
121+}
122+
123+void MirSurface::incrementViewCount()
124+{
125+ ++m_viewCount;
126+ qDebug().nospace() << "MirSurface::incrementViewCount() viewCount(after)=" << m_viewCount << " " << name();
127+}
128+
129+void MirSurface::decrementViewCount()
130+{
131+ --m_viewCount;
132+ qDebug().nospace() << "MirSurface::decrementViewCount() viewCount(after)=" << m_viewCount << " " << name();
133+
134+ Q_ASSERT(m_viewCount >= 0);
135+
136+ if (!m_live && m_viewCount == 0) {
137+ deleteLater();
138+ }
139+}
140+
141+int MirSurface::viewCount() const
142+{
143+ return m_viewCount;
144+}
145+
146+bool MirSurface::activeFocus() const
147+{
148+ return m_activeFocus;
149+}
150+
151+void MirSurface::setActiveFocus(bool value)
152+{
153+ if (m_activeFocus == value)
154+ return;
155+
156+ m_activeFocus = value;
157+
158+ Q_EMIT activeFocusChanged(value);
159+}
160+
161+int MirSurface::width() const
162+{
163+ return m_width;
164+}
165+
166+int MirSurface::height() const
167+{
168+ return m_height;
169+}
170+
171+void MirSurface::resize(int width, int height)
172+{
173+ if (width != m_width) {
174+ m_width = width;
175+ Q_EMIT widthChanged();
176+ }
177+
178+ if (m_height != height) {
179+ m_height = height;
180+ Q_EMIT heightChanged();
181+ }
182+}
tests/mocks/Unity/Application/MirSurface.hnew file+113
@@ -0,0 +1,113 @@
1+/*
2+ * Copyright (C) 2015 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+#ifndef MOCK_MIR_SURFACE_H
18+#define MOCK_MIR_SURFACE_H
19+
20+#include <QObject>
21+#include <QUrl>
22+
23+// unity-api
24+#include <unity/shell/application/MirSurfaceInterface.h>
25+
26+class MirSurface : public unity::shell::application::MirSurfaceInterface
27+{
28+ Q_OBJECT
29+
30+ ////
31+ // for use in qml tests
32+ Q_PROPERTY(int width READ width NOTIFY widthChanged)
33+ Q_PROPERTY(int height READ height NOTIFY heightChanged)
34+ Q_PROPERTY(bool activeFocus READ activeFocus NOTIFY activeFocusChanged)
35+
36+public:
37+ MirSurface(const QString& name,
38+ Mir::Type type,
39+ Mir::State state,
40+ const QUrl& screenshot,
41+ const QString &qmlFilePath = QString());
42+ virtual ~MirSurface();
43+
44+ ////
45+ // unity.shell.application.MirSurface
46+
47+ Mir::Type type() const override;
48+
49+ QString name() const override;
50+
51+ QSize size() const override { return QSize(width(),height()); }
52+ void resize(int width, int height) override;
53+ void resize(const QSize &size) override { resize(size.width(), size.height()); }
54+
55+
56+ Mir::State state() const override;
57+ Q_INVOKABLE void setState(Mir::State) override;
58+
59+ bool live() const override;
60+
61+ Mir::OrientationAngle orientationAngle() const override;
62+ void setOrientationAngle(Mir::OrientationAngle) override;
63+
64+ ////
65+ // API for tests
66+
67+ Q_INVOKABLE void setLive(bool live);
68+
69+ void incrementViewCount();
70+ void decrementViewCount();
71+ int viewCount() const;
72+
73+ int width() const;
74+ int height() const;
75+
76+ /////
77+ // internal mock stuff
78+
79+ QString qmlFilePath() const;
80+
81+ QUrl screenshotUrl() const;
82+ void setScreenshotUrl(QUrl);
83+
84+ bool activeFocus() const;
85+ void setActiveFocus(bool);
86+
87+Q_SIGNALS:
88+ void stateChanged(Mir::State);
89+ void liveChanged(bool live);
90+ void orientationAngleChanged(Mir::OrientationAngle angle);
91+ void widthChanged();
92+ void heightChanged();
93+
94+ ////
95+ // internal mock stuff
96+ void screenshotUrlChanged(QUrl);
97+ void activeFocusChanged(bool);
98+
99+private:
100+ const QString m_name;
101+ const Mir::Type m_type;
102+ Mir::State m_state;
103+ Mir::OrientationAngle m_orientationAngle;
104+ QUrl m_screenshotUrl;
105+ QString m_qmlFilePath;
106+ bool m_live;
107+ int m_viewCount;
108+ bool m_activeFocus;
109+ int m_width;
110+ int m_height;
111+};
112+
113+#endif // MOCK_MIR_SURFACE_H
tests/mocks/Unity/Application/MirSurfaceItem.cpp+178−85
@@ -15,7 +15,6 @@
15 */
15 */
16
16
17#include "MirSurfaceItem.h"
17#include "MirSurfaceItem.h"
18−#include "Session.h"
19
18
20#include <paths.h>
19#include <paths.h>
21
20
@@ -27,69 +26,30 @@
27
26
28#include <QDebug>
27#include <QDebug>
29
28
30−MirSurfaceItem::MirSurfaceItem(const QString& name,
29+using namespace unity::shell::application;
31− MirSurfaceItem::Type type,
30+
32− MirSurfaceItem::State state,
33− const QUrl& screenshot,
34− const QString &qmlFilePath,
35− QQuickItem *parent)
31+MirSurfaceItem::MirSurfaceItem(QQuickItem *parent)
36− : QQuickItem(parent)
32+ : MirSurfaceItemInterface(parent)
37− , m_session(nullptr)
33+ , m_qmlSurface(nullptr)
38− , m_name(name)
39− , m_type(type)
40− , m_state(state)
41− , m_live(true)
42− , m_orientationAngle(Angle0)
43 , m_qmlItem(nullptr)
34 , m_qmlItem(nullptr)
44− , m_screenshotUrl(screenshot)
35+ , m_consumesInput(false)
36+ , m_surfaceWidth(0)
37+ , m_surfaceHeight(0)
45 , m_touchPressCount(0)
38 , m_touchPressCount(0)
46 , m_touchReleaseCount(0)
39 , m_touchReleaseCount(0)
47{
40{
41+ qDebug() << "MirSurfaceItem::MirSurfaceItem() " << (void*)(this) << name();
48 setAcceptedMouseButtons(Qt::LeftButton | Qt::MiddleButton | Qt::RightButton |
42 setAcceptedMouseButtons(Qt::LeftButton | Qt::MiddleButton | Qt::RightButton |
49 Qt::ExtraButton1 | Qt::ExtraButton2 | Qt::ExtraButton3 | Qt::ExtraButton4 |
43 Qt::ExtraButton1 | Qt::ExtraButton2 | Qt::ExtraButton3 | Qt::ExtraButton4 |
50 Qt::ExtraButton5 | Qt::ExtraButton6 | Qt::ExtraButton7 | Qt::ExtraButton8 |
44 Qt::ExtraButton5 | Qt::ExtraButton6 | Qt::ExtraButton7 | Qt::ExtraButton8 |
51 Qt::ExtraButton9 | Qt::ExtraButton10 | Qt::ExtraButton11 |
45 Qt::ExtraButton9 | Qt::ExtraButton10 | Qt::ExtraButton11 |
52 Qt::ExtraButton12 | Qt::ExtraButton13);
46 Qt::ExtraButton12 | Qt::ExtraButton13);
53−
54− QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
55−
56− // The assumptions I make here really should hold.
57− QQuickView *quickView =
58− qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
59−
60− QString qmlComponentFilePath;
61− if (!qmlFilePath.isEmpty()) {
62− qmlComponentFilePath.append(qmlFilePath);
63− } else {
64− qmlComponentFilePath = QString("%1/Unity/Application/MirSurfaceItem.qml")
65− .arg(mockPluginsDir());
66− }
67−
68− m_qmlContentComponent = new QQmlComponent(quickView->engine(), qmlComponentFilePath);
69−
70− switch (m_qmlContentComponent->status()) {
71− case QQmlComponent::Ready:
72− createQmlContentItem();
73− break;
74− case QQmlComponent::Loading:
75− connect(m_qmlContentComponent, &QQmlComponent::statusChanged,
76− this, &MirSurfaceItem::onComponentStatusChanged);
77− break;
78− case QQmlComponent::Error:
79− printComponentErrors();
80− qFatal("MirSurfaceItem: failed to create content component.");
81− break;
82− default:
83− qFatal("MirSurfaceItem: Unhandled component status");
84− }
85}
47}
86
48
87MirSurfaceItem::~MirSurfaceItem()
49MirSurfaceItem::~MirSurfaceItem()
88{
50{
89− qDebug() << "MirSurfaceItem::~MirSurfaceItem() " << name();
51+ qDebug() << "MirSurfaceItem::~MirSurfaceItem() " << (void*)(this) << name();
90− if (m_session) {
91− m_session->setSurface(nullptr);
52+ setSurface(nullptr);
92− }
93}
53}
94
54
95void MirSurfaceItem::printComponentErrors()
55void MirSurfaceItem::printComponentErrors()
@@ -100,58 +60,70 @@ void MirSurfaceItem::printComponentErrors()
100 }
60 }
101}
61}
102
62
103−void MirSurfaceItem::release()
63+Mir::Type MirSurfaceItem::type() const
104{
64{
105− qDebug() << "MirSurfaceItem::release " << name();
65+ if (m_qmlSurface) {
106−
66+ return m_qmlSurface->type();
107− if (m_session) {
67+ } else {
108− m_session->setSurface(nullptr);
68+ return Mir::UnknownType;
109− }
110− if (!parent()) {
111− deleteLater();
112 }
69 }
113}
70}
114
71
115−void MirSurfaceItem::setOrientationAngle(OrientationAngle angle)
72+Mir::State MirSurfaceItem::surfaceState() const
116{
73{
117− if (m_orientationAngle == angle)
74+ if (m_qmlSurface) {
118− return;
75+ return m_qmlSurface->state();
119−
76+ } else {
120− m_orientationAngle = angle;
77+ return Mir::UnknownState;
121−
78+ }
122− QQmlProperty orientationProp(m_qmlItem, "orientationAngle");
123− orientationProp.write(QVariant::fromValue(m_orientationAngle));
124−
125− Q_EMIT orientationAngleChanged(m_orientationAngle);
126}
79}
127
80
128−void MirSurfaceItem::setSession(Session* session)
81+QString MirSurfaceItem::name() const
129{
82{
130− m_session = session;
83+ if (m_qmlSurface) {
84+ return m_qmlSurface->name();
85+ } else {
86+ return QString();
87+ }
131}
88}
132
89
133−void MirSurfaceItem::setScreenshot(const QUrl& screenshot)
90+bool MirSurfaceItem::live() const
134{
91{
135− m_screenshotUrl = screenshot;
92+ if (m_qmlSurface) {
136− if (m_qmlItem) {
93+ return m_qmlSurface->live();
137− QQmlProperty screenshotSource(m_qmlItem, "screenshotSource");
94+ } else {
138− screenshotSource.write(QVariant::fromValue(m_screenshotUrl));
95+ return false;
139 }
96 }
140}
97}
141
98
142−void MirSurfaceItem::setLive(bool live)
99+Mir::OrientationAngle MirSurfaceItem::orientationAngle() const
143{
100{
144− if (m_live != live) {
101+ if (m_qmlSurface) {
145− m_live = live;
102+ return m_qmlSurface->orientationAngle();
146− Q_EMIT liveChanged(m_live);
103+ } else {
104+ return Mir::Angle0;
147 }
105 }
148}
106}
149
107
150−void MirSurfaceItem::setState(MirSurfaceItem::State newState)
108+void MirSurfaceItem::setOrientationAngle(Mir::OrientationAngle angle)
151{
109{
152− if (newState != m_state) {
110+ if (!m_qmlSurface)
153− m_state = newState;
111+ return;
154− Q_EMIT stateChanged(newState);
112+
113+ if (m_qmlSurface->orientationAngle() == angle)
114+ return;
115+
116+ m_qmlSurface->setOrientationAngle(angle);
117+
118+ QQmlProperty orientationProp(m_qmlItem, "orientationAngle");
119+ orientationProp.write(QVariant::fromValue(m_qmlSurface->orientationAngle()));
120+}
121+
122+void MirSurfaceItem::updateScreenshot(QUrl screenshotUrl)
123+{
124+ if (m_qmlItem) {
125+ QQmlProperty screenshotSource(m_qmlItem, "screenshotSource");
126+ screenshotSource.write(QVariant::fromValue(screenshotUrl));
155 }
127 }
156}
128}
157
129
@@ -174,7 +146,7 @@ void MirSurfaceItem::createQmlContentItem()
174
146
175 {
147 {
176 QQmlProperty screenshotSource(m_qmlItem, "screenshotSource");
148 QQmlProperty screenshotSource(m_qmlItem, "screenshotSource");
177− screenshotSource.write(QVariant::fromValue(m_screenshotUrl));
149+ screenshotSource.write(QVariant::fromValue(m_qmlSurface->screenshotUrl()));
178 }
150 }
179}
151}
180
152
@@ -188,3 +160,124 @@ void MirSurfaceItem::touchEvent(QTouchEvent * event)
188 Q_EMIT touchReleaseCountChanged(m_touchReleaseCount);
160 Q_EMIT touchReleaseCountChanged(m_touchReleaseCount);
189 }
161 }
190}
162}
163+
164+void MirSurfaceItem::setSurface(MirSurfaceInterface* surface)
165+{
166+ qDebug().nospace() << "MirSurfaceItem::setSurface() this=" << (void*)(this)
167+ << " name=" << name()
168+ << " surface=" << surface;
169+
170+ if (m_qmlSurface == surface) {
171+ return;
172+ }
173+
174+ if (m_qmlSurface) {
175+ delete m_qmlItem;
176+ m_qmlItem = nullptr;
177+
178+ delete m_qmlContentComponent;
179+ m_qmlContentComponent = nullptr;
180+
181+ disconnect(m_qmlSurface, nullptr, this, nullptr);
182+ m_qmlSurface->decrementViewCount();
183+ }
184+
185+ m_qmlSurface = static_cast<MirSurface*>(surface);
186+
187+ if (m_qmlSurface) {
188+ m_qmlSurface->incrementViewCount();
189+
190+ m_qmlSurface->setActiveFocus(hasActiveFocus());
191+
192+ updateSurfaceSize();
193+
194+ connect(m_qmlSurface, &MirSurface::orientationAngleChanged, this, &MirSurfaceItem::orientationAngleChanged);
195+ connect(m_qmlSurface, &MirSurface::screenshotUrlChanged, this, &MirSurfaceItem::updateScreenshot);
196+ connect(m_qmlSurface, &MirSurface::liveChanged, this, &MirSurfaceItem::liveChanged);
197+ connect(m_qmlSurface, &MirSurface::stateChanged, this, &MirSurfaceItem::surfaceStateChanged);
198+
199+ // The assumptions I make here really should hold.
200+ QQuickView *quickView =
201+ qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
202+
203+ QString qmlComponentFilePath;
204+ if (!m_qmlSurface->qmlFilePath().isEmpty()) {
205+ qmlComponentFilePath.append(m_qmlSurface->qmlFilePath());
206+ } else {
207+ qmlComponentFilePath = QString("%1/Unity/Application/MirSurfaceItem.qml")
208+ .arg(mockPluginsDir());
209+ }
210+
211+ m_qmlContentComponent = new QQmlComponent(quickView->engine(), qmlComponentFilePath);
212+
213+ switch (m_qmlContentComponent->status()) {
214+ case QQmlComponent::Ready:
215+ createQmlContentItem();
216+ break;
217+ case QQmlComponent::Loading:
218+ connect(m_qmlContentComponent, &QQmlComponent::statusChanged,
219+ this, &MirSurfaceItem::onComponentStatusChanged);
220+ break;
221+ case QQmlComponent::Error:
222+ printComponentErrors();
223+ qFatal("MirSurfaceItem: failed to create content component.");
224+ break;
225+ default:
226+ qFatal("MirSurfaceItem: Unhandled component status");
227+ }
228+ }
229+
230+ Q_EMIT surfaceChanged(m_qmlSurface);
231+}
232+
233+void MirSurfaceItem::itemChange(ItemChange change, const ItemChangeData & value)
234+{
235+ if (change == QQuickItem::ItemActiveFocusHasChanged) {
236+ if (m_qmlSurface) {
237+ m_qmlSurface->setActiveFocus(value.boolValue);
238+ }
239+ }
240+}
241+
242+void MirSurfaceItem::setConsumesInput(bool value)
243+{
244+ if (m_consumesInput != value) {
245+ m_consumesInput = value;
246+ Q_EMIT consumesInputChanged(value);
247+ }
248+}
249+
250+int MirSurfaceItem::surfaceWidth() const
251+{
252+ return m_surfaceWidth;
253+}
254+
255+void MirSurfaceItem::setSurfaceWidth(int value)
256+{
257+ if (m_surfaceWidth != value) {
258+ m_surfaceWidth = value;
259+ Q_EMIT surfaceWidthChanged(m_surfaceWidth);
260+ updateSurfaceSize();
261+ }
262+}
263+
264+int MirSurfaceItem::surfaceHeight() const
265+{
266+ return m_surfaceHeight;
267+}
268+
269+void MirSurfaceItem::setSurfaceHeight(int value)
270+{
271+ if (m_surfaceHeight != value) {
272+ m_surfaceHeight = value;
273+ Q_EMIT surfaceHeightChanged(m_surfaceHeight);
274+ updateSurfaceSize();
275+ }
276+}
277+
278+void MirSurfaceItem::updateSurfaceSize()
279+{
280+ if (m_qmlSurface && m_surfaceWidth > 0 && m_surfaceHeight > 0) {
281+ m_qmlSurface->resize(m_surfaceWidth, m_surfaceHeight);
282+ }
283+}
tests/mocks/Unity/Application/MirSurfaceItem.h+40−75
@@ -17,73 +17,54 @@
17#ifndef MIRSURFACEITEM_H
17#ifndef MIRSURFACEITEM_H
18#define MIRSURFACEITEM_H
18#define MIRSURFACEITEM_H
19
19
20−#include "MirSurfaceItemModel.h"
20+#include "MirSurface.h"
21
21
22#include <QQuickItem>
22#include <QQuickItem>
23#include <QUrl>
23#include <QUrl>
24
24
25−class Session;
25+// unity-api
26+#include <unity/shell/application/MirSurfaceItemInterface.h>
26
27
27−class MirSurfaceItem : public QQuickItem
28+class MirSurfaceItem : public unity::shell::application::MirSurfaceItemInterface
28{
29{
29 Q_OBJECT
30 Q_OBJECT
30− Q_ENUMS(Type)
31+
31− Q_ENUMS(State)
32+ ////
32− Q_ENUMS(OrientationAngle)
33+ // for use in qml tests
33−
34− Q_PROPERTY(Type type READ type NOTIFY typeChanged)
35− Q_PROPERTY(State state READ state NOTIFY stateChanged)
36− Q_PROPERTY(QString name READ name CONSTANT)
37− Q_PROPERTY(bool live READ live NOTIFY liveChanged)
38− Q_PROPERTY(OrientationAngle orientationAngle READ orientationAngle WRITE setOrientationAngle
39− NOTIFY orientationAngleChanged DESIGNABLE false)
40 Q_PROPERTY(int touchPressCount READ touchPressCount WRITE setTouchPressCount
34 Q_PROPERTY(int touchPressCount READ touchPressCount WRITE setTouchPressCount
41 NOTIFY touchPressCountChanged DESIGNABLE false)
35 NOTIFY touchPressCountChanged DESIGNABLE false)
42 Q_PROPERTY(int touchReleaseCount READ touchReleaseCount WRITE setTouchReleaseCount
36 Q_PROPERTY(int touchReleaseCount READ touchReleaseCount WRITE setTouchReleaseCount
43 NOTIFY touchReleaseCountChanged DESIGNABLE false)
37 NOTIFY touchReleaseCountChanged DESIGNABLE false)
44
38
45public:
39public:
46− enum Type {
40+ explicit MirSurfaceItem(QQuickItem *parent = 0);
47− Normal,
48− Utility,
49− Dialog,
50− Overlay,
51− Freestyle,
52− Popover,
53− InputMethod,
54− };
55−
56− enum State {
57− Unknown,
58− Restored,
59− Minimized,
60− Maximized,
61− VertMaximized,
62− /* SemiMaximized, */
63− Fullscreen,
64− };
65−
66− enum OrientationAngle {
67− Angle0 = 0,
68− Angle90 = 90,
69− Angle180 = 180,
70− Angle270 = 270
71− };
72−
73 ~MirSurfaceItem();
41 ~MirSurfaceItem();
74
42
75− //getters
76− Session* session() const { return m_session; }
77− Type type() const { return m_type; }
43+ Mir::Type type() const override;
78− State state() const { return m_state; }
79− QString name() const { return m_name; }
44+ QString name() const override;
80− bool live() const { return m_live; }
45+ bool live() const override;
46+
47+ Mir::State surfaceState() const override;
48+ void setSurfaceState(Mir::State) override {}
49+
81− OrientationAngle orientationAngle() const { return m_orientationAngle; }
50+ Mir::OrientationAngle orientationAngle() const override;
51+ void setOrientationAngle(Mir::OrientationAngle angle) override;
52+
53+ unity::shell::application::MirSurfaceInterface* surface() const override { return m_qmlSurface; }
54+ void setSurface(unity::shell::application::MirSurfaceInterface*) override;
55+
56+ bool consumesInput() const override { return m_consumesInput; }
57+ void setConsumesInput(bool value) override;
58+
59+ int surfaceWidth() const override;
60+ void setSurfaceWidth(int value) override;
82
61
83− void setOrientationAngle(OrientationAngle angle);
62+ int surfaceHeight() const override;
63+ void setSurfaceHeight(int value) override;
64+
65+ /////
66+ // For use in qml tests
84
67
85− void setSession(Session* item);
86− void setScreenshot(const QUrl& screenshot);
87 void setLive(bool live);
68 void setLive(bool live);
88
69
89 int touchPressCount() const { return m_touchPressCount; }
70 int touchPressCount() const { return m_touchPressCount; }
@@ -92,47 +73,32 @@ public:
92 int touchReleaseCount() const { return m_touchReleaseCount; }
73 int touchReleaseCount() const { return m_touchReleaseCount; }
93 void setTouchReleaseCount(int count) { m_touchReleaseCount = count; Q_EMIT touchReleaseCountChanged(count); }
74 void setTouchReleaseCount(int count) { m_touchReleaseCount = count; Q_EMIT touchReleaseCountChanged(count); }
94
75
95− Q_INVOKABLE void setState(State newState);
96− Q_INVOKABLE void release();
97−
98Q_SIGNALS:
76Q_SIGNALS:
99− void typeChanged(Type);
100− void stateChanged(State);
101− void liveChanged(bool live);
102− void orientationAngleChanged(OrientationAngle angle);
103 void touchPressCountChanged(int count);
77 void touchPressCountChanged(int count);
104 void touchReleaseCountChanged(int count);
78 void touchReleaseCountChanged(int count);
105
79
106− // internal mock use
107− void deregister();
108−
109protected:
80protected:
110− explicit MirSurfaceItem(const QString& name,
111− Type type,
112− State state,
113− const QUrl& screenshot,
114− const QString &qmlFilePath = QString(),
115− QQuickItem *parent = 0);
116−
117 void touchEvent(QTouchEvent * event) override;
81 void touchEvent(QTouchEvent * event) override;
82+ void itemChange(ItemChange change, const ItemChangeData & value) override;
118
83
119private Q_SLOTS:
84private Q_SLOTS:
120 void onComponentStatusChanged(QQmlComponent::Status status);
85 void onComponentStatusChanged(QQmlComponent::Status status);
86+ void updateScreenshot(QUrl screenshot);
121
87
122private:
88private:
123 void createQmlContentItem();
89 void createQmlContentItem();
124 void printComponentErrors();
90 void printComponentErrors();
91+ void updateSurfaceSize();
125
92
126− Session* m_session;
93+ MirSurface* m_qmlSurface;
127− const QString m_name;
128− const Type m_type;
129− State m_state;
130− bool m_live;
131− OrientationAngle m_orientationAngle;
132
94
133 QQmlComponent *m_qmlContentComponent;
95 QQmlComponent *m_qmlContentComponent;
134 QQuickItem *m_qmlItem;
96 QQuickItem *m_qmlItem;
135− QUrl m_screenshotUrl;
97+
98+ bool m_consumesInput;
99+
100+ int m_surfaceWidth;
101+ int m_surfaceHeight;
136
102
137 int m_touchPressCount;
103 int m_touchPressCount;
138 int m_touchReleaseCount;
104 int m_touchReleaseCount;
@@ -142,6 +108,5 @@ private:
142
108
143Q_DECLARE_METATYPE(MirSurfaceItem*)
109Q_DECLARE_METATYPE(MirSurfaceItem*)
144Q_DECLARE_METATYPE(QList<MirSurfaceItem*>)
110Q_DECLARE_METATYPE(QList<MirSurfaceItem*>)
145−Q_DECLARE_METATYPE(MirSurfaceItem::OrientationAngle)
146
111
147#endif // MIRSURFACEITEM_H
112#endif // MIRSURFACEITEM_H
tests/mocks/Unity/Application/MirSurfaceItem.qml+2
@@ -47,6 +47,7 @@ Rectangle {
47 y: surfaceText.y
47 y: surfaceText.y
48 width: surfaceText.width
48 width: surfaceText.width
49 height: surfaceText.height
49 height: surfaceText.height
50+ clip: true
50
51
51 transform: Translate { x: -2; y: -2 }
52 transform: Translate { x: -2; y: -2 }
52 }
53 }
@@ -58,6 +59,7 @@ Rectangle {
58 fontSizeMode: Text.Fit
59 fontSizeMode: Text.Fit
59 minimumPixelSize: 10; font.pixelSize: 200
60 minimumPixelSize: 10; font.pixelSize: 200
60 verticalAlignment: Text.AlignVCenter
61 verticalAlignment: Text.AlignVCenter
62+ clip: true
61
63
62 rotation: root.orientationAngle
64 rotation: root.orientationAngle
63 x: (parent.width - width) / 2
65 x: (parent.width - width) / 2
tests/mocks/Unity/Application/MirSurfaceItemModel.hdeleted−35
@@ -1,35 +0,0 @@
1−/*
2− * Copyright (C) 2014 Canonical, Ltd.
3− *
4− * This program is free software: you can redistribute it and/or modify it under
5− * the terms of the GNU Lesser General Public License version 3, as published by
6− * the Free Software Foundation.
7− *
8− * This program is distributed in the hope that it will be useful, but WITHOUT
9− * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10− * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11− * 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−
17−#ifndef MIRSURFACEITEMMODEL_H
18−#define MIRSURFACEITEMMODEL_H
19−
20−// Local
21−#include "ObjectListModel.h"
22−
23−class MirSurfaceItem;
24−class MirSurfaceItemModel: public ObjectListModel<MirSurfaceItem>
25−{
26− Q_OBJECT
27−public:
28− MirSurfaceItemModel(QObject *parent = 0): ObjectListModel(parent) {}
29−
30− Q_INVOKABLE int count() const { return rowCount(); }
31−};
32−
33−Q_DECLARE_METATYPE(MirSurfaceItemModel*)
34−
35−#endif // MIRSURFACEITEMMODEL_H
tests/mocks/Unity/Application/Session.cpp+22−22
@@ -54,23 +54,21 @@ Session::~Session()
54 if (m_application) {
54 if (m_application) {
55 m_application->setSession(nullptr);
55 m_application->setSession(nullptr);
56 }
56 }
57− delete m_surface;
58 delete m_children;
57 delete m_children;
58+
59+ if (m_surface) {
60+ if (m_surface->viewCount() == 0) {
61+ delete m_surface;
62+ } else {
63+ m_surface->setLive(false);
64+ }
65+ }
59}
66}
60
67
61void Session::release()
68void Session::release()
62{
69{
63 qDebug() << "Session::release " << name();
70 qDebug() << "Session::release " << name();
64−
65− if (m_parentSession) {
66− m_parentSession->removeChildSession(this);
67− }
68− if (m_application) {
69− m_application->setSession(nullptr);
70− }
71− if (!parent()) {
72− deleteLater();
71+ deleteLater();
73− }
74}
72}
75
73
76void Session::setApplication(ApplicationInfo* application)
74void Session::setApplication(ApplicationInfo* application)
@@ -82,35 +80,37 @@ void Session::setApplication(ApplicationInfo* application)
82 Q_EMIT applicationChanged(application);
80 Q_EMIT applicationChanged(application);
83}
81}
84
82
85−void Session::setSurface(MirSurfaceItem* surface)
83+void Session::setSurface(MirSurface* surface)
86{
84{
87 qDebug() << "Session::setSurface - session=" << name() << "surface=" << surface;
85 qDebug() << "Session::setSurface - session=" << name() << "surface=" << surface;
88 if (m_surface == surface)
86 if (m_surface == surface)
89 return;
87 return;
90
88
91 if (m_surface) {
89 if (m_surface) {
92− m_surface->setSession(nullptr);
93− m_surface->setParent(nullptr);
90+ disconnect(m_surface, nullptr, this, nullptr);
94− Q_EMIT m_surface->deregister();
95 }
91 }
96
92
97 m_surface = surface;
93 m_surface = surface;
98
94
99 if (m_surface) {
95 if (m_surface) {
100− m_surface->setSession(this);
96+ connect(m_surface, &QObject::destroyed, this, &Session::onSurfaceDestroyed);
101− m_surface->setParent(this);
102− SurfaceManager::singleton()->registerSurface(m_surface);
103 }
97 }
104
98
105 Q_EMIT surfaceChanged(m_surface);
99 Q_EMIT surfaceChanged(m_surface);
106}
100}
107
101
102+void Session::onSurfaceDestroyed()
103+{
104+ m_surface = nullptr;
105+ Q_EMIT surfaceChanged(nullptr);
106+}
107+
108void Session::setScreenshot(const QUrl& screenshot)
108void Session::setScreenshot(const QUrl& screenshot)
109{
109{
110 if (screenshot != m_screenshot) {
110 if (screenshot != m_screenshot) {
111 m_screenshot = screenshot;
111 m_screenshot = screenshot;
112 if (m_surface) {
112 if (m_surface) {
113− m_surface->setScreenshot(m_screenshot);
113+ m_surface->setScreenshotUrl(m_screenshot);
114 }
114 }
115 }
115 }
116}
116}
@@ -137,9 +137,9 @@ void Session::createSurface()
137 if (m_surface) return;
137 if (m_surface) return;
138
138
139 setSurface(SurfaceManager::singleton()->createSurface(name(),
139 setSurface(SurfaceManager::singleton()->createSurface(name(),
140− MirSurfaceItem::Normal,
140+ Mir::NormalType,
141− m_application && m_application->fullscreen() ? MirSurfaceItem::Fullscreen :
141+ m_application && m_application->fullscreen() ? Mir::FullscreenState :
142− MirSurfaceItem::Maximized,
142+ Mir::MaximizedState,
143 m_screenshot));
143 m_screenshot));
144}
144}
145
145
tests/mocks/Unity/Application/Session.h+10−6
@@ -22,13 +22,13 @@
22#include <QQuickItem>
22#include <QQuickItem>
23
23
24class ApplicationInfo;
24class ApplicationInfo;
25−class MirSurfaceItem;
25+class MirSurface;
26
26
27class Session : public QObject
27class Session : public QObject
28{
28{
29 Q_OBJECT
29 Q_OBJECT
30 Q_PROPERTY(QString name READ name CONSTANT)
30 Q_PROPERTY(QString name READ name CONSTANT)
31− Q_PROPERTY(MirSurfaceItem* surface READ surface NOTIFY surfaceChanged)
31+ Q_PROPERTY(MirSurface* surface READ surface NOTIFY surfaceChanged)
32 Q_PROPERTY(ApplicationInfo* application READ application NOTIFY applicationChanged)
32 Q_PROPERTY(ApplicationInfo* application READ application NOTIFY applicationChanged)
33 Q_PROPERTY(Session* parentSession READ parentSession NOTIFY parentSessionChanged DESIGNABLE false)
33 Q_PROPERTY(Session* parentSession READ parentSession NOTIFY parentSessionChanged DESIGNABLE false)
34 Q_PROPERTY(SessionModel* childSessions READ childSessions DESIGNABLE false CONSTANT)
34 Q_PROPERTY(SessionModel* childSessions READ childSessions DESIGNABLE false CONSTANT)
@@ -46,11 +46,11 @@ public:
46 QString name() const { return m_name; }
46 QString name() const { return m_name; }
47 bool live() const { return m_live; }
47 bool live() const { return m_live; }
48 ApplicationInfo* application() const { return m_application; }
48 ApplicationInfo* application() const { return m_application; }
49− MirSurfaceItem* surface() const { return m_surface; }
49+ MirSurface* surface() const { return m_surface; }
50 Session* parentSession() const { return m_parentSession; }
50 Session* parentSession() const { return m_parentSession; }
51
51
52 void setApplication(ApplicationInfo* item);
52 void setApplication(ApplicationInfo* item);
53− void setSurface(MirSurfaceItem* surface);
53+ void setSurface(MirSurface* surface);
54 void setScreenshot(const QUrl& m_screenshot);
54 void setScreenshot(const QUrl& m_screenshot);
55 void setLive(bool live);
55 void setLive(bool live);
56
56
@@ -60,7 +60,7 @@ public:
60
60
61Q_SIGNALS:
61Q_SIGNALS:
62 void applicationChanged(ApplicationInfo*);
62 void applicationChanged(ApplicationInfo*);
63− void surfaceChanged(MirSurfaceItem*);
63+ void surfaceChanged(MirSurface*);
64 void parentSessionChanged(Session*);
64 void parentSessionChanged(Session*);
65 void liveChanged(bool live);
65 void liveChanged(bool live);
66
66
@@ -70,6 +70,10 @@ Q_SIGNALS:
70public Q_SLOTS:
70public Q_SLOTS:
71 Q_INVOKABLE void createSurface();
71 Q_INVOKABLE void createSurface();
72
72
73+
74+private Q_SLOTS:
75+ void onSurfaceDestroyed();
76+
73private:
77private:
74 SessionModel* childSessions() const;
78 SessionModel* childSessions() const;
75 void setParentSession(Session* session);
79 void setParentSession(Session* session);
@@ -78,7 +82,7 @@ private:
78 bool m_live;
82 bool m_live;
79 QUrl m_screenshot;
83 QUrl m_screenshot;
80 ApplicationInfo* m_application;
84 ApplicationInfo* m_application;
81− MirSurfaceItem* m_surface;
85+ MirSurface* m_surface;
82 Session* m_parentSession;
86 Session* m_parentSession;
83 SessionModel* m_children;
87 SessionModel* m_children;
84
88
tests/mocks/Unity/Application/SurfaceManager.cpp+14−17
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2014 Canonical, Ltd.
2+ * Copyright (C) 2014-2015 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU General Public License as published by
@@ -36,31 +36,28 @@ SurfaceManager::SurfaceManager(QObject *parent) :
36{
36{
37}
37}
38
38
39−MirSurfaceItem *SurfaceManager::createSurface(const QString& name,
39+MirSurface *SurfaceManager::createSurface(const QString& name,
40− MirSurfaceItem::Type type,
40+ Mir::Type type,
41− MirSurfaceItem::State state,
41+ Mir::State state,
42 const QUrl& screenshot)
42 const QUrl& screenshot)
43{
43{
44− MirSurfaceItem* surface = new MirSurfaceItem(name, type, state, screenshot);
44+ MirSurface* surface = new MirSurface(name, type, state, screenshot);
45− Q_EMIT surfaceCreated(surface);
46− return surface;
47−}
48−
49−void SurfaceManager::registerSurface(MirSurfaceItem *surface)
50−{
51− connect(surface, &MirSurfaceItem::deregister, this, [this] {
45+ connect(surface, &QObject::destroyed, this, [this](QObject *obj) {
52− MirSurfaceItem* surface = qobject_cast<MirSurfaceItem*>(sender());
46+ MirSurface* surface = qobject_cast<MirSurface*>(obj);
53− disconnect(surface, 0, this, 0);
54−
55− surface->setLive(false);
56 Q_EMIT surfaceDestroyed(surface);
47 Q_EMIT surfaceDestroyed(surface);
57 });
48 });
49+ Q_EMIT surfaceCreated(surface);
50+ return surface;
58}
51}
59
52
60−MirSurfaceItem *SurfaceManager::inputMethodSurface()
53+MirSurface *SurfaceManager::inputMethodSurface()
61{
54{
62 if (!m_virtualKeyboard) {
55 if (!m_virtualKeyboard) {
63 m_virtualKeyboard = new VirtualKeyboard;
56 m_virtualKeyboard = new VirtualKeyboard;
57+ connect(m_virtualKeyboard, &QObject::destroyed, this, [this](QObject *obj) {
58+ MirSurface* surface = qobject_cast<MirSurface*>(obj);
59+ Q_EMIT surfaceDestroyed(surface);
60+ });
64 Q_EMIT surfaceCreated(m_virtualKeyboard);
61 Q_EMIT surfaceCreated(m_virtualKeyboard);
65 }
62 }
66 return m_virtualKeyboard;
63 return m_virtualKeyboard;
tests/mocks/Unity/Application/SurfaceManager.h+8−11
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2014 Canonical, Ltd.
2+ * Copyright (C) 2014-2015 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU General Public License as published by
@@ -19,7 +19,7 @@
19
19
20#include <QObject>
20#include <QObject>
21
21
22−#include "MirSurfaceItem.h"
22+#include "MirSurface.h"
23#include "VirtualKeyboard.h"
23#include "VirtualKeyboard.h"
24
24
25class SurfaceManager : public QObject
25class SurfaceManager : public QObject
@@ -30,21 +30,18 @@ public:
30
30
31 static SurfaceManager *singleton();
31 static SurfaceManager *singleton();
32
32
33− Q_INVOKABLE MirSurfaceItem *createSurface(const QString& name,
33+ Q_INVOKABLE MirSurface* createSurface(const QString& name,
34− MirSurfaceItem::Type type,
34+ Mir::Type type,
35− MirSurfaceItem::State state,
35+ Mir::State state,
36 const QUrl& screenshot);
36 const QUrl& screenshot);
37
37
38− // Internal mock use
39− void registerSurface(MirSurfaceItem *surface);
40−
41 // To be used in the tests
38 // To be used in the tests
42− Q_INVOKABLE MirSurfaceItem *inputMethodSurface();
39+ Q_INVOKABLE MirSurface* inputMethodSurface();
43
40
44Q_SIGNALS:
41Q_SIGNALS:
45 void countChanged();
42 void countChanged();
46− void surfaceCreated(MirSurfaceItem *surface);
43+ void surfaceCreated(MirSurface *surface);
47− void surfaceDestroyed(MirSurfaceItem *surface);
44+ void surfaceDestroyed(MirSurface*surface);
48
45
49private:
46private:
50 static SurfaceManager *the_surface_manager;
47 static SurfaceManager *the_surface_manager;
tests/mocks/Unity/Application/VirtualKeyboard.cpp+5−11
@@ -22,23 +22,17 @@
22
22
23#include <QDebug>
23#include <QDebug>
24
24
25−VirtualKeyboard::VirtualKeyboard(QQuickItem *parent)
25+VirtualKeyboard::VirtualKeyboard()
26− : MirSurfaceItem("input-method",
26+ : MirSurface("input-method",
27− MirSurfaceItem::InputMethod,
27+ Mir::InputMethodType,
28− MirSurfaceItem::Minimized,
28+ Mir::MinimizedState,
29 QString("file://%1/Dash/graphics/phone/screenshots/vkb_portrait.png")
29 QString("file://%1/Dash/graphics/phone/screenshots/vkb_portrait.png")
30 .arg(qmlDirectory()),
30 .arg(qmlDirectory()),
31 QString("%1/Unity/Application/VirtualKeyboard.qml")
31 QString("%1/Unity/Application/VirtualKeyboard.qml")
32− .arg(mockPluginsDir()),
32+ .arg(mockPluginsDir()))
33− parent)
34{
33{
35}
34}
36
35
37VirtualKeyboard::~VirtualKeyboard()
36VirtualKeyboard::~VirtualKeyboard()
38{
37{
39}
38}
40−
41−void VirtualKeyboard::touchEvent(QTouchEvent *event)
42−{
43− event->setAccepted(false);
44−}
tests/mocks/Unity/Application/VirtualKeyboard.h+3−11
@@ -17,26 +17,18 @@
17#ifndef VIRTUALKEYBOARD_H
17#ifndef VIRTUALKEYBOARD_H
18#define VIRTUALKEYBOARD_H
18#define VIRTUALKEYBOARD_H
19
19
20−#include "MirSurfaceItem.h"
20+#include "MirSurface.h"
21−#include "MirSurfaceItemModel.h"
22
21
23#include <QQuickItem>
22#include <QQuickItem>
24−#include <QUrl>
25
23
26−class Session;
27−
28−class VirtualKeyboard : public MirSurfaceItem
24+class VirtualKeyboard : public MirSurface
29{
25{
30 Q_OBJECT
26 Q_OBJECT
31public:
27public:
32− explicit VirtualKeyboard(QQuickItem *parent = 0);
28+ explicit VirtualKeyboard();
33 ~VirtualKeyboard();
29 ~VirtualKeyboard();
34−
35−protected:
36− void touchEvent(QTouchEvent * event) override;
37};
30};
38
31
39Q_DECLARE_METATYPE(VirtualKeyboard*)
32Q_DECLARE_METATYPE(VirtualKeyboard*)
40−Q_DECLARE_METATYPE(QList<VirtualKeyboard*>)
41
33
42#endif // VIRTUALKEYBOARD_H
34#endif // VIRTUALKEYBOARD_H
tests/mocks/Unity/Application/plugin.cpp+11−8
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2013-2014 Canonical, Ltd.
2+ * Copyright (C) 2013-2015 Canonical, Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU General Public License as published by
@@ -20,12 +20,14 @@
20#include "ApplicationScreenshotProvider.h"
20#include "ApplicationScreenshotProvider.h"
21#include "Session.h"
21#include "Session.h"
22#include "MirSurfaceItem.h"
22#include "MirSurfaceItem.h"
23−#include "MirSurfaceItemModel.h"
24#include "SurfaceManager.h"
23#include "SurfaceManager.h"
25#include "SessionManager.h"
24#include "SessionManager.h"
26#include "ApplicationTestInterface.h"
25#include "ApplicationTestInterface.h"
27#include "UbuntuKeyboardInfo.h"
26#include "UbuntuKeyboardInfo.h"
28
27
28+// unity-api
29+#include <unity/shell/application/Mir.h>
30+
29#include <qqml.h>
31#include <qqml.h>
30#include <QQmlEngine>
32#include <QQmlEngine>
31
33
@@ -67,14 +69,16 @@ void FakeUnityApplicationQmlPlugin::registerTypes(const char *uri)
67{
69{
68 qRegisterMetaType<Session*>("Session*");
70 qRegisterMetaType<Session*>("Session*");
69 qRegisterMetaType<ApplicationInfo*>("ApplicationInfo*");
71 qRegisterMetaType<ApplicationInfo*>("ApplicationInfo*");
70− qRegisterMetaType<MirSurfaceItemModel*>("SessionModel*");
72+ qRegisterMetaType<SessionModel*>("SessionModel*");
71− qRegisterMetaType<MirSurfaceItem*>("MirSurfaceItem*");
73+ qRegisterMetaType<unity::shell::application::MirSurfaceInterface*>("unity::shell::application::MirSurfaceInterface*");
72− qRegisterMetaType<MirSurfaceItemModel*>("MirSurfaceItemModel*");
74+ qRegisterMetaType<Mir::Type>("Mir::Type");
75+ qRegisterMetaType<Mir::State>("Mir::State");
73
76
74 qmlRegisterUncreatableType<unity::shell::application::ApplicationManagerInterface>(uri, 0, 1, "ApplicationManagerInterface", "Abstract interface. Cannot be created in QML");
77 qmlRegisterUncreatableType<unity::shell::application::ApplicationManagerInterface>(uri, 0, 1, "ApplicationManagerInterface", "Abstract interface. Cannot be created in QML");
75 qmlRegisterUncreatableType<unity::shell::application::ApplicationInfoInterface>(uri, 0, 1, "ApplicationInfoInterface", "Abstract interface. Cannot be created in QML");
78 qmlRegisterUncreatableType<unity::shell::application::ApplicationInfoInterface>(uri, 0, 1, "ApplicationInfoInterface", "Abstract interface. Cannot be created in QML");
76 qmlRegisterUncreatableType<Session>(uri, 0, 1, "Session", "Session can't be instantiated from QML");
79 qmlRegisterUncreatableType<Session>(uri, 0, 1, "Session", "Session can't be instantiated from QML");
77− qmlRegisterUncreatableType<MirSurfaceItem>(uri, 0, 1, "MirSurfaceItem", "MirSurfaceItem can't be instantiated from QML");
80+ qmlRegisterUncreatableType<MirSurface>(uri, 0, 1, "MirSurface", "MirSurface can't be instantiated from QML");
81+ qmlRegisterType<MirSurfaceItem>(uri, 0, 1, "MirSurfaceItem");
78
82
79 qmlRegisterType<ApplicationInfo>(uri, 0, 1, "ApplicationInfo");
83 qmlRegisterType<ApplicationInfo>(uri, 0, 1, "ApplicationInfo");
80
84
@@ -84,8 +88,7 @@ void FakeUnityApplicationQmlPlugin::registerTypes(const char *uri)
84 qmlRegisterSingletonType<ApplicationTestInterface>(uri, 0, 1, "ApplicationTest", applicationTestInterface);
88 qmlRegisterSingletonType<ApplicationTestInterface>(uri, 0, 1, "ApplicationTest", applicationTestInterface);
85 qmlRegisterSingletonType<UbuntuKeyboardInfo>(uri, 0, 1, "UbuntuKeyboardInfo", ubuntuKeyboardInfoSingleton);
89 qmlRegisterSingletonType<UbuntuKeyboardInfo>(uri, 0, 1, "UbuntuKeyboardInfo", ubuntuKeyboardInfoSingleton);
86
90
87− qRegisterMetaType<MirSurfaceItem::Type>("MirSurfaceItem::Type");
91+ qmlRegisterUncreatableType<Mir>(uri, 0, 1, "Mir", "Mir provides enum values, it can't be instantiated");
88− qRegisterMetaType<MirSurfaceItem::State>("MirSurfaceItem::State");
89}
92}
90
93
91void FakeUnityApplicationQmlPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
94void FakeUnityApplicationQmlPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
tests/qmltests/Stages/tst_ApplicationWindow.qml+39−29
@@ -45,16 +45,6 @@ Rectangle {
45 }
45 }
46 }
46 }
47
47
48− Component {
49− id: applicationWindowComponent
50− ApplicationWindow {
51− anchors.fill: parent
52− application: fakeApplication
53− surfaceOrientationAngle: 0
54− interactive: true
55− focus: true
56− }
57− }
58 Loader {
48 Loader {
59 id: applicationWindowLoader
49 id: applicationWindowLoader
60 focus: true
50 focus: true
@@ -64,7 +54,19 @@ Rectangle {
64 left: parent.left
54 left: parent.left
65 }
55 }
66 width: units.gu(40)
56 width: units.gu(40)
57+ property bool itemDestroyed: false
67− sourceComponent: applicationWindowComponent
58+ sourceComponent: Component {
59+ ApplicationWindow {
60+ anchors.fill: parent
61+ application: fakeApplication
62+ surfaceOrientationAngle: 0
63+ interactive: true
64+ focus: true
65+ Component.onDestruction: {
66+ applicationWindowLoader.itemDestroyed = true;
67+ }
68+ }
69+ }
68 }
70 }
69
71
70 Rectangle {
72 Rectangle {
@@ -87,13 +89,10 @@ Rectangle {
87 id: sessionCheckbox; checked: false
89 id: sessionCheckbox; checked: false
88 activeFocusOnPress: false
90 activeFocusOnPress: false
89 onCheckedChanged: {
91 onCheckedChanged: {
90− if (applicationWindowLoader.status !== Loader.Ready)
91− return;
92−
93 if (checked && !fakeApplication.session) {
92 if (checked && !fakeApplication.session) {
94 fakeApplication.createSession();
93 fakeApplication.createSession();
95 } else if (!checked && fakeApplication.session) {
94 } else if (!checked && fakeApplication.session) {
96− fakeApplication.session.release();
95+ fakeApplication.destroySession();
97 }
96 }
98 }
97 }
99 }
98 }
@@ -218,21 +217,29 @@ Rectangle {
218 sessionCheckbox.checked = true;
217 sessionCheckbox.checked = true;
219 sessionControl.surfaceCheckbox.checked = true;
218 sessionControl.surfaceCheckbox.checked = true;
220 }
219 }
221− function cleanupSession() {
222− sessionCheckbox.checked = false;
223− }
224
220
225 function cleanup() {
221 function cleanup() {
226 forgetApplicationWindowChildren();
222 forgetApplicationWindowChildren();
227
223
224+ applicationWindowLoader.itemDestroyed = false;
225+
228 // reload our test subject to get it in a fresh state once again
226 // reload our test subject to get it in a fresh state once again
229 applicationWindowLoader.active = false;
227 applicationWindowLoader.active = false;
230
228
231− appStateSelector.selectedIndex = 0;
229+ tryCompare(applicationWindowLoader, "status", Loader.Null);
232− cleanupSession();
230+ tryCompare(applicationWindowLoader, "item", null);
231+ // Loader.status might be Loader.Null and Loader.item might be null but the Loader
232+ // item might still be alive. So if we set Loader.active back to true
233+ // again right now we will get the very same ApplicationWindow instance back. So no reload
234+ // actually took place. Likely because Loader waits until the next event loop
235+ // iteration to do its work. So to ensure the reload, we will wait until the
236+ // ApplicationWindow instance gets destroyed.
237+ // Another thing that happens is that we do get a new object but the old one doesn't get
238+ // deleted, so you end up with two instances in memory.
239+ tryCompare(applicationWindowLoader, "itemDestroyed", true);
233
240
234− if (fakeApplication.session)
241+ appStateSelector.selectedIndex = 0;
235− fakeApplication.session.release();
242+ sessionCheckbox.checked = false;
236
243
237 applicationWindowLoader.active = true;
244 applicationWindowLoader.active = true;
238 }
245 }
@@ -372,15 +379,18 @@ Rectangle {
372
379
373 waitUntilTransitionsEnd(stateGroup);
380 waitUntilTransitionsEnd(stateGroup);
374
381
382+ var surfaceItem = findChild(applicationWindowLoader.item, "surfaceItem");
383+ verify(surfaceItem);
375− var fakeSurface = fakeSession.surface;
384+ verify(surfaceItem.surface === fakeSession.surface);
385+
376− fakeSurface.touchPressCount = 0;
386+ surfaceItem.touchPressCount = 0;
377− fakeSurface.touchReleaseCount = 0;
387+ surfaceItem.touchReleaseCount = 0;
378
388
379 tap(applicationWindowLoader.item,
389 tap(applicationWindowLoader.item,
380 applicationWindowLoader.item.width / 2, applicationWindowLoader.item.height / 2);
390 applicationWindowLoader.item.width / 2, applicationWindowLoader.item.height / 2);
381
391
382− verify(fakeSurface.touchPressCount === 1);
392+ verify(surfaceItem.touchPressCount === 1);
383− verify(fakeSurface.touchReleaseCount === 1);
393+ verify(surfaceItem.touchReleaseCount === 1);
384 }
394 }
385
395
386 function test_showNothingOnSuddenSurfaceLoss() {
396 function test_showNothingOnSuddenSurfaceLoss() {
@@ -389,9 +399,9 @@ Rectangle {
389 tryCompare(stateGroup, "state", "surface");
399 tryCompare(stateGroup, "state", "surface");
390 waitUntilTransitionsEnd(stateGroup);
400 waitUntilTransitionsEnd(stateGroup);
391
401
392− cleanupSession();
402+ sessionControl.surfaceCheckbox.checked = false;
393
403
394− verify(stateGroup.state === "void");
404+ tryCompare(stateGroup, "state", "void");
395 }
405 }
396
406
397 function test_surfaceActiveFocusFollowsAppWindowInterative() {
407 function test_surfaceActiveFocusFollowsAppWindowInterative() {
tests/qmltests/Stages/tst_SurfaceContainer.qml+26−32
@@ -70,12 +70,12 @@ Rectangle {
70
70
71 if (checked) {
71 if (checked) {
72 var fakeSurface = SurfaceManager.createSurface("fake-surface",
72 var fakeSurface = SurfaceManager.createSurface("fake-surface",
73− MirSurfaceItem.Normal,
73+ Mir.NormalType,
74− MirSurfaceItem.Restored,
74+ Mir.RestoredState,
75 Qt.resolvedUrl("../Dash/artwork/music-player-design.png"));
75 Qt.resolvedUrl("../Dash/artwork/music-player-design.png"));
76 surfaceContainerLoader.item.surface = fakeSurface;
76 surfaceContainerLoader.item.surface = fakeSurface;
77 } else {
77 } else {
78− ApplicationTest.removeSurface(surfaceContainerLoader.item.surface);
78+ surfaceContainerLoader.item.surface.setLive(false);
79 }
79 }
80 }
80 }
81 }
81 }
@@ -121,70 +121,64 @@ Rectangle {
121 interactiveCheckbox.checked = true;
121 interactiveCheckbox.checked = true;
122 }
122 }
123
123
124− /*
125− Add a first surface. Then remove it. Then add a second surface.
126− That second surface should be properly sized.
127−
128− Regression test for https://bugs.launchpad.net/ubuntu/+source/qtmir/+bug/1359819
129− */
130− function test_resetSurfaceGetsProperlySized() {
131− surfaceCheckbox.checked = true;
132− surfaceCheckbox.checked = false;
133− surfaceCheckbox.checked = true;
134− var fakeSurface = surfaceContainerLoader.item.surface;
135− compare(fakeSurface.width, surfaceContainerLoader.item.width);
136− compare(fakeSurface.height, surfaceContainerLoader.item.height);
137− }
138−
139 function test_animateRemoval() {
124 function test_animateRemoval() {
140 surfaceCheckbox.checked = true;
125 surfaceCheckbox.checked = true;
141
126
142 verify(surfaceContainer.surface !== null);
127 verify(surfaceContainer.surface !== null);
143
128
144− ApplicationTest.removeSurface(surfaceContainer.surface);
129+ surfaceContainer.surface.setLive(false);
145
130
146 compare(surfaceContainer.state, "zombie");
131 compare(surfaceContainer.state, "zombie");
147 tryCompare(surfaceContainer, "surface", null);
132 tryCompare(surfaceContainer, "surface", null);
148 }
133 }
149
134
150− function test_surfaceGetsNoTouchesWhenContainerNotInteractive() {
135+ function test_surfaceItemGetsNoTouchesWhenContainerNotInteractive() {
151 surfaceCheckbox.checked = true;
136 surfaceCheckbox.checked = true;
152 verify(surfaceContainer.surface !== null);
137 verify(surfaceContainer.surface !== null);
153
138
139+ var surfaceItem = findChild(surfaceContainer, "surfaceItem");
140+ verify(surfaceItem !== null);
141+
154− surfaceContainer.surface.touchPressCount = 0;
142+ surfaceItem.touchPressCount = 0;
155− surfaceContainer.surface.touchReleaseCount = 0;
143+ surfaceItem.touchReleaseCount = 0;
156
144
157 tap(surfaceContainer, surfaceContainer.width / 2, surfaceContainer.height / 2);
145 tap(surfaceContainer, surfaceContainer.width / 2, surfaceContainer.height / 2);
158
146
159 // surface got touches as the surfaceContainer is interactive
147 // surface got touches as the surfaceContainer is interactive
160− compare(surfaceContainer.surface.touchPressCount, 1)
148+ compare(surfaceItem.touchPressCount, 1)
161− compare(surfaceContainer.surface.touchReleaseCount, 1);
149+ compare(surfaceItem.touchReleaseCount, 1);
162
150
163 interactiveCheckbox.checked = false;
151 interactiveCheckbox.checked = false;
164 tap(surfaceContainer, surfaceContainer.width / 2, surfaceContainer.height / 2);
152 tap(surfaceContainer, surfaceContainer.width / 2, surfaceContainer.height / 2);
165
153
166 // surface shouldn't get the touches from the second tap as the surfaceContainer
154 // surface shouldn't get the touches from the second tap as the surfaceContainer
167 // was *not* interactive when it happened.
155 // was *not* interactive when it happened.
168− compare(surfaceContainer.surface.touchPressCount, 1)
156+ compare(surfaceItem.touchPressCount, 1)
169− compare(surfaceContainer.surface.touchReleaseCount, 1);
157+ compare(surfaceItem.touchReleaseCount, 1);
170 }
158 }
171
159
172− function test_surfaceGetsActiveFocusOnMousePress() {
160+ function test_surfaceItemGetsActiveFocusOnMousePress() {
173 surfaceCheckbox.checked = true;
161 surfaceCheckbox.checked = true;
174 verify(surfaceContainer.surface !== null);
162 verify(surfaceContainer.surface !== null);
175
163
164+ var surfaceItem = findChild(surfaceContainer, "surfaceItem");
165+ verify(surfaceItem !== null);
166+
176− compare(surfaceContainer.surface.activeFocus, false);
167+ compare(surfaceItem.activeFocus, false);
177 mouseClick(surfaceContainer);
168 mouseClick(surfaceContainer);
178− compare(surfaceContainer.surface.activeFocus, true);
169+ compare(surfaceItem.activeFocus, true);
179 }
170 }
180
171
181− function test_surfaceGetsActiveFocusOnTap() {
172+ function test_surfaceItemGetsActiveFocusOnTap() {
182 surfaceCheckbox.checked = true;
173 surfaceCheckbox.checked = true;
183 verify(surfaceContainer.surface !== null);
174 verify(surfaceContainer.surface !== null);
184
175
176+ var surfaceItem = findChild(surfaceContainer, "surfaceItem");
177+ verify(surfaceItem !== null);
178+
185− compare(surfaceContainer.surface.activeFocus, false);
179+ compare(surfaceItem.activeFocus, false);
186 tap(surfaceContainer);
180 tap(surfaceContainer);
187− compare(surfaceContainer.surface.activeFocus, true);
181+ compare(surfaceItem.activeFocus, true);
188 }
182 }
189 }
183 }
190}
184}
tests/qmltests/tst_OrientedShell.qml+28−20
@@ -280,9 +280,9 @@ Rectangle {
280 onCheckedChanged: {
280 onCheckedChanged: {
281 var surface = SurfaceManager.inputMethodSurface();
281 var surface = SurfaceManager.inputMethodSurface();
282 if (checked) {
282 if (checked) {
283− surface.setState(MirSurfaceItem.Restored);
283+ surface.setState(Mir.RestoredState);
284 } else {
284 } else {
285− surface.setState(MirSurfaceItem.Minimized);
285+ surface.setState(Mir.MinimizedState);
286 }
286 }
287 }
287 }
288 }
288 }
@@ -415,22 +415,22 @@ Rectangle {
415 compare(dashApp.stage, ApplicationInfoInterface.MainStage);
415 compare(dashApp.stage, ApplicationInfoInterface.MainStage);
416
416
417 tryCompareFunction(function(){return dashApp.session.surface != null;}, true);
417 tryCompareFunction(function(){return dashApp.session.surface != null;}, true);
418− verify(checkAppSurfaceOrientation(dashApp, root.primaryOrientationAngle));
418+ verify(checkAppSurfaceOrientation(dashAppWindow, dashApp, root.primaryOrientationAngle));
419
419
420 compare(shell.transformRotationAngle, root.primaryOrientationAngle);
420 compare(shell.transformRotationAngle, root.primaryOrientationAngle);
421 rotateTo(90);
421 rotateTo(90);
422
422
423− verify(checkAppSurfaceOrientation(dashApp, root.primaryOrientationAngle));
423+ verify(checkAppSurfaceOrientation(dashAppWindow, dashApp, root.primaryOrientationAngle));
424 compare(shell.transformRotationAngle, root.primaryOrientationAngle);
424 compare(shell.transformRotationAngle, root.primaryOrientationAngle);
425
425
426 rotateTo(180);
426 rotateTo(180);
427
427
428− verify(checkAppSurfaceOrientation(dashApp, root.primaryOrientationAngle));
428+ verify(checkAppSurfaceOrientation(dashAppWindow, dashApp, root.primaryOrientationAngle));
429 compare(shell.transformRotationAngle, root.primaryOrientationAngle);
429 compare(shell.transformRotationAngle, root.primaryOrientationAngle);
430
430
431 rotateTo(270);
431 rotateTo(270);
432
432
433− verify(checkAppSurfaceOrientation(dashApp, root.primaryOrientationAngle));
433+ verify(checkAppSurfaceOrientation(dashAppWindow, dashApp, root.primaryOrientationAngle));
434 compare(shell.transformRotationAngle, root.primaryOrientationAngle);
434 compare(shell.transformRotationAngle, root.primaryOrientationAngle);
435 }
435 }
436
436
@@ -1200,18 +1200,13 @@ Rectangle {
1200 }
1200 }
1201
1201
1202 // expectedAngle is in orientedShell's coordinate system
1202 // expectedAngle is in orientedShell's coordinate system
1203− function checkAppSurfaceOrientation(app, expectedAngle) {
1203+ function checkAppSurfaceOrientation(item, app, expectedAngle) {
1204 var surface = app.session.surface;
1204 var surface = app.session.surface;
1205 if (!surface) {
1205 if (!surface) {
1206 console.warn("no surface");
1206 console.warn("no surface");
1207 return false;
1207 return false;
1208 }
1208 }
1209
1209
1210− if (!itemIsChildOfOrientedShell(surface)) {
1211− console.warn("surface not a child of OrientedShell");
1212− return false;
1213− }
1214−
1215 var topMargin = 0.;
1210 var topMargin = 0.;
1216 if (!app.fullscreen) {
1211 if (!app.fullscreen) {
1217 var appsDisplayLoader = findChild(shell, "applicationsDisplayLoader");
1212 var appsDisplayLoader = findChild(shell, "applicationsDisplayLoader");
@@ -1221,7 +1216,12 @@ Rectangle {
1221 topMargin = appsDisplayLoader.item.maximizedAppTopMargin;
1216 topMargin = appsDisplayLoader.item.maximizedAppTopMargin;
1222 }
1217 }
1223
1218
1219+ var surfaceItem = findSurfaceItem(item, surface);
1220+ if (!surfaceItem) {
1221+ console.warn("no surfaceItem rendering app surface");
1222+ return false;
1223+ }
1224− var point = surface.mapToItem(orientedShell, 0, 0);
1224+ var point = surfaceItem.mapToItem(orientedShell, 0, 0);
1225
1225
1226 switch (expectedAngle) {
1226 switch (expectedAngle) {
1227 case 0:
1227 case 0:
@@ -1235,14 +1235,22 @@ Rectangle {
1235 }
1235 }
1236 }
1236 }
1237
1237
1238− function itemIsChildOfOrientedShell(item) {
1238+ function findSurfaceItem(obj, surface) {
1239− var parent = item.parent;
1239+ var childs = new Array(0);
1240− var found = false;
1240+ childs.push(obj)
1241− while (parent && !found) {
1241+ while (childs.length > 0) {
1242− found = parent === orientedShell;
1242+ console.log("Checking " + childs[0].objectName);
1243− parent = parent.parent;
1243+ if (childs[0].objectName === "surfaceItem"
1244+ && childs[0].surface !== undefined
1245+ && childs[0].surface === surface) {
1246+ return childs[0];
1247+ }
1248+ for (var i in childs[0].children) {
1249+ childs.push(childs[0].children[i])
1250+ }
1251+ childs.splice(0, 1);
1244 }
1252 }
1245− return found;
1253+ return null;
1246 }
1254 }
1247 }
1255 }
1248}
1256}
tests/qmltests/tst_Shell.qml+16−16
@@ -726,19 +726,19 @@ Rectangle {
726 var item = findChild(shell, "inputMethod");
726 var item = findChild(shell, "inputMethod");
727 var surface = SurfaceManager.inputMethodSurface();
727 var surface = SurfaceManager.inputMethodSurface();
728
728
729− surface.setState(MirSurfaceItem.Minimized);
729+ surface.setState(Mir.MinimizedState);
730 tryCompare(item, "visible", false);
730 tryCompare(item, "visible", false);
731
731
732− surface.setState(MirSurfaceItem.Restored);
732+ surface.setState(Mir.RestoredState);
733 tryCompare(item, "visible", true);
733 tryCompare(item, "visible", true);
734
734
735− surface.setState(MirSurfaceItem.Minimized);
735+ surface.setState(Mir.MinimizedState);
736 tryCompare(item, "visible", false);
736 tryCompare(item, "visible", false);
737
737
738− surface.setState(MirSurfaceItem.Maximized);
738+ surface.setState(Mir.MaximizedState);
739 tryCompare(item, "visible", true);
739 tryCompare(item, "visible", true);
740
740
741− surface.setState(MirSurfaceItem.Minimized);
741+ surface.setState(Mir.MinimizedState);
742 tryCompare(item, "visible", false);
742 tryCompare(item, "visible", false);
743 }
743 }
744
744
@@ -1112,20 +1112,20 @@ Rectangle {
1112
1112
1113 waitUntilFocusedApplicationIsShowingItsSurface();
1113 waitUntilFocusedApplicationIsShowingItsSurface();
1114
1114
1115− var topmostSurface = findChild(topmostSpreadDelegate, "surfaceContainer").surface;
1115+ var topmostSurfaceItem = findChild(topmostSpreadDelegate, "surfaceItem");
1116− verify(topmostSurface);
1116+ verify(topmostSurfaceItem);
1117
1117
1118 var rightEdgeDragArea = findChild(shell, "spreadDragArea");
1118 var rightEdgeDragArea = findChild(shell, "spreadDragArea");
1119− topmostSurface.touchPressCount = 0;
1119+ topmostSurfaceItem.touchPressCount = 0;
1120− topmostSurface.touchReleaseCount = 0;
1120+ topmostSurfaceItem.touchReleaseCount = 0;
1121
1121
1122 var tapPoint = rightEdgeDragArea.mapToItem(shell, rightEdgeDragArea.width / 2,
1122 var tapPoint = rightEdgeDragArea.mapToItem(shell, rightEdgeDragArea.width / 2,
1123 rightEdgeDragArea.height / 2);
1123 rightEdgeDragArea.height / 2);
1124
1124
1125 tap(shell, tapPoint.x, tapPoint.y);
1125 tap(shell, tapPoint.x, tapPoint.y);
1126
1126
1127− tryCompare(topmostSurface, "touchPressCount", 1);
1127+ tryCompare(topmostSurfaceItem, "touchPressCount", 1);
1128− tryCompare(topmostSurface, "touchReleaseCount", 1);
1128+ tryCompare(topmostSurfaceItem, "touchReleaseCount", 1);
1129 }
1129 }
1130
1130
1131 /*
1131 /*
@@ -1137,11 +1137,11 @@ Rectangle {
1137 loadShell("phone");
1137 loadShell("phone");
1138 swipeAwayGreeter();
1138 swipeAwayGreeter();
1139 var topmostSpreadDelegate = findChild(shell, "appDelegate0");
1139 var topmostSpreadDelegate = findChild(shell, "appDelegate0");
1140− var topmostSurface = findChild(topmostSpreadDelegate, "surfaceContainer").surface;
1140+ var topmostSurfaceItem = findChild(topmostSpreadDelegate, "surfaceItem");
1141 var rightEdgeDragArea = findChild(shell, "spreadDragArea");
1141 var rightEdgeDragArea = findChild(shell, "spreadDragArea");
1142
1142
1143− topmostSurface.touchPressCount = 0;
1143+ topmostSurfaceItem.touchPressCount = 0;
1144− topmostSurface.touchReleaseCount = 0;
1144+ topmostSurfaceItem.touchReleaseCount = 0;
1145
1145
1146 var gestureStartPoint = rightEdgeDragArea.mapToItem(shell, rightEdgeDragArea.width / 2,
1146 var gestureStartPoint = rightEdgeDragArea.mapToItem(shell, rightEdgeDragArea.width / 2,
1147 rightEdgeDragArea.height / 2);
1147 rightEdgeDragArea.height / 2);
@@ -1150,8 +1150,8 @@ Rectangle {
1150 gestureStartPoint.x /* fromX */, gestureStartPoint.y /* fromY */,
1150 gestureStartPoint.x /* fromX */, gestureStartPoint.y /* fromY */,
1151 units.gu(1) /* toX */, gestureStartPoint.y /* toY */);
1151 units.gu(1) /* toX */, gestureStartPoint.y /* toY */);
1152
1152
1153− tryCompare(topmostSurface, "touchPressCount", 0);
1153+ tryCompare(topmostSurfaceItem, "touchPressCount", 0);
1154− tryCompare(topmostSurface, "touchReleaseCount", 0);
1154+ tryCompare(topmostSurfaceItem, "touchReleaseCount", 0);
1155 }
1155 }
1156
1156
1157 function waitUntilFocusedApplicationIsShowingItsSurface()
1157 function waitUntilFocusedApplicationIsShowingItsSurface()