on xenial help sign in
merge lp:~mzanetti/unity8/launcher-surfaceCount-pips
8beb548Lukáš Tinkl
CMakeLists.txt+1−1
@@ -57,7 +57,7 @@ find_package(Qt5DBus 5.4 REQUIRED)
57find_package(Qt5Concurrent 5.4 REQUIRED)
57find_package(Qt5Concurrent 5.4 REQUIRED)
58find_package(Qt5Sql 5.4 REQUIRED)
58find_package(Qt5Sql 5.4 REQUIRED)
59
59
60−pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=17)
60+pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=18)
61pkg_check_modules(GEONAMES REQUIRED geonames>=0.2)
61pkg_check_modules(GEONAMES REQUIRED geonames>=0.2)
62pkg_check_modules(GIO REQUIRED gio-2.0>=2.32)
62pkg_check_modules(GIO REQUIRED gio-2.0>=2.32)
63pkg_check_modules(GLIB REQUIRED glib-2.0>=2.32)
63pkg_check_modules(GLIB REQUIRED glib-2.0>=2.32)
debian/control+1−1
@@ -32,7 +32,7 @@ Build-Depends: cmake,
32 libubuntugestures5-dev,
32 libubuntugestures5-dev,
33 libubuntugestures5-private-dev,
33 libubuntugestures5-private-dev,
34 libudev-dev,
34 libudev-dev,
35− libunity-api-dev (>= 7.113),
35+ libunity-api-dev (>= 7.114),
36 libusermetricsoutput1-dev,
36 libusermetricsoutput1-dev,
37# Need those X11 libs touch emulation from mouse events in manual QML tests on a X11 desktop
37# Need those X11 libs touch emulation from mouse events in manual QML tests on a X11 desktop
38 libx11-dev[!armhf],
38 libx11-dev[!armhf],
plugins/Greeter/Unity/Launcher/CMakeLists.txt+1−1
@@ -1,4 +1,4 @@
1−pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=7)
1+pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=8)
2pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt)
2pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt)
3
3
4add_definitions(-DSM_BUSNAME=systemBus)
4add_definitions(-DSM_BUSNAME=systemBus)
plugins/Greeter/Unity/Launcher/launcheritem.cpp+14
@@ -32,6 +32,7 @@ LauncherItem::LauncherItem(const QString &appId, const QString &name, const QStr
32 m_countVisible(false),
32 m_countVisible(false),
33 m_focused(false),
33 m_focused(false),
34 m_alerting(false),
34 m_alerting(false),
35+ m_surfaceCount(0),
35 m_quickList(new QuickListModel(this))
36 m_quickList(new QuickListModel(this))
36{
37{
37 QuickListEntry nameAction;
38 QuickListEntry nameAction;
@@ -179,6 +180,19 @@ void LauncherItem::setAlerting(bool alerting)
179 }
180 }
180}
181}
181
182
183+int LauncherItem::surfaceCount() const
184+{
185+ return m_surfaceCount;
186+}
187+
188+void LauncherItem::setSurfaceCount(int surfaceCount)
189+{
190+ if (m_surfaceCount != surfaceCount) {
191+ m_surfaceCount = surfaceCount;
192+ Q_EMIT surfaceCountChanged(surfaceCount);
193+ }
194+}
195+
182unity::shell::launcher::QuickListModelInterface *LauncherItem::quickList() const
196unity::shell::launcher::QuickListModelInterface *LauncherItem::quickList() const
183{
197{
184 return m_quickList;
198 return m_quickList;
plugins/Greeter/Unity/Launcher/launcheritem.h+3−1
@@ -42,6 +42,7 @@ public:
42 bool countVisible() const override;
42 bool countVisible() const override;
43 bool focused() const override;
43 bool focused() const override;
44 bool alerting() const override;
44 bool alerting() const override;
45+ int surfaceCount() const override;
45
46
46 unity::shell::launcher::QuickListModelInterface *quickList() const override;
47 unity::shell::launcher::QuickListModelInterface *quickList() const override;
47
48
@@ -56,7 +57,7 @@ private:
56 void setCountVisible(bool countVisible);
57 void setCountVisible(bool countVisible);
57 void setFocused(bool focused);
58 void setFocused(bool focused);
58 void setAlerting(bool alerting);
59 void setAlerting(bool alerting);
59−
60+ void setSurfaceCount(int surfaceCount);
60
61
61private:
62private:
62 QString m_appId;
63 QString m_appId;
@@ -70,6 +71,7 @@ private:
70 bool m_countVisible;
71 bool m_countVisible;
71 bool m_focused;
72 bool m_focused;
72 bool m_alerting;
73 bool m_alerting;
74+ int m_surfaceCount;
73 QuickListModel *m_quickList;
75 QuickListModel *m_quickList;
74
76
75 friend class LauncherModel;
77 friend class LauncherModel;
plugins/Greeter/Unity/Launcher/launchermodelas.cpp+2
@@ -69,6 +69,8 @@ QVariant LauncherModel::data(const QModelIndex &index, int role) const
69 return item->focused();
69 return item->focused();
70 case RoleRunning:
70 case RoleRunning:
71 return item->running();
71 return item->running();
72+ case RoleSurfaceCount:
73+ return item->surfaceCount();
72 }
74 }
73
75
74 return QVariant();
76 return QVariant();
plugins/Unity/Launcher/CMakeLists.txt+3−1
@@ -1,4 +1,4 @@
1−pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=7)
1+pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=8)
2pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt)
2pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt)
3
3
4add_definitions(-DSM_BUSNAME=systemBus)
4add_definitions(-DSM_BUSNAME=systemBus)
@@ -23,6 +23,8 @@ set(QMLLAUNCHERPLUGIN_SRC
23 asadapter.cpp
23 asadapter.cpp
24 ${CMAKE_SOURCE_DIR}/plugins/AccountsService/AccountsServiceDBusAdaptor.cpp
24 ${CMAKE_SOURCE_DIR}/plugins/AccountsService/AccountsServiceDBusAdaptor.cpp
25 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationManagerInterface.h
25 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationManagerInterface.h
26+ ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
27+ ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/MirSurfaceListInterface.h
26 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherItemInterface.h
28 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherItemInterface.h
27 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherModelInterface.h
29 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/LauncherModelInterface.h
28 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/QuickListModelInterface.h
30 ${LAUNCHER_API_INCLUDEDIR}/unity/shell/launcher/QuickListModelInterface.h
plugins/Unity/Launcher/Launcher.qmltypesdeleted−182
@@ -1,182 +0,0 @@
1−import QtQuick.tooling 1.1
2−
3−// This file describes the plugin-supplied types contained in the library.
4−// It is used for QML tooling purposes only.
5−//
6−// This file was auto-generated by:
7−// 'qmlplugindump -notrelocatable Unity.Launcher 0.1 plugins'
8−
9−Module {
10− Component {
11− name: "LauncherItem"
12− prototype: "unity::shell::launcher::LauncherItemInterface"
13− exports: ["Unity.Launcher/LauncherItem 0.1"]
14− isCreatable: false
15− exportMetaObjectRevisions: [0]
16− }
17− Component {
18− name: "LauncherModel"
19− prototype: "unity::shell::launcher::LauncherModelInterface"
20− exports: ["Unity.Launcher/LauncherModel 0.1"]
21− isCreatable: false
22− isSingleton: true
23− exportMetaObjectRevisions: [0]
24− Method {
25− name: "requestRemove"
26− Parameter { name: "appId"; type: "string" }
27− }
28− Method { name: "refresh" }
29− Method {
30− name: "get"
31− type: "unity::shell::launcher::LauncherItemInterface*"
32− Parameter { name: "index"; type: "int" }
33− }
34− Method {
35− name: "move"
36− Parameter { name: "oldIndex"; type: "int" }
37− Parameter { name: "newIndex"; type: "int" }
38− }
39− Method {
40− name: "pin"
41− Parameter { name: "appId"; type: "string" }
42− Parameter { name: "index"; type: "int" }
43− }
44− Method {
45− name: "pin"
46− Parameter { name: "appId"; type: "string" }
47− }
48− Method {
49− name: "quickListActionInvoked"
50− Parameter { name: "appId"; type: "string" }
51− Parameter { name: "actionIndex"; type: "int" }
52− }
53− Method {
54− name: "setUser"
55− Parameter { name: "username"; type: "string" }
56− }
57− Method {
58− name: "getUrlForAppId"
59− type: "string"
60− Parameter { name: "appId"; type: "string" }
61− }
62− }
63− Component {
64− name: "QuickListModel"
65− prototype: "unity::shell::launcher::QuickListModelInterface"
66− exports: ["Unity.Launcher/QuickListModel 0.1"]
67− isCreatable: false
68− exportMetaObjectRevisions: [0]
69− }
70− Component {
71− name: "unity::shell::launcher::LauncherItemInterface"
72− prototype: "QObject"
73− exports: ["Unity.Launcher/LauncherItemInterface 0.1"]
74− isCreatable: false
75− exportMetaObjectRevisions: [0]
76− Property { name: "appId"; type: "string"; isReadonly: true }
77− Property { name: "name"; type: "string"; isReadonly: true }
78− Property { name: "icon"; type: "string"; isReadonly: true }
79− Property { name: "pinned"; type: "bool"; isReadonly: true }
80− Property { name: "running"; type: "bool"; isReadonly: true }
81− Property { name: "recent"; type: "bool"; isReadonly: true }
82− Property { name: "progress"; type: "int"; isReadonly: true }
83− Property { name: "count"; type: "int"; isReadonly: true }
84− Property { name: "countVisible"; type: "bool"; isReadonly: true }
85− Property { name: "focused"; type: "bool"; isReadonly: true }
86− Property {
87− name: "quickList"
88− type: "unity::shell::launcher::QuickListModelInterface"
89− isReadonly: true
90− isPointer: true
91− }
92− Signal {
93− name: "nameChanged"
94− Parameter { name: "name"; type: "string" }
95− }
96− Signal {
97− name: "iconChanged"
98− Parameter { name: "icon"; type: "string" }
99− }
100− Signal {
101− name: "pinnedChanged"
102− Parameter { name: "pinned"; type: "bool" }
103− }
104− Signal {
105− name: "runningChanged"
106− Parameter { name: "running"; type: "bool" }
107− }
108− Signal {
109− name: "recentChanged"
110− Parameter { name: "running"; type: "bool" }
111− }
112− Signal {
113− name: "progressChanged"
114− Parameter { name: "progress"; type: "int" }
115− }
116− Signal {
117− name: "countChanged"
118− Parameter { name: "count"; type: "int" }
119− }
120− Signal {
121− name: "countVisibleChanged"
122− Parameter { name: "countVisible"; type: "bool" }
123− }
124− Signal {
125− name: "focusedChanged"
126− Parameter { name: "focused"; type: "bool" }
127− }
128− }
129− Component {
130− name: "unity::shell::launcher::LauncherModelInterface"
131− prototype: "QAbstractListModel"
132− exports: ["Unity.Launcher/LauncherModelInterface 0.1"]
133− isCreatable: false
134− exportMetaObjectRevisions: [0]
135− Property {
136− name: "applicationManager"
137− type: "unity::shell::application::ApplicationManagerInterface"
138− isPointer: true
139− }
140− Property { name: "onlyPinned"; type: "bool" }
141− Signal { name: "hint" }
142− Method {
143− name: "move"
144− Parameter { name: "oldIndex"; type: "int" }
145− Parameter { name: "newIndex"; type: "int" }
146− }
147− Method {
148− name: "get"
149− type: "unity::shell::launcher::LauncherItemInterface*"
150− Parameter { name: "index"; type: "int" }
151− }
152− Method {
153− name: "pin"
154− Parameter { name: "appId"; type: "string" }
155− Parameter { name: "index"; type: "int" }
156− }
157− Method {
158− name: "pin"
159− Parameter { name: "appId"; type: "string" }
160− }
161− Method {
162− name: "requestRemove"
163− Parameter { name: "appId"; type: "string" }
164− }
165− Method {
166− name: "quickListActionInvoked"
167− Parameter { name: "appId"; type: "string" }
168− Parameter { name: "actionIndex"; type: "int" }
169− }
170− Method {
171− name: "setUser"
172− Parameter { name: "username"; type: "string" }
173− }
174− }
175− Component {
176− name: "unity::shell::launcher::QuickListModelInterface"
177− prototype: "QAbstractListModel"
178− exports: ["Unity.Launcher/QuickListInterface 0.1"]
179− isCreatable: false
180− exportMetaObjectRevisions: [0]
181− }
182−}
plugins/Unity/Launcher/launcheritem.cpp+14
@@ -35,6 +35,7 @@ LauncherItem::LauncherItem(const QString &appId, const QString &name, const QStr
35 m_countVisible(false),
35 m_countVisible(false),
36 m_focused(false),
36 m_focused(false),
37 m_alerting(false),
37 m_alerting(false),
38+ m_surfaceCount(0),
38 m_quickList(new QuickListModel(this))
39 m_quickList(new QuickListModel(this))
39{
40{
40 Q_ASSERT(parent != nullptr);
41 Q_ASSERT(parent != nullptr);
@@ -213,6 +214,19 @@ void LauncherItem::setAlerting(bool alerting)
213 }
214 }
214}
215}
215
216
217+int LauncherItem::surfaceCount() const
218+{
219+ return m_surfaceCount;
220+}
221+
222+void LauncherItem::setSurfaceCount(int surfaceCount)
223+{
224+ if (m_surfaceCount != surfaceCount) {
225+ m_surfaceCount = surfaceCount;
226+ Q_EMIT surfaceCountChanged(surfaceCount);
227+ }
228+}
229+
216unity::shell::launcher::QuickListModelInterface *LauncherItem::quickList() const
230unity::shell::launcher::QuickListModelInterface *LauncherItem::quickList() const
217{
231{
218 return m_quickList;
232 return m_quickList;
plugins/Unity/Launcher/launcheritem.h+3
@@ -45,6 +45,7 @@ public:
45 bool countVisible() const override;
45 bool countVisible() const override;
46 bool focused() const override;
46 bool focused() const override;
47 bool alerting() const override;
47 bool alerting() const override;
48+ int surfaceCount() const override;
48
49
49 unity::shell::launcher::QuickListModelInterface *quickList() const override;
50 unity::shell::launcher::QuickListModelInterface *quickList() const override;
50
51
@@ -59,6 +60,7 @@ private:
59 void setCountVisible(bool countVisible);
60 void setCountVisible(bool countVisible);
60 void setFocused(bool focused);
61 void setFocused(bool focused);
61 void setAlerting(bool alerting);
62 void setAlerting(bool alerting);
63+ void setSurfaceCount(int surfaceCount);
62
64
63private:
65private:
64 QString m_appId;
66 QString m_appId;
@@ -72,6 +74,7 @@ private:
72 bool m_countVisible;
74 bool m_countVisible;
73 bool m_focused;
75 bool m_focused;
74 bool m_alerting;
76 bool m_alerting;
77+ int m_surfaceCount;
75 QuickListModel *m_quickList;
78 QuickListModel *m_quickList;
76 QuickListEntry m_quitAction;
79 QuickListEntry m_quitAction;
77
80
plugins/Unity/Launcher/launchermodel.cpp+29−2
@@ -25,6 +25,7 @@
25#include "asadapter.h"
25#include "asadapter.h"
26
26
27#include <unity/shell/application/ApplicationInfoInterface.h>
27#include <unity/shell/application/ApplicationInfoInterface.h>
28+#include <unity/shell/application/MirSurfaceListInterface.h>
28
29
29#include <QDesktopServices>
30#include <QDesktopServices>
30#include <QDebug>
31#include <QDebug>
@@ -88,6 +89,8 @@ QVariant LauncherModel::data(const QModelIndex &index, int role) const
88 return item->alerting();
89 return item->alerting();
89 case RoleRunning:
90 case RoleRunning:
90 return item->running();
91 return item->running();
92+ case RoleSurfaceCount:
93+ return item->surfaceCount();
91 default:
94 default:
92 qWarning() << Q_FUNC_INFO << "missing role, implement me";
95 qWarning() << Q_FUNC_INFO << "missing role, implement me";
93 return QVariant();
96 return QVariant();
@@ -525,28 +528,50 @@ void LauncherModel::applicationAdded(const QModelIndex &parent, int row)
525 item->setRecent(true);
528 item->setRecent(true);
526 Q_EMIT dataChanged(index(itemIndex), index(itemIndex), {RoleRecent});
529 Q_EMIT dataChanged(index(itemIndex), index(itemIndex), {RoleRecent});
527 }
530 }
531+ if (item->surfaceCount() != app->surfaceCount()) {
532+ item->setSurfaceCount(app->surfaceCount());
533+ Q_EMIT dataChanged(index(itemIndex), index(itemIndex), {RoleSurfaceCount});
534+ }
535+
528 item->setRunning(true);
536 item->setRunning(true);
529 } else {
537 } else {
530 LauncherItem *item = new LauncherItem(app->appId(), app->name(), app->icon().toString(), this);
538 LauncherItem *item = new LauncherItem(app->appId(), app->name(), app->icon().toString(), this);
531 item->setRecent(true);
539 item->setRecent(true);
532 item->setRunning(true);
540 item->setRunning(true);
533 item->setFocused(app->focused());
541 item->setFocused(app->focused());
534−
542+ item->setSurfaceCount(app->surfaceCount());
535 beginInsertRows(QModelIndex(), m_list.count(), m_list.count());
543 beginInsertRows(QModelIndex(), m_list.count(), m_list.count());
536 m_list.append(item);
544 m_list.append(item);
537 endInsertRows();
545 endInsertRows();
538 }
546 }
547+ connect(app, &ApplicationInfoInterface::surfaceCountChanged, this, &LauncherModel::applicationSurfaceCountChanged);
539 m_asAdapter->syncItems(m_list);
548 m_asAdapter->syncItems(m_list);
540 Q_EMIT dataChanged(index(itemIndex), index(itemIndex), {RoleRunning});
549 Q_EMIT dataChanged(index(itemIndex), index(itemIndex), {RoleRunning});
541}
550}
542
551
552+void LauncherModel::applicationSurfaceCountChanged(int count)
553+{
554+ ApplicationInfoInterface *app = static_cast<ApplicationInfoInterface*>(sender());
555+ int idx = findApplication(app->appId());
556+ if (idx < 0) {
557+ qWarning() << "Received a surface count changed event from an app that's not in the Launcher model";
558+ return;
559+ }
560+ LauncherItem *item = m_list.at(idx);
561+ if (item->surfaceCount() != count) {
562+ item->setSurfaceCount(count);
563+ Q_EMIT dataChanged(index(idx), index(idx), {RoleSurfaceCount});
564+ }
565+}
566+
543void LauncherModel::applicationRemoved(const QModelIndex &parent, int row)
567void LauncherModel::applicationRemoved(const QModelIndex &parent, int row)
544{
568{
545 Q_UNUSED(parent)
569 Q_UNUSED(parent)
546
570
571+ ApplicationInfoInterface *app = m_appManager->get(row);
547 int appIndex = -1;
572 int appIndex = -1;
548 for (int i = 0; i < m_list.count(); ++i) {
573 for (int i = 0; i < m_list.count(); ++i) {
549− if (m_list.at(i)->appId() == m_appManager->get(row)->appId()) {
574+ if (m_list.at(i)->appId() == app->appId()) {
550 appIndex = i;
575 appIndex = i;
551 break;
576 break;
552 }
577 }
@@ -557,6 +582,8 @@ void LauncherModel::applicationRemoved(const QModelIndex &parent, int row)
557 return;
582 return;
558 }
583 }
559
584
585+ disconnect(app, &ApplicationInfoInterface::surfaceCountChanged, this, &LauncherModel::applicationSurfaceCountChanged);
586+
560 LauncherItem * item = m_list.at(appIndex);
587 LauncherItem * item = m_list.at(appIndex);
561 item->setRunning(false);
588 item->setRunning(false);
562
589
plugins/Unity/Launcher/launchermodel.h+1
@@ -79,6 +79,7 @@ private Q_SLOTS:
79 void applicationAdded(const QModelIndex &parent, int row);
79 void applicationAdded(const QModelIndex &parent, int row);
80 void applicationRemoved(const QModelIndex &parent, int row);
80 void applicationRemoved(const QModelIndex &parent, int row);
81 void focusedAppIdChanged();
81 void focusedAppIdChanged();
82+ void applicationSurfaceCountChanged(int);
82
83
83private:
84private:
84 QList<LauncherItem*> m_list;
85 QList<LauncherItem*> m_list;
qml/Launcher/LauncherDelegate.qml+3−1
@@ -32,6 +32,7 @@ Item {
32 property bool alerting: false
32 property bool alerting: false
33 property bool highlighted: false
33 property bool highlighted: false
34 property bool shortcutHintShown: false
34 property bool shortcutHintShown: false
35+ property int surfaceCount: 1
35
36
36 readonly property int effectiveHeight: Math.cos(angle * Math.PI / 180) * itemHeight
37 readonly property int effectiveHeight: Math.cos(angle * Math.PI / 180) * itemHeight
37 readonly property real foldedHeight: Math.cos(maxAngle * Math.PI / 180) * itemHeight
38 readonly property real foldedHeight: Math.cos(maxAngle * Math.PI / 180) * itemHeight
@@ -221,7 +222,8 @@ Item {
221 }
222 }
222 spacing: units.gu(.5)
223 spacing: units.gu(.5)
223 Repeater {
224 Repeater {
225+ objectName: "surfacePipRepeater"
224− model: 1 // TODO: This should be "Math.min(3, app.surfaceCount)" once we have multiple surfaces
226+ model: Math.min(3, root.surfaceCount)
225 Rectangle {
227 Rectangle {
226 objectName: "runningHighlight" + index
228 objectName: "runningHighlight" + index
227 width: units.gu(0.25)
229 width: units.gu(0.25)
qml/Launcher/LauncherPanel.qml+1
@@ -239,6 +239,7 @@ Rectangle {
239 alerting: model.alerting
239 alerting: model.alerting
240 highlighted: root.highlightIndex == index
240 highlighted: root.highlightIndex == index
241 shortcutHintShown: root.shortcutHintsShown && index <= 9
241 shortcutHintShown: root.shortcutHintsShown && index <= 9
242+ surfaceCount: model.surfaceCount
242 z: -Math.abs(offset)
243 z: -Math.abs(offset)
243 maxAngle: 55
244 maxAngle: 55
244 property bool dragging: false
245 property bool dragging: false
qml/Stages/ApplicationWindow.qml+25−9
@@ -121,15 +121,12 @@ FocusScope {
121
121
122 property bool surfaceOldEnoughToBeResized: false
122 property bool surfaceOldEnoughToBeResized: false
123
123
124− property var focusedSurface: {
125− if (promptSurfacesRepeater.count == 0) {
124+ property Item focusedSurface: promptSurfacesRepeater.count === 0 ? surfaceContainer
126− return surfaceContainer;
127− } else {
128− return promptSurfacesRepeater.itemAt(promptSurfacesRepeater.count - 1);
125+ : promptSurfacesRepeater.first
129− }
130− }
131 onFocusedSurfaceChanged: {
126 onFocusedSurfaceChanged: {
127+ if (focusedSurface) {
132− focusedSurface.focus = true;
128+ focusedSurface.focus = true;
129+ }
133 }
130 }
134 }
131 }
135
132
@@ -158,6 +155,7 @@ FocusScope {
158 objectName: "screenshotImage"
155 objectName: "screenshotImage"
159 anchors.fill: parent
156 anchors.fill: parent
160 antialiasing: !root.interactive
157 antialiasing: !root.interactive
158+ z: 1
161
159
162 function take() {
160 function take() {
163 // Save memory by using a half-resolution (thus quarter size) screenshot.
161 // Save memory by using a half-resolution (thus quarter size) screenshot.
@@ -175,6 +173,7 @@ FocusScope {
175 visible: active
173 visible: active
176 active: false
174 active: false
177 anchors.fill: parent
175 anchors.fill: parent
176+ z: screenshotImage.z + 1
178 sourceComponent: Component {
177 sourceComponent: Component {
179 Splash {
178 Splash {
180 id: splash
179 id: splash
@@ -191,6 +190,7 @@ FocusScope {
191
190
192 SurfaceContainer {
191 SurfaceContainer {
193 id: surfaceContainer
192 id: surfaceContainer
193+ z: splashLoader.z + 1
194 requestedWidth: root.requestedWidth
194 requestedWidth: root.requestedWidth
195 requestedHeight: root.requestedHeight
195 requestedHeight: root.requestedHeight
196 surfaceOrientationAngle: application && application.rotatesWindowContents ? root.surfaceOrientationAngle : 0
196 surfaceOrientationAngle: application && application.rotatesWindowContents ? root.surfaceOrientationAngle : 0
@@ -208,12 +208,28 @@ FocusScope {
208 }
208 }
209 }
209 }
210 delegate: SurfaceContainer {
210 delegate: SurfaceContainer {
211+ id: promptSurfaceContainer
211− interactive: index == (promptSurfacesRepeater.count - 1) && root.interactive
212+ interactive: index === 0 && root.interactive
212 surface: model.surface
213 surface: model.surface
213 width: root.width
214 width: root.width
214 height: root.height
215 height: root.height
215 isPromptSurface: true
216 isPromptSurface: true
217+ z: surfaceContainer.z + (promptSurfacesRepeater.count - index)
218+ property int index: model.index
219+ onIndexChanged: updateFirst()
220+ Component.onCompleted: updateFirst()
221+ function updateFirst() {
222+ if (index === 0) {
223+ promptSurfacesRepeater.first = promptSurfaceContainer;
224+ }
225+ }
226+ }
227+ onCountChanged: {
228+ if (count === 0) {
229+ first = null;
230+ }
216 }
231 }
232+ property Item first: null
217 }
233 }
218
234
219 // SurfaceContainer size drives ApplicationWindow size
235 // SurfaceContainer size drives ApplicationWindow size
tests/mocks/Unity/Application/ApplicationInfo.cpp+29−27
@@ -55,8 +55,10 @@ QString stateToStr(ApplicationInfo::State state)
55ApplicationInfo::ApplicationInfo(const QString &appId, QObject *parent)
55ApplicationInfo::ApplicationInfo(const QString &appId, QObject *parent)
56 : ApplicationInfoInterface(appId, parent)
56 : ApplicationInfoInterface(appId, parent)
57 , m_appId(appId)
57 , m_appId(appId)
58+ , m_surfaceList(new MirSurfaceListModel(this))
59+ , m_promptSurfaceList(new MirSurfaceListModel(this))
58{
60{
59− connect(&m_surfaceList, &MirSurfaceListModel::countChanged,
61+ connect(m_surfaceList, &MirSurfaceListModel::countChanged,
60 this, &ApplicationInfo::onSurfaceCountChanged, Qt::QueuedConnection);
62 this, &ApplicationInfo::onSurfaceCountChanged, Qt::QueuedConnection);
61
63
62 m_surfaceCreationTimer.setSingleShot(true);
64 m_surfaceCreationTimer.setSingleShot(true);
@@ -78,8 +80,8 @@ void ApplicationInfo::createSurface()
78 if (state() == ApplicationInfo::Stopped) { return; }
80 if (state() == ApplicationInfo::Stopped) { return; }
79
81
80 QString surfaceName = name();
82 QString surfaceName = name();
81− if (m_surfaceList.count() > 0) {
83+ if (m_surfaceList->count() > 0) {
82− surfaceName.append(QString(" %1").arg(m_surfaceList.count()+1));
84+ surfaceName.append(QString(" %1").arg(m_surfaceList->count()+1));
83 }
85 }
84
86
85 auto surfaceManager = SurfaceManager::instance();
87 auto surfaceManager = SurfaceManager::instance();
@@ -95,7 +97,7 @@ void ApplicationInfo::createSurface()
95
97
96 surface->setShellChrome(m_shellChrome);
98 surface->setShellChrome(m_shellChrome);
97
99
98− m_surfaceList.appendSurface(surface);
100+ m_surfaceList->appendSurface(surface);
99
101
100 ++m_liveSurfaceCount;
102 ++m_liveSurfaceCount;
101 connect(surface, &MirSurface::liveChanged, this, [this, surface](){
103 connect(surface, &MirSurface::liveChanged, this, [this, surface](){
@@ -186,16 +188,16 @@ void ApplicationInfo::setState(State value)
186 if (value != m_state) {
188 if (value != m_state) {
187 DEBUG_MSG(qPrintable(stateToStr(value)));
189 DEBUG_MSG(qPrintable(stateToStr(value)));
188 if (!m_manualSurfaceCreation && value == ApplicationInfo::Starting) {
190 if (!m_manualSurfaceCreation && value == ApplicationInfo::Starting) {
189− Q_ASSERT(m_surfaceList.count() == 0);
191+ Q_ASSERT(m_surfaceList->count() == 0);
190 m_surfaceCreationTimer.start();
192 m_surfaceCreationTimer.start();
191 } else if (value == ApplicationInfo::Stopped) {
193 } else if (value == ApplicationInfo::Stopped) {
192 m_surfaceCreationTimer.stop();
194 m_surfaceCreationTimer.stop();
193− for (int i = 0; i < m_surfaceList.count(); ++i) {
195+ for (int i = 0; i < m_surfaceList->count(); ++i) {
194− MirSurface *surface = static_cast<MirSurface*>(m_surfaceList.get(i));
196+ MirSurface *surface = static_cast<MirSurface*>(m_surfaceList->get(i));
195 surface->setLive(false);
197 surface->setLive(false);
196 }
198 }
197− for (int i = 0; i < m_promptSurfaceList.count(); ++i) {
199+ for (int i = 0; i < m_promptSurfaceList->count(); ++i) {
198− auto surface = static_cast<MirSurface*>(m_promptSurfaceList.get(i));
200+ auto surface = static_cast<MirSurface*>(m_promptSurfaceList->get(i));
199 surface->setLive(false);
201 surface->setLive(false);
200 }
202 }
201 }
203 }
@@ -209,9 +211,9 @@ void ApplicationInfo::close()
209{
211{
210 DEBUG_MSG("");
212 DEBUG_MSG("");
211
213
212− if (m_surfaceList.count() > 0) {
214+ if (m_surfaceList->count() > 0) {
213− for (int i = 0; i < m_surfaceList.count(); ++i) {
215+ for (int i = 0; i < m_surfaceList->count(); ++i) {
214− MirSurface *surface = static_cast<MirSurface*>(m_surfaceList.get(i));
216+ MirSurface *surface = static_cast<MirSurface*>(m_surfaceList->get(i));
215 surface->close();
217 surface->close();
216 }
218 }
217 } else {
219 } else {
@@ -223,15 +225,15 @@ void ApplicationInfo::close()
223void ApplicationInfo::setFullscreen(bool value)
225void ApplicationInfo::setFullscreen(bool value)
224{
226{
225 m_fullscreen = value;
227 m_fullscreen = value;
226− if (m_surfaceList.rowCount() > 0) {
228+ if (m_surfaceList->rowCount() > 0) {
227− m_surfaceList.get(0)->setState(Mir::FullscreenState);
229+ m_surfaceList->get(0)->setState(Mir::FullscreenState);
228 }
230 }
229}
231}
230
232
231bool ApplicationInfo::fullscreen() const
233bool ApplicationInfo::fullscreen() const
232{
234{
233− if (m_surfaceList.rowCount() > 0) {
235+ if (m_surfaceList->rowCount() > 0) {
234− return m_surfaceList.get(0)->state() == Mir::FullscreenState;
236+ return m_surfaceList->get(0)->state() == Mir::FullscreenState;
235 } else {
237 } else {
236 return m_fullscreen;
238 return m_fullscreen;
237 }
239 }
@@ -341,16 +343,16 @@ void ApplicationInfo::setInitialSurfaceSize(const QSize &size)
341void ApplicationInfo::setShellChrome(Mir::ShellChrome shellChrome)
343void ApplicationInfo::setShellChrome(Mir::ShellChrome shellChrome)
342{
344{
343 m_shellChrome = shellChrome;
345 m_shellChrome = shellChrome;
344− if (m_surfaceList.rowCount() > 0) {
346+ if (m_surfaceList->rowCount() > 0) {
345− static_cast<MirSurface*>(m_surfaceList.get(0))->setShellChrome(shellChrome);
347+ static_cast<MirSurface*>(m_surfaceList->get(0))->setShellChrome(shellChrome);
346 }
348 }
347}
349}
348
350
349bool ApplicationInfo::focused() const
351bool ApplicationInfo::focused() const
350{
352{
351 bool someSurfaceHasFocus = false; // to be proven wrong
353 bool someSurfaceHasFocus = false; // to be proven wrong
352− for (int i = 0; i < m_surfaceList.count() && !someSurfaceHasFocus; ++i) {
354+ for (int i = 0; i < m_surfaceList->count() && !someSurfaceHasFocus; ++i) {
353− someSurfaceHasFocus = m_surfaceList.get(i)->focused();
355+ someSurfaceHasFocus = m_surfaceList->get(i)->focused();
354 }
356 }
355 return someSurfaceHasFocus;
357 return someSurfaceHasFocus;
356}
358}
@@ -362,12 +364,12 @@ void ApplicationInfo::setFocused(bool value)
362 }
364 }
363
365
364 if (value) {
366 if (value) {
365− if (m_surfaceList.count() > 0) {
367+ if (m_surfaceList->count() > 0) {
366− m_surfaceList.get(0)->requestFocus();
368+ m_surfaceList->get(0)->requestFocus();
367 }
369 }
368 } else {
370 } else {
369− for (int i = 0; i < m_surfaceList.count(); ++i) {
371+ for (int i = 0; i < m_surfaceList->count(); ++i) {
370− MirSurface *surface = static_cast<MirSurface*>(m_surfaceList.get(i));
372+ MirSurface *surface = static_cast<MirSurface*>(m_surfaceList->get(i));
371 if (surface->focused()) {
373 if (surface->focused()) {
372 surface->setFocused(false);
374 surface->setFocused(false);
373 }
375 }
@@ -377,16 +379,16 @@ void ApplicationInfo::setFocused(bool value)
377
379
378void ApplicationInfo::onSurfaceCountChanged()
380void ApplicationInfo::onSurfaceCountChanged()
379{
381{
380− if (m_surfaceList.count() == 0 && m_state == Running) {
382+ if (m_surfaceList->count() == 0 && m_state == Running) {
381 setState(Stopped);
383 setState(Stopped);
382 }
384 }
383}
385}
384
386
385void ApplicationInfo::requestFocus()
387void ApplicationInfo::requestFocus()
386{
388{
387− if (m_surfaceList.count() == 0) {
389+ if (m_surfaceList->count() == 0) {
388 Q_EMIT focusRequested();
390 Q_EMIT focusRequested();
389 } else {
391 } else {
390− m_surfaceList.get(0)->requestFocus();
392+ m_surfaceList->get(0)->requestFocus();
391 }
393 }
392}
394}
tests/mocks/Unity/Application/ApplicationInfo.h+5−4
@@ -107,8 +107,9 @@ public:
107
107
108 Q_INVOKABLE void setShellChrome(Mir::ShellChrome shellChrome);
108 Q_INVOKABLE void setShellChrome(Mir::ShellChrome shellChrome);
109
109
110− MirSurfaceListInterface* surfaceList() override { return &m_surfaceList; }
110+ MirSurfaceListInterface* surfaceList() const override { return m_surfaceList; }
111− MirSurfaceListInterface* promptSurfaceList() override { return &m_promptSurfaceList; }
111+ MirSurfaceListInterface* promptSurfaceList() const override { return m_promptSurfaceList; }
112+ int surfaceCount() const override { return m_surfaceList->count(); }
112
113
113 void setFocused(bool value);
114 void setFocused(bool value);
114
115
@@ -148,8 +149,8 @@ private:
148 bool m_isTouchApp{true};
149 bool m_isTouchApp{true};
149 bool m_exemptFromLifecycle{false};
150 bool m_exemptFromLifecycle{false};
150 QSize m_initialSurfaceSize;
151 QSize m_initialSurfaceSize;
151− MirSurfaceListModel m_surfaceList;
152+ MirSurfaceListModel *m_surfaceList;
152− MirSurfaceListModel m_promptSurfaceList;
153+ MirSurfaceListModel *m_promptSurfaceList;
153 int m_liveSurfaceCount{0};
154 int m_liveSurfaceCount{0};
154 QTimer m_surfaceCreationTimer;
155 QTimer m_surfaceCreationTimer;
155 QList<MirSurface*> m_closingSurfaces;
156 QList<MirSurface*> m_closingSurfaces;
tests/mocks/Unity/Application/MirSurfaceListModel.cpp+13−3
@@ -66,12 +66,22 @@ void MirSurfaceListModel::appendSurface(MirSurface *surface)
66 m_surfaceList.append(surface);
66 m_surfaceList.append(surface);
67 connectSurface(surface);
67 connectSurface(surface);
68 endInsertRows();
68 endInsertRows();
69− Q_EMIT countChanged();
69+ Q_EMIT countChanged(m_surfaceList.count());
70 if (m_surfaceList.count() == 1) {
70 if (m_surfaceList.count() == 1) {
71 Q_EMIT firstChanged();
71 Q_EMIT firstChanged();
72 }
72 }
73}
73}
74
74
75+void MirSurfaceListModel::prependSurface(MirSurface *surface)
76+{
77+ beginInsertRows(QModelIndex(), 0, 0);
78+ m_surfaceList.prepend(surface);
79+ connectSurface(surface);
80+ endInsertRows();
81+ Q_EMIT countChanged(m_surfaceList.count());
82+ Q_EMIT firstChanged();
83+}
84+
75void MirSurfaceListModel::connectSurface(MirSurface *surface)
85void MirSurfaceListModel::connectSurface(MirSurface *surface)
76{
86{
77 connect(surface, &MirSurface::raiseRequested, this, [this, surface](){ this->raise(surface); });
87 connect(surface, &MirSurface::raiseRequested, this, [this, surface](){ this->raise(surface); });
@@ -85,7 +95,7 @@ void MirSurfaceListModel::removeSurface(MirSurface *surface)
85 beginRemoveRows(QModelIndex(), i, i);
95 beginRemoveRows(QModelIndex(), i, i);
86 m_surfaceList.removeAt(i);
96 m_surfaceList.removeAt(i);
87 endRemoveRows();
97 endRemoveRows();
88− Q_EMIT countChanged();
98+ Q_EMIT countChanged(m_surfaceList.count());
89 if (m_surfaceList.count() == 0 || i == 0) {
99 if (m_surfaceList.count() == 0 || i == 0) {
90 Q_EMIT firstChanged();
100 Q_EMIT firstChanged();
91 }
101 }
@@ -143,7 +153,7 @@ MirSurfaceInterface *MirSurfaceListModel::createSurface()
143 Mir::RestoredState,
153 Mir::RestoredState,
144 screenshotUrl);
154 screenshotUrl);
145
155
146− appendSurface(surface);
156+ prependSurface(surface);
147
157
148 return surface;
158 return surface;
149}
159}
tests/mocks/Unity/Application/MirSurfaceListModel.h+1
@@ -49,6 +49,7 @@ public:
49 Q_INVOKABLE unity::shell::application::MirSurfaceInterface *createSurface();
49 Q_INVOKABLE unity::shell::application::MirSurfaceInterface *createSurface();
50
50
51private:
51private:
52+ void prependSurface(MirSurface *surface);
52 void raise(MirSurface *surface);
53 void raise(MirSurface *surface);
53 void moveSurface(int from, int to);
54 void moveSurface(int from, int to);
54 void connectSurface(MirSurface *surface);
55 void connectSurface(MirSurface *surface);
tests/mocks/Unity/Launcher/CMakeLists.txt+1−1
@@ -1,4 +1,4 @@
1−pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=7)
1+pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=8)
2
2
3include_directories(
3include_directories(
4 ${CMAKE_CURRENT_SOURCE_DIR}
4 ${CMAKE_CURRENT_SOURCE_DIR}
tests/mocks/Unity/Launcher/MockLauncherItem.cpp+14
@@ -38,6 +38,7 @@ MockLauncherItem::MockLauncherItem(const QString &appId, const QString& desktopF
38 m_countVisible(false),
38 m_countVisible(false),
39 m_focused(false),
39 m_focused(false),
40 m_alerting(false),
40 m_alerting(false),
41+ m_surfaceCount(0),
41 m_quickList(new MockQuickListModel(this))
42 m_quickList(new MockQuickListModel(this))
42{
43{
43}
44}
@@ -182,6 +183,19 @@ void MockLauncherItem::setAlerting(bool alerting)
182 }
183 }
183}
184}
184
185
186+int MockLauncherItem::surfaceCount() const
187+{
188+ return m_surfaceCount;
189+}
190+
191+void MockLauncherItem::setSurfaceCount(int surfaceCount)
192+{
193+ if (m_surfaceCount != surfaceCount) {
194+ m_surfaceCount = surfaceCount;
195+ Q_EMIT surfaceCountChanged(surfaceCount);
196+ }
197+}
198+
185unity::shell::launcher::QuickListModelInterface *MockLauncherItem::quickList() const
199unity::shell::launcher::QuickListModelInterface *MockLauncherItem::quickList() const
186{
200{
187 return m_quickList;
201 return m_quickList;
tests/mocks/Unity/Launcher/MockLauncherItem.h+3
@@ -46,6 +46,7 @@ public:
46 bool countVisible() const override;
46 bool countVisible() const override;
47 bool focused() const override;
47 bool focused() const override;
48 bool alerting() const override;
48 bool alerting() const override;
49+ int surfaceCount() const override;
49
50
50 unity::shell::launcher::QuickListModelInterface *quickList() const override;
51 unity::shell::launcher::QuickListModelInterface *quickList() const override;
51
52
@@ -58,6 +59,7 @@ private:
58 void setCountVisible(bool countVisible);
59 void setCountVisible(bool countVisible);
59 void setFocused(bool focused);
60 void setFocused(bool focused);
60 void setAlerting(bool alerting);
61 void setAlerting(bool alerting);
62+ void setSurfaceCount(int surfaceCount);
61
63
62 QString m_appId;
64 QString m_appId;
63 QString m_desktopFile;
65 QString m_desktopFile;
@@ -71,6 +73,7 @@ private:
71 bool m_countVisible;
73 bool m_countVisible;
72 bool m_focused;
74 bool m_focused;
73 bool m_alerting;
75 bool m_alerting;
76+ int m_surfaceCount;
74 MockQuickListModel *m_quickList;
77 MockQuickListModel *m_quickList;
75
78
76 friend class MockLauncherModel;
79 friend class MockLauncherModel;
tests/mocks/Unity/Launcher/MockLauncherModel.cpp+5
@@ -25,6 +25,7 @@ MockLauncherModel::MockLauncherModel(QObject* parent): LauncherModelInterface(pa
25 MockLauncherItem *item = new MockLauncherItem("dialer-app", "/usr/share/applications/dialer-app.desktop", "Dialer", "dialer-app", this);
25 MockLauncherItem *item = new MockLauncherItem("dialer-app", "/usr/share/applications/dialer-app.desktop", "Dialer", "dialer-app", this);
26 item->setProgress(0);
26 item->setProgress(0);
27 item->setPinned(true);
27 item->setPinned(true);
28+ item->setSurfaceCount(1);
28 item->setRunning(true);
29 item->setRunning(true);
29 item->setFocused(true);
30 item->setFocused(true);
30 m_list.append(item);
31 m_list.append(item);
@@ -36,6 +37,7 @@ MockLauncherModel::MockLauncherModel(QObject* parent): LauncherModelInterface(pa
36 item->setProgress(50);
37 item->setProgress(50);
37 item->setCountVisible(true);
38 item->setCountVisible(true);
38 item->setRunning(true);
39 item->setRunning(true);
40+ item->setSurfaceCount(2);
39 item->setAlerting(false);
41 item->setAlerting(false);
40 m_list.append(item);
42 m_list.append(item);
41 item = new MockLauncherItem("music-app", "/usr/share/applications/music-app.desktop", "Music", "soundcloud", this);
43 item = new MockLauncherItem("music-app", "/usr/share/applications/music-app.desktop", "Music", "soundcloud", this);
@@ -44,6 +46,7 @@ MockLauncherModel::MockLauncherModel(QObject* parent): LauncherModelInterface(pa
44 item->setProgress(150);
46 item->setProgress(150);
45 m_list.append(item);
47 m_list.append(item);
46 item = new MockLauncherItem("webbrowser-app", "/usr/share/applications/webbrowser-app.desktop", "Browser", "browser", this);
48 item = new MockLauncherItem("webbrowser-app", "/usr/share/applications/webbrowser-app.desktop", "Browser", "browser", this);
49+ item->setSurfaceCount(5);
47 item->setCount(1);
50 item->setCount(1);
48 item->setCountVisible(true);
51 item->setCountVisible(true);
49 item->setRunning(true);
52 item->setRunning(true);
@@ -119,6 +122,8 @@ QVariant MockLauncherModel::data(const QModelIndex& index, int role) const
119 return item->focused();
122 return item->focused();
120 case RoleAlerting:
123 case RoleAlerting:
121 return item->alerting();
124 return item->alerting();
125+ case RoleSurfaceCount:
126+ return item->surfaceCount();
122 }
127 }
123
128
124 return QVariant();
129 return QVariant();
tests/plugins/Unity/Launcher/CMakeLists.txt+1−1
@@ -1,5 +1,5 @@
1pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt)
1pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt)
2−pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=7)
2+pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=8)
3
3
4include_directories(
4include_directories(
5 ${CMAKE_CURRENT_SOURCE_DIR}
5 ${CMAKE_CURRENT_SOURCE_DIR}
tests/plugins/Unity/Launcher/launchermodeltest.cpp+14−2
@@ -66,14 +66,17 @@ public:
66 void setExemptFromLifecycle(bool) override {}
66 void setExemptFromLifecycle(bool) override {}
67 QSize initialSurfaceSize() const override { return QSize(); }
67 QSize initialSurfaceSize() const override { return QSize(); }
68 void setInitialSurfaceSize(const QSize &) override {}
68 void setInitialSurfaceSize(const QSize &) override {}
69− MirSurfaceListInterface* surfaceList() override { return nullptr; }
69+ MirSurfaceListInterface* surfaceList() const override { return nullptr; }
70− MirSurfaceListInterface* promptSurfaceList() override { return nullptr; }
70+ MirSurfaceListInterface* promptSurfaceList() const override { return nullptr; }
71+ int surfaceCount() const override { return m_surfaceCount; }
72+ void setSurfaceCount(int count) { m_surfaceCount = count; Q_EMIT surfaceCountChanged(count); }
71
73
72 // Methods used for mocking (not in the interface)
74 // Methods used for mocking (not in the interface)
73 void setFocused(bool focused) { m_focused = focused; Q_EMIT focusedChanged(focused); }
75 void setFocused(bool focused) { m_focused = focused; Q_EMIT focusedChanged(focused); }
74private:
76private:
75 QString m_appId;
77 QString m_appId;
76 bool m_focused;
78 bool m_focused;
79+ int m_surfaceCount = 0;
77};
80};
78
81
79// This is a mock, specifically to test the LauncherModel
82// This is a mock, specifically to test the LauncherModel
@@ -692,6 +695,15 @@ private Q_SLOTS:
692 QCOMPARE(getASConfig().at(index).value("countVisible").toBool(), true);
695 QCOMPARE(getASConfig().at(index).value("countVisible").toBool(), true);
693 QCOMPARE(getASConfig().at(index).value("count").toInt(), 55);
696 QCOMPARE(getASConfig().at(index).value("count").toInt(), 55);
694 }
697 }
698+
699+ void testSurfaceCountUpdates() {
700+ QString appId = launcherModel->get(0)->appId();
701+
702+ QCOMPARE(launcherModel->get(0)->surfaceCount(), 0);
703+ MockApp *app = qobject_cast<MockApp*>(appManager->findApplication(appId));
704+ app->setSurfaceCount(1);
705+ QCOMPARE(launcherModel->get(0)->surfaceCount(), 1);
706+ }
695};
707};
696
708
697QTEST_GUILESS_MAIN(LauncherModelTest)
709QTEST_GUILESS_MAIN(LauncherModelTest)
tests/qmltests/Launcher/tst_Launcher.qml+25−9
@@ -486,25 +486,26 @@ Rectangle {
486 function test_progressOverlays() {
486 function test_progressOverlays() {
487 dragLauncherIntoView();
487 dragLauncherIntoView();
488 var launcherListView = findChild(launcher, "launcherListView");
488 var launcherListView = findChild(launcher, "launcherListView");
489+ var moveAnimation = findInvisibleChild(launcherListView, "moveAnimation")
489 for (var i = 0; i < launcherListView.count; ++i) {
490 for (var i = 0; i < launcherListView.count; ++i) {
490− var delegate = findChild(launcherListView, "launcherDelegate" + i)
491+ launcherListView.moveToIndex(i);
491− compare(findChild(delegate, "progressOverlay").visible, LauncherModel.get(i).progress >= 0)
492+ waitForRendering(launcherListView);
492− }
493+ tryCompare(moveAnimation, "running", false);
493− }
494
494
495− function test_runningHighlight() {
496− dragLauncherIntoView();
497− var launcherListView = findChild(launcher, "launcherListView");
498− for (var i = 0; i < launcherListView.count; ++i) {
499 var delegate = findChild(launcherListView, "launcherDelegate" + i)
495 var delegate = findChild(launcherListView, "launcherDelegate" + i)
500− compare(findChild(delegate, "runningHighlight0").visible, LauncherModel.get(i).running)
496+ compare(findChild(delegate, "progressOverlay").visible, LauncherModel.get(i).progress >= 0)
501 }
497 }
502 }
498 }
503
499
504 function test_focusedHighlight() {
500 function test_focusedHighlight() {
505 dragLauncherIntoView();
501 dragLauncherIntoView();
506 var launcherListView = findChild(launcher, "launcherListView");
502 var launcherListView = findChild(launcher, "launcherListView");
503+ var moveAnimation = findInvisibleChild(launcherListView, "moveAnimation")
504+
507 for (var i = 0; i < launcherListView.count; ++i) {
505 for (var i = 0; i < launcherListView.count; ++i) {
506+ launcherListView.moveToIndex(i);
507+ waitForRendering(launcherListView);
508+ tryCompare(moveAnimation, "running", false);
508 var delegate = findChild(launcherListView, "launcherDelegate" + i)
509 var delegate = findChild(launcherListView, "launcherDelegate" + i)
509 compare(findChild(delegate, "focusedHighlight").visible, LauncherModel.get(i).focused)
510 compare(findChild(delegate, "focusedHighlight").visible, LauncherModel.get(i).focused)
510 }
511 }
@@ -1295,5 +1296,20 @@ Rectangle {
1295
1296
1296 assertFocusOnIndex(-2);
1297 assertFocusOnIndex(-2);
1297 }
1298 }
1299+
1300+ function test_surfaceCountPips() {
1301+ var launcherListView = findChild(launcher, "launcherListView")
1302+ var moveAnimation = findInvisibleChild(launcherListView, "moveAnimation")
1303+
1304+ for (var i = 0; i < launcherListView.count; i++) {
1305+ launcherListView.moveToIndex(i);
1306+ waitForRendering(launcherListView);
1307+ tryCompare(moveAnimation, "running", false);
1308+
1309+ var delegate = findChild(launcher, "launcherDelegate" + i);
1310+ var surfacePipRepeater = findInvisibleChild(delegate, "surfacePipRepeater");
1311+ compare(surfacePipRepeater.model, Math.min(3, LauncherModel.get(i).surfaceCount))
1312+ }
1313+ }
1298 }
1314 }
1299}
1315}
tests/qmltests/Stages/ApplicationCheckBox.qml+1−1
@@ -156,7 +156,7 @@ Column {
156 width: height
156 width: height
157 height: promptsLabel.height * 0.7
157 height: promptsLabel.height * 0.7
158 anchors.verticalCenter: parent.verticalCenter
158 anchors.verticalCenter: parent.verticalCenter
159− onClicked: d.application.promptSurfaceList.get(d.application.promptSurfaceList.count - 1).close()
159+ onClicked: d.application.promptSurfaceList.get(0).close()
160 enabled: d.application && d.application.promptSurfaceList.count > 0
160 enabled: d.application && d.application.promptSurfaceList.count > 0
161 Label { text: "➖"; anchors.centerIn: parent; enabled: parent.enabled }
161 Label { text: "➖"; anchors.centerIn: parent; enabled: parent.enabled }
162 }
162 }
tests/qmltests/Stages/tst_ApplicationWindow.qml+39−9
@@ -106,7 +106,7 @@ Rectangle {
106 enabled: parent.promptSurfaceList !== null && parent.promptSurfaceList.count > 0
106 enabled: parent.promptSurfaceList !== null && parent.promptSurfaceList.count > 0
107 activeFocusOnPress: false
107 activeFocusOnPress: false
108 text: "Remove"
108 text: "Remove"
109− onClicked: { parent.promptSurfaceList.get(parent.promptSurfaceList.count - 1).close(); }
109+ onClicked: { parent.promptSurfaceList.get(0).close(); }
110 }
110 }
111
111
112 Button {
112 Button {
@@ -449,20 +449,21 @@ Rectangle {
449 for (i = 0; i < 3; i++) {
449 for (i = 0; i < 3; i++) {
450 promptSurfaceList.createSurface();
450 promptSurfaceList.createSurface();
451 compare(promptSurfaces.count, i+1);
451 compare(promptSurfaces.count, i+1);
452− waitUntilSurfaceContainerStopsAnimating(promptSurfaces.itemAt(promptSurfaces.count - 1));
452+ waitUntilSurfaceContainerStopsAnimating(promptSurfaces.itemAt(0));
453 }
453 }
454
454
455− for (i = 2; i >= 0; --i) {
455+ for (i = 3; i > 0; --i) {
456− var promptSurface = promptSurfaceList.get(i);
456+ var promptSurface = promptSurfaceList.get(0);
457 compare(promptSurface.activeFocus, true);
457 compare(promptSurface.activeFocus, true);
458
458
459 promptSurface.close();
459 promptSurface.close();
460+ promptSurface = null;
460− tryCompareFunction(function() { return promptSurfaces.count; }, i);
461+ tryCompareFunction(function() { return promptSurfaces.count; }, i-1);
461
462
462− if (i > 0) {
463+ if (promptSurfaces.count > 0) {
463− // active focus should have gone to the yongest remaining sibling
464+ // active focus should have gone to the new head of the list
464− var previousPromptSurface = promptSurfaceList.get(i-1);
465+ promptSurface = promptSurfaceList.get(0);
465− tryCompare(previousPromptSurface, "activeFocus", true);
466+ tryCompare(promptSurface, "activeFocus", true);
466 } else {
467 } else {
467 // active focus should have gone to the application surface
468 // active focus should have gone to the application surface
468 tryCompare(applicationWindow.surface, "activeFocus", true);
469 tryCompare(applicationWindow.surface, "activeFocus", true);
@@ -498,5 +499,34 @@ Rectangle {
498 delegate.surface.close();
499 delegate.surface.close();
499 tryCompare(promptSurfaces, "count", 0);
500 tryCompare(promptSurfaces, "count", 0);
500 }
501 }
502+
503+ // Check that the z value of SurfaceContainers for prompt surfaces go from highest
504+ // for index 0 to lowest for the last index in the prompt surface list.
505+ // Regression test for https://bugs.launchpad.net/bugs/1586219
506+ function test_promptSurfacesZOrdering() {
507+ var promptSurfaceList = root.fakeApplication.promptSurfaceList;
508+ var promptSurfaces = testCase.findChild(applicationWindow, "promptSurfacesRepeater");
509+
510+ promptSurfaceList.createSurface();
511+
512+ for (var i = 2; i <= 3; i++) {
513+ promptSurfaceList.createSurface();
514+ tryCompare(promptSurfaces, "count", i);
515+ waitUntilSurfaceContainerStopsAnimating(promptSurfaces.itemAt(0));
516+
517+ for (var j = 1; j < promptSurfaces.count; j++) {
518+ var delegate = promptSurfaces.itemAt(j);
519+ var previousDelegate = promptSurfaces.itemAt(j-1);
520+ verify(previousDelegate.z > delegate.z);
521+ }
522+ }
523+
524+ // clean up
525+ while (promptSurfaceList.count > 0) {
526+ var currentCount = promptSurfaceList.count;
527+ promptSurfaceList.get(0).close();
528+ tryCompare(promptSurfaceList, "count", currentCount - 1);
529+ }
530+ }
501 }
531 }
502}
532}