Merge lp:~mzanetti/unity8/dash-as-app into lp:unity8

Proposed by Michael Zanetti
Status: Rejected
Rejected by: Michael Zanetti
Proposed branch: lp:~mzanetti/unity8/dash-as-app
Merge into: lp:unity8
Prerequisite: lp:~mzanetti/unity8/drop-running-apps-from-dash
Diff against target: 2874 lines (+972/-763) (has conflicts)
51 files modified
CMakeLists.txt (+1/-0)
data/CMakeLists.txt (+5/-2)
data/unity8-dash.conf (+22/-0)
data/unity8-dash.desktop.in (+9/-0)
data/unity8.conf (+1/-7)
debian/unity8.install (+3/-0)
plugins/Unity/CMakeLists.txt (+1/-0)
plugins/Unity/DashCommunicator/CMakeLists.txt (+19/-0)
plugins/Unity/DashCommunicator/dashcommunicator.cpp (+43/-0)
plugins/Unity/DashCommunicator/dashcommunicator.h (+35/-0)
plugins/Unity/DashCommunicator/dashcommunicatorservice.cpp (+30/-0)
plugins/Unity/DashCommunicator/dashcommunicatorservice.h (+38/-0)
plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.cpp (+39/-0)
plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.h (+39/-0)
plugins/Unity/DashCommunicator/plugin.cpp (+31/-0)
plugins/Unity/DashCommunicator/plugin.h (+34/-0)
plugins/Unity/DashCommunicator/qmldir (+3/-0)
plugins/Unity/Launcher/launchermodel.cpp (+5/-0)
qml/Components/EdgeDemo.qml (+5/-6)
qml/Dash/Dash.qml (+8/-0)
qml/Dash/DashApplication.qml (+13/-0)
qml/Dash/GenericScopeView.qml (+1/-1)
qml/Dash/ScopeListView.qml (+0/-5)
qml/Launcher/Launcher.qml (+2/-3)
qml/Shell.qml (+23/-124)
qml/Stages/PhoneStage.qml (+60/-26)
qml/Stages/SpreadDelegate.qml (+6/-0)
qml/Stages/TabletStage.qml (+82/-36)
qml/Stages/TransformedSpreadDelegate.qml (+6/-5)
qml/Stages/TransformedTabletSpreadDelegate.qml (+29/-1)
src/CMakeLists.txt (+1/-0)
src/Dash/CMakeLists.txt (+12/-0)
src/Dash/main.cpp (+49/-0)
tests/mocks/Unity/Application/ApplicationInfo.cpp (+0/-62)
tests/mocks/Unity/Application/ApplicationInfo.h (+0/-10)
tests/mocks/Unity/Application/ApplicationManager.cpp (+15/-142)
tests/mocks/Unity/Application/ApplicationManager.h (+0/-16)
tests/mocks/Unity/Application/ApplicationScreenshotProvider.cpp (+1/-1)
tests/mocks/Unity/CMakeLists.txt (+1/-0)
tests/mocks/Unity/DashCommunicator/CMakeLists.txt (+18/-0)
tests/mocks/Unity/DashCommunicator/dashcommunicator.cpp (+37/-0)
tests/mocks/Unity/DashCommunicator/dashcommunicator.h (+39/-0)
tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.cpp (+33/-0)
tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.h (+36/-0)
tests/mocks/Unity/DashCommunicator/plugin.cpp (+31/-0)
tests/mocks/Unity/DashCommunicator/plugin.h (+34/-0)
tests/mocks/Unity/DashCommunicator/qmldir (+3/-0)
tests/qmltests/Dash/tst_Dash.qml (+19/-0)
tests/qmltests/Stages/tst_PhoneStage.qml (+3/-2)
tests/qmltests/tst_Shell.qml (+43/-277)
tests/qmltests/tst_ShellWithPin.qml (+4/-37)
Text conflict in debian/changelog
To merge this branch: bzr merge lp:~mzanetti/unity8/dash-as-app
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing
Michael Zanetti (community) Disapprove
Daniel d'Andrada (community) Needs Fixing
Michał Sawicz Needs Fixing
Review via email: mp+227868@code.launchpad.net

Commit message

Split the dash from the shell into a separate app

Description of the change

### Notes for reviewers ###

* It depends on QtCompositor (silo 6). Alternatively this and qtcomp rc can be installed through ppa:unity-team/phone-right-edge

* Adds an upstart script to autolaunch and respawn the dash app.

* Introduces a new plugin DashCommunicator which consists of a server and a client part, to be used to communicate between shell and dash.

* Adds a mock plugin for the DashCommunicator plugin

* Drops a whole bunch of useless stuff from MockApplicationManager which isn't needed any more since QtCompositor. (The fake placing of surfaces behind the shell - as unity-mir did it.). This could/should have been gone earlier, but only became a visible issue with this branch. Those changes are isolated in commit 1099.

* Adds a fake unity8-dash app (screenshot) to MockApplicationManager which will always be there, simulating the running dash app.

* Drops some code and tests for stages in/out dragging, given the dash is a regular app now, the stages are always visible now.

* Updates/simplifies shell and dash tests for the split app scenario.

* Does some slight updates to the Stages to keep the Dash behind the current app when not in spread mode so a left edge flick still shows the dash behind the app.

### Still TODO ###

* Make autopilot work again

### Checklist ###

 * Are there any related MPs required for this MP to build/function as expected? Please list.

https://code.launchpad.net/~unity-team/unity-scopes-shell/drop-appid-workaround/+merge/228427

 * Did you perform an exploratory manual test run of your code change and any related functionality?

Yes, works fine for me, except launching apps from dash and AP (see TODO section)

 * Did you make sure that your branch does not contain spurious tags?

Yes.

 * If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?

I added the additional binary and upstart script to installs, to be reviewed.

 * If you changed the UI, has there been a design review?

Vesa is on holiday atm. I tried to keep UI changes as minimal as possible to fulfill the design request of adding the dash into the spread. So should be good I hope.

To post a comment you must log in.
Revision history for this message
Michał Sawicz (saviq) wrote :

See inline.

Now, on DashCommunicator... I was wondering if we should instead register a scope:/// url handler, and then just dispatch scope:///clickscope/ when needed.

Only tricky part would be on left edge, when we should bring the dash in from the left with your finger, url-dispatcher would request focus, but we should ignore that request then.

review: Needs Fixing
lp:~mzanetti/unity8/dash-as-app updated
1123. By Michael Zanetti

review-fixes for upstart script

Revision history for this message
Michael Zanetti (mzanetti) wrote :

> See inline.

Fixed/replied.

>
> Now, on DashCommunicator... I was wondering if we should instead register a
> scope:/// url handler, and then just dispatch scope:///clickscope/ when
> needed.
>
> Only tricky part would be on left edge, when we should bring the dash in from
> the left with your finger, url-dispatcher would request focus, but we should
> ignore that request then.

I agree the url handler sounds like a useful/required thing for the future, however, as you already mentioned it adds complexity. I tend to think we need both in the long run.

Revision history for this message
Michael Zanetti (mzanetti) wrote :

inline...

lp:~mzanetti/unity8/dash-as-app updated
1124. By Michael Zanetti

merge prereq

1125. By Michael Zanetti

merge prereq

Revision history for this message
Daniel d'Andrada (dandrader) :
review: Needs Fixing
Revision history for this message
Daniel d'Andrada (dandrader) wrote :

Repeating as the inline comments don't work so well.

In SpreadDelegate.qml

"""
1114 + objectName: "surfaceContainer" + index
"""

Using index from inside SpreadDelegate breaks encapsulation. You can achive the same result in tst_Shell.qml by fetching first "appDelegate0" and then fecthing the "surfaceContainer" from within "appDelegate0".

lp:~mzanetti/unity8/dash-as-app updated
1126. By Michael Zanetti

fix review comment and test

Revision history for this message
Michael Zanetti (mzanetti) wrote :

thanks Daniel. Fixed it.

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

Solved the issue I found. But as I didn't actually go through the full diff at all I'll just unblock it by abstaining.

review: Abstain
Revision history for this message
Daniel d'Andrada (dandrader) wrote :

$ make tryShell
1 - launch an app from the launcher
2 - tap on it
<vkb shows up>
3 - do a left edge drag

expected result:
vkb should go away as soon as the app window starts moving righwards.
Just like when you start a right-edge gesture.

actual result:
vkb goes away only once you finish the gesture

vkb going away means the MirSurfaceItem losing focus which on its turn means the SpreadDelegate.interactive going false.

review: Needs Fixing
lp:~mzanetti/unity8/dash-as-app updated
1127. By Michael Zanetti

make the spread non-interactive when dragging from left

Revision history for this message
Michael Zanetti (mzanetti) wrote :

> $ make tryShell
> 1 - launch an app from the launcher
> 2 - tap on it
> <vkb shows up>
> 3 - do a left edge drag
>
> expected result:
> vkb should go away as soon as the app window starts moving righwards.
> Just like when you start a right-edge gesture.
>
> actual result:
> vkb goes away only once you finish the gesture
>
> vkb going away means the MirSurfaceItem losing focus which on its turn means
> the SpreadDelegate.interactive going false.

another good catch. fixed.

Revision history for this message
Michael Zanetti (mzanetti) wrote :
review: Disapprove
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)

Unmerged revisions

1127. By Michael Zanetti

make the spread non-interactive when dragging from left

1126. By Michael Zanetti

fix review comment and test

1125. By Michael Zanetti

merge prereq

1124. By Michael Zanetti

merge prereq

1123. By Michael Zanetti

review-fixes for upstart script

1122. By Michael Zanetti

one more fix for the side stage

1121. By Michael Zanetti

more fixes for tablet mode

1120. By Michael Zanetti

small fix for tablet stage

1119. By Michael Zanetti

fix some visual glitches in the tabletstage

1118. By Michael Zanetti

