on xenial help sign in
rebased
commita0432d36154bd789ee90b9a70fa57823ab5c8e0f authorNick Dedekind <nicholas.dedekind@gmail.com> dateSat 19 Jul 2014, 12:47 (12 years ago) parentc5f5062c4e54da
14 files changed+380−73
qml/Components/Lockscreen.qml+1−1 qml/Shell.qml+1−1 qml/Stages/SpreadDelegate.qml+7−6 qml/Stages/TabletStage.qml+39−15 tests/mocks/Unity/Application/ApplicationInfo.cpp+59−21 tests/mocks/Unity/Application/ApplicationInfo.h+21−8 tests/mocks/Unity/Application/ApplicationManager.cpp+32−19 tests/mocks/Unity/Application/ApplicationManager.h+7−1 tests/mocks/Unity/Application/CMakeLists.txt+2 tests/mocks/Unity/Application/MirSurfaceItem.cpp+40 tests/mocks/Unity/Application/MirSurfaceItem.h+84 tests/mocks/Unity/Application/SurfaceManager.cpp+31 tests/mocks/Unity/Application/SurfaceManager.h+42 tests/mocks/Unity/Application/plugin.cpp+14−1
qml/Components/Lockscreen.qml+1−1
@@ -48,7 +48,7 @@ Showable {
4848 property int minPinLength: -1
4949 property int maxPinLength: -1
5050
51− property url background: shell.background
51+ property url background: ""
5252
5353 signal entered(string passphrase)
5454 signal cancel()
qml/Shell.qml+1−1
@@ -493,7 +493,7 @@ Item {
493493 visible: required
494494 width: parent.width
495495 height: parent.height - panel.panelHeight
496− //background: shell.background // FIXME: Commenting out as Qt was complaining about this line
496+ background: shell.background
497497 minPinLength: 4
498498 maxPinLength: 4
499499
qml/Stages/SpreadDelegate.qml+7−6
@@ -174,9 +174,10 @@ Item {
174174 }
175175
176176 onDragEnd: {
177− if ((dragVelocity < -600 && distance < -units.gu(8)) || distance < -root.height / 2) {
177+ // velocity and distance values specified by design prototype
178+ if ((dragVelocity < -units.gu(40) && distance < -units.gu(8)) || distance < -root.height / 2) {
178179 animation.animate("up")
179− } else if ((dragVelocity > 600 && distance > units.gu(8)) || distance > root.height / 2) {
180+ } else if ((dragVelocity > units.gu(40) && distance > units.gu(8)) || distance > root.height / 2) {
180181 animation.animate("down")
181182 } else {
182183 animation.animate("center")
@@ -190,14 +191,14 @@ Item {
190191 property bool requestClose: false
191192
192193 function animate(direction) {
193− animation.from = dragArea.distance
194+ animation.from = dragArea.distance;
194195 switch (direction) {
195196 case "up":
196− animation.to = -root.height * 1.5
197+ animation.to = -root.height * 1.5;
197198 requestClose = true;
198199 break;
199200 case "down":
200− animation.to = root.height * 1.5
201+ animation.to = root.height * 1.5;
201202 requestClose = true;
202203 break;
203204 default:
@@ -211,7 +212,7 @@ Item {
211212 dragArea.moving = false;
212213 dragArea.distance = 0;
213214 if (requestClose) {
214− root.closed()
215+ root.closed();
215216 }
216217 }
217218 }
qml/Stages/TabletStage.qml+39−15
@@ -131,19 +131,28 @@ Item {
131131 property int sideStageWidth: units.gu(40)
132132 property bool sideStageVisible: priv.sideStageAppId
133133
134+ // Phase of the animation:
135+ // 0: Starting from right edge, a new app (index 1) comes in from the right
136+ // 1: The app has reached the first snap position.
137+ // 2: The list is dragged further and snaps into the spread view when entering phase 2
134138 property int phase
135139
136− property int phase0Width: sideStageWidth
137− property int phase1Width: sideStageWidth
140+ readonly property int phase0Width: sideStageWidth
141+ readonly property int phase1Width: sideStageWidth
138142
139− property real positionMarker1: 0.2
140− property real positionMarker2: sideStageWidth / spreadView.width
141− property real positionMarker3: 0.6
142− property real positionMarker4: 0.8
143+ // Those markers mark the various positions in the spread (ratio to screen width from right to left):
144+ // 0 - 1: following finger, snap back to the beginning on release
145+ readonly property real positionMarker1: 0.2
146+ // 1 - 2: curved snapping movement, snap to nextInStack on release
147+ readonly property real positionMarker2: sideStageWidth / spreadView.width
148+ // 2 - 3: movement follows finger, snaps to phase 2 (full spread) on release
149+ readonly property real positionMarker3: 0.6
150+ // passing 3, we detach movement from the finger and snap to phase 2 (full spread)
151+ readonly property real positionMarker4: 0.8
143152
144− property int startSnapPosition: phase0Width * 0.5
145− property int endSnapPosition: phase0Width * 0.75
146− property real snapPosition: 0.75
153+ readonly property int startSnapPosition: phase0Width * 0.5
154+ readonly property int endSnapPosition: phase0Width * 0.75
155+ readonly property real snapPosition: 0.75
147156
148157 property int selectedIndex: -1
149158 property int draggedIndex: -1
@@ -187,18 +196,18 @@ Item {
187196
188197 states: [
189198 State {
190− name: "invalid"
199+ name: "empty"
191200 },
192201 State {
193202 name: "main"
194203 },
195− State {
204+ State { // Side Stage only in overlay mode
196205 name: "overlay"
197206 },
198− State {
207+ State { // Main Stage and Side Stage in overlay mode
199208 name: "mainAndOverlay"
200209 },
201− State {
210+ State { // Main Stage and Side Stage in split mode
202211 name: "mainAndSplit"
203212 }
204213 ]
@@ -212,7 +221,7 @@ Item {
212221 if (priv.mainStageAppId && priv.sideStageAppId) {
213222 return "mainAndOverlay";
214223 }
215− return "invalid";
224+ return "empty";
216225 }
217226
218227 onContentXChanged: {
@@ -254,32 +263,47 @@ Item {
254263
255264 var isActive = app.appId == priv.mainStageAppId || app.appId == priv.sideStageAppId;
256265 if (isActive && app.stage == ApplicationInfoInterface.MainStage) {
266+ // if this app is active, and its the MainStage, always put it to index 0
257267 return 0;
258268 }
259269 if (isActive && app.stage == ApplicationInfoInterface.SideStage) {
260270 if (!priv.mainStageAppId) {
261− // only have SS apps running
271+ // Only have SS apps running. Put the active one at 0
262272 return 0;
263273 }
264274
275+ // Precondition now: There's an active MS app and this is SS app:
265276 if (spreadView.nextInStack >= 0 && ApplicationManager.get(spreadView.nextInStack).stage == ApplicationInfoInterface.MainStage) {
277+ // If the next app coming from the right is a MS app, we need to elevate this SS ap above it.
278+ // Put it to at least level 2, or higher if there's more apps coming in before this one.
266279 return Math.max(index, 2);
267280 } else {
281+ // if this is no next app to come in from the right, place this one at index 1, just on top the active MS app.
268282 return 1;
269283 }
270284 }
271285 if (index <= 2 && app.stage == ApplicationInfoInterface.MainStage && priv.sideStageAppId) {
286+ // Ok, this is an inactive MS app. If there's an active SS app around, we need to place this one
287+ // in between the active MS app and the active SS app, so that it comes in from there when dragging from the right.
288+ // If there's now active SS app, just leave it where it is.
272289 return priv.indexOf(priv.sideStageAppId) < index ? index - 1 : index;
273290 }
274291 if (index == spreadView.nextInStack && app.stage == ApplicationInfoInterface.SideStage) {
292+ // This is a SS app and the next one to come in from the right:
275293 if (priv.sideStageAppId && priv.mainStageAppId) {
294+ // If there's both, an active MS and an active SS app, put this one right on top of that
276295 return 2;
277296 }
297+ // Or if there's only one other active app, put it on top of that.
298+ // The case that there isn't any other active app is already handled above.
278299 return 1;
279300 }
280301 if (index == 2 && spreadView.nextInStack == 1 && priv.sideStageAppId) {
302+ // If its index 2 but not the next one to come in, it means
303+ // we've pulled another one down to index 2. Move this one up to 2 instead.
281304 return 3;
282305 }
306+ // don't touch all others... (mostly index > 3 + simple cases where the above doesn't shuffle much)
283307 return index;
284308 }
285309
tests/mocks/Unity/Application/ApplicationInfo.cpp+59−21
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013-2014 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -15,6 +15,8 @@
1515 */
1616
1717#include "ApplicationInfo.h"
18+#include "MirSurfaceItem.h"
19+#include "SurfaceManager.h"
1820
1921#include <QGuiApplication>
2022#include <QQuickItem>
@@ -24,29 +26,39 @@
2426
2527ApplicationInfo::ApplicationInfo(const QString &appId, QObject *parent)
2628 : ApplicationInfoInterface(appId, parent)
27− ,m_appId(appId)
28− ,m_stage(MainStage)
29− ,m_state(Starting)
30− ,m_focused(false)
31− ,m_fullscreen(false)
32− ,m_windowItem(0)
33− ,m_windowComponent(0)
34− ,m_parentItem(0)
29+ , m_appId(appId)
30+ , m_stage(MainStage)
31+ , m_state(Starting)
32+ , m_focused(false)
33+ , m_fullscreen(false)
34+ , m_windowItem(0)
35+ , m_windowComponent(0)
36+ , m_parentItem(0)
37+ , m_surface(0)
3538{
36− QTimer::singleShot(300, this, SLOT(setRunning()));
39+ connect(this, &ApplicationInfo::stateChanged, this, &ApplicationInfo::onStateChanged);
3740}
3841
3942ApplicationInfo::ApplicationInfo(QObject *parent)
4043 : ApplicationInfoInterface(QString(), parent)
41− ,m_stage(MainStage)
42− ,m_state(Starting)
43− ,m_focused(false)
44− ,m_fullscreen(false)
45− ,m_windowItem(0)
46− ,m_windowComponent(0)
47− ,m_parentItem(0)
44+ , m_stage(MainStage)
45+ , m_state(Starting)
46+ , m_focused(false)
47+ , m_fullscreen(false)
48+ , m_windowItem(0)
49+ , m_windowComponent(0)
50+ , m_parentItem(0)
51+ , m_surface(0)
4852{
49− QTimer::singleShot(300, this, SLOT(setRunning()));
53+ connect(this, &ApplicationInfo::stateChanged, this, &ApplicationInfo::onStateChanged);
54+}
55+
56+ApplicationInfo::~ApplicationInfo()
57+{
58+ if (m_surface) {
59+ Q_EMIT SurfaceManager::singleton()->surfaceDestroyed(m_surface);
60+ m_surface->deleteLater();
61+ }
5062}
5163
5264void ApplicationInfo::onWindowComponentStatusChanged(QQmlComponent::Status status)
@@ -55,10 +67,36 @@ void ApplicationInfo::onWindowComponentStatusChanged(QQmlComponent::Status statu
5567 doCreateWindowItem();
5668}
5769
58−void ApplicationInfo::setRunning()
70+void ApplicationInfo::onStateChanged(State state)
71+{
72+ if (state == ApplicationInfo::Running) {
73+ QTimer::singleShot(1000, this, SLOT(createSurface()));
74+ } else if (state == ApplicationInfo::Stopped) {
75+ destroySurface();
76+ }
77+}
78+
79+void ApplicationInfo::createSurface()
80+{
81+ if (m_surface || state() == ApplicationInfo::Stopped) return;
82+
83+ m_surface = new MirSurfaceItem(name(),
84+ MirSurfaceItem::Normal,
85+ fullscreen() ? MirSurfaceItem::Fullscreen : MirSurfaceItem::Maximized,
86+ screenshot());
87+ Q_EMIT surfaceChanged(m_surface);
88+ Q_EMIT SurfaceManager::singleton()->surfaceCreated(m_surface);
89+}
90+
91+void ApplicationInfo::destroySurface()
5992{
60− m_state = Running;
61− Q_EMIT stateChanged();
93+ if (!m_surface) return;
94+ MirSurfaceItem* oldSurface = m_surface;
95+ m_surface = nullptr;
96+
97+ Q_EMIT surfaceChanged(nullptr);
98+ Q_EMIT SurfaceManager::singleton()->surfaceDestroyed(oldSurface);
99+ oldSurface->deleteLater();
62100}
63101
64102void ApplicationInfo::createWindowComponent()
tests/mocks/Unity/Application/ApplicationInfo.h+21−8
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013-2014 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -21,6 +21,7 @@
2121#include <QQmlComponent>
2222
2323class QQuickItem;
24+class MirSurfaceItem;
2425
2526// unity-api
2627#include <unity/shell/application/ApplicationInfoInterface.h>
@@ -36,6 +37,7 @@ class ApplicationInfo : public ApplicationInfoInterface {
3637
3738 Q_PROPERTY(bool fullscreen READ fullscreen WRITE setFullscreen NOTIFY fullscreenChanged)
3839 Q_PROPERTY(Stage stage READ stage WRITE setStage NOTIFY stageChanged)
40+ Q_PROPERTY(MirSurfaceItem* surface READ surface NOTIFY surfaceChanged)
3941
4042 // Only exists in this fake implementation
4143
@@ -45,9 +47,10 @@ class ApplicationInfo : public ApplicationInfoInterface {
4547 // QML component used to represent the application window
4648 Q_PROPERTY(QString windowQml READ windowQml WRITE setWindowQml NOTIFY windowQmlChanged)
4749
48− public:
50+public:
4951 ApplicationInfo(QObject *parent = NULL);
5052 ApplicationInfo(const QString &appId, QObject *parent = NULL);
53+ ~ApplicationInfo();
5154
5255 #define IMPLEMENT_PROPERTY(name, Name, type) \
5356 public: \
@@ -56,11 +59,11 @@ class ApplicationInfo : public ApplicationInfoInterface {
5659 { \
5760 if (m_##name != value) { \
5861 m_##name = value; \
59− Q_EMIT name##Changed(); \
62+ Q_EMIT name##Changed(value); \
6063 } \
6164 } \
6265 Q_SIGNALS: \
63− void name##Changed(); \
66+ void name##Changed(const type&); \
6467 private: \
6568 type m_##name;
6669
@@ -78,21 +81,31 @@ class ApplicationInfo : public ApplicationInfoInterface {
7881
7982 #undef IMPLEMENT_PROPERTY
8083
81− public:
84+public:
85+ MirSurfaceItem* surface() const { return m_surface; }
86+
87+Q_SIGNALS:
88+ void surfaceChanged(MirSurfaceItem*);
89+
90+public:
8291 void showWindow(QQuickItem *parent);
8392 void hideWindow();
8493
85− private Q_SLOTS:
94+private Q_SLOTS:
8695 void onWindowComponentStatusChanged(QQmlComponent::Status status);
87− void setRunning();
96+ void onStateChanged(State state);
97+
98+ void createSurface();
99+ void destroySurface();
88100
89− private:
101+private:
90102 void createWindowItem();
91103 void doCreateWindowItem();
92104 void createWindowComponent();
93105 QQuickItem *m_windowItem;
94106 QQmlComponent *m_windowComponent;
95107 QQuickItem *m_parentItem;
108+ MirSurfaceItem* m_surface;
96109};
97110
98111Q_DECLARE_METATYPE(ApplicationInfo*)
tests/mocks/Unity/Application/ApplicationManager.cpp+32−19
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013-2014 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -16,6 +16,7 @@
1616
1717#include "ApplicationManager.h"
1818#include "ApplicationInfo.h"
19+#include "MirSurfaceItem.h"
1920
2021#include <paths.h>
2122
@@ -36,6 +37,9 @@ ApplicationManager::ApplicationManager(QObject *parent)
3637 , m_sideStage(0)
3738 , m_rightMargin(0)
3839{
40+ m_roleNames.insert(RoleSurface, "surface");
41+ m_roleNames.insert(RoleFullscreen, "fullscreen");
42+
3943 buildListOfAvailableApplications();
4044}
4145
@@ -69,6 +73,10 @@ QVariant ApplicationManager::data(const QModelIndex& index, int role) const {
6973 return app->focused();
7074 case RoleScreenshot:
7175 return app->screenshot();
76+ case RoleSurface:
77+ return QVariant::fromValue(app->surface());
78+ case RoleFullscreen:
79+ return app->fullscreen();
7280 default:
7381 return QVariant();
7482 }
@@ -89,6 +97,17 @@ ApplicationInfo *ApplicationManager::findApplication(const QString &appId) const
8997 return nullptr;
9098}
9199
100+QModelIndex ApplicationManager::findIndex(ApplicationInfo* application)
101+{
102+ for (int i = 0; i < m_runningApplications.size(); ++i) {
103+ if (m_runningApplications.at(i) == application) {
104+ return index(i);
105+ }
106+ }
107+
108+ return QModelIndex();
109+}
110+
92111void ApplicationManager::add(ApplicationInfo *application) {
93112 if (!application) {
94113 return;
@@ -100,6 +119,12 @@ void ApplicationManager::add(ApplicationInfo *application) {
100119 Q_EMIT applicationAdded(application->appId());
101120 Q_EMIT countChanged();
102121 Q_EMIT focusRequested(application->appId());
122+
123+ connect(application, &ApplicationInfo::surfaceChanged, this, [application, this]() {
124+ QModelIndex appIndex = findIndex(application);
125+ if (!appIndex.isValid()) return;
126+ Q_EMIT dataChanged(appIndex, appIndex, QVector<int>() << ApplicationManager::RoleSurface);
127+ });
103128}
104129
105130void ApplicationManager::remove(ApplicationInfo *application) {
@@ -111,6 +136,7 @@ void ApplicationManager::remove(ApplicationInfo *application) {
111136 Q_EMIT applicationRemoved(application->appId());
112137 Q_EMIT countChanged();
113138 }
139+ disconnect(application, &ApplicationInfo::surfaceChanged, this, 0);
114140}
115141
116142void ApplicationManager::move(int from, int to) {
@@ -180,6 +206,7 @@ ApplicationInfo* ApplicationManager::startApplication(const QString &appId,
180206 application->setStage(ApplicationInfo::MainStage);
181207 }
182208 add(application);
209+ application->setState(ApplicationInfo::Running);
183210
184211 return application;
185212}
@@ -193,6 +220,7 @@ bool ApplicationManager::stopApplication(const QString &appId)
193220 if (application->appId() == focusedApplicationId()) {
194221 unfocusCurrentApplication();
195222 }
223+ application->setState(ApplicationInfo::Stopped);
196224 remove(application);
197225 return true;
198226}
@@ -213,7 +241,6 @@ bool ApplicationManager::updateScreenshot(const QString &appId)
213241 return false;
214242 }
215243
216− application->setScreenshot(QString("image://application/%1/%2").arg(appId).arg(QDateTime::currentMSecsSinceEpoch()));
217244 QModelIndex appIndex = index(idx);
218245 Q_EMIT dataChanged(appIndex, appIndex, QVector<int>() << RoleScreenshot);
219246 return true;
@@ -352,6 +379,9 @@ void ApplicationManager::generateQmlStrings(ApplicationInfo *application)
352379 "}").arg(qmlDirectory())
353380 .arg(application->icon().toString());
354381 application->setImageQml(imageQml);
382+
383+ application->setScreenshot(QString("file://%1/Dash/graphics/phone/screenshots/%2@12.png").arg(qmlDirectory())
384+ .arg(application->icon().toString()));
355385}
356386
357387void ApplicationManager::buildListOfAvailableApplications()
@@ -363,7 +393,6 @@ void ApplicationManager::buildListOfAvailableApplications()
363393 application->setName("Dialer");
364394 application->setIcon(QUrl("dialer"));
365395 application->setStage(ApplicationInfo::SideStage);
366− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
367396 generateQmlStrings(application);
368397 m_availableApplications.append(application);
369398
@@ -372,7 +401,6 @@ void ApplicationManager::buildListOfAvailableApplications()
372401 application->setName("Camera");
373402 application->setIcon(QUrl("camera"));
374403 application->setFullscreen(true);
375− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
376404 generateQmlStrings(application);
377405 m_availableApplications.append(application);
378406
@@ -380,7 +408,6 @@ void ApplicationManager::buildListOfAvailableApplications()
380408 application->setAppId("gallery-app");
381409 application->setName("Gallery");
382410 application->setIcon(QUrl("gallery"));
383− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
384411 generateQmlStrings(application);
385412 m_availableApplications.append(application);
386413
@@ -389,7 +416,6 @@ void ApplicationManager::buildListOfAvailableApplications()
389416 application->setName("Facebook");
390417 application->setIcon(QUrl("facebook"));
391418 application->setStage(ApplicationInfo::SideStage);
392− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
393419 generateQmlStrings(application);
394420 m_availableApplications.append(application);
395421
@@ -398,7 +424,6 @@ void ApplicationManager::buildListOfAvailableApplications()
398424 application->setFullscreen(true);
399425 application->setName("Browser");
400426 application->setIcon(QUrl("browser"));
401− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
402427 generateQmlStrings(application);
403428 m_availableApplications.append(application);
404429
@@ -407,7 +432,6 @@ void ApplicationManager::buildListOfAvailableApplications()
407432 application->setName("Twitter");
408433 application->setIcon(QUrl("twitter"));
409434 application->setStage(ApplicationInfo::SideStage);
410− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
411435 generateQmlStrings(application);
412436 m_availableApplications.append(application);
413437
@@ -415,7 +439,6 @@ void ApplicationManager::buildListOfAvailableApplications()
415439 application->setAppId("gmail-webapp");
416440 application->setName("GMail");
417441 application->setIcon(QUrl("gmail"));
418− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
419442 m_availableApplications.append(application);
420443
421444 application = new ApplicationInfo(this);
@@ -423,7 +446,6 @@ void ApplicationManager::buildListOfAvailableApplications()
423446 application->setName("Weather");
424447 application->setIcon(QUrl("weather"));
425448 application->setStage(ApplicationInfo::SideStage);
426− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
427449 generateQmlStrings(application);
428450 m_availableApplications.append(application);
429451
@@ -432,7 +454,6 @@ void ApplicationManager::buildListOfAvailableApplications()
432454 application->setName("Notepad");
433455 application->setIcon(QUrl("notepad"));
434456 application->setStage(ApplicationInfo::SideStage);
435− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
436457 m_availableApplications.append(application);
437458
438459 application = new ApplicationInfo(this);
@@ -440,7 +461,6 @@ void ApplicationManager::buildListOfAvailableApplications()
440461 application->setName("Calendar");
441462 application->setIcon(QUrl("calendar"));
442463 application->setStage(ApplicationInfo::SideStage);
443− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
444464 m_availableApplications.append(application);
445465
446466 application = new ApplicationInfo(this);
@@ -448,21 +468,18 @@ void ApplicationManager::buildListOfAvailableApplications()
448468 application->setName("Media Player");
449469 application->setIcon(QUrl("mediaplayer-app"));
450470 application->setFullscreen(true);
451− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
452471 m_availableApplications.append(application);
453472
454473 application = new ApplicationInfo(this);
455474 application->setAppId("evernote");
456475 application->setName("Evernote");
457476 application->setIcon(QUrl("evernote"));
458− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
459477 m_availableApplications.append(application);
460478
461479 application = new ApplicationInfo(this);
462480 application->setAppId("map");
463481 application->setName("Map");
464482 application->setIcon(QUrl("map"));
465− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
466483 generateQmlStrings(application);
467484 m_availableApplications.append(application);
468485
@@ -470,28 +487,24 @@ void ApplicationManager::buildListOfAvailableApplications()
470487 application->setAppId("pinterest");
471488 application->setName("Pinterest");
472489 application->setIcon(QUrl("pinterest"));
473− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
474490 m_availableApplications.append(application);
475491
476492 application = new ApplicationInfo(this);
477493 application->setAppId("soundcloud");
478494 application->setName("SoundCloud");
479495 application->setIcon(QUrl("soundcloud"));
480− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
481496 m_availableApplications.append(application);
482497
483498 application = new ApplicationInfo(this);
484499 application->setAppId("wikipedia");
485500 application->setName("Wikipedia");
486501 application->setIcon(QUrl("wikipedia"));
487− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
488502 m_availableApplications.append(application);
489503
490504 application = new ApplicationInfo(this);
491505 application->setAppId("youtube");
492506 application->setName("YouTube");
493507 application->setIcon(QUrl("youtube"));
494− application->setScreenshot(QString("image://application/%1/%2").arg(application->appId()).arg(QDateTime::currentMSecsSinceEpoch()));
495508 m_availableApplications.append(application);
496509}
497510
tests/mocks/Unity/Application/ApplicationManager.h+7−1
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013-2014 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -53,6 +53,10 @@ class ApplicationManager : public ApplicationManagerInterface {
5353 ApplicationManager(QObject *parent = NULL);
5454 virtual ~ApplicationManager();
5555
56+ enum MoreRoles {
57+ RoleSurface = RoleScreenshot+1,
58+ RoleFullscreen,
59+ };
5660 enum Role {
5761 Dash, Default, Indicators, Notifications, Greeter, Launcher, OnScreenKeyboard,
5862 ShutdownDialog
@@ -108,6 +112,8 @@ class ApplicationManager : public ApplicationManagerInterface {
108112 int rightMargin() const;
109113 void setRightMargin(int rightMargin);
110114
115+ QModelIndex findIndex(ApplicationInfo* application);
116+
111117 Q_SIGNALS:
112118 void keyboardHeightChanged();
113119 void keyboardVisibleChanged();
tests/mocks/Unity/Application/CMakeLists.txt+2
@@ -6,6 +6,8 @@ set(FakeUnityApplicationQml_SOURCES
66 ApplicationImage.cpp
77 ApplicationManager.cpp
88 ApplicationScreenshotProvider.cpp
9+ MirSurfaceItem.cpp
10+ SurfaceManager.cpp
911 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
1012 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationManagerInterface.h
1113)
tests/mocks/Unity/Application/MirSurfaceItem.cppnew file+40
@@ -0,0 +1,40 @@
1+/*
2+ * Copyright (C) 2014 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 "MirSurfaceItem.h"
18+
19+#include <QPainter>
20+
21+MirSurfaceItem::MirSurfaceItem(const QString& name,
22+ MirSurfaceItem::Type type,
23+ MirSurfaceItem::State state,
24+ const QUrl& screenshot,
25+ QQuickItem *parent)
26+ : QQuickPaintedItem(parent)
27+ , m_name(name)
28+ , m_type(type)
29+ , m_state(state)
30+ , m_img(screenshot.isLocalFile() ? screenshot.toLocalFile() : screenshot.toString())
31+{
32+ setFillColor(Qt::white);
33+}
34+
35+void MirSurfaceItem::paint(QPainter * painter)
36+{
37+ if (!m_img.isNull()) {
38+ painter->drawImage(contentsBoundingRect(), m_img, QRect(QPoint(0,0), m_img.size()));
39+ }
40+}
tests/mocks/Unity/Application/MirSurfaceItem.hnew file+84
@@ -0,0 +1,84 @@
1+/*
2+ * Copyright (C) 2014 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 MIRSURFACEITEM_H
18+#define MIRSURFACEITEM_H
19+
20+#include <QQuickPaintedItem>
21+#include <QImage>
22+
23+class MirSurfaceItem : public QQuickPaintedItem
24+{
25+ Q_OBJECT
26+ Q_ENUMS(Type)
27+ Q_ENUMS(State)
28+
29+ Q_PROPERTY(Type type READ type NOTIFY typeChanged)
30+ Q_PROPERTY(State state READ state NOTIFY stateChanged)
31+ Q_PROPERTY(QString name READ name NOTIFY nameChanged)
32+
33+public:
34+ enum Type {
35+ Normal,
36+ Utility,
37+ Dialog,
38+ Overlay,
39+ Freestyle,
40+ Popover,
41+ InputMethod,
42+ };
43+
44+ enum State {
45+ Unknown,
46+ Restored,
47+ Minimized,
48+ Maximized,
49+ VertMaximized,
50+ /* SemiMaximized, */
51+ Fullscreen,
52+ };
53+
54+ explicit MirSurfaceItem(const QString& name,
55+ Type type,
56+ State state,
57+ const QUrl& screenshot,
58+ QQuickItem *parent = 0);
59+
60+ //getters
61+ Type type() const { return m_type; }
62+ State state() const { return m_state; }
63+ QString name() const { return m_name; }
64+
65+ Q_INVOKABLE void release() {}
66+
67+ void paint(QPainter * painter) override;
68+
69+Q_SIGNALS:
70+ void typeChanged(Type);
71+ void stateChanged(State);
72+ void nameChanged(QString);
73+
74+private:
75+
76+ const QString m_name;
77+ const Type m_type;
78+ const State m_state;
79+ const QImage m_img;
80+};
81+
82+Q_DECLARE_METATYPE(MirSurfaceItem*)
83+
84+#endif // MIRSURFACEITEM_H
tests/mocks/Unity/Application/SurfaceManager.cppnew file+31
@@ -0,0 +1,31 @@
1+/*
2+ * Copyright (C) 2014 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+#include "SurfaceManager.h"
17+
18+SurfaceManager *SurfaceManager::the_surface_manager = nullptr;
19+
20+SurfaceManager *SurfaceManager::singleton()
21+{
22+ if (!the_surface_manager) {
23+ the_surface_manager = new SurfaceManager();
24+ }
25+ return the_surface_manager;
26+}
27+
28+SurfaceManager::SurfaceManager(QObject *parent) :
29+ QObject(parent)
30+{
31+}
tests/mocks/Unity/Application/SurfaceManager.hnew file+42
@@ -0,0 +1,42 @@
1+/*
2+ * Copyright (C) 2014 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 SURFACEMANAGER_H
18+#define SURFACEMANAGER_H
19+
20+#include <QObject>
21+
22+class MirSurfaceItem;
23+
24+class SurfaceManager : public QObject
25+{
26+ Q_OBJECT
27+public:
28+ explicit SurfaceManager(QObject *parent = 0);
29+
30+ static SurfaceManager *singleton();
31+
32+Q_SIGNALS:
33+ void countChanged();
34+ void surfaceCreated(MirSurfaceItem *surface);
35+ void surfaceDestroyed(MirSurfaceItem *surface);
36+
37+private:
38+ static SurfaceManager *the_surface_manager;
39+
40+};
41+
42+#endif // SURFACEMANAGER_H
tests/mocks/Unity/Application/plugin.cpp+14−1
@@ -1,5 +1,5 @@
11/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013-2014 Canonical, Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -19,6 +19,8 @@
1919#include "ApplicationImage.h"
2020#include "ApplicationManager.h"
2121#include "ApplicationScreenshotProvider.h"
22+#include "MirSurfaceItem.h"
23+#include "SurfaceManager.h"
2224
2325#include <qqml.h>
2426#include <QQmlEngine>
@@ -34,14 +36,25 @@ static QObject* applicationManagerSingleton(QQmlEngine* engine, QJSEngine* scrip
3436 return s_appManager;
3537}
3638
39+static QObject* surfaceManagerSingleton(QQmlEngine* engine, QJSEngine* scriptEngine) {
40+ Q_UNUSED(engine);
41+ Q_UNUSED(scriptEngine);
42+ return SurfaceManager::singleton();
43+}
44+
3745void FakeUnityApplicationQmlPlugin::registerTypes(const char *uri)
3846{
47+ qRegisterMetaType<MirSurfaceItem*>("MirSurfaceItem*");
48+
3949 qmlRegisterUncreatableType<unity::shell::application::ApplicationManagerInterface>(uri, 0, 1, "ApplicationManagerInterface", "Abstract interface. Cannot be created in QML");
4050 qmlRegisterSingletonType<ApplicationManager>(uri, 0, 1, "ApplicationManager", applicationManagerSingleton);
51+ qmlRegisterSingletonType<SurfaceManager>(uri, 0, 1, "SurfaceManager", surfaceManagerSingleton);
4152
4253 qmlRegisterUncreatableType<unity::shell::application::ApplicationInfoInterface>(uri, 0, 1, "ApplicationInfoInterface", "Abstract interface. Cannot be created in QML");
4354 qmlRegisterType<ApplicationInfo>(uri, 0, 1, "ApplicationInfo");
4455
56+ qmlRegisterUncreatableType<MirSurfaceItem>(uri, 0, 1, "MirSurfaceItem", "MirSurfaceItem can't be instantiated from QML");
57+
4558 qmlRegisterType<ApplicationImage>(uri, 0, 1, "ApplicationImage");
4659}
4760