Merge lp:~mterry/unity8/greeter-apps into lp:unity8
- greeter-apps
- Merge into trunk
Status: | Superseded |
---|---|
Proposed branch: | lp:~mterry/unity8/greeter-apps |
Merge into: | lp:unity8 |
Prerequisite: | lp:~mterry/unity8/greeter-focus |
Diff against target: |
1630 lines (+1080/-38) 37 files modified
data/unity8-greeter-wrapper (+11/-3) debian/control (+3/-1) plugins/SessionBroadcast/SessionBroadcast.cpp (+36/-10) plugins/SessionBroadcast/SessionBroadcast.h (+10/-3) plugins/Unity/Indicators/indicatorsmanager.cpp (+3/-5) plugins/Utils/CMakeLists.txt (+1/-0) plugins/Utils/URLDispatcher.cpp (+77/-0) plugins/Utils/URLDispatcher.h (+47/-0) plugins/Utils/plugin.cpp (+2/-0) qml/Components/KeymapSwitcher.qml (+27/-1) qml/Greeter/Greeter.qml (+2/-2) qml/Panel/IndicatorItemRow.qml (+13/-2) qml/Panel/Indicators/MenuItemFactory.qml (+65/-0) qml/Shell.qml (+35/-10) tests/mocks/CMakeLists.txt (+1/-0) tests/mocks/SessionBroadcast/CMakeLists.txt (+8/-0) tests/mocks/SessionBroadcast/SessionBroadcast.cpp (+34/-0) tests/mocks/SessionBroadcast/SessionBroadcast.h (+39/-0) tests/mocks/SessionBroadcast/plugin.cpp (+31/-0) tests/mocks/SessionBroadcast/plugin.h (+32/-0) tests/mocks/SessionBroadcast/qmldir (+2/-0) tests/mocks/Unity/Indicators/IndicatorsModel.qml (+41/-1) tests/mocks/Utils/CMakeLists.txt (+1/-0) tests/mocks/Utils/URLDispatcher.cpp (+38/-0) tests/mocks/Utils/URLDispatcher.h (+47/-0) tests/mocks/Utils/plugin.cpp (+2/-0) tests/plugins/CMakeLists.txt (+1/-0) tests/plugins/SessionBroadcast/BroadcastServer.cpp (+33/-0) tests/plugins/SessionBroadcast/BroadcastServer.h (+40/-0) tests/plugins/SessionBroadcast/CMakeLists.txt (+45/-0) tests/plugins/SessionBroadcast/interfaces.xml (+18/-0) tests/plugins/SessionBroadcast/server.cpp (+37/-0) tests/plugins/SessionBroadcast/sessionbroadcasttest.cpp (+111/-0) tests/plugins/Utils/CMakeLists.txt (+9/-0) tests/plugins/Utils/URLDispatcherTest.cpp (+78/-0) tests/qmltests/Panel/tst_IndicatorItemRow.qml (+25/-0) tests/qmltests/tst_Shell.qml (+75/-0) |
To merge this branch: | bzr merge lp:~mterry/unity8/greeter-apps |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Unity8 CI Bot | continuous-integration | Needs Fixing | |
Daniel d'Andrada (community) | Approve | ||
Review via email: mp+299550@code.launchpad.net |
This proposal supersedes a proposal from 2016-06-29.
This proposal has been superseded by a proposal from 2016-07-20.
Commit message
Support launching apps inside a unity8 session from the greeter and support emergency dialing inside the greeter.
Description of the change
Testing instructions:
(You can test this on desktop just fine. But you won't see the emergency dialer functionality that way. And you'd have to be running unity8 as a session too. So easier to do it on the phone.)
- "citrain device-upgrade 55 XXXX" to install a backported yakkety lightdm and this MP to your phone.
- On your phone, "sudo apt install unity8-greeter unity-greeter-
- On your phone, edit /etc/lightdm/
Now reboot and try launching apps from the launcher and from indicators. When you unlock the phone, you should see that app.
Also try pressing the "Home" button on the launcher. It should go-to-home in the session.
Also try pressing the "Emergency Call" button and see how it launches the dialer-app.
After logging in and you press the power button, you get a mere lockscreen, which isn't suitable for testing this branch. If you go to the Settings indicator and press lock, you'll get a proper greeter which is suitable. You can tell whether you're in a lockscreen or the greeter because the greeter currently has less indicators (separate issue). You may see some odd behaviors/visuals here and there. Using a separate greeter is certainly not seamless yet. Working on it. But this MP is just about launching apps. Other issues will be fixed in due time.
* Are there any related MPs required for this MP to build/function as expected? Please list.
No, except it needs a backported lightdm to test on the phone.
* Did you perform an exploratory manual test run of your code change and any related functionality?
Yes
* If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
I'm on that team.
* If you changed the UI, has there been a design review?
NA
Unity8 CI Bot (unity8-ci-bot) wrote : Posted in a previous version of this proposal | # |
Unity8 CI Bot (unity8-ci-bot) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:2497
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
UNSTABLE: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2498
https:/
Executed test runs:
SUCCESS: https:/
UNSTABLE: https:/
UNSTABLE: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 2499. By Michael Terry
-
Merge trunk
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2499
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2499
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2499
https:/
Executed test runs:
SUCCESS: https:/
UNSTABLE: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 2500. By Michael Terry
-
And unregister the url-dispatcher well-known dbus name if we are set inactive (shouldn't happen in real practice)
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:2500
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Daniel d'Andrada (dandrader) wrote : | # |
Some minor stuff:
"""
+++ qml/Greeter/
@@ -99,7 +99,7 @@
}
// Notify that the user has explicitly requested the given app through unity8 GUI.
- function notifyUserReque
+ function notifyUserReque
if (!active) {
}
"""
Worth updating the documentation.
-------
URLDispatcher:
I suggest naming it urlRequested instead. Client dispatches a URL, service receives the URL request. From the service's point of view a URL has been requested.
-------
In Shell.qml:
"""
URLDispatcher {
[...]
function activateURL(url) {
}
}
"""
I think a more appropriate place for activateURL() would be next to activateApplica
Daniel d'Andrada (dandrader) wrote : | # |
How does logging work when you have two unity8 instances running?
- 2501. By Michael Terry
-
Address review comments
- 2502. By Michael Terry
-
Save dbus-session in /run/ again, in attempt to make dialer-app launching more reliable
Michael Terry (mterry) wrote : | # |
I addressed your comments. Regarding logging, I'll just repeat here what I said on IRC for posterity:
The lightdm user logs to its home in /var/lib/
You also mentioned on IRC a problem launching the emergency dialer. I was able to reproduce once but then had problems. I made a stab at something that might help? But I'm curious how reproducable it is for you.
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2502
https:/
Executed test runs:
SUCCESS: https:/
UNSTABLE: https:/
UNSTABLE: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 2503. By Michael Terry
-
Fix race with upstart socket
Michael Terry (mterry) wrote : | # |
OK, try again Daniel. I think I fixed the race condition with upstart causing the emergency dialer from not appearing.
Daniel d'Andrada (dandrader) wrote : | # |
Launching dialer does work now
Daniel d'Andrada (dandrader) wrote : | # |
Tapping on application icons in the greeter launcher has no effect whatsoever.
Michael Terry (mterry) wrote : | # |
Whoops, I left out an instruction: you also have to install unity-greeter-
(This MP adds a Recommends for unity-greeter-
Daniel d'Andrada (dandrader) wrote : | # |
* Did you perform an exploratory manual test run of the code change and any related functionality?
Yes
* Did CI run pass? If not, please explain why.
No. Unrelated qmluitest failures. The same failures appear in other MPs.
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:2503
https:/
Executed test runs:
SUCCESS: https:/
UNSTABLE: https:/
SUCCESS: https:/
UNSTABLE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 2504. By Michael Terry
-
Merge in keyboardIndicator, since we conflict
- 2505. By Michael Terry
-
Move new tst_Shell tests, to avoid conflict
- 2506. By Michael Terry
-
merge from parent
- 2507. By Michael Terry
-
Merge from trunk
- 2508. By Michael Terry
-
Merge session-chooser-gui
- 2509. By Michael Terry
-
Merge from session-chooser-gui
- 2510. By Michael Terry
-
Merge session-chooser-gui
Unmerged revisions
Preview Diff
1 | === modified file 'data/unity8-greeter-wrapper' |
2 | --- data/unity8-greeter-wrapper 2016-06-14 17:53:56 +0000 |
3 | +++ data/unity8-greeter-wrapper 2016-07-20 13:18:38 +0000 |
4 | @@ -1,8 +1,7 @@ |
5 | #!/bin/sh |
6 | # -*- Mode: sh; indent-tabs-mode: nil; tab-width: 4 -*- |
7 | # |
8 | -# Copyright (C) 2011,2013 Canonical Ltd |
9 | -# Author: Michael Terry <michael.terry@canonical.com> |
10 | +# Copyright (C) 2011,2013,2016 Canonical Ltd |
11 | # |
12 | # This program is free software: you can redistribute it and/or modify it under |
13 | # the terms of the GNU General Public License as published by the Free Software |
14 | @@ -42,6 +41,8 @@ |
15 | SUB_SOCKET=$XDG_RUNTIME_DIR/mir_socket |
16 | rm -f $SUB_SOCKET # clear socket in case we were hard shut down |
17 | |
18 | +echo "DBUS_SESSION_BUS_ADDRESS=${DBUS_SESSION_BUS_ADDRESS}" >"$XDG_RUNTIME_DIR/dbus-session" |
19 | + |
20 | # If touch session script (which sets up grid units and mir variables) is available, use it |
21 | TOUCH_WRAPPER= |
22 | if [ -x /usr/bin/ubuntu-touch-session ]; then |
23 | @@ -65,7 +66,14 @@ |
24 | MIR_SOCKET=$SUB_SOCKET $TOUCH_WRAPPER /sbin/upstart --user --no-startup-event & |
25 | INIT_PID=$! |
26 | while [ ! -e "$XDG_RUNTIME_DIR/upstart/sessions/$INIT_PID.session" ]; do sleep 0.1; done |
27 | -export UPSTART_SESSION=$(/sbin/initctl list-sessions | grep "^$INIT_PID " | cut -d' ' -f2) |
28 | +. "$XDG_RUNTIME_DIR/upstart/sessions/$INIT_PID.session" |
29 | +export UPSTART_SESSION |
30 | + |
31 | +# Connect upstart to system, but do first command in a loop to avoid any |
32 | +# race condition between the session file above being written and upstart being |
33 | +# ready to handle requests. |
34 | +while ! /sbin/initctl notify-dbus-address "$DBUS_SESSION_BUS_ADDRESS"; do sleep 0.1; done |
35 | +/sbin/initctl start notify-cgmanager |
36 | |
37 | # Start any pre-greeter tasks if needed (like wizard) |
38 | /sbin/initctl emit unity8-greeter-starting |
39 | |
40 | === modified file 'debian/control' |
41 | --- debian/control 2016-06-29 14:45:18 +0000 |
42 | +++ debian/control 2016-07-20 13:18:38 +0000 |
43 | @@ -130,7 +130,9 @@ |
44 | unity8-private | unity-launcher-impl, |
45 | ${misc:Depends}, |
46 | ${shlibs:Depends}, |
47 | -Recommends: indicator-session, |
48 | +Recommends: indicator-keyboard, |
49 | + indicator-session, |
50 | + unity-greeter-session-broadcast, |
51 | unity-scope-click, |
52 | unity-scope-mediascanner2, |
53 | Breaks: indicator-network (<< 0.5.1+14.10.20141014), |
54 | |
55 | === modified file 'plugins/SessionBroadcast/SessionBroadcast.cpp' |
56 | --- plugins/SessionBroadcast/SessionBroadcast.cpp 2016-04-19 20:36:29 +0000 |
57 | +++ plugins/SessionBroadcast/SessionBroadcast.cpp 2016-07-20 13:18:38 +0000 |
58 | @@ -1,5 +1,5 @@ |
59 | /* |
60 | - * Copyright (C) 2013 Canonical, Ltd. |
61 | + * Copyright (C) 2013,2016 Canonical, Ltd. |
62 | * |
63 | * This program is free software; you can redistribute it and/or modify |
64 | * it under the terms of the GNU General Public License as published by |
65 | @@ -12,12 +12,12 @@ |
66 | * |
67 | * You should have received a copy of the GNU General Public License |
68 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
69 | - * |
70 | - * Author: Michael Terry <michael.terry@canonical.com> |
71 | */ |
72 | |
73 | #include "SessionBroadcast.h" |
74 | #include <QDBusConnection> |
75 | +#include <QDBusConnectionInterface> |
76 | +#include <QDBusInterface> |
77 | |
78 | #include <glib.h> |
79 | |
80 | @@ -27,13 +27,39 @@ |
81 | m_username = QString::fromUtf8(g_get_user_name()); |
82 | |
83 | auto connection = QDBusConnection::SM_BUSNAME(); |
84 | - |
85 | - connection.connect(QStringLiteral("com.canonical.Unity.Greeter.Broadcast"), |
86 | - QStringLiteral("/com/canonical/Unity/Greeter/Broadcast"), |
87 | - QStringLiteral("com.canonical.Unity.Greeter.Broadcast"), |
88 | - QStringLiteral("ShowHome"), |
89 | - this, |
90 | - SLOT(onShowHome(const QString &))); |
91 | + auto interface = connection.interface(); |
92 | + interface->startService(QStringLiteral("com.canonical.Unity.Greeter.Broadcast")); |
93 | + |
94 | + m_broadcaster = new QDBusInterface(QStringLiteral("com.canonical.Unity.Greeter.Broadcast"), |
95 | + QStringLiteral("/com/canonical/Unity/Greeter/Broadcast"), |
96 | + QStringLiteral("com.canonical.Unity.Greeter.Broadcast"), |
97 | + connection, this); |
98 | + |
99 | + connect(m_broadcaster, SIGNAL(StartUrl(const QString &, const QString &)), |
100 | + this, SLOT(onStartUrl(const QString &, const QString &))); |
101 | + |
102 | + connect(m_broadcaster, SIGNAL(ShowHome(const QString &)), |
103 | + this, SLOT(onShowHome(const QString &))); |
104 | +} |
105 | + |
106 | +void SessionBroadcast::requestUrlStart(const QString &username, const QString &url) |
107 | +{ |
108 | + m_broadcaster->asyncCall(QStringLiteral("RequestUrlStart"), username, url); |
109 | +} |
110 | + |
111 | +void SessionBroadcast::requestHomeShown(const QString &username) |
112 | +{ |
113 | + m_broadcaster->asyncCall(QStringLiteral("RequestHomeShown"), username); |
114 | +} |
115 | + |
116 | +void SessionBroadcast::onStartUrl(const QString &username, const QString &url) |
117 | +{ |
118 | + // Since this signal is just used for testing, we don't *really* care if |
119 | + // username matches, but just in case we do eventually use the signal, we |
120 | + // should only listen to our own requests. |
121 | + if (username == m_username) { |
122 | + Q_EMIT startUrl(url); |
123 | + } |
124 | } |
125 | |
126 | void SessionBroadcast::onShowHome(const QString &username) |
127 | |
128 | === modified file 'plugins/SessionBroadcast/SessionBroadcast.h' |
129 | --- plugins/SessionBroadcast/SessionBroadcast.h 2016-04-06 19:03:42 +0000 |
130 | +++ plugins/SessionBroadcast/SessionBroadcast.h 2016-07-20 13:18:38 +0000 |
131 | @@ -1,5 +1,5 @@ |
132 | /* |
133 | - * Copyright (C) 2013 Canonical, Ltd. |
134 | + * Copyright (C) 2013,2016 Canonical, Ltd. |
135 | * |
136 | * This program is free software; you can redistribute it and/or modify |
137 | * it under the terms of the GNU General Public License as published by |
138 | @@ -12,8 +12,6 @@ |
139 | * |
140 | * You should have received a copy of the GNU General Public License |
141 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
142 | - * |
143 | - * Authors: Michael Terry <michael.terry@canonical.com> |
144 | */ |
145 | |
146 | #ifndef UNITY_SESSIONBROADCAST_H |
147 | @@ -31,14 +29,23 @@ |
148 | public: |
149 | explicit SessionBroadcast(QObject *parent = 0); |
150 | |
151 | + Q_INVOKABLE void requestUrlStart(const QString &username, const QString &url); |
152 | + Q_INVOKABLE void requestHomeShown(const QString &username); |
153 | + |
154 | Q_SIGNALS: |
155 | + // This signal isn't actually used by the shell |
156 | + // (unity-greeter-session-broadcast handles launching an app for us), but |
157 | + // it's useful for testing the plugin. |
158 | + void startUrl(const QString &url); |
159 | void showHome(); |
160 | |
161 | private Q_SLOTS: |
162 | + void onStartUrl(const QString &username, const QString &url); |
163 | void onShowHome(const QString &username); |
164 | |
165 | private: |
166 | QString m_username; |
167 | + QDBusInterface *m_broadcaster; |
168 | }; |
169 | |
170 | #endif |
171 | |
172 | === modified file 'plugins/Unity/Indicators/indicatorsmanager.cpp' |
173 | --- plugins/Unity/Indicators/indicatorsmanager.cpp 2016-06-08 21:52:16 +0000 |
174 | +++ plugins/Unity/Indicators/indicatorsmanager.cpp 2016-07-20 13:18:38 +0000 |
175 | @@ -114,10 +114,6 @@ |
176 | QSettings indicator_settings(file_info.absoluteFilePath(), QSettings::IniFormat, this); |
177 | const QString name = indicator_settings.value(QStringLiteral("Indicator Service/Name")).toString(); |
178 | |
179 | - if (m_platform.isPC() && name == QLatin1String("indicator-keyboard")) { |
180 | - return; // convergence: skip this indicator until it works in Mir |
181 | - } |
182 | - |
183 | auto iter = m_indicatorsData.constFind(name); |
184 | if (iter != m_indicatorsData.constEnd()) |
185 | { |
186 | @@ -285,11 +281,13 @@ |
187 | |
188 | // convergence: |
189 | // 1) enable session indicator |
190 | - // 2) on a PC, switch the battery/power indicator to desktop mode, |
191 | + // 2) enable keyboard indicator |
192 | + // 3) on a PC, switch the battery/power indicator to desktop mode, |
193 | // can't control brightness for now and phone-on-desktop broken (FIXME) |
194 | // |
195 | // The rest of the indicators respect their default profile (which is "phone", even on desktop PCs) |
196 | if ((new_indicator->identifier() == QStringLiteral("indicator-session")) |
197 | + || new_indicator->identifier() == QStringLiteral("indicator-keyboard") |
198 | || (new_indicator->identifier() == QStringLiteral("indicator-power") && m_platform.isPC())) { |
199 | new_indicator->setProfile(m_profile.replace(QStringLiteral("phone"), QStringLiteral("desktop"))); |
200 | } else { |
201 | |
202 | === modified file 'plugins/Utils/CMakeLists.txt' |
203 | --- plugins/Utils/CMakeLists.txt 2016-06-27 18:45:27 +0000 |
204 | +++ plugins/Utils/CMakeLists.txt 2016-07-20 13:18:38 +0000 |
205 | @@ -29,6 +29,7 @@ |
206 | inputeventgenerator.cpp |
207 | deviceconfigparser.cpp |
208 | globalfunctions.cpp |
209 | + URLDispatcher.cpp |
210 | plugin.cpp |
211 | ) |
212 | |
213 | |
214 | === added file 'plugins/Utils/URLDispatcher.cpp' |
215 | --- plugins/Utils/URLDispatcher.cpp 1970-01-01 00:00:00 +0000 |
216 | +++ plugins/Utils/URLDispatcher.cpp 2016-07-20 13:18:38 +0000 |
217 | @@ -0,0 +1,77 @@ |
218 | +/* |
219 | + * Copyright (C) 2016 Canonical, Ltd. |
220 | + * |
221 | + * This program is free software; you can redistribute it and/or modify |
222 | + * it under the terms of the GNU General Public License as published by |
223 | + * the Free Software Foundation; version 3. |
224 | + * |
225 | + * This program is distributed in the hope that it will be useful, |
226 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
227 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
228 | + * GNU General Public License for more details. |
229 | + * |
230 | + * You should have received a copy of the GNU General Public License |
231 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
232 | + */ |
233 | + |
234 | +#include "URLDispatcher.h" |
235 | + |
236 | +#include <QDBusConnection> |
237 | + |
238 | +class URLDispatcherInterface : public QObject |
239 | +{ |
240 | + Q_OBJECT |
241 | + Q_CLASSINFO("D-Bus Interface", "com.canonical.URLDispatcher") |
242 | + |
243 | +public: |
244 | + explicit URLDispatcherInterface(URLDispatcher *parent); |
245 | + |
246 | + Q_SCRIPTABLE void DispatchURL(const QString &url, const QString &package); |
247 | +}; |
248 | + |
249 | +URLDispatcherInterface::URLDispatcherInterface(URLDispatcher *parent) |
250 | + : QObject(parent) |
251 | +{ |
252 | +} |
253 | + |
254 | +void URLDispatcherInterface::DispatchURL(const QString &url, const QString &package) |
255 | +{ |
256 | + Q_UNUSED(package); |
257 | + Q_EMIT static_cast<URLDispatcher *>(parent())->urlRequested(url); |
258 | +} |
259 | + |
260 | +URLDispatcher::URLDispatcher(QObject *parent) |
261 | + : QObject(parent) |
262 | + , m_dispatcher(nullptr) |
263 | +{ |
264 | +} |
265 | + |
266 | +bool URLDispatcher::active() const |
267 | +{ |
268 | + return m_dispatcher != nullptr; |
269 | +} |
270 | + |
271 | +void URLDispatcher::setActive(bool value) |
272 | +{ |
273 | + if (value == active()) |
274 | + return; |
275 | + |
276 | + QDBusConnection connection = QDBusConnection::sessionBus(); |
277 | + |
278 | + if (value) { |
279 | + URLDispatcherInterface *dispatcher = new URLDispatcherInterface(this); |
280 | + connection.registerObject(QStringLiteral("/com/canonical/URLDispatcher"), |
281 | + dispatcher, |
282 | + QDBusConnection::ExportScriptableContents); |
283 | + connection.registerService(QStringLiteral("com.canonical.URLDispatcher")); |
284 | + m_dispatcher = dispatcher; |
285 | + } else { |
286 | + connection.unregisterService(QStringLiteral("com.canonical.URLDispatcher")); |
287 | + delete m_dispatcher; |
288 | + m_dispatcher = nullptr; |
289 | + } |
290 | + |
291 | + Q_EMIT activeChanged(); |
292 | +} |
293 | + |
294 | +#include "URLDispatcher.moc" |
295 | |
296 | === added file 'plugins/Utils/URLDispatcher.h' |
297 | --- plugins/Utils/URLDispatcher.h 1970-01-01 00:00:00 +0000 |
298 | +++ plugins/Utils/URLDispatcher.h 2016-07-20 13:18:38 +0000 |
299 | @@ -0,0 +1,47 @@ |
300 | +/* |
301 | + * Copyright (C) 2016 Canonical, Ltd. |
302 | + * |
303 | + * This program is free software; you can redistribute it and/or modify |
304 | + * it under the terms of the GNU General Public License as published by |
305 | + * the Free Software Foundation; version 3. |
306 | + * |
307 | + * This program is distributed in the hope that it will be useful, |
308 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
309 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
310 | + * GNU General Public License for more details. |
311 | + * |
312 | + * You should have received a copy of the GNU General Public License |
313 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
314 | + */ |
315 | + |
316 | +#ifndef UNITY_URLDISPATCHER_H |
317 | +#define UNITY_URLDISPATCHER_H |
318 | + |
319 | +#include <QObject> |
320 | +#include <QString> |
321 | + |
322 | +// This class manages our url-dispatcher interception. We intercept |
323 | +// url-dispatcher because rather than spawning the handler for the URL |
324 | +// in our own session, we want to notify the user session to do it for us |
325 | +// (and start an unlock in the process). |
326 | + |
327 | +class URLDispatcher : public QObject |
328 | +{ |
329 | + Q_OBJECT |
330 | + Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged) |
331 | + |
332 | +public: |
333 | + explicit URLDispatcher(QObject *parent=0); |
334 | + |
335 | + bool active() const; |
336 | + void setActive(bool active); |
337 | + |
338 | +Q_SIGNALS: |
339 | + void urlRequested(const QString &url); |
340 | + void activeChanged(); |
341 | + |
342 | +private: |
343 | + QObject *m_dispatcher; |
344 | +}; |
345 | + |
346 | +#endif |
347 | |
348 | === modified file 'plugins/Utils/plugin.cpp' |
349 | --- plugins/Utils/plugin.cpp 2016-04-29 20:07:03 +0000 |
350 | +++ plugins/Utils/plugin.cpp 2016-07-20 13:18:38 +0000 |
351 | @@ -38,6 +38,7 @@ |
352 | #include "inputeventgenerator.h" |
353 | #include "deviceconfigparser.h" |
354 | #include "globalfunctions.h" |
355 | +#include "URLDispatcher.h" |
356 | |
357 | static QObject *createWindowStateStorage(QQmlEngine *engine, QJSEngine *scriptEngine) |
358 | { |
359 | @@ -80,4 +81,5 @@ |
360 | qmlRegisterType<InputEventGenerator>(uri, 0, 1, "InputEventGenerator"); |
361 | qmlRegisterType<DeviceConfigParser>(uri, 0, 1, "DeviceConfigParser"); |
362 | qmlRegisterSingletonType<GlobalFunctions>(uri, 0, 1, "Functions", createGlobalFunctions); |
363 | + qmlRegisterType<URLDispatcher>(uri, 0, 1, "URLDispatcher"); |
364 | } |
365 | |
366 | === modified file 'qml/Components/KeymapSwitcher.qml' |
367 | --- qml/Components/KeymapSwitcher.qml 2016-04-04 13:38:56 +0000 |
368 | +++ qml/Components/KeymapSwitcher.qml 2016-07-20 13:18:38 +0000 |
369 | @@ -17,6 +17,7 @@ |
370 | import QtQuick 2.4 |
371 | import AccountsService 0.1 |
372 | import GlobalShortcut 1.0 |
373 | +import QMenuModel 0.1 |
374 | import Unity.Application 0.1 |
375 | |
376 | QtObject { |
377 | @@ -36,7 +37,8 @@ |
378 | |
379 | readonly property var keymaps: AccountsService.keymaps |
380 | readonly property int keymapCount: keymaps.length |
381 | - property int currentKeymapIndex: 0 |
382 | + // default keymap, either the one remembered by the indicator, or the 1st one selected by user |
383 | + property int currentKeymapIndex: actionGroup.currentAction.valid ? actionGroup.currentAction.state : 0 |
384 | readonly property string currentKeymap: keymaps[currentKeymapIndex] |
385 | |
386 | function nextKeymap() { |
387 | @@ -62,4 +64,28 @@ |
388 | property: "keymap" |
389 | value: root.currentKeymap |
390 | } |
391 | + |
392 | + // indicator |
393 | + property QDBusActionGroup actionGroup: QDBusActionGroup { |
394 | + busType: DBus.SessionBus |
395 | + busName: "com.canonical.indicator.keyboard" |
396 | + objectPath: "/com/canonical/indicator/keyboard" |
397 | + |
398 | + property variant currentAction: action("current") |
399 | + property variant activeAction: action("active") |
400 | + |
401 | + Component.onCompleted: actionGroup.start(); |
402 | + } |
403 | + |
404 | + onCurrentKeymapIndexChanged: { |
405 | + actionGroup.currentAction.updateState(currentKeymapIndex); |
406 | + } |
407 | + |
408 | + readonly property int activeActionState: actionGroup.activeAction.valid ? actionGroup.activeAction.state : -1 |
409 | + |
410 | + onActiveActionStateChanged: { |
411 | + if (activeActionState != -1) { |
412 | + currentKeymapIndex = activeActionState; |
413 | + } |
414 | + } |
415 | } |
416 | |
417 | === modified file 'qml/Greeter/Greeter.qml' |
418 | --- qml/Greeter/Greeter.qml 2016-07-07 19:52:57 +0000 |
419 | +++ qml/Greeter/Greeter.qml 2016-07-20 13:18:38 +0000 |
420 | @@ -98,8 +98,8 @@ |
421 | } |
422 | } |
423 | |
424 | - // Notify that the user has explicitly requested the given app through unity8 GUI. |
425 | - function notifyUserRequestedApp(appId) { |
426 | + // Notify that the user has explicitly requested an app |
427 | + function notifyUserRequestedApp() { |
428 | if (!active) { |
429 | return; |
430 | } |
431 | |
432 | === modified file 'qml/Panel/IndicatorItemRow.qml' |
433 | --- qml/Panel/IndicatorItemRow.qml 2016-03-29 03:47:39 +0000 |
434 | +++ qml/Panel/IndicatorItemRow.qml 2016-07-20 13:18:38 +0000 |
435 | @@ -18,6 +18,10 @@ |
436 | import QtQuick.Window 2.2 |
437 | import Ubuntu.Components 1.3 |
438 | |
439 | +// for indicator-keyboard |
440 | +import AccountsService 0.1 |
441 | +import Unity.InputInfo 0.1 |
442 | + |
443 | Item { |
444 | id: root |
445 | width: row.width |
446 | @@ -127,6 +131,11 @@ |
447 | property bool forceAlignmentAnimationDisabled: false |
448 | } |
449 | |
450 | + InputDeviceModel { |
451 | + id: keyboardsModel |
452 | + deviceFilter: InputInfo.Keyboard |
453 | + } |
454 | + |
455 | onCurrentItemChanged: { |
456 | if (d.previousItem) { |
457 | d.firstItemSwitch = false; |
458 | @@ -184,9 +193,11 @@ |
459 | |
460 | property int ownIndex: index |
461 | property bool overflow: row.width - x > overFlowWidth |
462 | - property bool hidden: !expanded && (overflow || !indicatorVisible || hideSessionIndicator) |
463 | + property bool hidden: !expanded && (overflow || !indicatorVisible || hideSessionIndicator || hideKeyboardIndicator) |
464 | // HACK for indicator-session |
465 | readonly property bool hideSessionIndicator: identifier == "indicator-session" && Math.min(Screen.width, Screen.height) <= units.gu(60) |
466 | + // HACK for indicator-keyboard |
467 | + readonly property bool hideKeyboardIndicator: identifier == "indicator-keyboard" && (AccountsService.keymaps.length < 2 || keyboardsModel.count == 0) |
468 | |
469 | height: row.height |
470 | expanded: root.expanded |
471 | @@ -202,7 +213,7 @@ |
472 | NumberAnimation { duration: UbuntuAnimation.SnapDuration; easing: UbuntuAnimation.StandardEasing } |
473 | } |
474 | |
475 | - width: ((expanded || indicatorVisible) && !hideSessionIndicator) ? implicitWidth : 0 |
476 | + width: ((expanded || indicatorVisible) && !hideSessionIndicator && !hideKeyboardIndicator) ? implicitWidth : 0 |
477 | |
478 | Behavior on width { |
479 | NumberAnimation { duration: UbuntuAnimation.SnapDuration; easing: UbuntuAnimation.StandardEasing } |
480 | |
481 | === modified file 'qml/Panel/Indicators/MenuItemFactory.qml' |
482 | --- qml/Panel/Indicators/MenuItemFactory.qml 2016-05-20 08:43:45 +0000 |
483 | +++ qml/Panel/Indicators/MenuItemFactory.qml 2016-07-20 13:18:38 +0000 |
484 | @@ -985,6 +985,62 @@ |
485 | } |
486 | } |
487 | |
488 | + Component { |
489 | + id: keymapMenu; |
490 | + |
491 | + // FIXME this should use a "radio button" menu, once we have it in the SDK |
492 | + ListItems.Empty { |
493 | + id: checkItem |
494 | + objectName: "keymapMenu" |
495 | + property QtObject menuData: null |
496 | + property int menuIndex: -1 |
497 | + readonly property bool serverChecked: menuData && menuData.isToggled || false |
498 | + |
499 | + enabled: menuData && menuData.sensitive || false |
500 | + highlightWhenPressed: false |
501 | + __acceptEvents: !serverChecked |
502 | + |
503 | + CheckBox { |
504 | + id: checkbox |
505 | + __acceptEvents: !checkItem.serverChecked |
506 | + anchors { |
507 | + left: parent.left |
508 | + leftMargin: checkItem.__contentsMargins |
509 | + verticalCenter: parent.verticalCenter |
510 | + } |
511 | + } |
512 | + |
513 | + ServerPropertySynchroniser { |
514 | + objectName: "sync" |
515 | + syncTimeout: Utils.Constants.indicatorValueTimeout |
516 | + |
517 | + serverTarget: checkItem |
518 | + serverProperty: "serverChecked" |
519 | + userTarget: checkbox |
520 | + userProperty: "checked" |
521 | + |
522 | + onSyncTriggered: { |
523 | + menuModel.activate(checkItem.menuIndex); |
524 | + } |
525 | + } |
526 | + |
527 | + Label { |
528 | + id: label |
529 | + anchors { |
530 | + left: checkbox.right |
531 | + leftMargin: checkItem.__contentsMargins |
532 | + right: parent.right |
533 | + rightMargin: checkItem.__contentsMargins |
534 | + verticalCenter: parent.verticalCenter |
535 | + } |
536 | + elide: Text.ElideRight |
537 | + text: checkItem.menuData && checkItem.menuData.label || "" |
538 | + } |
539 | + |
540 | + onClicked: menuModel.activate(menuIndex); |
541 | + } |
542 | + } |
543 | + |
544 | function load(modelData, context) { |
545 | // tweak indicator-session items |
546 | if (context === "indicator-session") { |
547 | @@ -995,6 +1051,15 @@ |
548 | } |
549 | } |
550 | |
551 | + // specialize for indicator-keyboard |
552 | + if (context === "indicator-keyboard") { |
553 | + if (modelData.isRadio) { |
554 | + return keymapMenu; |
555 | + } else if (modelData.action === "indicator.map" || modelData.action === "indicator.chart") { |
556 | + return null; // map and chart not available |
557 | + } |
558 | + } |
559 | + |
560 | if (modelData.type !== undefined && modelData.type !== "") { |
561 | var component = undefined; |
562 | |
563 | |
564 | === modified file 'qml/Shell.qml' |
565 | --- qml/Shell.qml 2016-07-11 17:23:38 +0000 |
566 | +++ qml/Shell.qml 2016-07-20 13:18:38 +0000 |
567 | @@ -151,6 +151,22 @@ |
568 | readonly property alias greeter: greeterLoader.item |
569 | |
570 | function activateApplication(appId) { |
571 | + // Either open the app in our own session, or -- if we're acting as a |
572 | + // greeter -- ask the user's session to open it for us. |
573 | + if (shell.mode === "greeter") { |
574 | + activateURL("application:///" + appId + ".desktop"); |
575 | + } else { |
576 | + startApp(appId); |
577 | + } |
578 | + } |
579 | + |
580 | + function activateURL(url) { |
581 | + SessionBroadcast.requestUrlStart(AccountsService.user, url); |
582 | + greeter.notifyUserRequestedApp(); |
583 | + panel.indicators.hide(); |
584 | + } |
585 | + |
586 | + function startApp(appId) { |
587 | if (ApplicationManager.findApplication(appId)) { |
588 | ApplicationManager.requestFocusApplication(appId); |
589 | } else { |
590 | @@ -162,7 +178,7 @@ |
591 | if (greeter.locked) { |
592 | greeter.lockedApp = app; |
593 | } |
594 | - shell.activateApplication(app); |
595 | + startApp(app); // locked apps are always in our same session |
596 | } |
597 | |
598 | Binding { |
599 | @@ -259,9 +275,7 @@ |
600 | ? "phone" |
601 | : shell.usageScenario |
602 | readonly property string qmlComponent: { |
603 | - if (shell.mode === "greeter") { |
604 | - return "Stages/AbstractStage.qml" |
605 | - } else if (applicationsDisplayLoader.usageScenario === "phone") { |
606 | + if (applicationsDisplayLoader.usageScenario === "phone") { |
607 | return "Stages/PhoneStage.qml"; |
608 | } else if (applicationsDisplayLoader.usageScenario === "tablet") { |
609 | return "Stages/TabletStage.qml"; |
610 | @@ -499,11 +513,15 @@ |
611 | } |
612 | |
613 | function showHome() { |
614 | - greeter.notifyUserRequestedApp("unity8-dash"); |
615 | + greeter.notifyUserRequestedApp(); |
616 | |
617 | - var animate = !LightDMService.greeter.active && !stages.shown |
618 | - dash.setCurrentScope(0, animate, false) |
619 | - ApplicationManager.requestFocusApplication("unity8-dash") |
620 | + if (shell.mode === "greeter") { |
621 | + SessionBroadcast.requestHomeShown(AccountsService.user); |
622 | + } else { |
623 | + var animate = !LightDMService.greeter.active && !stages.shown; |
624 | + dash.setCurrentScope(0, animate, false); |
625 | + ApplicationManager.requestFocusApplication("unity8-dash"); |
626 | + } |
627 | } |
628 | |
629 | function showDash() { |
630 | @@ -599,7 +617,7 @@ |
631 | } |
632 | } |
633 | onLauncherApplicationSelected: { |
634 | - greeter.notifyUserRequestedApp(appId); |
635 | + greeter.notifyUserRequestedApp(); |
636 | shell.activateApplication(appId); |
637 | } |
638 | onShownChanged: { |
639 | @@ -745,7 +763,14 @@ |
640 | |
641 | Connections { |
642 | target: SessionBroadcast |
643 | - onShowHome: showHome() |
644 | + onShowHome: if (shell.mode !== "greeter") showHome() |
645 | + } |
646 | + |
647 | + URLDispatcher { |
648 | + id: urlDispatcher |
649 | + objectName: "urlDispatcher" |
650 | + active: shell.mode === "greeter" |
651 | + onUrlRequested: shell.activateURL(url) |
652 | } |
653 | |
654 | ItemGrabber { |
655 | |
656 | === modified file 'tests/mocks/CMakeLists.txt' |
657 | --- tests/mocks/CMakeLists.txt 2016-06-27 14:51:40 +0000 |
658 | +++ tests/mocks/CMakeLists.txt 2016-07-20 13:18:38 +0000 |
659 | @@ -39,6 +39,7 @@ |
660 | add_subdirectory(MeeGo) |
661 | add_subdirectory(Powerd) |
662 | add_subdirectory(QMenuModel) |
663 | +add_subdirectory(SessionBroadcast) |
664 | add_subdirectory(Ubuntu) |
665 | add_subdirectory(Unity) |
666 | add_subdirectory(QtMultimedia) |
667 | |
668 | === added directory 'tests/mocks/SessionBroadcast' |
669 | === added file 'tests/mocks/SessionBroadcast/CMakeLists.txt' |
670 | --- tests/mocks/SessionBroadcast/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
671 | +++ tests/mocks/SessionBroadcast/CMakeLists.txt 2016-07-20 13:18:38 +0000 |
672 | @@ -0,0 +1,8 @@ |
673 | +add_library(MockSessionBroadcast-qml MODULE |
674 | + plugin.cpp |
675 | + SessionBroadcast.cpp |
676 | + ) |
677 | + |
678 | +qt5_use_modules(MockSessionBroadcast-qml Qml) |
679 | + |
680 | +add_unity8_mock(SessionBroadcast 0.1 SessionBroadcast TARGETS MockSessionBroadcast-qml) |
681 | |
682 | === added file 'tests/mocks/SessionBroadcast/SessionBroadcast.cpp' |
683 | --- tests/mocks/SessionBroadcast/SessionBroadcast.cpp 1970-01-01 00:00:00 +0000 |
684 | +++ tests/mocks/SessionBroadcast/SessionBroadcast.cpp 2016-07-20 13:18:38 +0000 |
685 | @@ -0,0 +1,34 @@ |
686 | +/* |
687 | + * Copyright (C) 2016 Canonical, Ltd. |
688 | + * |
689 | + * This program is free software; you can redistribute it and/or modify |
690 | + * it under the terms of the GNU General Public License as published by |
691 | + * the Free Software Foundation; version 3. |
692 | + * |
693 | + * This program is distributed in the hope that it will be useful, |
694 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
695 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
696 | + * GNU General Public License for more details. |
697 | + * |
698 | + * You should have received a copy of the GNU General Public License |
699 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
700 | + */ |
701 | + |
702 | +#include "SessionBroadcast.h" |
703 | + |
704 | +SessionBroadcast::SessionBroadcast(QObject* parent) |
705 | + : QObject(parent) |
706 | +{ |
707 | +} |
708 | + |
709 | +void SessionBroadcast::requestUrlStart(const QString &, const QString &url) |
710 | +{ |
711 | + // No user name guards, we won't worry about that aspect of the plugin here |
712 | + Q_EMIT startUrl(url); |
713 | +} |
714 | + |
715 | +void SessionBroadcast::requestHomeShown(const QString &) |
716 | +{ |
717 | + // No user name guards, we won't worry about that aspect of the plugin here |
718 | + Q_EMIT showHome(); |
719 | +} |
720 | |
721 | === added file 'tests/mocks/SessionBroadcast/SessionBroadcast.h' |
722 | --- tests/mocks/SessionBroadcast/SessionBroadcast.h 1970-01-01 00:00:00 +0000 |
723 | +++ tests/mocks/SessionBroadcast/SessionBroadcast.h 2016-07-20 13:18:38 +0000 |
724 | @@ -0,0 +1,39 @@ |
725 | +/* |
726 | + * Copyright (C) 2012,2013 Canonical, Ltd. |
727 | + * |
728 | + * This program is free software; you can redistribute it and/or modify |
729 | + * it under the terms of the GNU General Public License as published by |
730 | + * the Free Software Foundation; version 3. |
731 | + * |
732 | + * This program is distributed in the hope that it will be useful, |
733 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
734 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
735 | + * GNU General Public License for more details. |
736 | + * |
737 | + * You should have received a copy of the GNU General Public License |
738 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
739 | + * |
740 | + * Authors: Michael Terry <michael.terry@canonical.com> |
741 | + */ |
742 | + |
743 | +#ifndef UNITY_MOCK_SESSIONBROADCAST_H |
744 | +#define UNITY_MOCK_SESSIONBROADCAST_H |
745 | + |
746 | +#include <QObject> |
747 | + |
748 | +class SessionBroadcast: public QObject |
749 | +{ |
750 | + Q_OBJECT |
751 | + |
752 | +public: |
753 | + explicit SessionBroadcast(QObject *parent = 0); |
754 | + |
755 | + Q_INVOKABLE void requestUrlStart(const QString &username, const QString &url); |
756 | + Q_INVOKABLE void requestHomeShown(const QString &username); |
757 | + |
758 | +Q_SIGNALS: |
759 | + void startUrl(const QString &url); |
760 | + void showHome(); |
761 | +}; |
762 | + |
763 | +#endif |
764 | |
765 | === added file 'tests/mocks/SessionBroadcast/plugin.cpp' |
766 | --- tests/mocks/SessionBroadcast/plugin.cpp 1970-01-01 00:00:00 +0000 |
767 | +++ tests/mocks/SessionBroadcast/plugin.cpp 2016-07-20 13:18:38 +0000 |
768 | @@ -0,0 +1,31 @@ |
769 | +/* |
770 | + * Copyright (C) 2016 Canonical, Ltd. |
771 | + * |
772 | + * This program is free software; you can redistribute it and/or modify |
773 | + * it under the terms of the GNU General Public License as published by |
774 | + * the Free Software Foundation; version 3. |
775 | + * |
776 | + * This program is distributed in the hope that it will be useful, |
777 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
778 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
779 | + * GNU General Public License for more details. |
780 | + * |
781 | + * You should have received a copy of the GNU General Public License |
782 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
783 | + */ |
784 | + |
785 | +#include "plugin.h" |
786 | +#include "SessionBroadcast.h" |
787 | + |
788 | +#include <QtQml/qqml.h> |
789 | + |
790 | +static QObject *broadcast_provider(QQmlEngine *, QJSEngine *) |
791 | +{ |
792 | + return new SessionBroadcast(); |
793 | +} |
794 | + |
795 | +void PowerdPlugin::registerTypes(const char *uri) |
796 | +{ |
797 | + Q_ASSERT(uri == QLatin1String("SessionBroadcast")); |
798 | + qmlRegisterSingletonType<SessionBroadcast>(uri, 0, 1, "SessionBroadcast", broadcast_provider); |
799 | +} |
800 | |
801 | === added file 'tests/mocks/SessionBroadcast/plugin.h' |
802 | --- tests/mocks/SessionBroadcast/plugin.h 1970-01-01 00:00:00 +0000 |
803 | +++ tests/mocks/SessionBroadcast/plugin.h 2016-07-20 13:18:38 +0000 |
804 | @@ -0,0 +1,32 @@ |
805 | +/* |
806 | + * Copyright (C) 2016 Canonical, Ltd. |
807 | + * |
808 | + * This program is free software; you can redistribute it and/or modify |
809 | + * it under the terms of the GNU General Public License as published by |
810 | + * the Free Software Foundation; version 3. |
811 | + * |
812 | + * This program is distributed in the hope that it will be useful, |
813 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
814 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
815 | + * GNU General Public License for more details. |
816 | + * |
817 | + * You should have received a copy of the GNU General Public License |
818 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
819 | + */ |
820 | + |
821 | +#ifndef MOCK_SESSIONBROADCAST_PLUGIN_H |
822 | +#define MOCK_SESSIONBROADCAST_PLUGIN_H |
823 | + |
824 | +#include <QtQml/QQmlEngine> |
825 | +#include <QtQml/QQmlExtensionPlugin> |
826 | + |
827 | +class PowerdPlugin : public QQmlExtensionPlugin |
828 | +{ |
829 | + Q_OBJECT |
830 | + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") |
831 | + |
832 | +public: |
833 | + void registerTypes(const char *uri) override; |
834 | +}; |
835 | + |
836 | +#endif |
837 | |
838 | === added file 'tests/mocks/SessionBroadcast/qmldir' |
839 | --- tests/mocks/SessionBroadcast/qmldir 1970-01-01 00:00:00 +0000 |
840 | +++ tests/mocks/SessionBroadcast/qmldir 2016-07-20 13:18:38 +0000 |
841 | @@ -0,0 +1,2 @@ |
842 | +module SessionBroadcast |
843 | +plugin MockSessionBroadcast-qml |
844 | |
845 | === modified file 'tests/mocks/Unity/Indicators/IndicatorsModel.qml' |
846 | --- tests/mocks/Unity/Indicators/IndicatorsModel.qml 2015-07-15 15:07:19 +0000 |
847 | +++ tests/mocks/Unity/Indicators/IndicatorsModel.qml 2016-07-20 13:18:38 +0000 |
848 | @@ -16,12 +16,23 @@ |
849 | |
850 | import QtQuick 2.4 |
851 | import Unity.Indicators 0.1 as Indicators |
852 | +import Unity.InputInfo 0.1 |
853 | +import AccountsService 0.1 |
854 | |
855 | Indicators.FakeIndicatorsModel { |
856 | id: root |
857 | |
858 | property var originalModelData: [ |
859 | { |
860 | + "identifier": "indicator-keyboard", |
861 | + "indicatorProperties": { |
862 | + "enabled": true, |
863 | + "busName": "com.canonical.indicators.fake0", |
864 | + "menuObjectPath": "/com/canonical/indicators/fake0", |
865 | + "actionsObjectPath": "/com/canonical/indicators/fake0" |
866 | + } |
867 | + }, |
868 | + { |
869 | "identifier": "fake-indicator-bluetooth", |
870 | "indicatorProperties": { |
871 | "enabled": true, |
872 | @@ -74,13 +85,38 @@ |
873 | "menuObjectPath": "/com/canonical/indicators/fake6", |
874 | "actionsObjectPath": "/com/canonical/indicators/fake6" |
875 | } |
876 | + }, |
877 | + { |
878 | + "identifier": "fake-indicator-session", |
879 | + "indicatorProperties": { |
880 | + "enabled": true, |
881 | + "busName": "com.canonical.indicators.fake7", |
882 | + "menuObjectPath": "/com/canonical/indicators/fake7", |
883 | + "actionsObjectPath": "/com/canonical/indicators/fake7" |
884 | + } |
885 | } |
886 | ] |
887 | |
888 | + Component.onCompleted: { |
889 | + // init data for the fake indicator-keyboard |
890 | + MockInputDeviceBackend.addMockDevice("/kbd0", InputInfo.Keyboard); |
891 | + AccountsService.keymaps = ["us", "cs"]; |
892 | + } |
893 | + |
894 | + Component.onDestruction: { |
895 | + MockInputDeviceBackend.removeDevice("/kbd0"); |
896 | + AccountsService.keymaps = ["us"]; |
897 | + } |
898 | + |
899 | function load(profile) { |
900 | unload(); |
901 | root.modelData = originalModelData; |
902 | |
903 | + Indicators.UnityMenuModelCache.setCachedModelData("/com/canonical/indicators/fake0", |
904 | + getUnityMenuModelData("indicator-keyboard", |
905 | + "Czech (F)", |
906 | + "", |
907 | + [ "image://theme/indicator-keyboard-Cs-1" ])); |
908 | Indicators.UnityMenuModelCache.setCachedModelData("/com/canonical/indicators/fake1", |
909 | getUnityMenuModelData("fake-indicator-bluetooth", |
910 | "Bluetooth (F)", |
911 | @@ -111,6 +147,11 @@ |
912 | "Upcoming Events (F)", |
913 | "12:04", |
914 | [])); |
915 | + Indicators.UnityMenuModelCache.setCachedModelData("/com/canonical/indicators/fake7", |
916 | + getUnityMenuModelData("fake-indicator-session", |
917 | + "System (F)", |
918 | + "", |
919 | + ["image://theme/system-devices-panel"])); |
920 | } |
921 | |
922 | function getUnityMenuModelData(identifier, title, label, icons) { |
923 | @@ -173,6 +214,5 @@ |
924 | break; |
925 | } |
926 | } |
927 | - |
928 | } |
929 | } |
930 | |
931 | === modified file 'tests/mocks/Utils/CMakeLists.txt' |
932 | --- tests/mocks/Utils/CMakeLists.txt 2016-06-02 09:32:33 +0000 |
933 | +++ tests/mocks/Utils/CMakeLists.txt 2016-07-20 13:18:38 +0000 |
934 | @@ -32,6 +32,7 @@ |
935 | constants.cpp |
936 | plugin.cpp |
937 | windowstatestorage.cpp |
938 | + URLDispatcher.cpp |
939 | ) |
940 | |
941 | add_library(FakeUtils-qml SHARED |
942 | |
943 | === added file 'tests/mocks/Utils/URLDispatcher.cpp' |
944 | --- tests/mocks/Utils/URLDispatcher.cpp 1970-01-01 00:00:00 +0000 |
945 | +++ tests/mocks/Utils/URLDispatcher.cpp 2016-07-20 13:18:38 +0000 |
946 | @@ -0,0 +1,38 @@ |
947 | +/* |
948 | + * Copyright (C) 2016 Canonical, Ltd. |
949 | + * |
950 | + * This program is free software; you can redistribute it and/or modify |
951 | + * it under the terms of the GNU General Public License as published by |
952 | + * the Free Software Foundation; version 3. |
953 | + * |
954 | + * This program is distributed in the hope that it will be useful, |
955 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
956 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
957 | + * GNU General Public License for more details. |
958 | + * |
959 | + * You should have received a copy of the GNU General Public License |
960 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
961 | + */ |
962 | + |
963 | +#include "URLDispatcher.h" |
964 | + |
965 | +#include <QDBusConnection> |
966 | + |
967 | +URLDispatcher::URLDispatcher(QObject *parent) |
968 | + : QObject(parent) |
969 | + , m_active(false) |
970 | +{ |
971 | +} |
972 | + |
973 | +bool URLDispatcher::active() const |
974 | +{ |
975 | + return m_active; |
976 | +} |
977 | + |
978 | +void URLDispatcher::setActive(bool value) |
979 | +{ |
980 | + if (m_active != value) { |
981 | + m_active = value; |
982 | + Q_EMIT activeChanged(); |
983 | + } |
984 | +} |
985 | |
986 | === added file 'tests/mocks/Utils/URLDispatcher.h' |
987 | --- tests/mocks/Utils/URLDispatcher.h 1970-01-01 00:00:00 +0000 |
988 | +++ tests/mocks/Utils/URLDispatcher.h 2016-07-20 13:18:38 +0000 |
989 | @@ -0,0 +1,47 @@ |
990 | +/* |
991 | + * Copyright (C) 2016 Canonical, Ltd. |
992 | + * |
993 | + * This program is free software; you can redistribute it and/or modify |
994 | + * it under the terms of the GNU General Public License as published by |
995 | + * the Free Software Foundation; version 3. |
996 | + * |
997 | + * This program is distributed in the hope that it will be useful, |
998 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
999 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1000 | + * GNU General Public License for more details. |
1001 | + * |
1002 | + * You should have received a copy of the GNU General Public License |
1003 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1004 | + */ |
1005 | + |
1006 | +#ifndef UNITY_URLDISPATCHER_H |
1007 | +#define UNITY_URLDISPATCHER_H |
1008 | + |
1009 | +#include <QObject> |
1010 | +#include <QString> |
1011 | + |
1012 | +// This class manages our url-dispatcher interception. We intercept |
1013 | +// url-dispatcher because rather than spawning the handler for the URL |
1014 | +// in our own session, we want to notify the user session to do it for us |
1015 | +// (and start an unlock in the process). |
1016 | + |
1017 | +class URLDispatcher : public QObject |
1018 | +{ |
1019 | + Q_OBJECT |
1020 | + Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged) |
1021 | + |
1022 | +public: |
1023 | + explicit URLDispatcher(QObject *parent=0); |
1024 | + |
1025 | + bool active() const; |
1026 | + void setActive(bool active); |
1027 | + |
1028 | +Q_SIGNALS: |
1029 | + void urlRequested(const QString &url); |
1030 | + void activeChanged(); |
1031 | + |
1032 | +private: |
1033 | + bool m_active; |
1034 | +}; |
1035 | + |
1036 | +#endif |
1037 | |
1038 | === modified file 'tests/mocks/Utils/plugin.cpp' |
1039 | --- tests/mocks/Utils/plugin.cpp 2016-04-29 20:07:03 +0000 |
1040 | +++ tests/mocks/Utils/plugin.cpp 2016-07-20 13:18:38 +0000 |
1041 | @@ -25,6 +25,7 @@ |
1042 | #include "plugin.h" |
1043 | #include "windowstatestorage.h" |
1044 | #include "constants.h" |
1045 | +#include "URLDispatcher.h" |
1046 | |
1047 | // plugin |
1048 | #include <activefocuslogger.h> |
1049 | @@ -80,4 +81,5 @@ |
1050 | qmlRegisterType<InputEventGenerator>(uri, 0, 1, "InputEventGenerator"); |
1051 | qmlRegisterType<DeviceConfigParser>(uri, 0, 1, "DeviceConfigParser"); |
1052 | qmlRegisterSingletonType<GlobalFunctions>(uri, 0, 1, "Functions", createGlobalFunctions); |
1053 | + qmlRegisterType<URLDispatcher>(uri, 0, 1, "URLDispatcher"); |
1054 | } |
1055 | |
1056 | === modified file 'tests/plugins/CMakeLists.txt' |
1057 | --- tests/plugins/CMakeLists.txt 2016-06-07 16:10:36 +0000 |
1058 | +++ tests/plugins/CMakeLists.txt 2016-07-20 13:18:38 +0000 |
1059 | @@ -4,6 +4,7 @@ |
1060 | add_subdirectory(GlobalShortcut) |
1061 | add_subdirectory(Greeter) |
1062 | add_subdirectory(LightDM) |
1063 | +add_subdirectory(SessionBroadcast) |
1064 | add_subdirectory(Ubuntu) |
1065 | add_subdirectory(Unity) |
1066 | add_subdirectory(Utils) |
1067 | |
1068 | === added directory 'tests/plugins/SessionBroadcast' |
1069 | === added file 'tests/plugins/SessionBroadcast/BroadcastServer.cpp' |
1070 | --- tests/plugins/SessionBroadcast/BroadcastServer.cpp 1970-01-01 00:00:00 +0000 |
1071 | +++ tests/plugins/SessionBroadcast/BroadcastServer.cpp 2016-07-20 13:18:38 +0000 |
1072 | @@ -0,0 +1,33 @@ |
1073 | +/* |
1074 | + * Copyright 2016 Canonical Ltd. |
1075 | + * |
1076 | + * This program is free software: you can redistribute it and/or modify it |
1077 | + * under the terms of the GNU General Public License version 3, as published |
1078 | + * by the Free Software Foundation. |
1079 | + * |
1080 | + * This program is distributed in the hope that it will be useful, but |
1081 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1082 | + * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR |
1083 | + * PURPOSE. See the GNU General Public License for more details. |
1084 | + * |
1085 | + * You should have received a copy of the GNU General Public License |
1086 | + * version 3 along with this program. If not, see |
1087 | + * <http://www.gnu.org/licenses/> |
1088 | + */ |
1089 | + |
1090 | +#include "BroadcastServer.h" |
1091 | + |
1092 | +BroadcastServer::BroadcastServer(QObject *parent) |
1093 | + : QObject(parent) |
1094 | +{ |
1095 | +} |
1096 | + |
1097 | +void BroadcastServer::RequestUrlStart(const QString &username, const QString &url) |
1098 | +{ |
1099 | + Q_EMIT StartUrl(username, url); |
1100 | +} |
1101 | + |
1102 | +void BroadcastServer::RequestHomeShown(const QString &username) |
1103 | +{ |
1104 | + Q_EMIT ShowHome(username); |
1105 | +} |
1106 | |
1107 | === added file 'tests/plugins/SessionBroadcast/BroadcastServer.h' |
1108 | --- tests/plugins/SessionBroadcast/BroadcastServer.h 1970-01-01 00:00:00 +0000 |
1109 | +++ tests/plugins/SessionBroadcast/BroadcastServer.h 2016-07-20 13:18:38 +0000 |
1110 | @@ -0,0 +1,40 @@ |
1111 | +/* |
1112 | + * Copyright 2016 Canonical Ltd. |
1113 | + * |
1114 | + * This program is free software: you can redistribute it and/or modify it |
1115 | + * under the terms of the GNU General Public License version 3, as published |
1116 | + * by the Free Software Foundation. |
1117 | + * |
1118 | + * This program is distributed in the hope that it will be useful, but |
1119 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1120 | + * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR |
1121 | + * PURPOSE. See the GNU General Public License for more details. |
1122 | + * |
1123 | + * You should have received a copy of the GNU General Public License |
1124 | + * version 3 along with this program. If not, see |
1125 | + * <http://www.gnu.org/licenses/> |
1126 | + */ |
1127 | + |
1128 | +#ifndef UNITY_BROADCASTSERVER_H |
1129 | +#define UNITY_BROADCASTSERVER_H |
1130 | + |
1131 | +#include <QDBusContext> |
1132 | +#include <QObject> |
1133 | + |
1134 | +class BroadcastServer: public QObject, protected QDBusContext |
1135 | +{ |
1136 | + Q_OBJECT |
1137 | + |
1138 | +public: |
1139 | + explicit BroadcastServer(QObject *parent = nullptr); |
1140 | + |
1141 | +public Q_SLOTS: |
1142 | + void RequestUrlStart(const QString &username, const QString &url); |
1143 | + void RequestHomeShown(const QString &username); |
1144 | + |
1145 | +Q_SIGNALS: |
1146 | + void StartUrl(const QString &username, const QString &url); |
1147 | + void ShowHome(const QString &username); |
1148 | +}; |
1149 | + |
1150 | +#endif |
1151 | |
1152 | === added file 'tests/plugins/SessionBroadcast/CMakeLists.txt' |
1153 | --- tests/plugins/SessionBroadcast/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
1154 | +++ tests/plugins/SessionBroadcast/CMakeLists.txt 2016-07-20 13:18:38 +0000 |
1155 | @@ -0,0 +1,45 @@ |
1156 | +macro(make_dbus_class NAME INTERFACE) |
1157 | + if(${CMAKE_CURRENT_SOURCE_DIR}/interfaces.xml IS_NEWER_THAN ${CMAKE_CURRENT_BINARY_DIR}/${NAME}Adaptor.h) |
1158 | + execute_process(COMMAND ${QDBUSXML2CPP_EXECUTABLE} -c ${NAME}Adaptor -a ${CMAKE_CURRENT_BINARY_DIR}/${NAME}Adaptor ${CMAKE_CURRENT_SOURCE_DIR}/interfaces.xml ${INTERFACE}) |
1159 | + endif() |
1160 | +endmacro(make_dbus_class) |
1161 | + |
1162 | +make_dbus_class(Broadcast com.canonical.Unity.Greeter.Broadcast) |
1163 | + |
1164 | +add_definitions(-DSM_BUSNAME=sessionBus) |
1165 | + |
1166 | +include_directories( |
1167 | + ${GLIB_INCLUDE_DIRS} |
1168 | + ${CMAKE_CURRENT_BINARY_DIR} |
1169 | + ${CMAKE_CURRENT_SOURCE_DIR} |
1170 | + ${CMAKE_SOURCE_DIR}/plugins/SessionBroadcast |
1171 | +) |
1172 | + |
1173 | +link_libraries( |
1174 | + ${GLIB_LIBRARIES} |
1175 | +) |
1176 | + |
1177 | +add_executable(MockBroadcastServer |
1178 | + ${CMAKE_CURRENT_BINARY_DIR}/BroadcastAdaptor.cpp |
1179 | + server.cpp |
1180 | + BroadcastServer.cpp |
1181 | +) |
1182 | +qt5_use_modules(MockBroadcastServer Core DBus) |
1183 | + |
1184 | +### SessionBroadcastTest |
1185 | +add_executable(sessionbroadcasttestExec |
1186 | + ${CMAKE_SOURCE_DIR}/plugins/SessionBroadcast/SessionBroadcast.cpp |
1187 | + sessionbroadcasttest.cpp |
1188 | +) |
1189 | +qt5_use_modules(sessionbroadcasttestExec Test Core Qml DBus) |
1190 | + |
1191 | +add_unity8_unittest(SessionBroadcast dbus-test-runner |
1192 | + ARG_PREFIX "--parameter" |
1193 | + ARGS |
1194 | + --task $<TARGET_FILE:MockBroadcastServer> |
1195 | + --task-name server |
1196 | + --ignore-return |
1197 | + --task $<TARGET_FILE:sessionbroadcasttestExec> |
1198 | + --task-name client |
1199 | + --wait-for com.canonical.Unity.Greeter.Broadcast |
1200 | +) |
1201 | |
1202 | === added file 'tests/plugins/SessionBroadcast/interfaces.xml' |
1203 | --- tests/plugins/SessionBroadcast/interfaces.xml 1970-01-01 00:00:00 +0000 |
1204 | +++ tests/plugins/SessionBroadcast/interfaces.xml 2016-07-20 13:18:38 +0000 |
1205 | @@ -0,0 +1,18 @@ |
1206 | +<node> |
1207 | + <interface name="com.canonical.Unity.Greeter.Broadcast"> |
1208 | + <method name="RequestUrlStart"> |
1209 | + <arg name="username" type="s" direction="in" /> |
1210 | + <arg name="url" type="s" direction="in" /> |
1211 | + </method> |
1212 | + <method name="RequestHomeShown"> |
1213 | + <arg name="username" type="s" direction="in" /> |
1214 | + </method> |
1215 | + <signal name="StartUrl"> |
1216 | + <arg name="username" type="s" direction="out" /> |
1217 | + <arg name="url" type="s" direction="out" /> |
1218 | + </signal> |
1219 | + <signal name="ShowHome"> |
1220 | + <arg name="username" type="s" direction="out" /> |
1221 | + </signal> |
1222 | + </interface> |
1223 | +</node> |
1224 | |
1225 | === added file 'tests/plugins/SessionBroadcast/server.cpp' |
1226 | --- tests/plugins/SessionBroadcast/server.cpp 1970-01-01 00:00:00 +0000 |
1227 | +++ tests/plugins/SessionBroadcast/server.cpp 2016-07-20 13:18:38 +0000 |
1228 | @@ -0,0 +1,37 @@ |
1229 | +/* |
1230 | + * Copyright 2016 Canonical Ltd. |
1231 | + * |
1232 | + * This program is free software: you can redistribute it and/or modify it |
1233 | + * under the terms of the GNU General Public License version 3, as published |
1234 | + * by the Free Software Foundation. |
1235 | + * |
1236 | + * This program is distributed in the hope that it will be useful, but |
1237 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1238 | + * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR |
1239 | + * PURPOSE. See the GNU General Public License for more details. |
1240 | + * |
1241 | + * You should have received a copy of the GNU General Public License |
1242 | + * version 3 along with this program. If not, see |
1243 | + * <http://www.gnu.org/licenses/> |
1244 | + */ |
1245 | + |
1246 | +#include "BroadcastAdaptor.h" |
1247 | +#include "BroadcastServer.h" |
1248 | +#include <QCoreApplication> |
1249 | + |
1250 | +int main(int argc, char *argv[]) |
1251 | +{ |
1252 | + QCoreApplication a(argc, argv); |
1253 | + |
1254 | + auto broadcast = new BroadcastServer(&a); |
1255 | + new BroadcastAdaptor(broadcast); |
1256 | + |
1257 | + // We use the session bus for testing. The real plugin uses the system bus |
1258 | + auto connection = QDBusConnection::sessionBus(); |
1259 | + if (!connection.registerObject("/com/canonical/Unity/Greeter/Broadcast", broadcast)) |
1260 | + return 1; |
1261 | + if (!connection.registerService("com.canonical.Unity.Greeter.Broadcast")) |
1262 | + return 1; |
1263 | + |
1264 | + return a.exec(); |
1265 | +} |
1266 | |
1267 | === added file 'tests/plugins/SessionBroadcast/sessionbroadcasttest.cpp' |
1268 | --- tests/plugins/SessionBroadcast/sessionbroadcasttest.cpp 1970-01-01 00:00:00 +0000 |
1269 | +++ tests/plugins/SessionBroadcast/sessionbroadcasttest.cpp 2016-07-20 13:18:38 +0000 |
1270 | @@ -0,0 +1,111 @@ |
1271 | +/* |
1272 | + * Copyright 2016 Canonical Ltd. |
1273 | + * |
1274 | + * This program is free software; you can redistribute it and/or modify |
1275 | + * it under the terms of the GNU Lesser General Public License as published by |
1276 | + * the Free Software Foundation; version 3. |
1277 | + * |
1278 | + * This program is distributed in the hope that it will be useful, |
1279 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1280 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1281 | + * GNU Lesser General Public License for more details. |
1282 | + * |
1283 | + * You should have received a copy of the GNU Lesser General Public License |
1284 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1285 | + */ |
1286 | + |
1287 | +#include <QtTest> |
1288 | +#include <QDBusInterface> |
1289 | +#include <QSignalSpy> |
1290 | + |
1291 | +#include <glib.h> |
1292 | + |
1293 | +#include "SessionBroadcast.h" |
1294 | + |
1295 | +class SessionBroadcastTest : public QObject |
1296 | +{ |
1297 | + Q_OBJECT |
1298 | + |
1299 | +private Q_SLOTS: |
1300 | + |
1301 | + void initTestCase() { |
1302 | + broadcastServer = new QDBusInterface("com.canonical.Unity.Greeter.Broadcast", |
1303 | + "/com/canonical/Unity/Greeter/Broadcast", |
1304 | + "com.canonical.Unity.Greeter.Broadcast", |
1305 | + QDBusConnection::sessionBus(), this); |
1306 | + serverStartUrlSpy = new QSignalSpy(broadcastServer, |
1307 | + SIGNAL(StartUrl(const QString &, const QString &))); |
1308 | + serverShowHomeSpy = new QSignalSpy(broadcastServer, |
1309 | + SIGNAL(ShowHome(const QString &))); |
1310 | + user = QString(g_get_user_name()); |
1311 | + otherUser = user + "2"; |
1312 | + } |
1313 | + |
1314 | + void init() |
1315 | + { |
1316 | + serverStartUrlSpy->clear(); |
1317 | + serverShowHomeSpy->clear(); |
1318 | + |
1319 | + broadcastPlugin = new SessionBroadcast(this); |
1320 | + pluginStartUrlSpy = new QSignalSpy(broadcastPlugin, |
1321 | + SIGNAL(startUrl(const QString &))); |
1322 | + pluginShowHomeSpy = new QSignalSpy(broadcastPlugin, |
1323 | + SIGNAL(showHome())); |
1324 | + } |
1325 | + |
1326 | + void cleanup() |
1327 | + { |
1328 | + delete broadcastPlugin; |
1329 | + } |
1330 | + |
1331 | + void testReceiveUrlStart() { |
1332 | + broadcastServer->call("RequestUrlStart", user, "test:"); |
1333 | + QTRY_COMPARE(serverStartUrlSpy->count(), 1); |
1334 | + QCOMPARE(pluginStartUrlSpy->count(), 1); |
1335 | + QCOMPARE((*pluginStartUrlSpy)[0][0], QVariant("test:")); |
1336 | + } |
1337 | + |
1338 | + void testReceiveUrlStartOtherUser() { |
1339 | + broadcastServer->call("RequestUrlStart", otherUser, "test:"); |
1340 | + QTRY_COMPARE(serverStartUrlSpy->count(), 1); |
1341 | + QCOMPARE(pluginStartUrlSpy->count(), 0); |
1342 | + } |
1343 | + |
1344 | + void testReceiveShowHome() { |
1345 | + broadcastServer->call("RequestHomeShown", user); |
1346 | + QTRY_COMPARE(serverShowHomeSpy->count(), 1); |
1347 | + QCOMPARE(pluginShowHomeSpy->count(), 1); |
1348 | + } |
1349 | + |
1350 | + void testReceiveShowHomeOtherUser() { |
1351 | + broadcastServer->call("RequestHomeShown", otherUser); |
1352 | + QTRY_COMPARE(serverShowHomeSpy->count(), 1); |
1353 | + QCOMPARE(pluginShowHomeSpy->count(), 0); |
1354 | + } |
1355 | + |
1356 | + void testSendUrlStart() { |
1357 | + broadcastPlugin->requestUrlStart(otherUser, "test:"); |
1358 | + QTRY_COMPARE(serverStartUrlSpy->count(), 1); |
1359 | + QCOMPARE((*serverStartUrlSpy)[0][0], QVariant(otherUser)); |
1360 | + QCOMPARE((*serverStartUrlSpy)[0][1], QVariant("test:")); |
1361 | + } |
1362 | + |
1363 | + void testSendShowHome() { |
1364 | + broadcastPlugin->requestHomeShown(otherUser); |
1365 | + QTRY_COMPARE(serverShowHomeSpy->count(), 1); |
1366 | + QCOMPARE((*serverShowHomeSpy)[0][0], QVariant(otherUser)); |
1367 | + } |
1368 | + |
1369 | +private: |
1370 | + QDBusInterface *broadcastServer; |
1371 | + SessionBroadcast *broadcastPlugin; |
1372 | + QSignalSpy *serverStartUrlSpy; |
1373 | + QSignalSpy *serverShowHomeSpy; |
1374 | + QSignalSpy *pluginStartUrlSpy; |
1375 | + QSignalSpy *pluginShowHomeSpy; |
1376 | + QString user; |
1377 | + QString otherUser; |
1378 | +}; |
1379 | + |
1380 | +QTEST_GUILESS_MAIN(SessionBroadcastTest) |
1381 | +#include "sessionbroadcasttest.moc" |
1382 | |
1383 | === modified file 'tests/plugins/Utils/CMakeLists.txt' |
1384 | --- tests/plugins/Utils/CMakeLists.txt 2016-02-18 16:53:54 +0000 |
1385 | +++ tests/plugins/Utils/CMakeLists.txt 2016-07-20 13:18:38 +0000 |
1386 | @@ -23,3 +23,12 @@ |
1387 | |
1388 | # plain qml test |
1389 | add_unity8_qmlunittest(. UtilsStyle) |
1390 | + |
1391 | +# URLDispatcher test needs dbus-test-runner because it claims a dbus name |
1392 | +add_executable(URLDispatcherTestExec URLDispatcherTest.cpp) |
1393 | +qt5_use_modules(URLDispatcherTestExec Test Core Qml) |
1394 | +target_link_libraries(URLDispatcherTestExec Utils-qml) |
1395 | +add_unity8_unittest(URLDispatcher dbus-test-runner |
1396 | + ARG_PREFIX "--parameter" |
1397 | + ARGS --task $<TARGET_FILE:URLDispatcherTestExec> |
1398 | +) |
1399 | |
1400 | === added file 'tests/plugins/Utils/URLDispatcherTest.cpp' |
1401 | --- tests/plugins/Utils/URLDispatcherTest.cpp 1970-01-01 00:00:00 +0000 |
1402 | +++ tests/plugins/Utils/URLDispatcherTest.cpp 2016-07-20 13:18:38 +0000 |
1403 | @@ -0,0 +1,78 @@ |
1404 | +/* |
1405 | + * Copyright (C) 2016 Canonical, Ltd. |
1406 | + * |
1407 | + * This program is free software; you can redistribute it and/or modify |
1408 | + * it under the terms of the GNU General Public License as published by |
1409 | + * the Free Software Foundation; version 3. |
1410 | + * |
1411 | + * This program is distributed in the hope that it will be useful, |
1412 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1413 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1414 | + * GNU General Public License for more details. |
1415 | + * |
1416 | + * You should have received a copy of the GNU General Public License |
1417 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1418 | + */ |
1419 | + |
1420 | +#include "URLDispatcher.h" |
1421 | + |
1422 | +#include <QDBusInterface> |
1423 | +#include <QSignalSpy> |
1424 | +#include <QTest> |
1425 | + |
1426 | +class URLDispatcherTest : public QObject |
1427 | +{ |
1428 | + Q_OBJECT |
1429 | + |
1430 | +private Q_SLOTS: |
1431 | + |
1432 | + void initTestCase() { |
1433 | + dispatchServer = new QDBusInterface("com.canonical.URLDispatcher", |
1434 | + "/com/canonical/URLDispatcher", |
1435 | + "com.canonical.URLDispatcher", |
1436 | + QDBusConnection::sessionBus(), this); |
1437 | + } |
1438 | + |
1439 | + void init() |
1440 | + { |
1441 | + dispatcher = new URLDispatcher(this); |
1442 | + dispatchSpy = new QSignalSpy(dispatcher, |
1443 | + SIGNAL(urlRequested(const QString &))); |
1444 | + } |
1445 | + |
1446 | + void cleanup() |
1447 | + { |
1448 | + delete dispatcher; |
1449 | + } |
1450 | + |
1451 | + void testInactiveByDefault() { |
1452 | + QVERIFY(!dispatcher->active()); |
1453 | + } |
1454 | + |
1455 | + void testActiveRequest() { |
1456 | + dispatcher->setActive(true); |
1457 | + dispatchServer->call("DispatchURL", "test:", "package"); |
1458 | + QCOMPARE(dispatchSpy->count(), 1); |
1459 | + QCOMPARE((*dispatchSpy)[0][0], QVariant("test:")); |
1460 | + } |
1461 | + |
1462 | + void testInactiveRequest() { |
1463 | + dispatchServer->call("DispatchURL", "test:", "package"); |
1464 | + QCOMPARE(dispatchSpy->count(), 0); |
1465 | + } |
1466 | + |
1467 | + void testInactiveAfterActiveRequest() { |
1468 | + dispatcher->setActive(true); |
1469 | + dispatcher->setActive(false); |
1470 | + dispatchServer->call("DispatchURL", "test:", "package"); |
1471 | + QCOMPARE(dispatchSpy->count(), 0); |
1472 | + } |
1473 | + |
1474 | +private: |
1475 | + QDBusInterface *dispatchServer; |
1476 | + URLDispatcher *dispatcher; |
1477 | + QSignalSpy *dispatchSpy; |
1478 | +}; |
1479 | + |
1480 | +QTEST_GUILESS_MAIN(URLDispatcherTest) |
1481 | +#include "URLDispatcherTest.moc" |
1482 | |
1483 | === modified file 'tests/qmltests/Panel/tst_IndicatorItemRow.qml' |
1484 | --- tests/qmltests/Panel/tst_IndicatorItemRow.qml 2016-03-29 03:47:39 +0000 |
1485 | +++ tests/qmltests/Panel/tst_IndicatorItemRow.qml 2016-07-20 13:18:38 +0000 |
1486 | @@ -21,6 +21,8 @@ |
1487 | import Ubuntu.Components 1.3 |
1488 | import Unity.Test 0.1 as UT |
1489 | import Unity.Indicators 0.1 as Indicators |
1490 | +import AccountsService 0.1 |
1491 | +import Unity.InputInfo 0.1 |
1492 | |
1493 | IndicatorTest { |
1494 | id: root |
1495 | @@ -285,5 +287,28 @@ |
1496 | // should go back to 0 |
1497 | tryCompare(findChild(indicatorsRow, "highlight"), "highlightCenterOffset", 0); |
1498 | } |
1499 | + |
1500 | + function test_hidingKeyboardIndicator_data() { |
1501 | + return [ |
1502 | + { tag: "No keyboard, no keymap", keyboard: false, keymaps: [], hidden: true }, |
1503 | + { tag: "No keyboard, one keymap", keyboard: false, keymaps: ["us"], hidden: true }, |
1504 | + { tag: "No keyboard, 2 keymaps", keyboard: false, keymaps: ["us", "cs"], hidden: true }, |
1505 | + { tag: "Keyboard, no keymap", keyboard: true, keymaps: [], hidden: true }, |
1506 | + { tag: "Keyboard, one keymap", keyboard: true, keymaps: ["us"], hidden: true }, |
1507 | + { tag: "Keyboard, 2 keymaps", keyboard: true, keymaps: ["us", "cs"], hidden: false } |
1508 | + ]; |
1509 | + } |
1510 | + |
1511 | + function test_hidingKeyboardIndicator(data) { |
1512 | + var item = findChild(indicatorsRow, "indicator-keyboard-panelItem"); |
1513 | + AccountsService.keymaps = data.keymaps; |
1514 | + if (data.keyboard) { |
1515 | + MockInputDeviceBackend.addMockDevice("/kbd0", InputInfo.Keyboard); |
1516 | + } else { |
1517 | + MockInputDeviceBackend.removeDevice("/kbd0"); |
1518 | + } |
1519 | + |
1520 | + compare(item.hidden, data.hidden); |
1521 | + } |
1522 | } |
1523 | } |
1524 | |
1525 | === modified file 'tests/qmltests/tst_Shell.qml' |
1526 | --- tests/qmltests/tst_Shell.qml 2016-07-06 19:45:19 +0000 |
1527 | +++ tests/qmltests/tst_Shell.qml 2016-07-20 13:18:38 +0000 |
1528 | @@ -19,6 +19,7 @@ |
1529 | import AccountsService 0.1 |
1530 | import GSettings 1.0 |
1531 | import LightDM.IntegratedLightDM 0.1 as LightDM |
1532 | +import SessionBroadcast 0.1 |
1533 | import Ubuntu.Components 1.3 |
1534 | import Ubuntu.Components.ListItems 1.3 as ListItem |
1535 | import Ubuntu.Telephony 0.1 as Telephony |
1536 | @@ -406,6 +407,18 @@ |
1537 | } |
1538 | |
1539 | SignalSpy { |
1540 | + id: broadcastUrlSpy |
1541 | + target: SessionBroadcast |
1542 | + signalName: "startUrl" |
1543 | + } |
1544 | + |
1545 | + SignalSpy { |
1546 | + id: broadcastHomeSpy |
1547 | + target: SessionBroadcast |
1548 | + signalName: "showHome" |
1549 | + } |
1550 | + |
1551 | + SignalSpy { |
1552 | id: unlockAllModemsSpy |
1553 | target: Connectivity |
1554 | signalName: "unlockingAllModems" |
1555 | @@ -546,6 +559,8 @@ |
1556 | LightDM.Greeter.authenticate(""); // reset greeter |
1557 | |
1558 | sessionSpy.clear(); |
1559 | + broadcastUrlSpy.clear(); |
1560 | + broadcastHomeSpy.clear(); |
1561 | |
1562 | GSettingsController.setLifecycleExemptAppids([]); |
1563 | |
1564 | @@ -2404,6 +2419,66 @@ |
1565 | compare(topmostSurfaceItem.touchReleaseCount, 2); |
1566 | } |
1567 | |
1568 | + function test_greeterModeBroadcastsApp() { |
1569 | + setLightDMMockMode("single-pin"); |
1570 | + shellLoader.mode = "greeter"; |
1571 | + loadShell("phone"); |
1572 | + shell.usageScenario = "phone"; |
1573 | + waitForRendering(shell); |
1574 | + |
1575 | + dragLauncherIntoView(); |
1576 | + var appIcon = findChild(shell, "launcherDelegate0") |
1577 | + tap(appIcon); |
1578 | + |
1579 | + tryCompare(broadcastUrlSpy, "count", 1); |
1580 | + compare(broadcastUrlSpy.signalArguments[0][0], "application:///" + appIcon.appId + ".desktop"); |
1581 | + compare(ApplicationManager.count, 1); // confirm only dash is open, we didn't start new app |
1582 | + |
1583 | + var coverPage = findChild(shell, "coverPage"); |
1584 | + tryCompare(coverPage, "showProgress", 0); |
1585 | + } |
1586 | + |
1587 | + function test_greeterModeBroadcastsHome() { |
1588 | + setLightDMMockMode("single-pin"); |
1589 | + shellLoader.mode = "greeter"; |
1590 | + loadShell("phone"); |
1591 | + shell.usageScenario = "phone"; |
1592 | + waitForRendering(shell); |
1593 | + |
1594 | + var gallerySurfaceId = topLevelSurfaceList.nextId; |
1595 | + var galleryApp = ApplicationManager.startApplication("gallery-app"); |
1596 | + waitUntilAppWindowIsFullyLoaded(gallerySurfaceId); |
1597 | + compare(ApplicationManager.focusedApplicationId, "gallery-app"); |
1598 | + |
1599 | + dragLauncherIntoView(); |
1600 | + tap(findChild(shell, "buttonShowDashHome")); |
1601 | + |
1602 | + tryCompare(broadcastHomeSpy, "count", 1); |
1603 | + compare(ApplicationManager.focusedApplicationId, "gallery-app"); // confirm we didn't focus dash |
1604 | + |
1605 | + var coverPage = findChild(shell, "coverPage"); |
1606 | + tryCompare(coverPage, "showProgress", 0); |
1607 | + } |
1608 | + |
1609 | + function test_greeterModeDispatchesURL() { |
1610 | + setLightDMMockMode("single-pin"); |
1611 | + shellLoader.mode = "greeter"; |
1612 | + loadShell("phone"); |
1613 | + shell.usageScenario = "phone"; |
1614 | + waitForRendering(shell); |
1615 | + |
1616 | + var urlDispatcher = findInvisibleChild(shell, "urlDispatcher"); |
1617 | + verify(urlDispatcher.active); |
1618 | + urlDispatcher.urlRequested("test:"); // force signal emission |
1619 | + |
1620 | + tryCompare(broadcastUrlSpy, "count", 1); |
1621 | + compare(broadcastUrlSpy.signalArguments[0][0], "test:"); |
1622 | + compare(ApplicationManager.count, 1); // confirm only dash is open, we didn't start new app |
1623 | + |
1624 | + var coverPage = findChild(shell, "coverPage"); |
1625 | + tryCompare(coverPage, "showProgress", 0); |
1626 | + } |
1627 | + |
1628 | function test_switchKeymap() { |
1629 | // start with phone shell |
1630 | loadShell("phone"); |
FAILED: Continuous integration, rev:2496 /unity8- jenkins. ubuntu. com/job/ lp-unity8- ci/1643/ /unity8- jenkins. ubuntu. com/job/ build/2185/ console /unity8- jenkins. ubuntu. com/job/ build-0- fetch/2213/ console
https:/
Executed test runs:
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild: /unity8- jenkins. ubuntu. com/job/ lp-unity8- ci/1643/ rebuild
https:/