don't bahave xTranslate when dragging the side stage

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2014-06-11 15:36:51 +0000
3+++ CMakeLists.txt 2014-07-28 15:50:22 +0000
4@@ -96,6 +96,7 @@
5 declare_autopilot_test(shell unity8.shell ${CMAKE_SOURCE_DIR}/tests/autopilot/)
6
7 set(SHELL_APP unity8)
8+set(DASH_APP unity8-dash)
9 set(SCOPE_TOOL unity-scope-tool)
10
11 include_directories(
12
13=== modified file 'data/CMakeLists.txt'
14--- data/CMakeLists.txt 2014-06-11 15:36:51 +0000
15+++ data/CMakeLists.txt 2014-07-28 15:50:22 +0000
16@@ -1,7 +1,10 @@
17-# generate desktop file
18+# generate desktop files
19 configure_file(${SHELL_APP}.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/${SHELL_APP}.desktop @ONLY)
20+configure_file(${DASH_APP}.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/${DASH_APP}.desktop @ONLY)
21
22 # install desktop files
23-install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${SHELL_APP}.desktop
24+install(FILES
25+ ${CMAKE_CURRENT_BINARY_DIR}/${SHELL_APP}.desktop
26+ ${CMAKE_CURRENT_BINARY_DIR}/${DASH_APP}.desktop
27 DESTINATION ${CMAKE_INSTALL_DATADIR}/applications
28 )
29
30=== added file 'data/unity8-dash.conf'
31--- data/unity8-dash.conf 1970-01-01 00:00:00 +0000
32+++ data/unity8-dash.conf 2014-07-28 15:50:22 +0000
33@@ -0,0 +1,22 @@
34+description "Unity Shell v8 Dash"
35+author "Michael Zanetti <michael.zanetti@canonical.com>"
36+
37+emits scope-ui-starting
38+
39+start on started unity8
40+stop on stopping unity8
41+
42+kill timeout 120
43+
44+respawn
45+
46+pre-start script
47+ if [ -z "$UNITY_SCOPES_LIST" ]; then
48+ # FIXME: remove once we have this in dconf
49+ initctl set-env UNITY_SCOPES_LIST="scopes;clickscope;musicaggregator;videoaggregator"
50+ fi
51+
52+ initctl emit scope-ui-starting
53+end script
54+
55+exec ${BINARY:-unity8-dash} $ARGS --desktop_file_hint=/usr/share/applications/unity8-dash.desktop
56
57=== added file 'data/unity8-dash.desktop.in'
58--- data/unity8-dash.desktop.in 1970-01-01 00:00:00 +0000
59+++ data/unity8-dash.desktop.in 2014-07-28 15:50:22 +0000
60@@ -0,0 +1,9 @@
61+[Desktop Entry]
62+Type=Application
63+Name=Unity 8 Dash
64+Comment=The converged Unity shell dash
65+Exec=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_BINDIR@/unity8-dash
66+Terminal=false
67+Icon=unity8
68+NoDisplay=true
69+X-Ubuntu-Touch=true
70
71=== modified file 'data/unity8.conf'
72--- data/unity8.conf 2014-07-16 15:51:56 +0000
73+++ data/unity8.conf 2014-07-28 15:50:22 +0000
74@@ -1,7 +1,7 @@
75 description "Unity Shell v8"
76 author "Ricardo Mendoza <ricmm@ubuntu.com>"
77
78-emits scope-ui-starting indicator-services-start
79+emits indicator-services-start
80
81 start on ((xsession SESSION=ubuntu-touch) or (xsession SESSION=ubuntu-touch-surfaceflinger)) and started dbus
82 stop on desktop-end
83@@ -34,11 +34,6 @@
84 gdbus call --session --dest org.freedesktop.DBus --object-path /org/freedesktop/DBus --method org.freedesktop.DBus.UpdateActivationEnvironment "@a{ss} {'MIR_SOCKET': '$MIR_SERVER_FILE'}"
85 fi
86
87- if [ -z "$UNITY_SCOPES_LIST" ]; then
88- # FIXME: remove once we have this in dconf
89- initctl set-env UNITY_SCOPES_LIST="scopes;clickscope;musicaggregator;videoaggregator"
90- fi
91-
92 # Remove the socket if still there
93 if [ -S "$MIR_SERVER_FILE" ]; then
94 rm "$MIR_SERVER_FILE"
95@@ -46,7 +41,6 @@
96
97 initctl set-env --global MIR_SERVER_PROMPT_FILE=1
98
99- initctl emit scope-ui-starting
100 initctl emit --no-wait indicator-services-start
101 end script
102
103
104=== modified file 'debian/unity8.install'
105--- debian/unity8.install 2014-06-11 15:36:51 +0000
106+++ debian/unity8.install 2014-07-28 15:50:22 +0000
107@@ -1,6 +1,9 @@
108 data/unity8.conf usr/share/upstart/sessions/
109+data/unity8-dash.conf usr/share/upstart/sessions/
110 usr/bin/unity8
111+usr/bin/unity8-dash
112 usr/share/applications/unity8.desktop
113+usr/share/applications/unity8-dash.desktop
114 usr/share/unity8/Greeter
115 usr/share/unity8/Hud
116 usr/share/unity8/Launcher
117
118=== modified file 'plugins/Unity/CMakeLists.txt'
119--- plugins/Unity/CMakeLists.txt 2014-05-06 14:28:48 +0000
120+++ plugins/Unity/CMakeLists.txt 2014-07-28 15:50:22 +0000
121@@ -1,3 +1,4 @@
122 add_subdirectory(Indicators)
123 add_subdirectory(Launcher)
124 add_subdirectory(Session)
125+add_subdirectory(DashCommunicator)
126
127=== added directory 'plugins/Unity/DashCommunicator'
128=== added file 'plugins/Unity/DashCommunicator/CMakeLists.txt'
129--- plugins/Unity/DashCommunicator/CMakeLists.txt 1970-01-01 00:00:00 +0000
130+++ plugins/Unity/DashCommunicator/CMakeLists.txt 2014-07-28 15:50:22 +0000
131@@ -0,0 +1,19 @@
132+include_directories(
133+ ${CMAKE_CURRENT_SOURCE_DIR}
134+)
135+
136+set(QMLDASHCOMMUNICATORPLUGIN_SRC
137+ plugin.cpp
138+ dbusdashcommunicatorservice.cpp
139+ dashcommunicatorservice.cpp
140+ dashcommunicator.cpp
141+ )
142+
143+add_library(DashCommunicator-qml MODULE
144+ ${QMLDASHCOMMUNICATORPLUGIN_SRC}
145+ )
146+
147+qt5_use_modules(DashCommunicator-qml DBus Qml)
148+
149+# export the qmldir and qmltypes files
150+add_unity8_plugin(Unity.DashCommunicator 0.1 Unity/DashCommunicator TARGETS DashCommunicator-qml)
151
152=== added file 'plugins/Unity/DashCommunicator/dashcommunicator.cpp'
153--- plugins/Unity/DashCommunicator/dashcommunicator.cpp 1970-01-01 00:00:00 +0000
154+++ plugins/Unity/DashCommunicator/dashcommunicator.cpp 2014-07-28 15:50:22 +0000
155@@ -0,0 +1,43 @@
156+/*
157+ * Copyright (C) 2014 Canonical, Ltd.
158+ *
159+ * This program is free software: you can redistribute it and/or modify it under
160+ * the terms of the GNU Lesser General Public License version 3, as published by
161+ * the Free Software Foundation.
162+ *
163+ * This program is distributed in the hope that it will be useful, but WITHOUT
164+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
165+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
166+ * Lesser General Public License for more details.
167+ *
168+ * You should have received a copy of the GNU Lesser General Public License
169+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
170+ */
171+
172+#include "dashcommunicator.h"
173+
174+#include <QObject>
175+#include <QDBusConnection>
176+#include <QDBusInterface>
177+#include <QDebug>
178+
179+DashCommunicator::DashCommunicator(QObject *parent):
180+ QObject(parent)
181+{
182+}
183+
184+DashCommunicator::~DashCommunicator()
185+{
186+}
187+
188+
189+void DashCommunicator::setCurrentScope(const QString &scopeId, bool animate, bool reset)
190+{
191+ QDBusConnection connection = QDBusConnection::sessionBus();
192+ QDBusInterface dashIface ("com.canonical.UnityDash",
193+ "/com/canonical/UnityDash",
194+ "",
195+ connection);
196+
197+ dashIface.call("SetCurrentScope", scopeId, animate, reset);
198+}
199
200=== added file 'plugins/Unity/DashCommunicator/dashcommunicator.h'
201--- plugins/Unity/DashCommunicator/dashcommunicator.h 1970-01-01 00:00:00 +0000
202+++ plugins/Unity/DashCommunicator/dashcommunicator.h 2014-07-28 15:50:22 +0000
203@@ -0,0 +1,35 @@
204+/*
205+ * Copyright (C) 2014 Canonical, Ltd.
206+ *
207+ * This program is free software: you can redistribute it and/or modify it under
208+ * the terms of the GNU Lesser General Public License version 3, as published by
209+ * the Free Software Foundation.
210+ *
211+ * This program is distributed in the hope that it will be useful, but WITHOUT
212+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
213+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
214+ * Lesser General Public License for more details.
215+ *
216+ * You should have received a copy of the GNU Lesser General Public License
217+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
218+ */
219+
220+#ifndef DASHCOMMUNICATOR_H
221+#define DASHCOMMUNICATOR_H
222+
223+#include <QObject>
224+
225+class DashCommunicator: public QObject
226+{
227+ Q_OBJECT
228+ Q_CLASSINFO("D-Bus Interface", "com.canonical.Unity.DashCommunicator")
229+
230+public:
231+ DashCommunicator(QObject *parent = 0);
232+ ~DashCommunicator();
233+
234+public Q_SLOTS:
235+ void setCurrentScope(const QString &scopeId, bool animate, bool reset);
236+};
237+
238+#endif
239
240=== added file 'plugins/Unity/DashCommunicator/dashcommunicatorservice.cpp'
241--- plugins/Unity/DashCommunicator/dashcommunicatorservice.cpp 1970-01-01 00:00:00 +0000
242+++ plugins/Unity/DashCommunicator/dashcommunicatorservice.cpp 2014-07-28 15:50:22 +0000
243@@ -0,0 +1,30 @@
244+/*
245+ * Copyright (C) 2014 Canonical, Ltd.
246+ *
247+ * This program is free software: you can redistribute it and/or modify it under
248+ * the terms of the GNU Lesser General Public License version 3, as published by
249+ * the Free Software Foundation.
250+ *
251+ * This program is distributed in the hope that it will be useful, but WITHOUT
252+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
253+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
254+ * Lesser General Public License for more details.
255+ *
256+ * You should have received a copy of the GNU Lesser General Public License
257+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
258+ */
259+
260+#include "dashcommunicatorservice.h"
261+
262+DashCommunicatorService::DashCommunicatorService(QObject *parent):
263+ QObject(parent),
264+ m_dbusService(new DBusDashCommunicatorService(this))
265+{
266+ connect(m_dbusService, &DBusDashCommunicatorService::setCurrentScope, this, &DashCommunicatorService::setCurrentScope);
267+}
268+
269+
270+DashCommunicatorService::~DashCommunicatorService()
271+{
272+
273+}
274
275=== added file 'plugins/Unity/DashCommunicator/dashcommunicatorservice.h'
276--- plugins/Unity/DashCommunicator/dashcommunicatorservice.h 1970-01-01 00:00:00 +0000
277+++ plugins/Unity/DashCommunicator/dashcommunicatorservice.h 2014-07-28 15:50:22 +0000
278@@ -0,0 +1,38 @@
279+/*
280+ * Copyright (C) 2014 Canonical, Ltd.
281+ *
282+ * This program is free software: you can redistribute it and/or modify it under
283+ * the terms of the GNU Lesser General Public License version 3, as published by
284+ * the Free Software Foundation.
285+ *
286+ * This program is distributed in the hope that it will be useful, but WITHOUT
287+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
288+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
289+ * Lesser General Public License for more details.
290+ *
291+ * You should have received a copy of the GNU Lesser General Public License
292+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
293+ */
294+
295+#ifndef DASHCOMMUNICATORSERVICE_H
296+#define DASHCOMMUNICATORSERVICE_H
297+
298+#include "dbusdashcommunicatorservice.h"
299+
300+#include <QObject>
301+
302+class DashCommunicatorService: public QObject
303+{
304+ Q_OBJECT
305+public:
306+ DashCommunicatorService(QObject *parent = 0);
307+ ~DashCommunicatorService();
308+
309+Q_SIGNALS:
310+ void setCurrentScope(const QString &scopeId, bool animate, bool reset);
311+
312+private:
313+ DBusDashCommunicatorService *m_dbusService;
314+};
315+
316+#endif // DBUSUNITYSESSIONSERVICE_H
317
318=== added file 'plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.cpp'
319--- plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.cpp 1970-01-01 00:00:00 +0000
320+++ plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.cpp 2014-07-28 15:50:22 +0000
321@@ -0,0 +1,39 @@
322+/*
323+ * Copyright (C) 2014 Canonical, Ltd.
324+ *
325+ * This program is free software: you can redistribute it and/or modify it under
326+ * the terms of the GNU Lesser General Public License version 3, as published by
327+ * the Free Software Foundation.
328+ *
329+ * This program is distributed in the hope that it will be useful, but WITHOUT
330+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
331+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
332+ * Lesser General Public License for more details.
333+ *
334+ * You should have received a copy of the GNU Lesser General Public License
335+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
336+ */
337+
338+#include "dbusdashcommunicatorservice.h"
339+
340+#include <QDBusConnection>
341+#include <QDBusInterface>
342+#include <QDebug>
343+
344+DBusDashCommunicatorService::DBusDashCommunicatorService(QObject *parent):
345+ QObject(parent)
346+{
347+ QDBusConnection connection = QDBusConnection::sessionBus();
348+
349+ connection.registerService("com.canonical.UnityDash");
350+ connection.registerObject("/com/canonical/UnityDash", this, QDBusConnection::ExportScriptableSlots);
351+}
352+
353+DBusDashCommunicatorService::~DBusDashCommunicatorService()
354+{
355+}
356+
357+void DBusDashCommunicatorService::SetCurrentScope(const QString &scopeId, bool animate, bool reset)
358+{
359+ Q_EMIT setCurrentScope(scopeId, animate, reset);
360+}
361
362=== added file 'plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.h'
363--- plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.h 1970-01-01 00:00:00 +0000
364+++ plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.h 2014-07-28 15:50:22 +0000
365@@ -0,0 +1,39 @@
366+/*
367+ * Copyright (C) 2014 Canonical, Ltd.
368+ *
369+ * This program is free software: you can redistribute it and/or modify it under
370+ * the terms of the GNU Lesser General Public License version 3, as published by
371+ * the Free Software Foundation.
372+ *
373+ * This program is distributed in the hope that it will be useful, but WITHOUT
374+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
375+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
376+ * Lesser General Public License for more details.
377+ *
378+ * You should have received a copy of the GNU Lesser General Public License
379+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
380+ */
381+
382+#ifndef DBUSDASHCOMMUNICATORSERVICE_H
383+#define DBUSDASHCOMMUNICATORSERVICE_H
384+
385+#include <QObject>
386+
387+class DBusDashCommunicatorService: public QObject
388+{
389+ Q_OBJECT
390+ Q_CLASSINFO("D-Bus Interface", "com.canonical.Unity.DashCommunicator")
391+
392+public:
393+ DBusDashCommunicatorService(QObject *parent = 0);
394+ ~DBusDashCommunicatorService();
395+
396+Q_SIGNALS:
397+ void setCurrentScope(const QString &scopeId, bool animate, bool reset);
398+
399+public Q_SLOTS:
400+ Q_SCRIPTABLE void SetCurrentScope(const QString &scopeId, bool animate, bool reset);
401+
402+};
403+
404+#endif // DBUSUNITYSESSIONSERVICE_H
405
406=== added file 'plugins/Unity/DashCommunicator/plugin.cpp'
407--- plugins/Unity/DashCommunicator/plugin.cpp 1970-01-01 00:00:00 +0000
408+++ plugins/Unity/DashCommunicator/plugin.cpp 2014-07-28 15:50:22 +0000
409@@ -0,0 +1,31 @@
410+/*
411+ * Copyright (C) 2014 Canonical, Ltd.
412+ *
413+ * This program is free software; you can redistribute it and/or modify
414+ * it under the terms of the GNU General Public License as published by
415+ * the Free Software Foundation; version 3.
416+ *
417+ * This program is distributed in the hope that it will be useful,
418+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
419+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
420+ * GNU General Public License for more details.
421+ *
422+ * You should have received a copy of the GNU General Public License
423+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
424+ *
425+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
426+ */
427+
428+#include "plugin.h"
429+#include "dashcommunicator.h"
430+#include "dashcommunicatorservice.h"
431+
432+#include <QDBusConnection>
433+#include <QtQml/qqml.h>
434+
435+void DashCommunicatorPlugin::registerTypes(const char *uri)
436+{
437+ Q_ASSERT(uri == QStringLiteral("Unity.DashCommunicator"));
438+ qmlRegisterType<DashCommunicatorService>(uri, 0, 1, "DashCommunicatorService");
439+ qmlRegisterType<DashCommunicator>(uri, 0, 1, "DashCommunicator");
440+}
441
442=== added file 'plugins/Unity/DashCommunicator/plugin.h'
443--- plugins/Unity/DashCommunicator/plugin.h 1970-01-01 00:00:00 +0000
444+++ plugins/Unity/DashCommunicator/plugin.h 2014-07-28 15:50:22 +0000
445@@ -0,0 +1,34 @@
446+/*
447+ * Copyright (C) 2014 Canonical, Ltd.
448+ *
449+ * This program is free software; you can redistribute it and/or modify
450+ * it under the terms of the GNU General Public License as published by
451+ * the Free Software Foundation; version 3.
452+ *
453+ * This program is distributed in the hope that it will be useful,
454+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
455+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
456+ * GNU General Public License for more details.
457+ *
458+ * You should have received a copy of the GNU General Public License
459+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
460+ *
461+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
462+ */
463+
464+#ifndef DASHCOMMUNICATOR_PLUGIN_H
465+#define DASHCOMMUNICATOR_PLUGIN_H
466+
467+#include <QtQml/QQmlEngine>
468+#include <QtQml/QQmlExtensionPlugin>
469+
470+class DashCommunicatorPlugin : public QQmlExtensionPlugin
471+{
472+ Q_OBJECT
473+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
474+
475+public:
476+ void registerTypes(const char *uri);
477+};
478+
479+#endif
480
481=== added file 'plugins/Unity/DashCommunicator/qmldir'
482--- plugins/Unity/DashCommunicator/qmldir 1970-01-01 00:00:00 +0000
483+++ plugins/Unity/DashCommunicator/qmldir 2014-07-28 15:50:22 +0000
484@@ -0,0 +1,3 @@
485+module Unity.DashCommunicator
486+plugin DashCommunicator-qml
487+typeinfo DashCommunicator.qmltypes
488
489=== modified file 'plugins/Unity/Launcher/launchermodel.cpp'
490--- plugins/Unity/Launcher/launchermodel.cpp 2014-07-24 06:11:07 +0000
491+++ plugins/Unity/Launcher/launchermodel.cpp 2014-07-28 15:50:22 +0000
492@@ -317,6 +317,11 @@
493 return;
494 }
495
496+ if (app->appId() == "unity8-dash") {
497+ // Not adding the dash app
498+ return;
499+ }
500+
501 bool found = false;
502 Q_FOREACH(LauncherItem *item, m_list) {
503 if (app->appId() == item->appId()) {
504
505=== modified file 'qml/Components/EdgeDemo.qml'
506--- qml/Components/EdgeDemo.qml 2014-06-11 15:36:51 +0000
507+++ qml/Components/EdgeDemo.qml 2014-07-28 15:50:22 +0000
508@@ -22,7 +22,6 @@
509 id: demo
510
511 property Item greeter
512- property Item dash
513 property Item launcher
514 property Item indicators
515 property Item underlay
516@@ -144,7 +143,7 @@
517 "edge": "top",
518 "title": i18n.tr("Top edge"),
519 "text": i18n.tr("Try swiping from the top edge to access the indicators"),
520- "anchors.fill": demo.dash,
521+ "anchors.fill": demo.underlay,
522 });
523 }
524 if (d.topEdgeDemo) {
525@@ -193,12 +192,12 @@
526 function startLeftEdgeDemo() {
527 demo.panelEnabled = false;
528 demo.launcherEnabled = true;
529- if (demo.dash && demo.underlay) {
530+ if (demo.underlay) {
531 d.leftEdgeDemo = d.overlay.createObject(demo.underlay, {
532 "edge": "left",
533 "title": i18n.tr("Left edge"),
534 "text": i18n.tr("Swipe from the left to reveal the launcher for quick access to apps"),
535- "anchors.fill": demo.dash,
536+ "anchors.fill": demo.underlay,
537 });
538 }
539 if (d.leftEdgeDemo) {
540@@ -221,12 +220,12 @@
541
542 function startFinalEdgeDemo() {
543 demo.launcherEnabled = false;
544- if (demo.dash && demo.underlay) {
545+ if (demo.underlay) {
546 d.finalEdgeDemo = d.overlay.createObject(demo.underlay, {
547 "edge": "none",
548 "title": i18n.tr("Well done"),
549 "text": i18n.tr("You have now mastered the edge gestures and can start using the phone<br><br>Tap on the screen to start"),
550- "anchors.fill": demo.dash,
551+ "anchors.fill": demo.underlay,
552 "showSkip": false,
553 });
554 }
555
556=== modified file 'qml/Dash/Dash.qml'
557--- qml/Dash/Dash.qml 2014-07-07 08:20:04 +0000
558+++ qml/Dash/Dash.qml 2014-07-28 15:50:22 +0000
559@@ -18,6 +18,7 @@
560 import Ubuntu.Components 0.1
561 import Unity 0.2
562 import Utils 0.1
563+import Unity.DashCommunicator 0.1
564 import "../Components"
565
566 Showable {
567@@ -29,6 +30,13 @@
568 property string showScopeOnLoaded: "clickscope"
569 property real contentScale: 1.0
570
571+ DashCommunicatorService {
572+ objectName: "dashCommunicatorService"
573+ onSetCurrentScope: {
574+ dash.setCurrentScope(scopeId, animate, reset)
575+ }
576+ }
577+
578 function setCurrentScope(scopeId, animate, reset) {
579 var scopeIndex = filteredScopes.findFirst(Scopes.RoleId, scopeId)
580
581
582=== added file 'qml/Dash/DashApplication.qml'
583--- qml/Dash/DashApplication.qml 1970-01-01 00:00:00 +0000
584+++ qml/Dash/DashApplication.qml 2014-07-28 15:50:22 +0000
585@@ -0,0 +1,13 @@
586+import QtQuick 2.2
587+import Ubuntu.Components 1.0
588+
589+MainView {
590+ width: units.gu(40)
591+ height: units.gu(71)
592+
593+ useDeprecatedToolbar: false
594+
595+ Dash {
596+ anchors.fill: parent
597+ }
598+}
599
600=== modified file 'qml/Dash/GenericScopeView.qml'
601--- qml/Dash/GenericScopeView.qml 2014-07-28 15:50:19 +0000
602+++ qml/Dash/GenericScopeView.qml 2014-07-28 15:50:22 +0000
603@@ -46,7 +46,7 @@
604 }
605
606 function activateApp(appId) {
607- shell.activateApplication(appId);
608+ Qt.openUrlExternally(appId);
609 }
610
611 function positionAtBeginning() {
612
613=== modified file 'qml/Dash/ScopeListView.qml'
614--- qml/Dash/ScopeListView.qml 2014-06-11 15:36:51 +0000
615+++ qml/Dash/ScopeListView.qml 2014-07-28 15:50:22 +0000
616@@ -20,9 +20,4 @@
617 ListViewWithPageHeader {
618 maximumFlickVelocity: height * 10
619 flickDeceleration: height * 2
620-
621- Connections {
622- target: greeter
623- onShownChanged: if (greeter.shown) showHeader()
624- }
625 }
626
627=== added file 'qml/Dash/graphics/phone/screenshots/dash.png'
628=== added file 'qml/Dash/graphics/phone/screenshots/unity8-dash@12.png'
629Binary files qml/Dash/graphics/phone/screenshots/unity8-dash@12.png 1970-01-01 00:00:00 +0000 and qml/Dash/graphics/phone/screenshots/unity8-dash@12.png 2014-07-28 15:50:22 +0000 differ
630=== modified file 'qml/Launcher/Launcher.qml'
631--- qml/Launcher/Launcher.qml 2014-07-28 15:50:19 +0000
632+++ qml/Launcher/Launcher.qml 2014-07-28 15:50:22 +0000
633@@ -29,8 +29,7 @@
634 property int dragAreaWidth: units.gu(1)
635 property int minimizeDistance: units.gu(26)
636 property real progress: dragArea.dragging && dragArea.touchX > panelWidth ?
637- (width * (dragArea.touchX-panelWidth) / (width - panelWidth)) :
638- (dragArea.dragging ? 0.001 : 0)
639+ (width * (dragArea.touchX-panelWidth) / (width - panelWidth)) : 0
640
641 readonly property bool shown: panel.x > -panel.width
642
643@@ -245,7 +244,7 @@
644 if (!dragging) {
645 if (distance > panel.width / 2) {
646 if (distance > minimizeDistance) {
647- root.dash()
648+ root.fadeOut();
649 } else {
650 root.switchToNextState("visible")
651 }
652
653=== modified file 'qml/Shell.qml'
654--- qml/Shell.qml 2014-07-28 15:50:19 +0000
655+++ qml/Shell.qml 2014-07-28 15:50:22 +0000
656@@ -25,7 +25,6 @@
657 import LightDM 0.1 as LightDM
658 import Powerd 0.1
659 import SessionBroadcast 0.1
660-import "Dash"
661 import "Greeter"
662 import "Launcher"
663 import "Panel"
664@@ -34,6 +33,7 @@
665 import "Stages"
666 import Unity.Notifications 1.0 as NotificationBackend
667 import Unity.Session 0.1
668+import Unity.DashCommunicator 0.1
669
670 Item {
671 id: shell
672@@ -48,8 +48,6 @@
673 property url background
674 readonly property real panelHeight: panel.panelHeight
675
676- property bool dashShown: dash.shown && dash.available && underlay.visible
677-
678 property bool sideStageEnabled: shell.width >= units.gu(100)
679 readonly property string focusedApplicationId: ApplicationManager.focusedApplicationId
680
681@@ -59,7 +57,6 @@
682 } else {
683 var execFlags = shell.sideStageEnabled ? ApplicationManager.NoFlag : ApplicationManager.ForceMainStage;
684 ApplicationManager.startApplication(appId, execFlags);
685- stages.show();
686 }
687 }
688
689@@ -86,6 +83,11 @@
690 id: volumeControl
691 }
692
693+ DashCommunicator {
694+ id: dash
695+ objectName: "dashCommunicator"
696+ }
697+
698 WindowKeysFilter {
699 // Handle but do not filter out volume keys
700 Keys.onVolumeUpPressed: { volumeControl.volumeUp(); event.accepted = false; }
701@@ -121,64 +123,12 @@
702 visible: !fullyCovered
703
704 Image {
705- anchors.fill: dash
706+ anchors.fill: underlay
707 source: shell.width > shell.height ? "Dash/graphics/paper_landscape.png" : "Dash/graphics/paper_portrait.png"
708 fillMode: Image.PreserveAspectCrop
709 horizontalAlignment: Image.AlignRight
710 verticalAlignment: Image.AlignTop
711 }
712-
713- Dash {
714- id: dash
715- objectName: "dash"
716-
717- available: !LightDM.Greeter.active
718- hides: [stages, launcher, panel.indicators]
719- shown: disappearingAnimationProgress !== 1.0 && greeterWrapper.showProgress !== 1.0 &&
720- !(panel.indicators.fullyOpened && !sideStageEnabled)
721- enabled: disappearingAnimationProgress === 0.0 && greeterWrapper.showProgress === 0.0 && edgeDemo.dashEnabled
722-
723- anchors {
724- fill: parent
725- topMargin: panel.panelHeight
726- }
727-
728- contentScale: 1.0 - 0.2 * disappearingAnimationProgress
729- opacity: 1.0 - disappearingAnimationProgress
730- property real disappearingAnimationProgress: stages.showProgress
731-
732- // FIXME: only necessary because stages.showProgress is not animated
733- Behavior on disappearingAnimationProgress { SmoothedAnimation { velocity: 5 }}
734- }
735- }
736-
737- EdgeDragArea {
738- id: stagesDragArea
739- direction: Direction.Leftwards
740-
741- anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
742- width: shell.edgeSize
743-
744- property real progress: stages.width
745-
746- onTouchXChanged: {
747- if (status == DirectionalDragArea.Recognized) {
748- if (ApplicationManager.empty) {
749- progress = Math.max(stages.width - stagesDragArea.width + touchX, stages.width * .3);
750- } else {
751- progress = stages.width - stagesDragArea.width + touchX;
752- }
753- }
754- }
755-
756- onDraggingChanged: {
757- if (!dragging) {
758- if (!ApplicationManager.empty && progress < stages.width - units.gu(10)) {
759- stages.show();
760- }
761- stagesDragArea.progress = Qt.binding(function () { return stages.width; });
762- }
763- }
764 }
765
766 Item {
767@@ -186,55 +136,7 @@
768 objectName: "stages"
769 width: parent.width
770 height: parent.height
771-
772- visible: !fullyHidden && !ApplicationManager.empty
773-
774- x: {
775- if (shown) {
776- if (locked || greeter.fakeActiveForApp !== "") {
777- return 0;
778- }
779- return launcher.progress;
780- } else {
781- return stagesDragArea.progress
782- }
783- }
784- Behavior on x { SmoothedAnimation { velocity: 600; duration: UbuntuAnimation.FastDuration } }
785-
786- property bool shown: false
787- onShownChanged: {
788- if (shown) {
789- if (ApplicationManager.count > 0) {
790- ApplicationManager.focusApplication(ApplicationManager.get(0).appId);
791- }
792- } else {
793- if (ApplicationManager.focusedApplicationId) {
794- ApplicationManager.updateScreenshot(ApplicationManager.focusedApplicationId);
795- ApplicationManager.unfocusCurrentApplication();
796- }
797- }
798- }
799-
800- // Avoid a silent "divide by zero -> NaN" situation during init as shell.width will be
801- // zero. That breaks the property binding and the function won't be reevaluated once
802- // shell.width is set, with the NaN result staying there for good.
803- property real showProgress: shell.width ? MathUtils.clamp(1 - x / shell.width, 0, 1) : 0
804-
805- property bool fullyShown: x == 0
806- property bool fullyHidden: x == width
807-
808- property bool locked: applicationsDisplayLoader.item ? applicationsDisplayLoader.item.locked : false
809-
810- // It might technically not be fullyShown but visually it just looks so.
811- property bool roughlyFullyShown: x >= 0 && x <= units.gu(1)
812-
813- function show() {
814- shown = true;
815- }
816-
817- function hide() {
818- shown = false;
819- }
820+ visible: !ApplicationManager.empty
821
822 Connections {
823 target: ApplicationManager
824@@ -243,7 +145,6 @@
825 lockscreen.show();
826 }
827 greeter.hide();
828- stages.show();
829 }
830
831 onFocusedApplicationIdChanged: {
832@@ -254,18 +155,9 @@
833 }
834
835 onApplicationAdded: {
836- if (greeter.shown) {
837+ if (greeter.shown && appId != "unity8-dash") {
838 greeter.hide();
839 }
840- if (!stages.shown) {
841- stages.show();
842- }
843- }
844-
845- onEmptyChanged: {
846- if (ApplicationManager.empty) {
847- stages.hide();
848- }
849 }
850 }
851
852@@ -294,14 +186,18 @@
853 Binding {
854 target: applicationsDisplayLoader.item
855 property: "interactive"
856- value: stages.roughlyFullyShown && !greeter.shown && !lockscreen.shown
857- && panel.indicators.fullyClosed
858+ value: !greeter.shown && !lockscreen.shown && panel.indicators.fullyClosed && launcher.progress == 0
859 }
860 Binding {
861 target: applicationsDisplayLoader.item
862 property: "spreadEnabled"
863 value: greeter.fakeActiveForApp === "" // to support emergency dialer hack
864 }
865+ Binding {
866+ target: applicationsDisplayLoader.item
867+ property: "inverseProgress"
868+ value: launcher.progress
869+ }
870 }
871 }
872
873@@ -525,7 +421,7 @@
874
875 var animate = !LightDM.Greeter.active && !stages.shown
876 dash.setCurrentScope("clickscope", animate, false)
877- stages.hide()
878+ ApplicationManager.requestFocusApplication("unity8-dash")
879 }
880
881 function showDash() {
882@@ -534,7 +430,7 @@
883 }
884
885 if (!stages.locked) {
886- stages.hide();
887+ ApplicationManager.requestFocusApplication("unity8-dash")
888 launcher.fadeOut();
889 } else {
890 launcher.switchToNextState("visible");
891@@ -568,7 +464,7 @@
892 ApplicationManager.focusedApplicationId &&
893 ApplicationManager.findApplication(ApplicationManager.focusedApplicationId).fullscreen
894
895- fullscreenMode: (stages.roughlyFullyShown && topmostApplicationIsFullscreen
896+ fullscreenMode: (topmostApplicationIsFullscreen
897 && !LightDM.Greeter.active) || greeter.fakeActiveForApp !== ""
898 }
899
900@@ -586,7 +482,11 @@
901
902 onShowDashHome: showHome()
903 onDash: showDash()
904- onDashSwipeChanged: if (dashSwipe && stages.shown) dash.setCurrentScope("clickscope", false, true)
905+ onDashSwipeChanged: {
906+ if (dashSwipe && ApplicationManager.focusedApplicationId !== "unity8-dash") {
907+ dash.setCurrentScope("clickscope", false, true)
908+ }
909+ }
910 onLauncherApplicationSelected: {
911 if (greeter.fakeActiveForApp !== "") {
912 lockscreen.show()
913@@ -678,7 +578,6 @@
914 z: alphaDisclaimerLabel.z + 10
915 greeter: greeter
916 launcher: launcher
917- dash: dash
918 indicators: panel.indicators
919 underlay: underlay
920 }
921
922=== modified file 'qml/Stages/PhoneStage.qml'
923--- qml/Stages/PhoneStage.qml 2014-07-28 15:50:19 +0000
924+++ qml/Stages/PhoneStage.qml 2014-07-28 15:50:22 +0000
925@@ -21,7 +21,7 @@
926 import Utils 0.1
927 import "../Components"
928
929-Item {
930+Rectangle {
931 id: root
932
933 // Controls to be set from outside
934@@ -29,10 +29,13 @@
935 property real maximizedAppTopMargin
936 property bool interactive
937 property bool spreadEnabled: true // If false, animations and right edge will be disabled
938+ property real inverseProgress: 0 // This is the progress for left edge drags, in pixels.
939
940 // State information propagated to the outside
941 readonly property bool locked: spreadView.phase == 2
942
943+ color: "black"
944+
945 function select(appId) {
946 spreadView.snapTo(priv.indexOf(appId));
947 }
948@@ -43,6 +46,16 @@
949 spreadView.contentX = -spreadView.shift;
950 }
951
952+ onInverseProgressChanged: {
953+ if (inverseProgress == 0 && priv.oldInverseProgress > 0) {
954+ // left edge drag released. Minimum distance is given by design.
955+ if (priv.oldInverseProgress > units.gu(22)) {
956+ ApplicationManager.focusApplication("unity8-dash");
957+ }
958+ }
959+ priv.oldInverseProgress = inverseProgress;
960+ }
961+
962 Connections {
963 target: ApplicationManager
964
965@@ -50,7 +63,7 @@
966 if (spreadView.phase > 0) {
967 spreadView.snapTo(priv.indexOf(appId));
968 } else {
969- priv.switchToApp(appId);
970+ ApplicationManager.focusApplication(appId);
971 }
972 }
973
974@@ -60,7 +73,7 @@
975 } else {
976 spreadView.phase = 0;
977 spreadView.contentX = -spreadView.shift;
978- priv.switchToApp(appId);
979+ ApplicationManager.focusApplication(appId);
980 }
981 }
982
983@@ -79,15 +92,11 @@
984
985 property string focusedAppId: ApplicationManager.focusedApplicationId
986 property var focusedApplication: ApplicationManager.findApplication(focusedAppId)
987-
988- function switchToApp(appId) {
989- if (priv.focusedAppId) {
990- spreadView.focusChanging = true;
991- ApplicationManager.focusApplication(appId);
992- } else {
993- ApplicationManager.focusApplication(appId);
994- }
995- }
996+ property var focusedAppDelegate: null
997+
998+ property real oldInverseProgress: 0
999+
1000+ onFocusedAppIdChanged: focusedAppDelegate = spreadRepeater.itemAt(0);
1001
1002 function indexOf(appId) {
1003 for (var i = 0; i < ApplicationManager.count; i++) {
1004@@ -100,14 +109,6 @@
1005
1006 }
1007
1008- Rectangle {
1009- id: coverFlipBackground
1010- anchors.fill: parent
1011- color: "black"
1012- visible: spreadView.visible
1013- }
1014-
1015-
1016 Flickable {
1017 id: spreadView
1018 objectName: "spreadView"
1019@@ -116,6 +117,8 @@
1020 contentWidth: spreadRow.width - shift
1021 contentX: -shift
1022
1023+ readonly property bool isActive: shiftedContentX > 0 || spreadDragArea.dragging
1024+
1025 // The flickable needs to fill the screen in order to get touch events all over.
1026 // However, we don't want to the user to be able to scroll back all the way. For
1027 // that, the beginning of the gesture starts with a negative value for contentX
1028@@ -198,6 +201,12 @@
1029 snapAnimation.start();
1030 }
1031
1032+ // In case the ApplicationManager already holds an app when starting up we're missing animations
1033+ // Make sure we end up in the same state
1034+ Component.onCompleted: {
1035+ spreadView.contentX = -spreadView.shift
1036+ }
1037+
1038 SequentialAnimation {
1039 id: snapAnimation
1040 property int targetContentX: -spreadView.shift
1041@@ -260,14 +269,33 @@
1042 && spreadView.shiftedContentX === 0 && root.interactive && index === 0
1043 swipeToCloseEnabled: spreadView.interactive
1044 maximizedAppTopMargin: root.maximizedAppTopMargin
1045- dropShadow: spreadView.shiftedContentX > 0 || spreadDragArea.status == DirectionalDragArea.Undecided
1046-
1047- z: behavioredIndex
1048- x: index == 0 ? 0 : spreadView.width + (index - 1) * spreadView.tileDistance
1049+ dropShadow: spreadView.isActive ||
1050+ priv.focusedAppDelegate.x !== 0
1051+
1052+ readonly property bool isDash: model.appId == "unity8-dash"
1053+
1054+ z: isDash && !spreadView.isActive ? -1 : behavioredIndex
1055+
1056+ x: {
1057+ // focused app is always positioned at 0 except when following left edge drag
1058+ if (index == 0) {
1059+ if (!isDash && root.inverseProgress > 0) {
1060+ return root.inverseProgress;
1061+ }
1062+ return 0;
1063+ }
1064+ if (isDash && !spreadView.isActive && !spreadDragArea.dragging) {
1065+ return 0;
1066+ }
1067+
1068+ // Otherwise line up for the spread
1069+ return spreadView.width + (index - 1) * spreadView.tileDistance;
1070+ }
1071 property real behavioredIndex: index
1072 Behavior on behavioredIndex {
1073 enabled: spreadView.closingIndex >= 0
1074 UbuntuNumberAnimation {
1075+ id: appXAnimation
1076 onRunningChanged: {
1077 if (!running) {
1078 spreadView.closingIndex = -1;
1079@@ -277,11 +305,13 @@
1080 }
1081
1082 Behavior on x {
1083- enabled: spreadView.focusChanging && index == 0 && root.spreadEnabled
1084+ enabled: root.spreadEnabled &&
1085+ !spreadView.isActive &&
1086+ !snapAnimation.running
1087 UbuntuNumberAnimation {
1088 duration: UbuntuAnimation.FastDuration
1089 onRunningChanged: {
1090- if (!running) {
1091+ if (!running && root.inverseProgress == 0) {
1092 spreadView.focusChanging = false;
1093 }
1094 }
1095@@ -322,6 +352,10 @@
1096 return progress;
1097 }
1098
1099+ // Hiding tiles when their progress is negative or reached the maximum
1100+ visible: (progress >= 0 && progress < 1.7) ||
1101+ (model.appId == "unity8-dash" && priv.focusedAppDelegate.x !== 0)
1102+
1103 EasingCurve {
1104 id: snappingCurve
1105 type: EasingCurve.Linear
1106
1107=== modified file 'qml/Stages/SpreadDelegate.qml'
1108--- qml/Stages/SpreadDelegate.qml 2014-07-28 15:50:19 +0000
1109+++ qml/Stages/SpreadDelegate.qml 2014-07-28 15:50:22 +0000
1110@@ -37,6 +37,7 @@
1111
1112 SurfaceContainer {
1113 id: surfaceContainer
1114+ objectName: "surfaceContainer"
1115 anchors.fill: parent
1116 surface: model.surface
1117 property bool appHasCreatedASurface: false
1118@@ -172,6 +173,11 @@
1119 }
1120
1121 onDragEnd: {
1122+ if (model.appId == "unity8-dash") {
1123+ animation.animate("center")
1124+ return;
1125+ }
1126+
1127 // velocity and distance values specified by design prototype
1128 if ((dragVelocity < -units.gu(40) && distance < -units.gu(8)) || distance < -root.height / 2) {
1129 animation.animate("up")
1130
1131=== modified file 'qml/Stages/TabletStage.qml'
1132--- qml/Stages/TabletStage.qml 2014-07-28 15:50:19 +0000
1133+++ qml/Stages/TabletStage.qml 2014-07-28 15:50:22 +0000
1134@@ -21,10 +21,11 @@
1135 import Utils 0.1
1136 import "../Components"
1137
1138-Item {
1139+Rectangle {
1140 id: root
1141 objectName: "stages"
1142 anchors.fill: parent
1143+ color: "black"
1144
1145 // Controls to be set from outside
1146 property bool shown: false
1147@@ -32,10 +33,21 @@
1148 property int dragAreaWidth
1149 property real maximizedAppTopMargin
1150 property bool interactive
1151+ property real inverseProgress: 0 // This is the progress for left edge drags, in pixels.
1152
1153 // State information propagated to the outside
1154 readonly property bool locked: spreadView.phase == 2
1155
1156+ onInverseProgressChanged: {
1157+ if (inverseProgress == 0 && priv.oldInverseProgress > 0) {
1158+ // left edge drag released. Minimum distance is given by design.
1159+ if (priv.oldInverseProgress > units.gu(22)) {
1160+ ApplicationManager.focusApplication("unity8-dash");
1161+ }
1162+ }
1163+ priv.oldInverseProgress = inverseProgress;
1164+ }
1165+
1166 QtObject {
1167 id: priv
1168
1169@@ -49,6 +61,8 @@
1170 property string appId0
1171 property string appId1
1172
1173+ property int oldInverseProgress: 0
1174+
1175 onFocusedAppIdChanged: {
1176 if (priv.focusedAppId.length > 0) {
1177 var focusedApp = ApplicationManager.findApplication(focusedAppId);
1178@@ -107,16 +121,26 @@
1179 }
1180 }
1181
1182+ onApplicationAdded: {
1183+ if (spreadView.phase == 2) {
1184+ spreadView.snapTo(ApplicationManager.count - 1);
1185+ } else {
1186+ spreadView.phase = 0;
1187+ spreadView.contentX = -spreadView.shift;
1188+ ApplicationManager.focusApplication(appId);
1189+ }
1190+ }
1191+
1192 onApplicationRemoved: {
1193 if (priv.mainStageAppId == appId) {
1194- priv.mainStageAppId = "";
1195+ ApplicationManager.focusApplication("unity8-dash")
1196 }
1197 if (priv.sideStageAppId == appId) {
1198 priv.sideStageAppId = "";
1199 }
1200 if (ApplicationManager.count == 0) {
1201 spreadView.phase = 0;
1202- spreadView.contentX = 0;
1203+ spreadView.contentX = -spreadView.shift;
1204 }
1205 }
1206 }
1207@@ -124,13 +148,25 @@
1208 Flickable {
1209 id: spreadView
1210 anchors.fill: parent
1211- contentWidth: spreadRow.width
1212 interactive: (spreadDragArea.status == DirectionalDragArea.Recognized || phase > 1) && draggedIndex == -1
1213+ contentWidth: spreadRow.width - shift
1214+ contentX: -shift
1215
1216 property int tileDistance: units.gu(20)
1217 property int sideStageWidth: units.gu(40)
1218 property bool sideStageVisible: priv.sideStageAppId
1219
1220+ readonly property bool isActive: shiftedContentX > 0 || spreadDragArea.dragging
1221+ onIsActiveChanged: print("spreadView isActive changed", isActive)
1222+
1223+ // The flickable needs to fill the screen in order to get touch events all over.
1224+ // However, we don't want to the user to be able to scroll back all the way. For
1225+ // that, the beginning of the gesture starts with a negative value for contentX
1226+ // so the flickable wants to pull it into the view already. "shift" tunes the
1227+ // distance where to "lock" the content.
1228+ readonly property real shift: width / 2
1229+ readonly property real shiftedContentX: contentX + shift
1230+
1231 // Phase of the animation:
1232 // 0: Starting from right edge, a new app (index 1) comes in from the right
1233 // 1: The app has reached the first snap position.
1234@@ -168,6 +204,12 @@
1235 }
1236 }
1237
1238+ // In case the ApplicationManager already holds an app when starting up we're missing animations
1239+ // Make sure we end up in the same state
1240+ Component.onCompleted: {
1241+ spreadView.contentX = -spreadView.shift
1242+ }
1243+
1244 property int nextInStack: {
1245 switch (state) {
1246 case "main":
1247@@ -224,31 +266,31 @@
1248 return "empty";
1249 }
1250
1251- onContentXChanged: {
1252- if (spreadView.phase == 0 && spreadView.contentX > spreadView.width * spreadView.positionMarker2) {
1253+ onShiftedContentXChanged: {
1254+ if (spreadView.phase == 0 && spreadView.shiftedContentX > spreadView.width * spreadView.positionMarker2) {
1255 spreadView.phase = 1;
1256- } else if (spreadView.phase == 1 && spreadView.contentX > spreadView.width * spreadView.positionMarker4) {
1257+ } else if (spreadView.phase == 1 && spreadView.shiftedContentX > spreadView.width * spreadView.positionMarker4) {
1258 spreadView.phase = 2;
1259- } else if (spreadView.phase == 1 && spreadView.contentX < spreadView.width * spreadView.positionMarker2) {
1260+ } else if (spreadView.phase == 1 && spreadView.shiftedContentX < spreadView.width * spreadView.positionMarker2) {
1261 spreadView.phase = 0;
1262 }
1263 }
1264
1265 function snap() {
1266- if (contentX < phase0Width) {
1267- snapAnimation.targetContentX = 0;
1268+ if (shiftedContentX < phase0Width) {
1269+ snapAnimation.targetContentX = -shift;
1270 snapAnimation.start();
1271- } else if (contentX < phase1Width) {
1272+ } else if (shiftedContentX < phase1Width) {
1273 snapTo(1);
1274 } else {
1275 // Add 1 pixel to make sure we definitely hit positionMarker4 even with rounding errors of the animation.
1276- snapAnimation.targetContentX = spreadView.width * spreadView.positionMarker4 + 1;
1277+ snapAnimation.targetContentX = spreadView.width * spreadView.positionMarker4 + 1 - shift;
1278 snapAnimation.start();
1279 }
1280 }
1281 function snapTo(index) {
1282 spreadView.selectedIndex = index;
1283- snapAnimation.targetContentX = 0;
1284+ snapAnimation.targetContentX = -shift;
1285 snapAnimation.start();
1286 }
1287
1288@@ -309,7 +351,7 @@
1289
1290 SequentialAnimation {
1291 id: snapAnimation
1292- property int targetContentX: 0
1293+ property int targetContentX: -spreadView.shift
1294
1295 UbuntuNumberAnimation {
1296 target: spreadView
1297@@ -325,15 +367,14 @@
1298 spreadView.selectedIndex = -1;
1299 ApplicationManager.focusApplication(ApplicationManager.get(newIndex).appId);
1300 spreadView.phase = 0;
1301- spreadView.contentX = 0;
1302+ spreadView.contentX = -spreadView.shift;
1303 }
1304 }
1305 }
1306 }
1307
1308- Rectangle {
1309+ Item {
1310 id: spreadRow
1311- color: "black"
1312 x: spreadView.contentX
1313 height: root.height
1314 width: spreadView.width + Math.max(spreadView.width, ApplicationManager.count * spreadView.tileDistance)
1315@@ -380,7 +421,7 @@
1316 MouseArea {
1317 id: sideStageDragHandleMouseArea
1318 anchors.fill: parent
1319- enabled: spreadView.contentX == 0
1320+ enabled: spreadView.shiftedContentX == 0
1321 property int startX
1322 property var gesturePoints: new Array()
1323
1324@@ -413,7 +454,7 @@
1325
1326 onRunningChanged: {
1327 if (!running) {
1328- sideStageDragHandle.dragging = false;;
1329+ sideStageDragHandle.dragging = false;
1330 }
1331 }
1332 }
1333@@ -427,17 +468,26 @@
1334 id: spreadTile
1335 height: spreadView.height
1336 width: model.stage == ApplicationInfoInterface.MainStage ? spreadView.width : spreadView.sideStageWidth
1337- x: spreadView.width
1338- z: spreadView.indexToZIndex(index)
1339 active: model.appId == priv.mainStageAppId || model.appId == priv.sideStageAppId
1340- zIndex: z
1341+ zIndex: spreadView.indexToZIndex(index)
1342 selected: spreadView.selectedIndex == index
1343 otherSelected: spreadView.selectedIndex >= 0 && !selected
1344 isInSideStage: priv.sideStageAppId == model.appId
1345 interactive: !spreadView.interactive && spreadView.phase === 0 && root.interactive
1346 swipeToCloseEnabled: spreadView.interactive
1347 maximizedAppTopMargin: root.maximizedAppTopMargin
1348- dropShadow: spreadView.contentX > 0 || spreadDragArea.status == DirectionalDragArea.Undecided
1349+ dragOffset: !isDash && model.appId == priv.mainStageAppId && root.inverseProgress > 0 ? root.inverseProgress : 0
1350+
1351+ readonly property bool isDash: model.appId == "unity8-dash"
1352+
1353+ // FIXME: A regular binding doesn't update any more after closing an app.
1354+ // Using a Binding for now.
1355+ Binding {
1356+ target: spreadTile
1357+ property: "z"
1358+ value: (!spreadView.isActive && isDash && !active) ? -1 : spreadTile.zIndex
1359+ }
1360+ x: spreadView.width
1361
1362 property real behavioredZIndex: zIndex
1363 Behavior on behavioredZIndex {
1364@@ -458,7 +508,7 @@
1365 }
1366
1367 progress: {
1368- var tileProgress = (spreadView.contentX - behavioredZIndex * spreadView.tileDistance) / spreadView.width;
1369+ var tileProgress = (spreadView.shiftedContentX - behavioredZIndex * spreadView.tileDistance) / spreadView.width;
1370 // Some tiles (nextInStack, active) need to move directly from the beginning, normalize progress to immediately start at 0
1371 if ((index == spreadView.nextInStack && spreadView.phase < 2) || (active && spreadView.phase < 1)) {
1372 tileProgress += behavioredZIndex * spreadView.tileDistance / spreadView.width;
1373@@ -481,11 +531,7 @@
1374
1375 onClicked: {
1376 if (spreadView.phase == 2) {
1377- if (ApplicationManager.focusedApplicationId == ApplicationManager.get(index).appId) {
1378- spreadView.snapTo(index);
1379- } else {
1380- ApplicationManager.requestFocusApplication(ApplicationManager.get(index).appId);
1381- }
1382+ spreadView.snapTo(index);
1383 }
1384 }
1385
1386@@ -518,12 +564,12 @@
1387 onTouchXChanged: {
1388 if (!dragging) {
1389 spreadView.phase = 0;
1390- spreadView.contentX = 0;
1391+ spreadView.contentX = -spreadView.shift;
1392 }
1393
1394- if (attachedToView) {
1395- spreadView.contentX = -touchX + spreadDragArea.width;
1396- if (spreadView.contentX > spreadView.phase0Width + spreadView.phase1Width / 2) {
1397+ if (dragging && attachedToView) {
1398+ spreadView.contentX = -touchX + spreadDragArea.width - spreadView.shift;
1399+ if (spreadView.shiftedContentX > spreadView.phase0Width + spreadView.phase1Width / 2) {
1400 attachedToView = false;
1401 spreadView.snap();
1402 }
1403@@ -548,14 +594,14 @@
1404 var oneWayFlick = priv.evaluateOneWayFlick(gesturePoints);
1405 gesturePoints = [];
1406
1407- if (oneWayFlick && spreadView.contentX < spreadView.positionMarker1 * spreadView.width) {
1408+ if (oneWayFlick && spreadView.shiftedContentX < spreadView.positionMarker1 * spreadView.width) {
1409 // If it was a short one-way movement, do the Alt+Tab switch
1410 // no matter if we didn't cross positionMarker1 yet.
1411 spreadView.snapTo(spreadView.nextInStack);
1412 } else if (!dragging && attachedToView) {
1413- if (spreadView.contentX < spreadView.width * spreadView.positionMarker1) {
1414+ if (spreadView.shiftedContentX < spreadView.width * spreadView.positionMarker1) {
1415 spreadView.snap();
1416- } else if (spreadView.contentX < spreadView.width * spreadView.positionMarker2) {
1417+ } else if (spreadView.shiftedContentX < spreadView.width * spreadView.positionMarker2) {
1418 spreadView.snapTo(spreadView.nextInStack);
1419 } else {
1420 // otherwise snap to the closest snap position we can find
1421
1422=== modified file 'qml/Stages/TransformedSpreadDelegate.qml'
1423--- qml/Stages/TransformedSpreadDelegate.qml 2014-07-28 15:50:19 +0000
1424+++ qml/Stages/TransformedSpreadDelegate.qml 2014-07-28 15:50:22 +0000
1425@@ -46,9 +46,6 @@
1426 property real startDistance: units.gu(5)
1427 property real endDistance: units.gu(.5)
1428
1429- // Hiding tiles when their progress is negative or reached the maximum
1430- visible: progress >= 0 && progress < 1.7
1431-
1432 onSelectedChanged: {
1433 if (selected) {
1434 priv.snapshot();
1435@@ -132,6 +129,10 @@
1436 // the selected tile, which is animated from the snapshotted position to be fullscreen.
1437
1438 readonly property real xTranslate: {
1439+ if (!spreadView.isActive) {
1440+ return 0;
1441+ }
1442+
1443 if (otherSelected) {
1444 if (spreadView.phase < 2 && index == 0) {
1445 return linearAnimation(selectedProgress, 0, selectedXTranslate,
1446@@ -183,7 +184,7 @@
1447 }
1448
1449 readonly property real angle: {
1450- if (spreadView.focusChanging) {
1451+ if (!spreadView.isActive) {
1452 return 0;
1453 }
1454
1455@@ -216,7 +217,7 @@
1456 }
1457
1458 readonly property real scale: {
1459- if (spreadView.focusChanging) {
1460+ if (!spreadView.isActive) {
1461 return 1;
1462 }
1463 if (priv.otherSelected) {
1464
1465=== modified file 'qml/Stages/TransformedTabletSpreadDelegate.qml'
1466--- qml/Stages/TransformedTabletSpreadDelegate.qml 2014-07-28 15:50:19 +0000
1467+++ qml/Stages/TransformedTabletSpreadDelegate.qml 2014-07-28 15:50:22 +0000
1468@@ -47,6 +47,11 @@
1469
1470 property bool isInSideStage: false
1471
1472+ property int dragOffset: 0
1473+
1474+ dropShadow: spreadView.isActive ||
1475+ (active && model.stage == ApplicationInfoInterface.MainStage && priv.xTranslate != 0)
1476+
1477 onSelectedChanged: {
1478 if (selected) {
1479 priv.snapshot();
1480@@ -129,6 +134,16 @@
1481 return helperEasingCurve.value * (endValue - startValue) + startValue;
1482 }
1483
1484+ Behavior on xTranslate {
1485+ enabled: !spreadView.isActive &&
1486+ !snapAnimation.running &&
1487+ model.appId !== "unity8-dash" &&
1488+ !spreadView.sideStageDragging
1489+ UbuntuNumberAnimation {
1490+ duration: UbuntuAnimation.FastDuration
1491+ }
1492+ }
1493+
1494 property real xTranslate: {
1495 var newTranslate = 0;
1496
1497@@ -155,7 +170,12 @@
1498 if (spreadView.phase == 0 && shouldMoveAway) {
1499 newTranslate += linearAnimation(0, spreadView.positionMarker2, 0, -units.gu(4), root.animatedProgress);
1500 }
1501- }
1502+ newTranslate += root.dragOffset;
1503+ }
1504+ if (!spreadView.isActive && model.appId == "unity8-dash" && !root.active) {
1505+ newTranslate -= root.width;
1506+ }
1507+
1508 if (nextInStack && spreadView.phase == 0) {
1509 if (model.stage == ApplicationInfoInterface.MainStage) {
1510 if (spreadView.sideStageVisible && root.progress > 0) {
1511@@ -205,6 +225,10 @@
1512 }
1513
1514 property real scale: {
1515+ if (!spreadView.isActive) {
1516+ return 1;
1517+ }
1518+
1519 if (otherSelected) {
1520 return selectedScale;
1521 }
1522@@ -249,6 +273,10 @@
1523 }
1524
1525 property real angle: {
1526+ if (!spreadView.isActive) {
1527+ return 0;
1528+ }
1529+
1530 if (otherSelected) {
1531 return selectedAngle;
1532 }
1533
1534=== modified file 'src/CMakeLists.txt'
1535--- src/CMakeLists.txt 2014-07-28 15:50:19 +0000
1536+++ src/CMakeLists.txt 2014-07-28 15:50:22 +0000
1537@@ -35,3 +35,4 @@
1538 )
1539
1540 add_subdirectory(Panel)
1541+add_subdirectory(Dash)
1542
1543=== added directory 'src/Dash'
1544=== added file 'src/Dash/CMakeLists.txt'
1545--- src/Dash/CMakeLists.txt 1970-01-01 00:00:00 +0000
1546+++ src/Dash/CMakeLists.txt 2014-07-28 15:50:22 +0000
1547@@ -0,0 +1,12 @@
1548+set(DASH_SRCS
1549+ main.cpp
1550+)
1551+
1552+add_executable(unity8-dash ${DASH_SRCS})
1553+
1554+qt5_use_modules(unity8-dash Gui Qml Quick Test)
1555+
1556+# install binaries
1557+install(TARGETS ${DASH_APP}
1558+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
1559+)
1560
1561=== added file 'src/Dash/main.cpp'
1562--- src/Dash/main.cpp 1970-01-01 00:00:00 +0000
1563+++ src/Dash/main.cpp 2014-07-28 15:50:22 +0000
1564@@ -0,0 +1,49 @@
1565+/*
1566+ * Copyright (C) 2014 Canonical, Ltd.
1567+ *
1568+ * Authors:
1569+ * Michael Zanetti <michael.zanetti@canonical.com>
1570+ *
1571+ * This program is free software; you can redistribute it and/or modify
1572+ * it under the terms of the GNU General Public License as published by
1573+ * the Free Software Foundation; version 3.
1574+ *
1575+ * This program is distributed in the hope that it will be useful,
1576+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1577+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1578+ * GNU General Public License for more details.
1579+ *
1580+ * You should have received a copy of the GNU General Public License
1581+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1582+ */
1583+
1584+#include <QtQuick/QQuickView>
1585+#include <QtGui/QGuiApplication>
1586+#include <QtQml/QQmlEngine>
1587+#include <QtQml/QQmlContext>
1588+#include <QDebug>
1589+
1590+#include <paths.h>
1591+
1592+int main(int argc, const char *argv[])
1593+{
1594+ QGuiApplication *application = new QGuiApplication(argc, (char**)argv);
1595+
1596+ QQuickView* view = new QQuickView();
1597+ view->setResizeMode(QQuickView::SizeRootObjectToView);
1598+ view->setTitle("Unity Dash");
1599+
1600+ QUrl source(::qmlDirectory()+"Dash/DashApplication.qml");
1601+ prependImportPaths(view->engine(), ::overrideImportPaths());
1602+ appendImportPaths(view->engine(), ::fallbackImportPaths());
1603+
1604+ view->setSource(source);
1605+ view->show();
1606+
1607+ int result = application->exec();
1608+
1609+ delete view;
1610+ delete application;
1611+
1612+ return result;
1613+}
1614
1615=== modified file 'tests/mocks/Unity/Application/ApplicationInfo.cpp'
1616--- tests/mocks/Unity/Application/ApplicationInfo.cpp 2014-07-28 15:50:19 +0000
1617+++ tests/mocks/Unity/Application/ApplicationInfo.cpp 2014-07-28 15:50:22 +0000
1618@@ -31,8 +31,6 @@
1619 , m_state(Starting)
1620 , m_focused(false)
1621 , m_fullscreen(false)
1622- , m_windowItem(0)
1623- , m_windowComponent(0)
1624 , m_parentItem(0)
1625 , m_surface(0)
1626 {
1627@@ -45,8 +43,6 @@
1628 , m_state(Starting)
1629 , m_focused(false)
1630 , m_fullscreen(false)
1631- , m_windowItem(0)
1632- , m_windowComponent(0)
1633 , m_parentItem(0)
1634 , m_surface(0)
1635 {
1636@@ -61,12 +57,6 @@
1637 }
1638 }
1639
1640-void ApplicationInfo::onWindowComponentStatusChanged(QQmlComponent::Status status)
1641-{
1642- if (status == QQmlComponent::Ready && !m_windowItem)
1643- doCreateWindowItem();
1644-}
1645-
1646 void ApplicationInfo::onStateChanged(State state)
1647 {
1648 if (state == ApplicationInfo::Running) {
1649@@ -108,55 +98,3 @@
1650 Q_EMIT surfaceChanged(m_surface);
1651 SurfaceManager::singleton()->registerSurface(m_surface);
1652 }
1653-
1654-void ApplicationInfo::createWindowComponent()
1655-{
1656- // The assumptions I make here really should hold.
1657- QQuickView *quickView =
1658- qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
1659-
1660- QQmlEngine *engine = quickView->engine();
1661-
1662- m_windowComponent = new QQmlComponent(engine, this);
1663- m_windowComponent->setData(m_windowQml.toLatin1(), QUrl());
1664-}
1665-
1666-void ApplicationInfo::doCreateWindowItem()
1667-{
1668- m_windowItem = qobject_cast<QQuickItem *>(m_windowComponent->create());
1669- m_windowItem->setParentItem(m_parentItem);
1670-}
1671-
1672-void ApplicationInfo::createWindowItem()
1673-{
1674- if (!m_windowComponent)
1675- createWindowComponent();
1676-
1677- // only create the windowItem once the component is ready
1678- if (!m_windowComponent->isReady()) {
1679- connect(m_windowComponent, &QQmlComponent::statusChanged,
1680- this, &ApplicationInfo::onWindowComponentStatusChanged);
1681- } else {
1682- doCreateWindowItem();
1683- }
1684-}
1685-
1686-void ApplicationInfo::showWindow(QQuickItem *parent)
1687-{
1688- m_parentItem = parent;
1689-
1690- if (!m_windowItem)
1691- createWindowItem();
1692-
1693- if (m_windowItem) {
1694- m_windowItem->setVisible(true);
1695- }
1696-}
1697-
1698-void ApplicationInfo::hideWindow()
1699-{
1700- if (!m_windowItem)
1701- return;
1702-
1703- m_windowItem->setVisible(false);
1704-}
1705
1706=== modified file 'tests/mocks/Unity/Application/ApplicationInfo.h'
1707--- tests/mocks/Unity/Application/ApplicationInfo.h 2014-07-28 15:50:19 +0000
1708+++ tests/mocks/Unity/Application/ApplicationInfo.h 2014-07-28 15:50:22 +0000
1709@@ -88,22 +88,12 @@
1710 Q_SIGNALS:
1711 void surfaceChanged(MirSurfaceItem*);
1712
1713-public:
1714- void showWindow(QQuickItem *parent);
1715- void hideWindow();
1716-
1717 private Q_SLOTS:
1718- void onWindowComponentStatusChanged(QQmlComponent::Status status);
1719 void onStateChanged(State state);
1720
1721 void createSurface();
1722
1723 private:
1724- void createWindowItem();
1725- void doCreateWindowItem();
1726- void createWindowComponent();
1727- QQuickItem *m_windowItem;
1728- QQmlComponent *m_windowComponent;
1729 QQuickItem *m_parentItem;
1730 MirSurfaceItem* m_surface;
1731 };
1732
1733=== modified file 'tests/mocks/Unity/Application/ApplicationManager.cpp'
1734--- tests/mocks/Unity/Application/ApplicationManager.cpp 2014-07-28 15:50:19 +0000
1735+++ tests/mocks/Unity/Application/ApplicationManager.cpp 2014-07-28 15:50:22 +0000
1736@@ -48,16 +48,14 @@
1737 ApplicationManager::ApplicationManager(QObject *parent)
1738 : ApplicationManagerInterface(parent)
1739 , m_suspended(false)
1740- , m_mainStageComponent(0)
1741- , m_mainStage(0)
1742- , m_sideStageComponent(0)
1743- , m_sideStage(0)
1744- , m_rightMargin(0)
1745 {
1746 m_roleNames.insert(RoleSurface, "surface");
1747 m_roleNames.insert(RoleFullscreen, "fullscreen");
1748
1749 buildListOfAvailableApplications();
1750+
1751+ startApplication("unity8-dash");
1752+ focusApplication("unity8-dash");
1753 }
1754
1755 ApplicationManager::~ApplicationManager()
1756@@ -136,7 +134,6 @@
1757 Q_EMIT applicationAdded(application->appId());
1758 Q_EMIT countChanged();
1759 if (count() == 1) Q_EMIT emptyChanged(isEmpty()); // was empty but not anymore
1760- Q_EMIT focusRequested(application->appId());
1761
1762 connect(application, &ApplicationInfo::surfaceChanged, this, [application, this]() {
1763 QModelIndex appIndex = findIndex(application);
1764@@ -222,6 +219,10 @@
1765
1766 bool ApplicationManager::stopApplication(const QString &appId)
1767 {
1768+ if (appId == "unity8-dash") {
1769+ return false;
1770+ }
1771+
1772 ApplicationInfo *application = findApplication(appId);
1773 if (application == nullptr)
1774 return false;
1775@@ -294,39 +295,25 @@
1776 for (ApplicationInfo *app : m_runningApplications) {
1777 if (app->focused() && app->stage() == ApplicationInfo::MainStage) {
1778 app->setFocused(false);
1779- app->hideWindow();
1780 app->setState(ApplicationInfo::Suspended);
1781 }
1782 }
1783
1784 // focus this app
1785 application->setFocused(true);
1786- if (!m_mainStage)
1787- createMainStage();
1788 application->setState(ApplicationInfo::Running);
1789- application->showWindow(m_mainStage);
1790- m_mainStage->setZ(-1000);
1791- if (m_sideStage)
1792- m_sideStage->setZ(-2000);
1793 } else if (application->stage() == ApplicationInfo::SideStage) {
1794 // unfocus currently focused sidestage app
1795 for (ApplicationInfo *app : m_runningApplications) {
1796 if (app->focused() && app->stage() == ApplicationInfo::SideStage) {
1797 app->setFocused(false);
1798- app->hideWindow();
1799 app->setState(ApplicationInfo::Suspended);
1800 }
1801 }
1802
1803 // focus this app
1804 application->setFocused(true);
1805- if (!m_sideStage)
1806- createSideStage();
1807 application->setState(ApplicationInfo::Running);
1808- application->showWindow(m_sideStage);
1809- m_sideStage->setZ(-1000);
1810- if (m_mainStage)
1811- m_mainStage->setZ(-2000);
1812 }
1813
1814 // move app to top of stack
1815@@ -348,7 +335,6 @@
1816 {
1817 for (ApplicationInfo *app : m_runningApplications) {
1818 if (app->focused()) {
1819- app->hideWindow();
1820 app->setFocused(false);
1821 }
1822 }
1823@@ -357,42 +343,6 @@
1824
1825 void ApplicationManager::generateQmlStrings(ApplicationInfo *application)
1826 {
1827- // TODO: Is there a better way of solving this fullscreen vs. regular
1828- // application height?
1829- QString topMargin;
1830- if (application->fullscreen()) {
1831- topMargin.append("0");
1832- } else {
1833- // Taken from Panel.panelHeight
1834- topMargin.append("units.gu(3) + units.dp(2)");
1835- }
1836-
1837- QString windowQml = QString(
1838- "import QtQuick 2.0\n"
1839- "Image {\n"
1840- " anchors.fill: parent\n"
1841- " anchors.topMargin: %1\n"
1842- " anchors.rightMargin: %2\n"
1843- " source: \"file://%3/Dash/graphics/phone/screenshots/%4.png\"\n"
1844- " smooth: true\n"
1845- " fillMode: Image.PreserveAspectCrop\n"
1846- "}").arg(topMargin)
1847- .arg(m_rightMargin)
1848- .arg(qmlDirectory())
1849- .arg(application->icon().toString());
1850- application->setWindowQml(windowQml);
1851-
1852- QString imageQml = QString(
1853- "import QtQuick 2.0\n"
1854- "Image {\n"
1855- " anchors.fill: parent\n"
1856- " source: \"file://%1/Dash/graphics/phone/screenshots/%2.png\"\n"
1857- " smooth: true\n"
1858- " fillMode: Image.PreserveAspectCrop\n"
1859- "}").arg(qmlDirectory())
1860- .arg(application->icon().toString());
1861- application->setImageQml(imageQml);
1862-
1863 application->setScreenshot(QString("file://%1/Dash/graphics/phone/screenshots/%2@12.png").arg(qmlDirectory())
1864 .arg(application->icon().toString()));
1865 }
1866@@ -402,6 +352,14 @@
1867 ApplicationInfo *application;
1868
1869 application = new ApplicationInfo(this);
1870+ application->setAppId("unity8-dash");
1871+ application->setName("Unity 8 Mock Dash");
1872+ application->setIcon(QUrl("unity8-dash"));
1873+ application->setStage(ApplicationInfo::MainStage);
1874+ generateQmlStrings(application);
1875+ m_availableApplications.append(application);
1876+
1877+ application = new ApplicationInfo(this);
1878 application->setAppId("dialer-app");
1879 application->setName("Dialer");
1880 application->setIcon(QUrl("dialer"));
1881@@ -521,78 +479,6 @@
1882 m_availableApplications.append(application);
1883 }
1884
1885-void ApplicationManager::createMainStageComponent()
1886-{
1887- // The assumptions I make here really should hold.
1888- QQuickView *quickView =
1889- qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
1890-
1891- QQmlEngine *engine = quickView->engine();
1892-
1893- m_mainStageComponent = new QQmlComponent(engine, this);
1894- QString mainStageQml =
1895- "import QtQuick 2.0\n"
1896- "Rectangle {\n"
1897- " anchors.fill: parent\n"
1898- " color: 'black'\n"
1899- " z: -2000\n"
1900- "}\n";
1901- m_mainStageComponent->setData(mainStageQml.toLatin1(), QUrl());
1902-}
1903-
1904-void ApplicationManager::createMainStage()
1905-{
1906- if (!m_mainStageComponent)
1907- createMainStageComponent();
1908-
1909- // The assumptions I make here really should hold.
1910- QQuickView *quickView =
1911- qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
1912-
1913- QQuickItem *shell = quickView->rootObject();
1914-
1915- m_mainStage = qobject_cast<QQuickItem *>(m_mainStageComponent->create());
1916- m_mainStage->setParentItem(shell);
1917-}
1918-
1919-void ApplicationManager::createSideStageComponent()
1920-{
1921- // The assumptions I make here really should hold.
1922- QQuickView *quickView =
1923- qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
1924-
1925- QQmlEngine *engine = quickView->engine();
1926-
1927- m_sideStageComponent = new QQmlComponent(engine, this);
1928- QString sideStageQml =
1929- "import QtQuick 2.0\n"
1930- "import Ubuntu.Components 0.1\n"
1931- "Item {\n"
1932- " width: units.gu(40)\n" // from SideStage in Shell.qml
1933- " anchors.top: parent.top\n"
1934- " anchors.bottom: parent.bottom\n"
1935- " anchors.right: parent.right\n"
1936- " z: -1000\n"
1937- "}\n";
1938- m_sideStageComponent->setData(sideStageQml.toLatin1(), QUrl());
1939-}
1940-
1941-void ApplicationManager::createSideStage()
1942-{
1943- if (!m_sideStageComponent)
1944- createSideStageComponent();
1945-
1946- // The assumptions I make here really should hold.
1947- QQuickView *quickView =
1948- qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
1949-
1950- QQuickItem *shell = quickView->rootObject();
1951-
1952- m_sideStage = qobject_cast<QQuickItem *>(m_sideStageComponent->create());
1953- m_sideStage->setParentItem(shell);
1954- m_sideStage->setFlag(QQuickItem::ItemHasContents, false);
1955-}
1956-
1957 QStringList ApplicationManager::availableApplications()
1958 {
1959 QStringList appIds;
1960@@ -602,19 +488,6 @@
1961 return appIds;
1962 }
1963
1964-int ApplicationManager::rightMargin() const
1965-{
1966- return m_rightMargin;
1967-}
1968-
1969-void ApplicationManager::setRightMargin(int rightMargin)
1970-{
1971- m_rightMargin = rightMargin;
1972- Q_FOREACH(ApplicationInfo *app, m_availableApplications) {
1973- generateQmlStrings(app);
1974- }
1975-}
1976-
1977 bool ApplicationManager::isEmpty() const
1978 {
1979 return m_runningApplications.isEmpty();
1980
1981=== modified file 'tests/mocks/Unity/Application/ApplicationManager.h'
1982--- tests/mocks/Unity/Application/ApplicationManager.h 2014-07-28 15:50:19 +0000
1983+++ tests/mocks/Unity/Application/ApplicationManager.h 2014-07-28 15:50:22 +0000
1984@@ -44,10 +44,6 @@
1985
1986 Q_PROPERTY(bool fake READ fake CONSTANT)
1987
1988- // Only for testing
1989- // This can be used to place some controls to right, like make tryPhoneStage for example
1990- Q_PROPERTY(int rightMargin READ rightMargin WRITE setRightMargin)
1991-
1992 public:
1993 ApplicationManager(QObject *parent = NULL);
1994 virtual ~ApplicationManager();
1995@@ -108,8 +104,6 @@
1996
1997 // Only for testing
1998 Q_INVOKABLE QStringList availableApplications();
1999- int rightMargin() const;
2000- void setRightMargin(int rightMargin);
2001
2002 QModelIndex findIndex(ApplicationInfo* application);
2003
2004@@ -126,19 +120,9 @@
2005 void showApplicationWindow(ApplicationInfo *application);
2006 void buildListOfAvailableApplications();
2007 void generateQmlStrings(ApplicationInfo *application);
2008- void createMainStageComponent();
2009- void createMainStage();
2010- void createSideStageComponent();
2011- void createSideStage();
2012 bool m_suspended;
2013 QList<ApplicationInfo*> m_runningApplications;
2014 QList<ApplicationInfo*> m_availableApplications;
2015- QQmlComponent *m_mainStageComponent;
2016- QQuickItem *m_mainStage;
2017- QQmlComponent *m_sideStageComponent;
2018- QQuickItem *m_sideStage;
2019-
2020- int m_rightMargin;
2021
2022 static ApplicationManager *the_application_manager;
2023 };
2024
2025=== modified file 'tests/mocks/Unity/Application/ApplicationScreenshotProvider.cpp'
2026--- tests/mocks/Unity/Application/ApplicationScreenshotProvider.cpp 2014-04-02 15:33:33 +0000
2027+++ tests/mocks/Unity/Application/ApplicationScreenshotProvider.cpp 2014-07-28 15:50:22 +0000
2028@@ -64,7 +64,7 @@
2029 Q_FOREACH (QWindow *win, unity->allWindows()) {
2030 QQuickWindow *quickWin = qobject_cast<QQuickWindow*>(win);
2031 if (quickWin) {
2032- image = image.scaledToWidth(quickWin->width() - m_appManager->rightMargin());
2033+ image = image.scaledToWidth(quickWin->width());
2034 break;
2035 }
2036 }
2037
2038=== modified file 'tests/mocks/Unity/CMakeLists.txt'
2039--- tests/mocks/Unity/CMakeLists.txt 2014-07-08 09:23:14 +0000
2040+++ tests/mocks/Unity/CMakeLists.txt 2014-07-28 15:50:22 +0000
2041@@ -2,6 +2,7 @@
2042 add_subdirectory(Indicators)
2043 add_subdirectory(Launcher)
2044 add_subdirectory(Notifications)
2045+add_subdirectory(DashCommunicator)
2046
2047 pkg_search_module(DEE dee-1.0 REQUIRED)
2048 pkg_search_module(GOBJECT gobject-2.0 REQUIRED)
2049
2050=== added directory 'tests/mocks/Unity/DashCommunicator'
2051=== added file 'tests/mocks/Unity/DashCommunicator/CMakeLists.txt'
2052--- tests/mocks/Unity/DashCommunicator/CMakeLists.txt 1970-01-01 00:00:00 +0000
2053+++ tests/mocks/Unity/DashCommunicator/CMakeLists.txt 2014-07-28 15:50:22 +0000
2054@@ -0,0 +1,18 @@
2055+include_directories(
2056+ ${CMAKE_CURRENT_SOURCE_DIR}
2057+)
2058+
2059+set(QMLDASHCOMMUNICATORPLUGIN_SRC
2060+ plugin.cpp
2061+ dashcommunicatorservice.cpp
2062+ dashcommunicator.cpp
2063+ )
2064+
2065+add_library(MockDashCommunicator-qml MODULE
2066+ ${QMLDASHCOMMUNICATORPLUGIN_SRC}
2067+ )
2068+
2069+qt5_use_modules(MockDashCommunicator-qml DBus Qml)
2070+
2071+# export the qmldir and qmltypes files
2072+add_unity8_mock(Unity.DashCommunicator 0.1 Unity/DashCommunicator TARGETS MockDashCommunicator-qml)
2073
2074=== added file 'tests/mocks/Unity/DashCommunicator/dashcommunicator.cpp'
2075--- tests/mocks/Unity/DashCommunicator/dashcommunicator.cpp 1970-01-01 00:00:00 +0000
2076+++ tests/mocks/Unity/DashCommunicator/dashcommunicator.cpp 2014-07-28 15:50:22 +0000
2077@@ -0,0 +1,37 @@
2078+/*
2079+ * Copyright (C) 2014 Canonical, Ltd.
2080+ *
2081+ * This program is free software: you can redistribute it and/or modify it under
2082+ * the terms of the GNU Lesser General Public License version 3, as published by
2083+ * the Free Software Foundation.
2084+ *
2085+ * This program is distributed in the hope that it will be useful, but WITHOUT
2086+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
2087+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2088+ * Lesser General Public License for more details.
2089+ *
2090+ * You should have received a copy of the GNU Lesser General Public License
2091+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2092+ */
2093+
2094+#include "dashcommunicator.h"
2095+
2096+#include <QObject>
2097+#include <QDBusConnection>
2098+#include <QDBusInterface>
2099+#include <QDebug>
2100+
2101+DashCommunicator::DashCommunicator(QObject *parent):
2102+ QObject(parent)
2103+{
2104+}
2105+
2106+DashCommunicator::~DashCommunicator()
2107+{
2108+}
2109+
2110+
2111+void DashCommunicator::setCurrentScope(const QString &scopeId, bool animate, bool reset)
2112+{
2113+ Q_EMIT setCurrentScopeCalled(scopeId, animate, reset);
2114+}
2115
2116=== added file 'tests/mocks/Unity/DashCommunicator/dashcommunicator.h'
2117--- tests/mocks/Unity/DashCommunicator/dashcommunicator.h 1970-01-01 00:00:00 +0000
2118+++ tests/mocks/Unity/DashCommunicator/dashcommunicator.h 2014-07-28 15:50:22 +0000
2119@@ -0,0 +1,39 @@
2120+/*
2121+ * Copyright (C) 2014 Canonical, Ltd.
2122+ *
2123+ * This program is free software: you can redistribute it and/or modify it under
2124+ * the terms of the GNU Lesser General Public License version 3, as published by
2125+ * the Free Software Foundation.
2126+ *
2127+ * This program is distributed in the hope that it will be useful, but WITHOUT
2128+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
2129+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2130+ * Lesser General Public License for more details.
2131+ *
2132+ * You should have received a copy of the GNU Lesser General Public License
2133+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2134+ */
2135+
2136+#ifndef DASHCOMMUNICATOR_H
2137+#define DASHCOMMUNICATOR_H
2138+
2139+#include <QObject>
2140+
2141+class DashCommunicator: public QObject
2142+{
2143+ Q_OBJECT
2144+ Q_CLASSINFO("D-Bus Interface", "com.canonical.Unity.DashCommunicator")
2145+
2146+public:
2147+ DashCommunicator(QObject *parent = 0);
2148+ ~DashCommunicator();
2149+
2150+public Q_SLOTS:
2151+ void setCurrentScope(const QString &scopeId, bool animate, bool reset);
2152+
2153+Q_SIGNALS:
2154+ // This mock just emits calls back to the QML api for the plugin to verify calls
2155+ void setCurrentScopeCalled(const QString &scopeId, bool animate, bool reset);
2156+};
2157+
2158+#endif
2159
2160=== added file 'tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.cpp'
2161--- tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.cpp 1970-01-01 00:00:00 +0000
2162+++ tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.cpp 2014-07-28 15:50:22 +0000
2163@@ -0,0 +1,33 @@
2164+/*
2165+ * Copyright (C) 2014 Canonical, Ltd.
2166+ *
2167+ * This program is free software: you can redistribute it and/or modify it under
2168+ * the terms of the GNU Lesser General Public License version 3, as published by
2169+ * the Free Software Foundation.
2170+ *
2171+ * This program is distributed in the hope that it will be useful, but WITHOUT
2172+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
2173+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2174+ * Lesser General Public License for more details.
2175+ *
2176+ * You should have received a copy of the GNU Lesser General Public License
2177+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2178+ */
2179+
2180+#include "dashcommunicatorservice.h"
2181+
2182+DashCommunicatorService::DashCommunicatorService(QObject *parent):
2183+ QObject(parent)
2184+{
2185+}
2186+
2187+
2188+DashCommunicatorService::~DashCommunicatorService()
2189+{
2190+
2191+}
2192+
2193+void DashCommunicatorService::mockSetCurrentScope(const QString &scopeId, bool animate, bool reset)
2194+{
2195+ Q_EMIT setCurrentScope(scopeId, animate, reset);
2196+}
2197
2198=== added file 'tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.h'
2199--- tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.h 1970-01-01 00:00:00 +0000
2200+++ tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.h 2014-07-28 15:50:22 +0000
2201@@ -0,0 +1,36 @@
2202+/*
2203+ * Copyright (C) 2014 Canonical, Ltd.
2204+ *
2205+ * This program is free software: you can redistribute it and/or modify it under
2206+ * the terms of the GNU Lesser General Public License version 3, as published by
2207+ * the Free Software Foundation.
2208+ *
2209+ * This program is distributed in the hope that it will be useful, but WITHOUT
2210+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
2211+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2212+ * Lesser General Public License for more details.
2213+ *
2214+ * You should have received a copy of the GNU Lesser General Public License
2215+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2216+ */
2217+
2218+#ifndef DASHCOMMUNICATORSERVICE_H
2219+#define DASHCOMMUNICATORSERVICE_H
2220+
2221+#include <QObject>
2222+
2223+class DashCommunicatorService: public QObject
2224+{
2225+ Q_OBJECT
2226+public:
2227+ DashCommunicatorService(QObject *parent = 0);
2228+ ~DashCommunicatorService();
2229+
2230+Q_SIGNALS:
2231+ void setCurrentScope(const QString &scopeId, bool animate, bool reset);
2232+
2233+public Q_SLOTS:
2234+ void mockSetCurrentScope(const QString &scopeId, bool animate, bool reset);
2235+};
2236+
2237+#endif // DBUSUNITYSESSIONSERVICE_H
2238
2239=== added file 'tests/mocks/Unity/DashCommunicator/plugin.cpp'
2240--- tests/mocks/Unity/DashCommunicator/plugin.cpp 1970-01-01 00:00:00 +0000
2241+++ tests/mocks/Unity/DashCommunicator/plugin.cpp 2014-07-28 15:50:22 +0000
2242@@ -0,0 +1,31 @@
2243+/*
2244+ * Copyright (C) 2014 Canonical, Ltd.
2245+ *
2246+ * This program is free software; you can redistribute it and/or modify
2247+ * it under the terms of the GNU General Public License as published by
2248+ * the Free Software Foundation; version 3.
2249+ *
2250+ * This program is distributed in the hope that it will be useful,
2251+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2252+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2253+ * GNU General Public License for more details.
2254+ *
2255+ * You should have received a copy of the GNU General Public License
2256+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2257+ *
2258+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
2259+ */
2260+
2261+#include "plugin.h"
2262+#include "dashcommunicator.h"
2263+#include "dashcommunicatorservice.h"
2264+
2265+#include <QDBusConnection>
2266+#include <QtQml/qqml.h>
2267+
2268+void DashCommunicatorPlugin::registerTypes(const char *uri)
2269+{
2270+ Q_ASSERT(uri == QStringLiteral("Unity.DashCommunicator"));
2271+ qmlRegisterType<DashCommunicatorService>(uri, 0, 1, "DashCommunicatorService");
2272+ qmlRegisterType<DashCommunicator>(uri, 0, 1, "DashCommunicator");
2273+}
2274
2275=== added file 'tests/mocks/Unity/DashCommunicator/plugin.h'
2276--- tests/mocks/Unity/DashCommunicator/plugin.h 1970-01-01 00:00:00 +0000
2277+++ tests/mocks/Unity/DashCommunicator/plugin.h 2014-07-28 15:50:22 +0000
2278@@ -0,0 +1,34 @@
2279+/*
2280+ * Copyright (C) 2014 Canonical, Ltd.
2281+ *
2282+ * This program is free software; you can redistribute it and/or modify
2283+ * it under the terms of the GNU General Public License as published by
2284+ * the Free Software Foundation; version 3.
2285+ *
2286+ * This program is distributed in the hope that it will be useful,
2287+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2288+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2289+ * GNU General Public License for more details.
2290+ *
2291+ * You should have received a copy of the GNU General Public License
2292+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2293+ *
2294+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
2295+ */
2296+
2297+#ifndef DASHCOMMUNICATOR_PLUGIN_H
2298+#define DASHCOMMUNICATOR_PLUGIN_H
2299+
2300+#include <QtQml/QQmlEngine>
2301+#include <QtQml/QQmlExtensionPlugin>
2302+
2303+class DashCommunicatorPlugin : public QQmlExtensionPlugin
2304+{
2305+ Q_OBJECT
2306+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
2307+
2308+public:
2309+ void registerTypes(const char *uri);
2310+};
2311+
2312+#endif
2313
2314=== added file 'tests/mocks/Unity/DashCommunicator/qmldir'
2315--- tests/mocks/Unity/DashCommunicator/qmldir 1970-01-01 00:00:00 +0000
2316+++ tests/mocks/Unity/DashCommunicator/qmldir 2014-07-28 15:50:22 +0000
2317@@ -0,0 +1,3 @@
2318+module Unity.DashCommunicator
2319+plugin MockDashCommunicator-qml
2320+typeinfo DashCommunicator.qmltypes
2321
2322=== modified file 'tests/qmltests/Dash/tst_Dash.qml'
2323--- tests/qmltests/Dash/tst_Dash.qml 2014-07-11 11:45:45 +0000
2324+++ tests/qmltests/Dash/tst_Dash.qml 2014-07-28 15:50:22 +0000
2325@@ -59,6 +59,7 @@
2326 verify(dashContentList != undefined);
2327 tryCompare(dashContentList, "count", 0);
2328 scopes.load();
2329+ tryCompare(dashContentList, "currentIndex", 0);
2330 }
2331
2332 function get_scope_data() {
2333@@ -91,5 +92,23 @@
2334 verify(dashContentList != undefined);
2335 tryCompare(dashContentList, "currentIndex", data.visualIndex);
2336 }
2337+
2338+ function test_setCurrentScope() {
2339+ var dashContentList = findChild(dash, "dashContentList");
2340+ var startX = dash.width - units.gu(1);
2341+ var startY = dash.height / 2;
2342+ var stopX = units.gu(1)
2343+ var stopY = startY;
2344+ var retry = 0;
2345+ while (dashContentList.currentIndex != 2 && retry <= 5) {
2346+ mouseFlick(dash, startX, startY, stopX, stopY)
2347+ waitForRendering(dashContentList)
2348+ retry++;
2349+ }
2350+ compare(dashContentList.currentIndex, 2);
2351+ var dashCommunicatorService = findInvisibleChild(dash, "dashCommunicatorService");
2352+ dashCommunicatorService.mockSetCurrentScope("clickscope", true, true);
2353+ tryCompare(dashContentList, "currentIndex", 1)
2354+ }
2355 }
2356 }
2357
2358=== modified file 'tests/qmltests/Stages/tst_PhoneStage.qml'
2359--- tests/qmltests/Stages/tst_PhoneStage.qml 2014-07-28 15:50:19 +0000
2360+++ tests/qmltests/Stages/tst_PhoneStage.qml 2014-07-28 15:50:22 +0000
2361@@ -231,9 +231,10 @@
2362 }
2363
2364 function cleanup() {
2365- while (ApplicationManager.count > 0) {
2366+ while (ApplicationManager.count > 1) {
2367 var oldCount = ApplicationManager.count;
2368- ApplicationManager.stopApplication(ApplicationManager.get(0).appId)
2369+ var closingIndex = ApplicationManager.focusedApplicationId == "unity8-dash" ? 1 : 0
2370+ ApplicationManager.stopApplication(ApplicationManager.get(closingIndex).appId)
2371 tryCompare(ApplicationManager, "count", oldCount - 1)
2372 }
2373 }
2374
2375=== modified file 'tests/qmltests/tst_Shell.qml'
2376--- tests/qmltests/tst_Shell.qml 2014-07-28 15:50:19 +0000
2377+++ tests/qmltests/tst_Shell.qml 2014-07-28 15:50:22 +0000
2378@@ -56,49 +56,20 @@
2379 signalName: "sessionStarted"
2380 }
2381
2382+ SignalSpy {
2383+ id: dashCommunicatorSpy
2384+ signalName: "setCurrentScopeCalled"
2385+ }
2386+
2387 UT.UnityTestCase {
2388 name: "Shell"
2389 when: windowShown
2390
2391 function initTestCase() {
2392- var ok = false;
2393- var attempts = 0;
2394- var maxAttempts = 1000;
2395-
2396- // Qt loads a qml scene asynchronously. So early on, some findChild() calls made in
2397- // tests may fail because the desired child item wasn't loaded yet.
2398- // Thus here we try to ensure the scene has been fully loaded before proceeding with the tests.
2399- // As I couldn't find an API in QQuickView & friends to tell me that the scene is 100% loaded
2400- // (all items instantiated, etc), I resort to checking the existence of some key items until
2401- // repeatedly until they're all there.
2402- do {
2403- var dashContentList = findChild(shell, "dashContentList");
2404- waitForRendering(dashContentList);
2405- var homeLoader = findChild(dashContentList, "clickscope loader");
2406- ok = homeLoader !== null
2407- && homeLoader.item !== undefined;
2408-
2409- var greeter = findChild(shell, "greeter");
2410- ok &= greeter !== null;
2411-
2412- var launcherPanel = findChild(shell, "launcherPanel");
2413- ok &= launcherPanel !== null;
2414-
2415- attempts++;
2416- if (!ok) {
2417- console.log("Attempt " + attempts + " failed. Waiting a bit before trying again.");
2418- // wait a bit before retrying
2419- wait(100);
2420- } else {
2421- console.log("All seem fine after " + attempts + " attempts.");
2422- }
2423- } while (!ok && attempts <= maxAttempts);
2424-
2425- verify(ok);
2426-
2427 swipeAwayGreeter();
2428
2429 sessionSpy.target = findChild(shell, "greeter")
2430+ dashCommunicatorSpy.target = findInvisibleChild(shell, "dashCommunicator");
2431 }
2432
2433 function cleanup() {
2434@@ -111,56 +82,16 @@
2435 // kill all (fake) running apps
2436 killApps(ApplicationManager);
2437
2438- var dashContent = findChild(shell, "dashContent");
2439- dashContent.closePreview();
2440-
2441- var dashHome = findChild(shell, "clickscope loader");
2442- swipeUntilScopeViewIsReached(dashHome);
2443-
2444+ waitForUIToSettle();
2445 hideIndicators();
2446 }
2447
2448- function killApps(apps) {
2449- if (!apps) return;
2450- while (apps.count > 0) {
2451- ApplicationManager.stopApplication(apps.get(0).appId);
2452+ function killApps() {
2453+ while (ApplicationManager.count > 1) {
2454+ var appIndex = ApplicationManager.get(0).appId == "unity8-dash" ? 1 : 0
2455+ ApplicationManager.stopApplication(ApplicationManager.get(appIndex).appId);
2456 }
2457- compare(ApplicationManager.count, 0)
2458- }
2459-
2460- /*
2461- Test the effect of a right-edge drag on the dash in 3 situations:
2462- 1 - when no application has been launched yet
2463- 2 - when there's a minimized application
2464- 3 - after the last running application has been closed/stopped
2465-
2466- The behavior of Dash on 3 should be the same as on 1.
2467- */
2468- function test_rightEdgeDrag() {
2469- checkRightEdgeDragWithNoRunningApps();
2470-
2471- dragLauncherIntoView();
2472-
2473- // Launch an app from the launcher
2474- tapOnAppIconInLauncher();
2475- waitUntilApplicationWindowIsFullyVisible();
2476-
2477- // Minimize the application we just launched
2478- swipeFromLeftEdge(units.gu(27));
2479-
2480- waitForUIToSettle();
2481-
2482- checkRightEdgeDragWithMinimizedApp();
2483-
2484- // Minimize that application once again
2485- swipeFromLeftEdge(units.gu(27));
2486-
2487- // Right edge behavior should now be the same as before that app,
2488- // was launched. Manually cleanup beforehand to get to initial
2489- // state.
2490- cleanup();
2491- waitForUIToSettle();
2492- checkRightEdgeDragWithNoRunningApps();
2493+ compare(ApplicationManager.count, 1)
2494 }
2495
2496 function test_leftEdgeDrag_data() {
2497@@ -183,7 +114,7 @@
2498
2499 swipeFromLeftEdge(data.swipeLength);
2500 if (data.appHides)
2501- waitUntilApplicationWindowIsFullyHidden();
2502+ waitUntilDashIsFocused();
2503 else
2504 waitUntilApplicationWindowIsFullyVisible();
2505 }
2506@@ -240,99 +171,17 @@
2507 }
2508
2509 /*
2510- Perform a right-edge drag when the Dash is being show and there are
2511- no running/minimized apps to be restored.
2512-
2513- The expected behavior is that an animation should be played to hint the
2514- user that his right-edge drag gesture has been successfully recognized
2515- but there is no application to be brought to foreground.
2516- */
2517- function checkRightEdgeDragWithNoRunningApps() {
2518- var touchX = shell.width - (shell.edgeSize / 2);
2519- var touchY = shell.height / 2;
2520-
2521- var dash = findChild(shell, "dash");
2522- // check that dash has normal scale and opacity
2523- tryCompare(dash, "contentScale", 1.0);
2524- tryCompare(dash, "opacity", 1.0);
2525-
2526- touchFlick(shell, touchX, touchY, shell.width * 0.1, touchY,
2527- true /* beginTouch */, false /* endTouch */, units.gu(10), 50);
2528-
2529- // check that Dash has been scaled down and had its opacity reduced
2530- tryCompareFunction(function() { return dash.contentScale <= 0.9; }, true);
2531- tryCompareFunction(function() { return dash.opacity <= 0.5; }, true);
2532-
2533- touchRelease(shell, shell.width * 0.1, touchY);
2534-
2535- // and now everything should have gone back to normal
2536- tryCompare(dash, "contentScale", 1.0);
2537- tryCompare(dash, "opacity", 1.0);
2538- }
2539-
2540- /*
2541- Perform a right-edge drag when the Dash is being show and there is
2542- a running/minimized app to be restored.
2543-
2544- The expected behavior is that the dash should fade away and ultimately be
2545- made invisible once the gesture is finished as the restored app will now
2546- be on foreground.
2547- */
2548- function checkRightEdgeDragWithMinimizedApp() {
2549- var touchX = shell.width - (shell.edgeSize / 2);
2550- var touchY = shell.height / 2;
2551-
2552- var dash = findChild(shell, "dash");
2553- // check that dash has normal scale and opacity
2554- tryCompare(dash, "contentScale", 1.0);
2555- tryCompare(dash, "opacity", 1.0);
2556-
2557- touchFlick(shell, touchX, touchY, shell.width * 0.1, touchY,
2558- true /* beginTouch */, false /* endTouch */, units.gu(10), 50);
2559-
2560- // check that Dash has been scaled down and had its opacity reduced
2561- tryCompareFunction(function() { return dash.contentScale <= 0.9; }, true);
2562- tryCompareFunction(function() { return dash.opacity <= 0.5; }, true);
2563-
2564- touchRelease(shell, shell.width * 0.1, touchY);
2565-
2566- // dash should have gone away, now that the app is on foreground
2567- tryCompare(dash, "visible", false);
2568- }
2569-
2570- /*
2571 Regression test for bug https://bugs.launchpad.net/touch-preview-images/+bug/1193419
2572
2573- When the user minimizes an application (left-edge swipe) he should always end up in the "Running Apps"
2574- category of the "Applications" scope view.
2575+ When the user minimizes an application (left-edge swipe) he should always end up in the
2576+ "Applications" scope view.
2577
2578 Steps:
2579- - go to apps lens
2580- - scroll to the bottom
2581- - reveal launcher and launch an app
2582+ - reveal launcher and launch an app that covers the dash
2583 - perform long left edge swipe to go minimize the app and go back to the dash.
2584-
2585- Expected Results
2586- - apps lens shown
2587+ - verify the setCurrentScope() D-Bus call to the dash has been called for the correct scope id.
2588 */
2589 function test_minimizingAppTakesToDashApps() {
2590- var dashApps = findChild(shell, "clickscope");
2591- swipeUntilScopeViewIsReached(dashApps);
2592-
2593- // swipe finger up until the running/recent apps section (which we assume
2594- // it's the first one) is as far from view as possible.
2595- // We also assume that DashApps is tall enough that it's scrollable
2596- var appsCategoryListView = findChild(dashApps, "categoryListView");
2597- while (!appsCategoryListView.atYEnd) {
2598- swipeUpFromCenter();
2599- tryCompare(appsCategoryListView, "moving", false);
2600- }
2601-
2602- // Switch away from the Applications scope.
2603- swipeRightFromCenter();
2604- waitUntilItemStopsMoving(dashApps);
2605- verify(!itemIsOnScreen(dashApps));
2606-
2607 dragLauncherIntoView();
2608
2609 // Launch an app from the launcher
2610@@ -340,19 +189,16 @@
2611
2612 waitUntilApplicationWindowIsFullyVisible();
2613
2614- // Dragging launcher into view with a little bit of gap (units.gu(1)) should switch to Apps scope
2615- dragLauncherIntoView();
2616- verify(itemIsOnScreen(dashApps));
2617+ verify(ApplicationManager.focusedApplicationId !== "unity8-dash")
2618
2619+ dashCommunicatorSpy.clear();
2620 // Minimize the application we just launched
2621 swipeFromLeftEdge(units.gu(27));
2622
2623- // Wait for the whole UI to settle down
2624- waitUntilApplicationWindowIsFullyHidden();
2625- waitUntilItemStopsMoving(dashApps);
2626- tryCompare(appsCategoryListView, "moving", false);
2627+ tryCompare(ApplicationManager, "focusedApplicationId", "unity8-dash");
2628
2629- verify(itemIsOnScreen(dashApps));
2630+ compare(dashCommunicatorSpy.count, 1);
2631+ compare(dashCommunicatorSpy.signalArguments[0][0], "clickscope");
2632 }
2633
2634 function test_showInputMethod() {
2635@@ -409,9 +255,14 @@
2636
2637 // Wait for the whole UI to settle down
2638 function waitForUIToSettle() {
2639- waitUntilApplicationWindowIsFullyHidden();
2640- var dashContentList = findChild(shell, "dashContentList");
2641- tryCompare(dashContentList, "moving", false);
2642+ var launcher = findChild(shell, "launcherPanel")
2643+ tryCompareFunction(function() {return launcher.x === 0 || launcher.x === -launcher.width;}, true);
2644+ if (launcher.x === 0) {
2645+ mouseClick(shell, shell.width / 2, shell.height / 2)
2646+ }
2647+ tryCompare(launcher, "x", -launcher.width)
2648+
2649+ waitForRendering(shell)
2650 }
2651
2652 function dragToCloseIndicatorsPanel() {
2653@@ -468,24 +319,13 @@
2654 }
2655
2656 function waitUntilApplicationWindowIsFullyVisible() {
2657- var underlay = findChild(shell, "underlay");
2658- tryCompare(underlay, "visible", false);
2659- }
2660-
2661- function waitUntilApplicationWindowIsFullyHidden() {
2662- var stages = findChild(shell, "stages");
2663- tryCompare(stages, "fullyHidden", true);
2664- }
2665-
2666- function swipeUntilScopeViewIsReached(scopeView) {
2667- while (!itemIsOnScreen(scopeView)) {
2668- if (itemIsToLeftOfScreen(scopeView)) {
2669- swipeRightFromCenter();
2670- } else {
2671- swipeLeftFromCenter();
2672- }
2673- waitUntilItemStopsMoving(scopeView);
2674- }
2675+ var appDelegate = findChild(shell, "appDelegate0")
2676+ var surfaceContainer = findChild(appDelegate, "surfaceContainer");
2677+ tryCompareFunction(function() { return surfaceContainer.surface !== null; }, true);
2678+ }
2679+
2680+ function waitUntilDashIsFocused() {
2681+ tryCompare(ApplicationManager, "focusedApplicationId", "unity8-dash");
2682 }
2683
2684 function swipeFromLeftEdge(swipeLength) {
2685@@ -494,24 +334,6 @@
2686 touchFlick(shell, touchStartX, touchStartY, swipeLength, touchStartY);
2687 }
2688
2689- function swipeLeftFromCenter() {
2690- var touchStartX = shell.width * 3 / 4;
2691- var touchStartY = shell.height / 2;
2692- touchFlick(shell, touchStartX, touchStartY, 0, touchStartY);
2693- }
2694-
2695- function swipeRightFromCenter() {
2696- var touchStartX = shell.width * 3 / 4;
2697- var touchStartY = shell.height / 2;
2698- touchFlick(shell, touchStartX, touchStartY, shell.width, touchStartY);
2699- }
2700-
2701- function swipeUpFromCenter() {
2702- var touchStartX = shell.width / 2;
2703- var touchStartY = shell.height / 2;
2704- touchFlick(shell, touchStartX, touchStartY, touchStartX, 0);
2705- }
2706-
2707 function itemIsOnScreen(item) {
2708 var itemRectInShell = item.mapToItem(shell, 0, 0, item.width, item.height);
2709
2710@@ -521,64 +343,6 @@
2711 && itemRectInShell.y + itemRectInShell.height <= shell.height;
2712 }
2713
2714- function itemIsToLeftOfScreen(item) {
2715- var itemRectInShell = item.mapToItem(shell, 0, 0, item.width, item.height);
2716- return itemRectInShell.x < 0;
2717- }
2718-
2719- function waitUntilItemStopsMoving(item) {
2720- var itemRectInShell = item.mapToItem(shell, 0, 0, item.width, item.height);
2721- var previousX = itemRectInShell.x;
2722- var previousY = itemRectInShell.y;
2723- var isStill = false;
2724-
2725- do {
2726- wait(100);
2727- itemRectInShell = item.mapToItem(shell, 0, 0, item.width, item.height);
2728- if (itemRectInShell.x == previousX && itemRectInShell.y == previousY) {
2729- isStill = true;
2730- } else {
2731- previousX = itemRectInShell.x;
2732- previousY = itemRectInShell.y;
2733- }
2734- } while (!isStill);
2735- }
2736-
2737- function test_DashShown_data() {
2738- return [
2739- {tag: "in focus", greeter: false, app: false, launcher: false, indicators: false, expectedShown: true},
2740- {tag: "under greeter", greeter: true, app: false, launcher: false, indicators: false, expectedShown: false},
2741- {tag: "under app", greeter: false, app: true, launcher: false, indicators: false, expectedShown: false},
2742- {tag: "under launcher", greeter: false, app: false, launcher: true, indicators: false, expectedShown: true},
2743- {tag: "under indicators", greeter: false, app: false, launcher: false, indicators: true, expectedShown: false},
2744- ]
2745- }
2746-
2747- function test_DashShown(data) {
2748- if (data.greeter) {
2749- // Swipe the greeter in
2750- var greeter = findChild(shell, "greeter");
2751- Powerd.displayPowerStateChange(Powerd.Off, 0);
2752- tryCompare(greeter, "showProgress", 1);
2753- }
2754-
2755- if (data.app) {
2756- dragLauncherIntoView();
2757- tapOnAppIconInLauncher();
2758- }
2759-
2760- if (data.launcher) {
2761- dragLauncherIntoView();
2762- }
2763-
2764- if (data.indicators) {
2765- showIndicators();
2766- }
2767-
2768- var dash = findChild(shell, "dash");
2769- tryCompare(dash, "shown", data.expectedShown);
2770- }
2771-
2772 function test_focusRequestedHidesGreeter() {
2773 var greeter = findChild(shell, "greeter");
2774
2775@@ -587,10 +351,9 @@
2776 tryCompareFunction(function() { return app.surface != null }, true);
2777
2778 // Minimize the application we just launched
2779- swipeFromLeftEdge(units.gu(27));
2780+ swipeFromLeftEdge(units.gu(26) + 1);
2781
2782- // Wait for the whole UI to settle down
2783- waitUntilApplicationWindowIsFullyHidden();
2784+ waitUntilDashIsFocused();
2785
2786 greeter.show();
2787 tryCompare(greeter, "showProgress", 1);
2788@@ -606,8 +369,9 @@
2789
2790 showIndicators();
2791
2792+ var oldCount = ApplicationManager.count;
2793 ApplicationManager.startApplication("camera-app");
2794- tryCompare(ApplicationManager, "count", 1);
2795+ tryCompare(ApplicationManager, "count", oldCount + 1);
2796
2797 tryCompare(indicators, "fullyClosed", true);
2798 }
2799@@ -616,6 +380,7 @@
2800 function test_showGreeterDBusCall() {
2801 var greeter = findChild(shell, "greeter")
2802 tryCompare(greeter, "showProgress", 0)
2803+ waitForRendering(greeter);
2804 LightDM.Greeter.showGreeter()
2805 tryCompare(greeter, "showProgress", 1)
2806 }
2807@@ -624,6 +389,7 @@
2808 sessionSpy.clear()
2809
2810 var greeter = findChild(shell, "greeter")
2811+ waitForRendering(greeter)
2812 greeter.show()
2813 tryCompare(greeter, "showProgress", 1)
2814
2815
2816=== modified file 'tests/qmltests/tst_ShellWithPin.qml'
2817--- tests/qmltests/tst_ShellWithPin.qml 2014-07-15 18:26:25 +0000
2818+++ tests/qmltests/tst_ShellWithPin.qml 2014-07-28 15:50:22 +0000
2819@@ -58,40 +58,6 @@
2820 when: windowShown
2821
2822 function initTestCase() {
2823- var ok = false;
2824- var attempts = 0;
2825- var maxAttempts = 1000;
2826-
2827- // Qt loads a qml scene asynchronously. So early on, some findChild() calls made in
2828- // tests may fail because the desired child item wasn't loaded yet.
2829- // Thus here we try to ensure the scene has been fully loaded before proceeding with the tests.
2830- // As I couldn't find an API in QQuickView & friends to tell me that the scene is 100% loaded
2831- // (all items instantiated, etc), I resort to checking the existence of some key items until
2832- // repeatedly until they're all there.
2833- do {
2834- var dashContentList = findChild(shell, "dashContentList");
2835- waitForRendering(dashContentList);
2836- var homeLoader = findChild(dashContentList, "clickscope loader");
2837- ok = homeLoader !== null
2838- && homeLoader.item !== undefined;
2839-
2840- var greeter = findChild(shell, "greeter");
2841- ok &= greeter !== null;
2842-
2843- var launcherPanel = findChild(shell, "launcherPanel");
2844- ok &= launcherPanel !== null;
2845-
2846- attempts++;
2847- if (!ok) {
2848- console.log("Attempt " + attempts + " failed. Waiting a bit before trying again.");
2849- // wait a bit before retrying
2850- wait(100);
2851- } else {
2852- console.log("All seem fine after " + attempts + " attempts.");
2853- }
2854- } while (!ok && attempts <= maxAttempts);
2855-
2856- verify(ok);
2857
2858 sessionSpy.target = findChild(shell, "greeter")
2859 }
2860@@ -110,10 +76,11 @@
2861 }
2862
2863 function killApps() {
2864- while (ApplicationManager.count > 0) {
2865- ApplicationManager.stopApplication(ApplicationManager.get(0).appId)
2866+ while (ApplicationManager.count > 1) {
2867+ var appIndex = ApplicationManager.get(0).appId == "unity8-dash" ? 1 : 0
2868+ ApplicationManager.stopApplication(ApplicationManager.get(appIndex).appId);
2869 }
2870- compare(ApplicationManager.count, 0)
2871+ compare(ApplicationManager.count, 1)
2872 }
2873
2874 function swipeAwayGreeter() {

Subscribers

People subscribed via source and target branches