Merge lp:~lukas-kde/unity8/screenInhibitions into lp:unity8
- screenInhibitions
- Merge into trunk
Status: | Work in progress |
---|---|
Proposed branch: | lp:~lukas-kde/unity8/screenInhibitions |
Merge into: | lp:unity8 |
Diff against target: |
722 lines (+323/-64) 10 files modified
plugins/Unity/Session/CMakeLists.txt (+2/-0) plugins/Unity/Session/dbusunitysessionservice.cpp (+237/-28) plugins/Unity/Session/dbusunitysessionservice.h (+37/-2) qml/Components/Dialogs.qml (+3/-3) qml/Shell.qml (+1/-19) qml/Stage/Stage.qml (+39/-4) src/libunity8-private/unitydbusobject.cpp (+1/-6) src/libunity8-private/unitydbusobject.h (+0/-1) tests/plugins/Unity/Session/CMakeLists.txt (+2/-0) tests/plugins/Unity/Session/LogindServer.h (+1/-1) |
To merge this branch: | bzr merge lp:~lukas-kde/unity8/screenInhibitions |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Unity8 CI Bot | continuous-integration | Needs Fixing | |
Michael Zanetti | Pending | ||
Review via email: mp+309796@code.launchpad.net |
This proposal supersedes a proposal from 2016-10-14.
Commit message
Implement the FDO Inhibit DBUS API
Description of the change
This implements the de-facto freedesktop.org inhibit standard, as described in https:/
For the actual screenlock/saver keyboard shortcuts and dialogs, do not overpass the backend.
Simplify the *name* methods, add some missing documentation.
Checklist:
* Are there any related MPs required for this MP to build/function as expected? Please list.
No
* 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?
N/A
* If you changed the UI, has there been a design review?
N/A (no GUI change)
Michael Zanetti (mzanetti) wrote : Posted in a previous version of this proposal | # |
Michał Sawicz (saviq) wrote : Posted in a previous version of this proposal | # |
> In general it works, even from Firefox in libertine when watching a youtube video. However, if you close firefox while it's playing a video, it won't dispatch the Uninhibit call and the screen stays lit...
Oh yeah we totally need to track the requests and pop the ones where
requesters are gone.
Unity8 CI Bot (unity8-ci-bot) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:2662
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
UNSTABLE: https:/
UNSTABLE: 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:/
Michael Zanetti (mzanetti) wrote : Posted in a previous version of this proposal | # |
looks better in handling bad/crashing/
Unity8 CI Bot (unity8-ci-bot) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:2664
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
UNSTABLE: https:/
UNSTABLE: 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:2682
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
- 2683. By Lukáš Tinkl
-
use ual instead of qtmir::AppMan for the whitelisting of PIDs
Gerry Boland (gerboland) wrote : | # |
If you need an api in AppMan to wrap UAL's hasPid(), I'm happy to add it to qtmir. I just don't want to expose a list of PIDs for shell use.
- 2684. By Lukáš Tinkl
-
merge trunk
- 2685. By Lukáš Tinkl
-
merge trunk
- 2686. By Lukáš Tinkl
-
merge trunk
Unmerged revisions
- 2686. By Lukáš Tinkl
-
merge trunk
- 2685. By Lukáš Tinkl
-
merge trunk
- 2684. By Lukáš Tinkl
-
merge trunk
- 2683. By Lukáš Tinkl
-
use ual instead of qtmir::AppMan for the whitelisting of PIDs
- 2682. By Lukáš Tinkl
-
implement pidsForApplicat
ionid() - 2681. By Lukáš Tinkl
-
merge trunk
- 2680. By Lukáš Tinkl
-
fix PID type, get rid of Upstart
- 2679. By Lukáš Tinkl
-
don't take minimized delegates into account for the whitelist
- 2678. By Lukáš Tinkl
-
fix the whitelist checking
PID is different for DBUS and container apps :/
- 2677. By Lukáš Tinkl
-
fix the pid prop properly
Preview Diff
1 | === modified file 'plugins/Unity/Session/CMakeLists.txt' |
2 | --- plugins/Unity/Session/CMakeLists.txt 2016-06-21 14:23:49 +0000 |
3 | +++ plugins/Unity/Session/CMakeLists.txt 2016-11-22 09:36:12 +0000 |
4 | @@ -3,6 +3,7 @@ |
5 | ${CMAKE_CURRENT_BINARY_DIR} |
6 | ${GIO_INCLUDE_DIRS} |
7 | ${GLIB_INCLUDE_DIRS} |
8 | + ${UAL_INCLUDE_DIRS} |
9 | ${libunity8-private_SOURCE_DIR} |
10 | ) |
11 | |
12 | @@ -23,6 +24,7 @@ |
13 | unity8-private |
14 | ${GIO_LDFLAGS} |
15 | ${GLIB_LIBRARIES} |
16 | + ${UAL_LIBRARIES} |
17 | ) |
18 | |
19 | # export the qmldir and qmltypes files |
20 | |
21 | === modified file 'plugins/Unity/Session/dbusunitysessionservice.cpp' |
22 | --- plugins/Unity/Session/dbusunitysessionservice.cpp 2016-06-22 13:38:16 +0000 |
23 | +++ plugins/Unity/Session/dbusunitysessionservice.cpp 2016-11-22 09:36:12 +0000 |
24 | @@ -1,5 +1,5 @@ |
25 | /* |
26 | - * Copyright (C) 2014, 2015 Canonical, Ltd. |
27 | + * Copyright (C) 2014-2016 Canonical, Ltd. |
28 | * |
29 | * This program is free software: you can redistribute it and/or modify it under |
30 | * the terms of the GNU Lesser General Public License version 3, as published by |
31 | @@ -21,6 +21,7 @@ |
32 | #include <sys/types.h> |
33 | #include <unistd.h> |
34 | #include <pwd.h> |
35 | +#include <algorithm> |
36 | |
37 | // Qt |
38 | #include <QDebug> |
39 | @@ -29,6 +30,14 @@ |
40 | #include <QElapsedTimer> |
41 | #include <QDateTime> |
42 | #include <QDBusUnixFileDescriptor> |
43 | +#include <QDBusServiceWatcher> |
44 | +#include <QDBusConnectionInterface> |
45 | +#include <QPointer> |
46 | + |
47 | +// ual |
48 | +#include <ubuntu-app-launch/appid.h> |
49 | +#include <ubuntu-app-launch/application.h> |
50 | +#include <ubuntu-app-launch/registry.h> |
51 | |
52 | // Glib |
53 | #include <glib.h> |
54 | @@ -41,16 +50,39 @@ |
55 | #define ACTIVE_KEY QStringLiteral("Active") |
56 | #define IDLE_SINCE_KEY QStringLiteral("IdleSinceHint") |
57 | |
58 | +#define UNITY_SCREEN_SERVICE QStringLiteral("com.canonical.Unity.Screen") |
59 | +#define UNITY_SCREEN_PATH QStringLiteral("/com/canonical/Unity/Screen") |
60 | +#define UNITY_SCREEN_IFACE QStringLiteral("com.canonical.Unity.Screen") |
61 | + |
62 | +namespace ual = ubuntu::app_launch; |
63 | + |
64 | +struct InhibitionInfo { |
65 | + int cookie{0}; |
66 | + QString dbusAppName; |
67 | + QString dbusReason; |
68 | + QString dbusService; |
69 | + pid_t pid{0}; |
70 | +}; |
71 | + |
72 | class DBusUnitySessionServicePrivate: public QObject |
73 | { |
74 | Q_OBJECT |
75 | public: |
76 | QString logindSessionPath; |
77 | - bool isSessionActive = true; |
78 | + bool isSessionActive{true}; |
79 | QElapsedTimer screensaverActiveTimer; |
80 | QDBusUnixFileDescriptor m_systemdInhibitFd; |
81 | |
82 | - DBusUnitySessionServicePrivate(): QObject() { |
83 | + // inhibit stuff |
84 | + QPointer<QDBusServiceWatcher> busWatcher; |
85 | + std::list<InhibitionInfo> inhibitions; |
86 | + QStringList screenInhibitionsWhitelist; // list of appIds |
87 | + std::shared_ptr<ual::Registry> m_ualRegistry{std::make_shared<ual::Registry>()}; |
88 | + |
89 | + DBusUnitySessionServicePrivate(): |
90 | + QObject() |
91 | + , busWatcher(new QDBusServiceWatcher(this)) |
92 | + { |
93 | init(); |
94 | checkActive(); |
95 | } |
96 | @@ -80,6 +112,11 @@ |
97 | } else { |
98 | qWarning() << "Failed to get logind session path" << reply.error().message(); |
99 | } |
100 | + |
101 | + // watch services |
102 | + busWatcher->setConnection(QDBusConnection::sessionBus()); |
103 | + busWatcher->setWatchMode(QDBusServiceWatcher::WatchForUnregistration); |
104 | + connect(busWatcher, &QDBusServiceWatcher::serviceUnregistered, this, &DBusUnitySessionServicePrivate::onServiceUnregistered); |
105 | } |
106 | |
107 | void setupSystemdInhibition() |
108 | @@ -128,6 +165,7 @@ |
109 | QDBusConnection::SM_BUSNAME().asyncCall(msg); |
110 | } |
111 | |
112 | + // set the session as active or inactive |
113 | void setActive(bool active) |
114 | { |
115 | isSessionActive = active; |
116 | @@ -211,6 +249,139 @@ |
117 | QDBusConnection::SM_BUSNAME().asyncCall(msg); |
118 | } |
119 | |
120 | + /** |
121 | + * Register inhibition, enable it if on whitelist |
122 | + * |
123 | + * @return the inhibition cookie, or 0 if the call didn't succeed |
124 | + */ |
125 | + int addInhibition(const QString &service, int pid, const QString &appName, const QString &reason) |
126 | + { |
127 | + InhibitionInfo inh; |
128 | + inh.dbusAppName = appName; |
129 | + inh.dbusReason = reason; |
130 | + inh.dbusService = service; |
131 | + inh.pid = static_cast<pid_t>(pid); |
132 | + |
133 | + int cookie = 0; |
134 | + |
135 | + if (whiteListCheck(pid)) { |
136 | + cookie = addInhibitionHelper(); |
137 | + if (cookie > 0) { |
138 | + inh.cookie = cookie; |
139 | + } |
140 | + } else |
141 | + qDebug() << "!!! Whitelist doesn't contain pid:" << pid << screenInhibitionsWhitelist; |
142 | + |
143 | + if (!busWatcher.isNull() && !service.isEmpty() && !busWatcher->watchedServices().contains(service)) { |
144 | + qDebug() << "!!! Started watching service:" << service; |
145 | + busWatcher->addWatchedService(service); |
146 | + } |
147 | + |
148 | + qDebug() << "!!! addInhibition, cookie:" << cookie; |
149 | + |
150 | + inhibitions.push_back(inh); |
151 | + return cookie; |
152 | + } |
153 | + |
154 | + /** |
155 | + * Ask repowerd to keep the display on (enable the inhibition), start watching the service |
156 | + * @return cookie, 0 in failure |
157 | + */ |
158 | + int addInhibitionHelper() |
159 | + { |
160 | + QDBusMessage msg = QDBusMessage::createMethodCall(UNITY_SCREEN_SERVICE, UNITY_SCREEN_PATH, UNITY_SCREEN_IFACE, QStringLiteral("keepDisplayOn")); |
161 | + QDBusReply<int> cookie = QDBusConnection::SM_BUSNAME().call(msg); |
162 | + if (cookie.isValid()) { |
163 | + return cookie; |
164 | + } else { |
165 | + qWarning() << "Failed to inhibit screen blanking" << cookie.error().message(); |
166 | + } |
167 | + |
168 | + return 0; |
169 | + } |
170 | + |
171 | + /** |
172 | + * Release the repowerd screen inhibition based on @p cookie |
173 | + */ |
174 | + void removeInhibition(int cookie) |
175 | + { |
176 | + qDebug() << "!!! removeInhibition, cookie:" << cookie; |
177 | + QDBusMessage msg = QDBusMessage::createMethodCall(UNITY_SCREEN_SERVICE, UNITY_SCREEN_PATH, UNITY_SCREEN_IFACE, QStringLiteral("removeDisplayOnRequest")); |
178 | + msg << cookie; |
179 | + QDBusReply<void> reply = QDBusConnection::SM_BUSNAME().call(msg); |
180 | + if (!reply.isValid()) { |
181 | + qWarning() << "Failed to release screen blanking inhibition" << reply.error().message(); |
182 | + } |
183 | + } |
184 | + |
185 | + /** |
186 | + * Drop the inhibition from the list with the matching @p cookie, cleaning up the bus watcher as well if needed |
187 | + */ |
188 | + void removeInhibitionHelper(int cookie) |
189 | + { |
190 | + qDebug() << "!!! removeInhibitionHelper, cookie:" << cookie; |
191 | + // drop the inhibition from the list with the matching cookie |
192 | + QString service; |
193 | + inhibitions.remove_if([&service, cookie](const InhibitionInfo & inh) {service = inh.dbusService; return inh.cookie == cookie;}); |
194 | + |
195 | + qDebug() << "!!! Removed inhibition for service?:" << service; |
196 | + |
197 | + if (!busWatcher.isNull() && std::none_of(inhibitions.cbegin(), inhibitions.cend(), |
198 | + [service](const InhibitionInfo & inh){return inh.dbusService == service;})) { |
199 | + // no cookies from service left |
200 | + qDebug() << "!!! Stopped watching service:" << service; |
201 | + busWatcher->removeWatchedService(service); |
202 | + } |
203 | + } |
204 | + |
205 | + /** |
206 | + * Enable/disable inhibitions dynamically as the whitelist changes |
207 | + */ |
208 | + void updateInhibitions() |
209 | + { |
210 | + qDebug() << "!!! Update inhibitions, empty?" << inhibitions.empty(); |
211 | + if (inhibitions.empty()) // no inhibitions set up, bail out |
212 | + return; |
213 | + |
214 | + qDebug() << "!!! Update inhibitions, whitelist of PIDs:" << screenInhibitionsWhitelist; |
215 | + |
216 | + for (InhibitionInfo inh: inhibitions) { |
217 | + if (!whiteListCheck(inh.pid)) { // not on whitelist anymore, disable temporarily |
218 | + qDebug() << "!!! Disabling inhibition, not on whitelist:" << inh.dbusService; |
219 | + removeInhibition(inh.cookie); |
220 | + inh.cookie = 0; // reset the cookie |
221 | + } else if (whiteListCheck(inh.pid) && inh.cookie == 0) { // on whitelist but not enabled |
222 | + qDebug() << "!!! Enabling inhibition, on whitelist but not enabled:" << inh.dbusService; |
223 | + inh.cookie = addInhibitionHelper(); |
224 | + } |
225 | + } |
226 | + } |
227 | + |
228 | + bool whiteListCheck(pid_t pid) const { |
229 | + Q_FOREACH(const QString &appId, screenInhibitionsWhitelist) { |
230 | + ual::AppID ualAppId = ual::AppID::find(m_ualRegistry, appId.toStdString()); |
231 | + if (ualAppId.empty()) { |
232 | + continue; |
233 | + } |
234 | + |
235 | + std::shared_ptr<ual::Application> ualApp; |
236 | + try { |
237 | + ualApp = ual::Application::create(ualAppId, m_ualRegistry); |
238 | + } |
239 | + catch (std::runtime_error &e) { |
240 | + qWarning() << "Couldn't find UAL application object for" << appId << "-" << e.what(); |
241 | + continue; |
242 | + } |
243 | + if (ualApp) { |
244 | + if (std::any_of(ualApp->instances().cbegin(), ualApp->instances().cend(), |
245 | + [pid](const std::shared_ptr<ual::Application::Instance> &inst){ return inst && inst->hasPid(pid); })) { |
246 | + return true; |
247 | + } |
248 | + } |
249 | + } |
250 | + return false; |
251 | + } |
252 | + |
253 | private Q_SLOTS: |
254 | void onPropertiesChanged(const QString &iface, const QVariantMap &changedProps, const QStringList &invalidatedProps) |
255 | { |
256 | @@ -232,6 +403,19 @@ |
257 | } |
258 | } |
259 | |
260 | + void onServiceUnregistered(const QString &service) |
261 | + { |
262 | + // cleanup inhibitions |
263 | + qDebug() << "!!! Cleanup inhibitions"; |
264 | + Q_FOREACH(InhibitionInfo inh, inhibitions) { |
265 | + if (inh.dbusService == service) { |
266 | + qDebug() << "!!! Cleaning up cookie" << inh.cookie << ", after service:" << inh.dbusService; |
267 | + removeInhibition(inh.cookie); |
268 | + removeInhibitionHelper(inh.cookie); |
269 | + } |
270 | + } |
271 | + } |
272 | + |
273 | Q_SIGNALS: |
274 | void screensaverActiveChanged(bool active); |
275 | void prepareForSleep(); |
276 | @@ -245,7 +429,7 @@ |
277 | if (!d->logindSessionPath.isEmpty()) { |
278 | // connect our PromptLock() slot to the logind's session Lock() signal |
279 | QDBusConnection::SM_BUSNAME().connect(LOGIN1_SERVICE, d->logindSessionPath, LOGIN1_SESSION_IFACE, QStringLiteral("Lock"), this, SLOT(PromptLock())); |
280 | - // ... and our Unlocked() signal to the logind's session Unlock() signal |
281 | + // ... and our doUnlock() slot to the logind's session Unlock() signal |
282 | // (lightdm handles the unlocking by calling logind's Unlock method which in turn emits this signal we connect to) |
283 | QDBusConnection::SM_BUSNAME().connect(LOGIN1_SERVICE, d->logindSessionPath, LOGIN1_SESSION_IFACE, QStringLiteral("Unlock"), this, SLOT(doUnlock())); |
284 | connect(d, &DBusUnitySessionServicePrivate::prepareForSleep, this, &DBusUnitySessionService::PromptLock); |
285 | @@ -254,6 +438,22 @@ |
286 | } |
287 | } |
288 | |
289 | +QStringList DBusUnitySessionService::screenInhibitionsWhitelist() const |
290 | +{ |
291 | + return d->screenInhibitionsWhitelist; |
292 | +} |
293 | + |
294 | +void DBusUnitySessionService::setScreenInhibitionsWhitelist(const QStringList &screenInhibitionsWhitelist) |
295 | +{ |
296 | + qDebug() << "!!! Update whitelist, new one:" << screenInhibitionsWhitelist << ", old one:" << d->screenInhibitionsWhitelist; |
297 | + if (std::is_permutation(screenInhibitionsWhitelist.begin(), screenInhibitionsWhitelist.end(), d->screenInhibitionsWhitelist.begin())) |
298 | + return; |
299 | + |
300 | + d->screenInhibitionsWhitelist = screenInhibitionsWhitelist; |
301 | + Q_EMIT screenInhibitionsWhitelistChanged(); |
302 | + d->updateInhibitions(); |
303 | +} |
304 | + |
305 | void DBusUnitySessionService::Logout() |
306 | { |
307 | // TODO ask the apps to quit and then emit the signal |
308 | @@ -263,11 +463,11 @@ |
309 | |
310 | void DBusUnitySessionService::EndSession() |
311 | { |
312 | - const QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("com.ubuntu.Upstart"), |
313 | - QStringLiteral("/com/ubuntu/Upstart"), |
314 | - QStringLiteral("com.ubuntu.Upstart0_6"), |
315 | - QStringLiteral("EndSession")); |
316 | - QDBusConnection::sessionBus().asyncCall(msg); |
317 | + const QDBusMessage msg = QDBusMessage::createMethodCall(LOGIN1_SERVICE, |
318 | + d->logindSessionPath, |
319 | + LOGIN1_SESSION_IFACE, |
320 | + QStringLiteral("Terminate")); |
321 | + QDBusConnection::SM_BUSNAME().asyncCall(msg); |
322 | } |
323 | |
324 | bool DBusUnitySessionService::CanHibernate() const |
325 | @@ -307,27 +507,12 @@ |
326 | |
327 | QString DBusUnitySessionService::RealName() const |
328 | { |
329 | - struct passwd *p = getpwuid(geteuid()); |
330 | - if (p) { |
331 | - const QString gecos = QString::fromLocal8Bit(p->pw_gecos); |
332 | - if (!gecos.isEmpty()) { |
333 | - const QStringList splitGecos = gecos.split(QLatin1Char(',')); |
334 | - return splitGecos.first(); |
335 | - } |
336 | - } |
337 | - |
338 | - return QString(); |
339 | + return QString::fromUtf8(g_get_real_name()); |
340 | } |
341 | |
342 | QString DBusUnitySessionService::HostName() const |
343 | { |
344 | - char hostName[512]; |
345 | - if (gethostname(hostName, sizeof(hostName)) == -1) { |
346 | - qWarning() << "Could not determine local hostname"; |
347 | - return QString(); |
348 | - } |
349 | - hostName[sizeof(hostName) - 1] = '\0'; |
350 | - return QString::fromLocal8Bit(hostName); |
351 | + return QString::fromUtf8(g_get_host_name()); |
352 | } |
353 | |
354 | void DBusUnitySessionService::PromptLock() |
355 | @@ -337,6 +522,7 @@ |
356 | // user session. |
357 | Q_EMIT LockRequested(); |
358 | Q_EMIT lockRequested(); |
359 | + d->setActive(false); |
360 | } |
361 | |
362 | void DBusUnitySessionService::Lock() |
363 | @@ -395,6 +581,7 @@ |
364 | { |
365 | Q_EMIT Unlocked(); |
366 | Q_EMIT unlocked(); |
367 | + d->setActive(true); |
368 | } |
369 | |
370 | bool DBusUnitySessionService::IsLocked() const |
371 | @@ -528,7 +715,7 @@ |
372 | |
373 | void DBusGnomeScreensaverWrapper::SimulateUserActivity() |
374 | { |
375 | - d->setIdleHint(false); |
376 | + d->setActive(true); |
377 | } |
378 | |
379 | |
380 | @@ -570,7 +757,29 @@ |
381 | |
382 | void DBusScreensaverWrapper::SimulateUserActivity() |
383 | { |
384 | - d->setIdleHint(false); |
385 | + d->setActive(true); |
386 | +} |
387 | + |
388 | +uint DBusScreensaverWrapper::Inhibit(const QString &appName, const QString &reason) |
389 | +{ |
390 | + QString service; |
391 | + int pid = 0; |
392 | + if (calledFromDBus()) { |
393 | + service = message().service(); |
394 | + pid = connection().interface()->servicePid(service); |
395 | + } |
396 | + qDebug() << "!!! INHIBIT (appName, reason, dbusService, pid)" << appName << reason << service << pid; |
397 | + uint cookie = static_cast<uint>(d->addInhibition(service, pid, appName, reason)); |
398 | + d->checkActive(); |
399 | + return cookie; |
400 | +} |
401 | + |
402 | +void DBusScreensaverWrapper::UnInhibit(uint cookie) |
403 | +{ |
404 | + qDebug() << "!!! UNINHIBIT (cookie)" << cookie; |
405 | + d->removeInhibition(cookie); |
406 | + d->removeInhibitionHelper(cookie); |
407 | + d->checkActive(); |
408 | } |
409 | |
410 | #include "dbusunitysessionservice.moc" |
411 | |
412 | === modified file 'plugins/Unity/Session/dbusunitysessionservice.h' |
413 | --- plugins/Unity/Session/dbusunitysessionservice.h 2016-06-22 13:38:16 +0000 |
414 | +++ plugins/Unity/Session/dbusunitysessionservice.h 2016-11-22 09:36:12 +0000 |
415 | @@ -1,5 +1,5 @@ |
416 | /* |
417 | - * Copyright (C) 2014, 2015 Canonical, Ltd. |
418 | + * Copyright (C) 2014-2016 Canonical, Ltd. |
419 | * |
420 | * This program is free software: you can redistribute it and/or modify it under |
421 | * the terms of the GNU Lesser General Public License version 3, as published by |
422 | @@ -17,6 +17,7 @@ |
423 | #ifndef DBUSUNITYSESSIONSERVICE_H |
424 | #define DBUSUNITYSESSIONSERVICE_H |
425 | |
426 | +#include <QDBusContext> |
427 | #include <QDBusObjectPath> |
428 | |
429 | #include "unitydbusobject.h" |
430 | @@ -36,6 +37,12 @@ |
431 | Q_OBJECT |
432 | Q_CLASSINFO("D-Bus Interface", "com.canonical.Unity.Session") |
433 | |
434 | + /** |
435 | + * List of PIDs allowed to request screen inhibition |
436 | + */ |
437 | + Q_PROPERTY(QStringList screenInhibitionsWhitelist READ screenInhibitionsWhitelist WRITE setScreenInhibitionsWhitelist |
438 | + NOTIFY screenInhibitionsWhitelistChanged) |
439 | + |
440 | public: |
441 | DBusUnitySessionService(); |
442 | ~DBusUnitySessionService() = default; |
443 | @@ -48,6 +55,10 @@ |
444 | |
445 | // TODO: remove duplicate signals and split D-Bus and QML API's |
446 | // Apparently QML needs the signals in lowercase, while DBUS spec needs the uppercase version |
447 | + |
448 | + QStringList screenInhibitionsWhitelist() const; |
449 | + void setScreenInhibitionsWhitelist(const QStringList &screenInhibitionsWhitelist); |
450 | + |
451 | Q_SIGNALS: |
452 | /** |
453 | * LogoutRequested signal |
454 | @@ -108,6 +119,8 @@ |
455 | Q_SCRIPTABLE void Unlocked(); |
456 | void unlocked(); |
457 | |
458 | + void screenInhibitionsWhitelistChanged(); |
459 | + |
460 | public Q_SLOTS: |
461 | /** |
462 | * Logout the system. |
463 | @@ -313,13 +326,16 @@ |
464 | */ |
465 | Q_SCRIPTABLE quint32 GetActiveTime() const; |
466 | |
467 | + /** |
468 | + * Simulate user activity, thus interrupting the screensaver |
469 | + */ |
470 | Q_SCRIPTABLE void SimulateUserActivity(); |
471 | |
472 | Q_SIGNALS: |
473 | void ActiveChanged(bool active); |
474 | }; |
475 | |
476 | -class DBusScreensaverWrapper: public UnityDBusObject |
477 | +class DBusScreensaverWrapper: public UnityDBusObject, protected QDBusContext |
478 | { |
479 | Q_OBJECT |
480 | Q_CLASSINFO("D-Bus Interface", "org.freedesktop.ScreenSaver") |
481 | @@ -354,8 +370,27 @@ |
482 | */ |
483 | Q_SCRIPTABLE quint32 GetSessionIdleTime() const; |
484 | |
485 | + /** |
486 | + * Simulate user activity, thus interrupting the screensaver |
487 | + */ |
488 | Q_SCRIPTABLE void SimulateUserActivity(); |
489 | |
490 | + /** |
491 | + * Inhibit idleness (ie screen blanking) for the caller application. |
492 | + * |
493 | + * @param appName A unique identifier for the application, usually a reverse domain (such as 'org.freedesktop.example'). |
494 | + * @param reason A human-readable and possibly translated string explaining the reason why idleness is inhibited (such as 'Playing a movie'). |
495 | + * @return A cookie uniquely representing the inhibition request, to be passed to UnInhibit when done; 0 in case of error |
496 | + */ |
497 | + Q_SCRIPTABLE uint Inhibit(const QString &appName, const QString &reason); |
498 | + |
499 | + /** |
500 | + * Disable inhibit idleness for the caller application. |
501 | + * |
502 | + * @param cookie A cookie representing the inhibition request, as returned by the 'Inhibit' function. |
503 | + */ |
504 | + Q_SCRIPTABLE void UnInhibit(uint cookie); |
505 | + |
506 | Q_SIGNALS: |
507 | void ActiveChanged(bool active); |
508 | }; |
509 | |
510 | === modified file 'qml/Components/Dialogs.qml' |
511 | --- qml/Components/Dialogs.qml 2016-07-15 19:37:39 +0000 |
512 | +++ qml/Components/Dialogs.qml 2016-11-22 09:36:12 +0000 |
513 | @@ -112,12 +112,12 @@ |
514 | |
515 | GlobalShortcut { // lock screen |
516 | shortcut: Qt.Key_ScreenSaver |
517 | - onTriggered: LightDMService.greeter.showGreeter() |
518 | + onTriggered: root.unitySessionService.PromptLock() |
519 | } |
520 | |
521 | GlobalShortcut { // lock screen |
522 | shortcut: Qt.ControlModifier|Qt.AltModifier|Qt.Key_L |
523 | - onTriggered: LightDMService.greeter.showGreeter() |
524 | + onTriggered: root.unitySessionService.PromptLock() |
525 | } |
526 | |
527 | QtObject { |
528 | @@ -151,7 +151,7 @@ |
529 | Button { |
530 | text: i18n.ctr("Button: Lock the system", "Lock") |
531 | onClicked: { |
532 | - LightDMService.greeter.showGreeter() |
533 | + root.unitySessionService.PromptLock() |
534 | logoutDialog.hide(); |
535 | } |
536 | } |
537 | |
538 | === modified file 'qml/Shell.qml' |
539 | --- qml/Shell.qml 2016-11-09 15:07:26 +0000 |
540 | +++ qml/Shell.qml 2016-11-22 09:36:12 +0000 |
541 | @@ -375,15 +375,6 @@ |
542 | } |
543 | } |
544 | |
545 | - Timer { |
546 | - // See powerConnection for why this is useful |
547 | - id: showGreeterDelayed |
548 | - interval: 1 |
549 | - onTriggered: { |
550 | - greeter.forceShow(); |
551 | - } |
552 | - } |
553 | - |
554 | Connections { |
555 | id: callConnection |
556 | target: callManager |
557 | @@ -410,16 +401,7 @@ |
558 | onStatusChanged: { |
559 | if (Powerd.status === Powerd.Off && reason !== Powerd.Proximity && |
560 | !callManager.hasCalls && !wizard.active) { |
561 | - // We don't want to simply call greeter.showNow() here, because |
562 | - // that will take too long. Qt will delay button event |
563 | - // handling until the greeter is done loading and may think the |
564 | - // user held down the power button the whole time, leading to a |
565 | - // power dialog being shown. Instead, delay showing the |
566 | - // greeter until we've finished handling the event. We could |
567 | - // make the greeter load asynchronously instead, but that |
568 | - // introduces a whole host of timing issues, especially with |
569 | - // its animations. So this is simpler. |
570 | - showGreeterDelayed.start(); |
571 | + DBusUnitySessionService.PromptLock(); |
572 | } |
573 | } |
574 | } |
575 | |
576 | === modified file 'qml/Stage/Stage.qml' |
577 | --- qml/Stage/Stage.qml 2016-11-12 16:05:40 +0000 |
578 | +++ qml/Stage/Stage.qml 2016-11-22 09:36:12 +0000 |
579 | @@ -17,6 +17,7 @@ |
580 | import QtQuick 2.4 |
581 | import Ubuntu.Components 1.3 |
582 | import Unity.Application 0.1 |
583 | +import Unity.Session 0.1 |
584 | import "../Components/PanelState" |
585 | import "../Components" |
586 | import Utils 0.1 |
587 | @@ -346,6 +347,31 @@ |
588 | } |
589 | |
590 | readonly property real virtualKeyboardHeight: root.inputMethodRect.height |
591 | + |
592 | + function updateScreenInhibitionsWhiteList() { |
593 | + var result = []; |
594 | + if (root.state == "staged" && priv.mainStageDelegate) { |
595 | + result.push(priv.mainStageDelegate.appId); |
596 | + } else if (root.state == "stagedWithSideStage") { |
597 | + if (priv.mainStageDelegate) { |
598 | + result.push(priv.mainStageDelegate.appId); |
599 | + } |
600 | + if (priv.sideStageDelegate) { |
601 | + result.push(priv.sideStageDelegate.appId); |
602 | + } |
603 | + } else if (root.state == "windowed") { |
604 | + for (var i = 0; i < appRepeater.count; i++) { |
605 | + var appDelegate = appRepeater.itemAt(i); |
606 | + if (appDelegate && !appDelegate.minimized) { |
607 | + result.push(appDelegate.appId); |
608 | + } |
609 | + } |
610 | + } |
611 | + |
612 | + print("!!! Inhibition whitelist updated:", result); |
613 | + |
614 | + DBusUnitySessionService.screenInhibitionsWhitelist = result; |
615 | + } |
616 | } |
617 | |
618 | Component.onCompleted: priv.updateMainAndSideStageIndexes(); |
619 | @@ -521,9 +547,16 @@ |
620 | }, |
621 | Transition { |
622 | to: "stagedWithSideStage" |
623 | - ScriptAction { script: priv.updateMainAndSideStageIndexes(); } |
624 | + ScriptAction { script: { priv.updateMainAndSideStageIndexes(); priv.updateScreenInhibitionsWhiteList(); }} |
625 | + }, |
626 | + Transition { |
627 | + to: "staged" |
628 | + ScriptAction { script: priv.updateScreenInhibitionsWhiteList(); } |
629 | + }, |
630 | + Transition { |
631 | + to: "windowed" |
632 | + ScriptAction { script: priv.updateScreenInhibitionsWhiteList(); } |
633 | } |
634 | - |
635 | ] |
636 | |
637 | MouseArea { |
638 | @@ -571,10 +604,12 @@ |
639 | |
640 | Connections { |
641 | target: root.topLevelSurfaceList |
642 | - onListChanged: priv.updateMainAndSideStageIndexes() |
643 | + onListChanged: { |
644 | + priv.updateMainAndSideStageIndexes(); |
645 | + priv.updateScreenInhibitionsWhiteList(); |
646 | + } |
647 | } |
648 | |
649 | - |
650 | DropArea { |
651 | objectName: "MainStageDropArea" |
652 | anchors { |
653 | |
654 | === modified file 'src/libunity8-private/unitydbusobject.cpp' |
655 | --- src/libunity8-private/unitydbusobject.cpp 2015-09-14 09:11:08 +0000 |
656 | +++ src/libunity8-private/unitydbusobject.cpp 2016-11-22 09:36:12 +0000 |
657 | @@ -42,11 +42,6 @@ |
658 | m_connection.unregisterObject(path()); |
659 | } |
660 | |
661 | -QDBusConnection UnityDBusObject::connection() const |
662 | -{ |
663 | - return m_connection; |
664 | -} |
665 | - |
666 | QString UnityDBusObject::path() const |
667 | { |
668 | return m_path; |
669 | @@ -70,7 +65,7 @@ |
670 | message << changedProps; |
671 | message << QStringList(); |
672 | |
673 | - connection().send(message); |
674 | + m_connection.send(message); |
675 | } |
676 | |
677 | void UnityDBusObject::registerObject() |
678 | |
679 | === modified file 'src/libunity8-private/unitydbusobject.h' |
680 | --- src/libunity8-private/unitydbusobject.h 2014-10-09 21:29:00 +0000 |
681 | +++ src/libunity8-private/unitydbusobject.h 2016-11-22 09:36:12 +0000 |
682 | @@ -28,7 +28,6 @@ |
683 | explicit UnityDBusObject(const QString &path, const QString &service = QString(), bool async = true, QObject *parent = 0); |
684 | ~UnityDBusObject(); |
685 | |
686 | - QDBusConnection connection() const; |
687 | QString path() const; |
688 | |
689 | protected: |
690 | |
691 | === modified file 'tests/plugins/Unity/Session/CMakeLists.txt' |
692 | --- tests/plugins/Unity/Session/CMakeLists.txt 2016-06-21 14:23:49 +0000 |
693 | +++ tests/plugins/Unity/Session/CMakeLists.txt 2016-11-22 09:36:12 +0000 |
694 | @@ -13,6 +13,7 @@ |
695 | ${CMAKE_SOURCE_DIR}/plugins/Unity/Session |
696 | ${libunity8-private_SOURCE_DIR} |
697 | ${GLIB_INCLUDE_DIRS} |
698 | + ${UAL_INCLUDE_DIRS} |
699 | ) |
700 | |
701 | add_definitions(-DSM_BUSNAME=sessionBus) |
702 | @@ -38,6 +39,7 @@ |
703 | target_link_libraries(sessionbackendtestExec |
704 | unity8-private |
705 | ${GLIB_LIBRARIES} |
706 | + ${UAL_LIBRARIES} |
707 | ) |
708 | qt5_use_modules(sessionbackendtestExec Test Core Qml DBus) |
709 | |
710 | |
711 | === modified file 'tests/plugins/Unity/Session/LogindServer.h' |
712 | --- tests/plugins/Unity/Session/LogindServer.h 2016-06-22 13:38:16 +0000 |
713 | +++ tests/plugins/Unity/Session/LogindServer.h 2016-11-22 09:36:12 +0000 |
714 | @@ -37,7 +37,7 @@ |
715 | Q_SIGNALS: |
716 | void Lock(); |
717 | void Unlock(); |
718 | - void PrepareForSleep(); |
719 | + void PrepareForSleep(bool); |
720 | }; |
721 | |
722 | #endif |
In general it works, even from Firefox in libertine when watching a youtube video. However, if you close firefox while it's playing a video, it won't dispatch the Uninhibit call and the screen stays lit...