Merge lp:~albaguirre/unity-system-compositor/screen-power-state-handling into lp:unity-system-compositor
- screen-power-state-handling
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | kevin gunn |
Approved revision: | 157 |
Merged at revision: | 143 |
Proposed branch: | lp:~albaguirre/unity-system-compositor/screen-power-state-handling |
Merge into: | lp:unity-system-compositor |
Diff against target: |
1359 lines (+1057/-84) 16 files modified
debian/changelog (+6/-0) debian/control (+1/-0) src/CMakeLists.txt (+5/-0) src/com.canonical.Unity.Screen.conf (+4/-0) src/dbus_screen.cpp (+119/-58) src/dbus_screen.h (+28/-16) src/dbus_screen_observer.h (+38/-0) src/power_state_change_reason.h (+28/-0) src/powerd_mediator.cpp (+236/-0) src/powerd_mediator.h (+87/-0) src/powerkey_handler.cpp (+84/-0) src/powerkey_handler.h (+69/-0) src/screen_state_handler.cpp (+201/-0) src/screen_state_handler.h (+92/-0) src/system_compositor.cpp (+55/-10) src/system_compositor.h (+4/-0) |
To merge this branch: | bzr merge lp:~albaguirre/unity-system-compositor/screen-power-state-handling |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Michael Terry (community) | Approve | ||
PS Jenkins bot (community) | continuous-integration | Approve | |
Ricardo Mendoza (community) | Approve | ||
Ricardo Salveti (community) | Needs Information | ||
Review via email:
|
Commit message
Migrate display power state handling from powerd to usc
Description of the change
Migrate display power state handling from powerd to usc
This is mainly an effort to remove all input event processing from powerd. Since the mir server already handles input and manages display power states - any screen power state or inactivity timer logic is better suited to reside in USC.
Depends on:
https:/

PS Jenkins bot (ps-jenkins) wrote : | # |

Ricardo Salveti (rsalveti) wrote : | # |
MR that exports the dim value:
https:/
To land this MR, besides the need of another clean-up in powerd (to remove the screen states), we also need a clear way for the apps to request something similar to the powerd display state (probably just asking display to be on/off). Do you know if we already have a dbus interface for that?
We also need to coordinate and land changes for all apps that are currently using the powerd requestDisplayState dbus api, as that will be removed as well.

Alberto Aguirre (albaguirre) wrote : | # |
"we also need a clear way for the apps to request something similar to the powerd display state (probably just asking display to be on/off). Do you know if we already have a dbus interface for that?"
This MR keeps the com.canonical.
- 128. By Alberto Aguirre
-
Use powerd's dim value now that is exposed

PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:128
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://

Ricardo Mendoza (ricmm) wrote : | # |
As mentioned in the email, we need to sync with Unity8 regarding long-press for the power button, as this MR as-is would always turn off on power key up.
Also introduced conflict text in:
715 +<<<<<<< TREE
716 ("public-socket", po::value<bool>(), "Make the socket file publicly writable")
717 ("power-off-delay", po::value<int>(), "Delay in milliseconds before powering off screen [int]")
718 ("enable-
719 +=======
720 + ("power-
721 + ("dimmer-timeout", po::value<int>(), "The time in seconds before the screen is dimmed when there are no active sessions")
722 + ("public-socket", po::value<bool>(), "Make the socket file publicly writable");
723 +>>>>>>> MERGE-SOURCE
- 129. By Alberto Aguirre
-
merge main branch
- 130. By Alberto Aguirre
-
merge main branch
- 131. By Alberto Aguirre
-
Use mir timer support
Cleanup ScreenStateHandler
Make ScreenStateHandler state changes thread safe
Add long power key press detection
Emit DBus signal during after detecting long power press

PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:131
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://

Alberto Aguirre (albaguirre) wrote : | # |
> As mentioned in the email, we need to sync with Unity8 regarding long-press
> for the power button, as this MR as-is would always turn off on power key up.
>
> Also introduced conflict text in:
>
Fixed the conflicts and implemented the long-press detection.
- 132. By Alberto Aguirre
-
Remove emitting signal on long press of power key
Change default timeout for long press detection of power key to 5secs
Initiate a system shutdown when detecting long press of power key
Emit and accept reasons for display power state changes

PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:132
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 133. By Alberto Aguirre
-
Reset backlight to normal brightness when screen is already on and a power on state change is requested
- 134. By Alberto Aguirre
-
Remove powerkey dbus conf install step

PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:134
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 135. By Alberto Aguirre
-
Remove power key dbus conf install from debin install rules
- 136. By Alberto Aguirre
-
Add headers to source list

PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:135
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://

PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:136
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 137. By Alberto Aguirre
-
Avoid turning off display when power key is held on a short time.
The shell may want to show a dialog under such conditions.

PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:137
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 138. By Alberto Aguirre
-
Add support for keeping display on

PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:138
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 139. By Alberto Aguirre
-
merge trunk
- 140. By Alberto Aguirre
-
Add console dbus access policy as in powerd
- 141. By Alberto Aguirre
-
Add some logging
- 142. By Alberto Aguirre
-
Proxy brightness and auto brightness parameters.
- 143. By Alberto Aguirre
-
fix auto_brightness state machine

PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:143
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 144. By Alberto Aguirre
-
Change default inactivity timeouts

PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:144
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 145. By Alberto Aguirre
-
Refactor backlight state machine
- 146. By Alberto Aguirre
-
Turn on screen when a keepDisplayOn request is received

PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:146
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 147. By Alberto Aguirre
-
Reset timers when changing timeout values.

PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:147
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
Click here to trigger a rebuild:
http://

Ricardo Salveti (rsalveti) wrote : | # |
Comments inline.

Alberto Aguirre (albaguirre) wrote : | # |
Responded to inline comment.
- 148. By Alberto Aguirre
-
merge trunk
- 149. By Alberto Aguirre
-
Use new create_alarm api
- 150. By Alberto Aguirre
-
Only start compositor when turning on screen.
With the new swap unblock solution in mir, its no longer necessary to start the compositor while the screen is off.
- 151. By Alberto Aguirre
-
Add powerd to Recommends

PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:150
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://

PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:151
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 152. By Alberto Aguirre
-
merge trunk - fix simple conflict

PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:152
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 153. By Alberto Aguirre
-
Update changelog

PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:153
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 154. By Alberto Aguirre
-
Turn off screen during clean shutdown

PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:154
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 155. By Alberto Aguirre
-
Add dbus watcher to wait for powerd to become available if its DBus interface is not available when usc starts.

PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:155
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://

Ricardo Mendoza (ricmm) wrote : | # |
Looks fine for me so far, I dont see any obvious issues in the code. Works as expected on device.

Michael Terry (mterry) wrote : | # |
I didn't test all the features, since this has already been reviewed. But I wanted to give a few cents, comments inline using this fancy new LP feature.
- 156. By Alberto Aguirre
-
Rename is_invalid_reason to avoid double negatives.
- 157. By Alberto Aguirre
-
Always watch for powerd interface restart

PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:157
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://

Michael Terry (mterry) wrote : | # |
Looks good to me, thanks!
Preview Diff
1 | === modified file 'debian/changelog' |
2 | --- debian/changelog 2014-06-19 22:23:50 +0000 |
3 | +++ debian/changelog 2014-06-25 14:46:51 +0000 |
4 | @@ -1,3 +1,9 @@ |
5 | +unity-system-compositor (0.0.4) UNRELEASED; urgency=medium |
6 | + |
7 | + * Bump version due to new dbus interfaces |
8 | + |
9 | + -- Alberto Aguirre <alberto.aguirre@canonical.com> Fri, 20 Jun 2014 14:49:31 -0500 |
10 | + |
11 | unity-system-compositor (0.0.3+14.10.20140619-0ubuntu1) utopic; urgency=low |
12 | |
13 | [ Michael Terry ] |
14 | |
15 | === modified file 'debian/control' |
16 | --- debian/control 2014-06-13 16:08:51 +0000 |
17 | +++ debian/control 2014-06-25 14:46:51 +0000 |
18 | @@ -36,6 +36,7 @@ |
19 | Architecture: any |
20 | Depends: ${misc:Depends}, |
21 | ${shlibs:Depends}, |
22 | +Recommends: powerd, |
23 | Description: System compositor for Ubuntu |
24 | System compositor used by the Mir display server in Ubuntu. If the Unity |
25 | System Compositor can't start, LightDM will fallback to plain Xorg display |
26 | |
27 | === modified file 'src/CMakeLists.txt' |
28 | --- src/CMakeLists.txt 2014-06-02 19:33:25 +0000 |
29 | +++ src/CMakeLists.txt 2014-06-25 14:46:51 +0000 |
30 | @@ -18,10 +18,15 @@ |
31 | main.cpp |
32 | dbus_screen.cpp |
33 | dbus_screen.h |
34 | + powerd_mediator.cpp |
35 | dm_connection.cpp |
36 | dm_connection.h |
37 | system_compositor.cpp |
38 | system_compositor.h |
39 | + screen_state_handler.cpp |
40 | + screen_state_handler.h |
41 | + powerkey_handler.cpp |
42 | + powerkey_handler.h |
43 | ) |
44 | |
45 | qt5_generate_dbus_interface(dbus_screen.h com.canonical.Unity.Screen.xml) |
46 | |
47 | === modified file 'src/com.canonical.Unity.Screen.conf' |
48 | --- src/com.canonical.Unity.Screen.conf 2013-10-31 22:24:37 +0000 |
49 | +++ src/com.canonical.Unity.Screen.conf 2014-06-25 14:46:51 +0000 |
50 | @@ -14,4 +14,8 @@ |
51 | send_interface="org.freedesktop.DBus.Introspectable"/> |
52 | </policy> |
53 | |
54 | + <policy at_console="true"> |
55 | + <allow send_destination="com.canonical.Unity.Screen"/> |
56 | + </policy> |
57 | + |
58 | </busconfig> |
59 | |
60 | === modified file 'src/dbus_screen.cpp' |
61 | --- src/dbus_screen.cpp 2014-04-08 13:22:31 +0000 |
62 | +++ src/dbus_screen.cpp 2014-06-25 14:46:51 +0000 |
63 | @@ -1,5 +1,5 @@ |
64 | /* |
65 | - * Copyright © 2013 Canonical Ltd. |
66 | + * Copyright © 2013-2014 Canonical Ltd. |
67 | * |
68 | * This program is free software: you can redistribute it and/or modify |
69 | * it under the terms of the GNU General Public License version 3 as |
70 | @@ -16,70 +16,67 @@ |
71 | |
72 | #include "dbus_screen.h" |
73 | #include "dbus_screen_adaptor.h" |
74 | - |
75 | -#include <mir/compositor/compositor.h> |
76 | -#include <mir/default_server_configuration.h> |
77 | -#include <mir/graphics/display.h> |
78 | -#include <mir/graphics/display_configuration.h> |
79 | - |
80 | +#include "dbus_screen_observer.h" |
81 | +#include "power_state_change_reason.h" |
82 | + |
83 | +#include <atomic> |
84 | +#include <memory> |
85 | +#include <iostream> |
86 | + |
87 | +#include <QDBusMessage> |
88 | #include <QDBusConnection> |
89 | +#include <QDBusServiceWatcher> |
90 | #include <QDebug> |
91 | |
92 | -namespace mc = mir::compositor; |
93 | -namespace mg = mir::graphics; |
94 | - |
95 | -static void set_screen_power_mode(MirPowerMode mode, const std::shared_ptr<mir::DefaultServerConfiguration>& config) |
96 | +bool is_valid_reason(int raw_reason) |
97 | { |
98 | - std::shared_ptr<mg::Display> display = config->the_display(); |
99 | - std::shared_ptr<mg::DisplayConfiguration> displayConfig = display->configuration(); |
100 | - std::shared_ptr<mc::Compositor> compositor = config->the_compositor(); |
101 | - |
102 | - displayConfig->for_each_output( |
103 | - [&](const mg::UserDisplayConfigurationOutput displayConfigOutput) { |
104 | - displayConfigOutput.power_mode=mode; |
105 | - } |
106 | - ); |
107 | - |
108 | - compositor->stop(); |
109 | - display->configure(*displayConfig.get()); |
110 | - compositor->start(); |
111 | + auto reason = static_cast<PowerStateChangeReason>(raw_reason); |
112 | + switch (reason) |
113 | + { |
114 | + case PowerStateChangeReason::unknown: |
115 | + case PowerStateChangeReason::inactivity: |
116 | + case PowerStateChangeReason::power_key: |
117 | + case PowerStateChangeReason::proximity: |
118 | + return true; |
119 | + } |
120 | + return false; |
121 | } |
122 | |
123 | -// Note: this class should be created only after when the Mir DisplayServer has started |
124 | -DBusScreen::DBusScreen(std::shared_ptr<mir::DefaultServerConfiguration> config, |
125 | - int off_delay, QObject *parent) |
126 | + |
127 | +DBusScreen::DBusScreen(DBusScreenObserver& observer, QObject *parent) |
128 | : QObject(parent), |
129 | - config(config), |
130 | - power_off_timer(off_delay > 0 ? new QTimer(this) : nullptr), |
131 | - power_off_mode(MirPowerMode::mir_power_mode_off), |
132 | - power_off_delay(off_delay) |
133 | - |
134 | + dbus_adaptor{new DBusScreenAdaptor(this)}, |
135 | + service_watcher{new QDBusServiceWatcher()}, |
136 | + observer{&observer} |
137 | { |
138 | - new DBusScreenAdaptor(this); |
139 | QDBusConnection bus = QDBusConnection::systemBus(); |
140 | bus.registerObject("/com/canonical/Unity/Screen", this); |
141 | bus.registerService("com.canonical.Unity.Screen"); |
142 | |
143 | - if (power_off_timer != nullptr) { |
144 | - power_off_timer->setSingleShot(true); |
145 | - connect(power_off_timer, SIGNAL(timeout()), this, SLOT(power_off())); |
146 | - } |
147 | -} |
148 | - |
149 | -DBusScreen::~DBusScreen() |
150 | -{ |
151 | - delete power_off_timer; |
152 | -} |
153 | - |
154 | -bool DBusScreen::setScreenPowerMode(const QString &mode) |
155 | -{ |
156 | + service_watcher->setConnection(bus); |
157 | + service_watcher->setWatchMode(QDBusServiceWatcher::WatchForUnregistration); |
158 | + |
159 | + connect(service_watcher.get(), |
160 | + SIGNAL(serviceUnregistered(QString const&)), |
161 | + this, SLOT(remove_display_on_requestor(QString const&))); |
162 | + |
163 | + //QT's ~QObject will release this child object |
164 | + //so release ownership from the unique_ptr |
165 | + dbus_adaptor.release(); |
166 | +} |
167 | + |
168 | +DBusScreen::~DBusScreen() = default; |
169 | + |
170 | +bool DBusScreen::setScreenPowerMode(const QString &mode, int reason) |
171 | +{ |
172 | + if (!is_valid_reason(reason)) |
173 | + return false; |
174 | + |
175 | MirPowerMode newPowerMode; |
176 | + |
177 | // Note: the "standby" and "suspend" modes are mostly unused |
178 | - |
179 | if (mode == "on") { |
180 | newPowerMode = MirPowerMode::mir_power_mode_on; |
181 | - if (power_off_timer != nullptr && power_off_timer->isActive()) |
182 | - power_off_timer->stop(); |
183 | } else if (mode == "standby") { |
184 | newPowerMode = MirPowerMode::mir_power_mode_standby; // higher power "off" mode (fastest resume) |
185 | } else if (mode == "suspend") { |
186 | @@ -91,17 +88,81 @@ |
187 | return false; |
188 | } |
189 | |
190 | - if ((newPowerMode != MirPowerMode::mir_power_mode_on) && (power_off_timer != nullptr)) { |
191 | - power_off_mode = newPowerMode; |
192 | - power_off_timer->start(power_off_delay); |
193 | - } else { |
194 | - set_screen_power_mode(newPowerMode, config); |
195 | - } |
196 | + observer->set_screen_power_mode(newPowerMode, static_cast<PowerStateChangeReason>(reason)); |
197 | |
198 | return true; |
199 | } |
200 | |
201 | -void DBusScreen::power_off() |
202 | -{ |
203 | - set_screen_power_mode(power_off_mode, config); |
204 | +void DBusScreen::emit_power_state_change(MirPowerMode power_mode, PowerStateChangeReason reason) |
205 | +{ |
206 | + QDBusMessage message = QDBusMessage::createSignal("/com/canonical/Unity/Screen", |
207 | + "com.canonical.Unity.Screen", "DisplayPowerStateChange"); |
208 | + |
209 | + int power_state = (power_mode == MirPowerMode::mir_power_mode_off) ? 0 : 1; |
210 | + |
211 | + QVariant state(power_state); |
212 | + QList<QVariant> arguments; |
213 | + arguments.append(state); |
214 | + arguments.append(static_cast<int>(reason)); |
215 | + message.setArguments(arguments); |
216 | + |
217 | + QDBusConnection bus = QDBusConnection::systemBus(); |
218 | + bus.send(message); |
219 | +} |
220 | + |
221 | +int DBusScreen::keepDisplayOn() |
222 | +{ |
223 | + static std::atomic<uint32_t> request_id{0}; |
224 | + |
225 | + int id = request_id.fetch_add(1); |
226 | + observer->keep_display_on(true); |
227 | + |
228 | + auto const& caller = message().service(); |
229 | + auto& caller_requests = display_requests[caller.toStdString()]; |
230 | + |
231 | + if (caller_requests.size() == 0) |
232 | + service_watcher->addWatchedService(caller); |
233 | + |
234 | + caller_requests.insert(id); |
235 | + std::cerr << "keepDisplayOn request id:" << id; |
236 | + std::cerr << " requested by \"" << caller.toStdString() << "\"" << std::endl; |
237 | + return id; |
238 | +} |
239 | + |
240 | +void DBusScreen::removeDisplayOnRequest(int cookie) |
241 | +{ |
242 | + auto const& requestor = message().service(); |
243 | + |
244 | + auto it = display_requests.find(requestor.toStdString()); |
245 | + if (it == display_requests.end()) |
246 | + return; |
247 | + |
248 | + std::cerr << "removeDisplayOnRequest id:" << cookie; |
249 | + std::cerr << " requested by \"" << requestor.toStdString() << "\"" << std::endl; |
250 | + |
251 | + auto caller_requests = it->second; |
252 | + caller_requests.erase(cookie); |
253 | + if (caller_requests.size() == 0) |
254 | + remove_display_on_requestor(requestor); |
255 | +} |
256 | + |
257 | +void DBusScreen::remove_display_on_requestor(QString const& requestor) |
258 | +{ |
259 | + std::cerr << "remove_display_on_requestor \"" << requestor.toStdString() << "\""; |
260 | + std::cerr << std::endl; |
261 | + |
262 | + display_requests.erase(requestor.toStdString()); |
263 | + service_watcher->removeWatchedService(requestor); |
264 | + if (display_requests.size() == 0) |
265 | + observer->keep_display_on(false); |
266 | +} |
267 | + |
268 | +void DBusScreen::setUserBrightness(int brightness) |
269 | +{ |
270 | + observer->set_brightness(brightness); |
271 | +} |
272 | + |
273 | +void DBusScreen::userAutobrightnessEnable(bool enable) |
274 | +{ |
275 | + observer->enable_auto_brightness(enable); |
276 | } |
277 | |
278 | === modified file 'src/dbus_screen.h' |
279 | --- src/dbus_screen.h 2014-02-26 06:23:05 +0000 |
280 | +++ src/dbus_screen.h 2014-06-25 14:46:51 +0000 |
281 | @@ -1,5 +1,5 @@ |
282 | /* |
283 | - * Copyright © 2013 Canonical Ltd. |
284 | + * Copyright © 2013-2014 Canonical Ltd. |
285 | * |
286 | * This program is free software: you can redistribute it and/or modify |
287 | * it under the terms of the GNU General Public License version 3 as |
288 | @@ -20,35 +20,47 @@ |
289 | #include <mir_toolkit/common.h> |
290 | |
291 | #include <memory> |
292 | +#include <unordered_map> |
293 | +#include <unordered_set> |
294 | + |
295 | #include <QObject> |
296 | #include <QtCore> |
297 | - |
298 | -namespace mir |
299 | -{ |
300 | - class DefaultServerConfiguration; |
301 | -} |
302 | - |
303 | -class DBusScreen : public QObject |
304 | +#include <QDBusContext> |
305 | + |
306 | +class DBusScreenAdaptor; |
307 | +class DBusScreenObserver; |
308 | +class QDBusInterface; |
309 | +class QDBusServiceWatcher; |
310 | +enum class PowerStateChangeReason; |
311 | + |
312 | +class DBusScreen : public QObject, protected QDBusContext |
313 | { |
314 | Q_OBJECT |
315 | Q_CLASSINFO("D-Bus Interface", "com.canonical.Unity.Screen") |
316 | |
317 | public: |
318 | - explicit DBusScreen(std::shared_ptr<mir::DefaultServerConfiguration> config, |
319 | - int off_delay, QObject *parent = 0); |
320 | + explicit DBusScreen(DBusScreenObserver& observer, QObject *parent = 0); |
321 | virtual ~DBusScreen(); |
322 | |
323 | + void emit_power_state_change(MirPowerMode mode, PowerStateChangeReason reason); |
324 | + |
325 | public Q_SLOTS: |
326 | - bool setScreenPowerMode(const QString &mode); |
327 | + bool setScreenPowerMode(const QString &mode, int reason); |
328 | + int keepDisplayOn(); |
329 | + void removeDisplayOnRequest(int id); |
330 | + |
331 | + //TODO: Expose same DBus powerd interface for now |
332 | + void setUserBrightness(int brightness); |
333 | + void userAutobrightnessEnable(bool enable); |
334 | |
335 | private Q_SLOTS: |
336 | - void power_off(); |
337 | + void remove_display_on_requestor(QString const& requestor); |
338 | |
339 | private: |
340 | - std::shared_ptr<mir::DefaultServerConfiguration> config; |
341 | - QTimer *power_off_timer; |
342 | - MirPowerMode power_off_mode; |
343 | - int power_off_delay; |
344 | + std::unique_ptr<DBusScreenAdaptor> dbus_adaptor; |
345 | + std::unique_ptr<QDBusServiceWatcher> service_watcher; |
346 | + std::unordered_map<std::string, std::unordered_set<int>> display_requests; |
347 | + DBusScreenObserver* const observer; |
348 | }; |
349 | |
350 | #endif /* DBUS_SCREEN_H_ */ |
351 | |
352 | === added file 'src/dbus_screen_observer.h' |
353 | --- src/dbus_screen_observer.h 1970-01-01 00:00:00 +0000 |
354 | +++ src/dbus_screen_observer.h 2014-06-25 14:46:51 +0000 |
355 | @@ -0,0 +1,38 @@ |
356 | +/* |
357 | + * Copyright © 2014 Canonical Ltd. |
358 | + * |
359 | + * This program is free software: you can redistribute it and/or modify |
360 | + * it under the terms of the GNU General Public License version 3 as |
361 | + * published by the Free Software Foundation. |
362 | + * |
363 | + * This program is distributed in the hope that it will be useful, |
364 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
365 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
366 | + * GNU General Public License for more details. |
367 | + * |
368 | + * You should have received a copy of the GNU General Public License |
369 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
370 | + */ |
371 | + |
372 | +#ifndef DBUS_SCREEN_OBSERVER_H_ |
373 | +#define DBUS_SCREEN_OBSERVER_H_ |
374 | + |
375 | +enum class PowerStateChangeReason; |
376 | + |
377 | +class DBusScreenObserver |
378 | +{ |
379 | +public: |
380 | + virtual ~DBusScreenObserver() = default; |
381 | + |
382 | + virtual void set_screen_power_mode(MirPowerMode mode, PowerStateChangeReason reason) = 0; |
383 | + virtual void keep_display_on(bool on) = 0; |
384 | + virtual void set_brightness(int brightness) = 0; |
385 | + virtual void enable_auto_brightness(bool enable) = 0; |
386 | + |
387 | +protected: |
388 | + DBusScreenObserver() = default; |
389 | + DBusScreenObserver(const DBusScreenObserver&) = delete; |
390 | + DBusScreenObserver& operator=(const DBusScreenObserver&) = delete; |
391 | +}; |
392 | + |
393 | +#endif |
394 | |
395 | === added file 'src/power_state_change_reason.h' |
396 | --- src/power_state_change_reason.h 1970-01-01 00:00:00 +0000 |
397 | +++ src/power_state_change_reason.h 2014-06-25 14:46:51 +0000 |
398 | @@ -0,0 +1,28 @@ |
399 | +/* |
400 | + * Copyright © 2014 Canonical Ltd. |
401 | + * |
402 | + * This program is free software: you can redistribute it and/or modify |
403 | + * it under the terms of the GNU General Public License version 3 as |
404 | + * published by the Free Software Foundation. |
405 | + * |
406 | + * This program is distributed in the hope that it will be useful, |
407 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
408 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
409 | + * GNU General Public License for more details. |
410 | + * |
411 | + * You should have received a copy of the GNU General Public License |
412 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
413 | + */ |
414 | + |
415 | +#ifndef POWER_STATE_CHANGE_REASON_H_ |
416 | +#define POWER_STATE_CHANGE_REASON_H_ |
417 | + |
418 | +enum class PowerStateChangeReason |
419 | +{ |
420 | + unknown = 0, |
421 | + inactivity = 1, |
422 | + power_key = 2, |
423 | + proximity = 3 |
424 | +}; |
425 | + |
426 | +#endif |
427 | |
428 | === added file 'src/powerd_mediator.cpp' |
429 | --- src/powerd_mediator.cpp 1970-01-01 00:00:00 +0000 |
430 | +++ src/powerd_mediator.cpp 2014-06-25 14:46:51 +0000 |
431 | @@ -0,0 +1,236 @@ |
432 | +/* |
433 | + * Copyright © 2014 Canonical Ltd. |
434 | + * |
435 | + * This program is free software: you can redistribute it and/or modify |
436 | + * it under the terms of the GNU General Public License version 3 as |
437 | + * published by the Free Software Foundation. |
438 | + * |
439 | + * This program is distributed in the hope that it will be useful, |
440 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
441 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
442 | + * GNU General Public License for more details. |
443 | + * |
444 | + * You should have received a copy of the GNU General Public License |
445 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
446 | + */ |
447 | + |
448 | +#include "powerd_mediator.h" |
449 | + |
450 | +#include <QDBusConnection> |
451 | +#include <QDBusInterface> |
452 | +#include <QDBusReply> |
453 | +#include <QDBusMetaType> |
454 | +#include <QDBusArgument> |
455 | +#include <QDBusServiceWatcher> |
456 | + |
457 | +#include <iostream> |
458 | + |
459 | +/* Struct for reply to getBrightnessParams DBus call */ |
460 | +struct BrightnessParams |
461 | + { |
462 | + int dim_brightness; |
463 | + int min_brightness; |
464 | + int max_brightness; |
465 | + int default_brightness; |
466 | + bool auto_brightness_supported; |
467 | +}; |
468 | +Q_DECLARE_METATYPE(BrightnessParams); |
469 | + |
470 | +/* Not used but required by qDBusRegisterMetaType*/ |
471 | +QDBusArgument &operator<<(QDBusArgument &argument, const BrightnessParams &mystruct) |
472 | +{ |
473 | + argument.beginStructure(); |
474 | + argument << mystruct.dim_brightness << |
475 | + mystruct.min_brightness << |
476 | + mystruct.max_brightness << |
477 | + mystruct.default_brightness << |
478 | + mystruct.auto_brightness_supported; |
479 | + argument.endStructure(); |
480 | + return argument; |
481 | +} |
482 | + |
483 | +/* Needed to un-marshall powerd response */ |
484 | +const QDBusArgument &operator>>(const QDBusArgument &argument, BrightnessParams &mystruct) |
485 | +{ |
486 | + argument.beginStructure(); |
487 | + argument >> mystruct.dim_brightness >> |
488 | + mystruct.min_brightness >> |
489 | + mystruct.max_brightness >> |
490 | + mystruct.default_brightness >> |
491 | + mystruct.auto_brightness_supported; |
492 | + argument.endStructure(); |
493 | + return argument; |
494 | +} |
495 | + |
496 | +PowerdMediator::PowerdMediator() |
497 | + : dim_brightness{10}, |
498 | + normal_brightness{102}, |
499 | + current_brightness{0}, |
500 | + min_brightness_{10}, |
501 | + max_brightness_{102}, |
502 | + auto_brightness_supported_{false}, |
503 | + auto_brightness_requested{false}, |
504 | + backlight_state{BacklightState::normal}, |
505 | + acquired_sys_state{false}, |
506 | + powerd_interface{new QDBusInterface("com.canonical.powerd", |
507 | + "/com/canonical/powerd", "com.canonical.powerd", QDBusConnection::systemBus())}, |
508 | + service_watcher{new QDBusServiceWatcher("com.canonical.powerd", |
509 | + QDBusConnection::systemBus(), QDBusServiceWatcher::WatchForRegistration)} |
510 | +{ |
511 | + qDBusRegisterMetaType<BrightnessParams>(); |
512 | + |
513 | + if (powerd_interface->isValid()) |
514 | + { |
515 | + init_brightness_params(); |
516 | + } |
517 | + //Powerd interface may not be available right now or it may restart in the future |
518 | + //watch for changes so brightness params get initialized to the most recent values. |
519 | + connect(service_watcher.get(), |
520 | + SIGNAL(serviceRegistered(QString const&)), |
521 | + this, SLOT(powerd_registered())); |
522 | +} |
523 | + |
524 | +PowerdMediator::~PowerdMediator() = default; |
525 | + |
526 | +void PowerdMediator::set_dim_backlight() |
527 | +{ |
528 | + change_backlight_state(BacklightState::dim); |
529 | +} |
530 | + |
531 | +void PowerdMediator::set_normal_backlight() |
532 | +{ |
533 | + if (auto_brightness_requested) |
534 | + change_backlight_state(BacklightState::automatic); |
535 | + else |
536 | + change_backlight_state(BacklightState::normal); |
537 | +} |
538 | + |
539 | +void PowerdMediator::turn_off_backlight() |
540 | +{ |
541 | + change_backlight_state(BacklightState::off); |
542 | +} |
543 | + |
544 | +void PowerdMediator::change_backlight_values(int dim, int normal) |
545 | +{ |
546 | + if (normal >= min_brightness_ && normal <= max_brightness_) |
547 | + normal_brightness = normal; |
548 | + if (dim >= min_brightness_ && dim <= max_brightness_) |
549 | + dim_brightness = dim; |
550 | +} |
551 | + |
552 | +void PowerdMediator::enable_auto_brightness(bool enable) |
553 | +{ |
554 | + auto_brightness_requested = enable; |
555 | + if (auto_brightness_supported_ && enable) |
556 | + change_backlight_state(BacklightState::automatic); |
557 | + else |
558 | + change_backlight_state(BacklightState::normal); |
559 | +} |
560 | + |
561 | +bool PowerdMediator::auto_brightness_supported() |
562 | +{ |
563 | + return auto_brightness_supported_; |
564 | +} |
565 | + |
566 | +int PowerdMediator::min_brightness() |
567 | +{ |
568 | + return min_brightness_; |
569 | +} |
570 | + |
571 | +int PowerdMediator::max_brightness() |
572 | +{ |
573 | + return max_brightness_; |
574 | +} |
575 | + |
576 | +void PowerdMediator::powerd_registered() |
577 | +{ |
578 | + init_brightness_params(); |
579 | +} |
580 | + |
581 | +void PowerdMediator::set_brightness(int brightness) |
582 | +{ |
583 | + normal_brightness = brightness; |
584 | + |
585 | + if (backlight_state != BacklightState::automatic) |
586 | + powerd_interface->call("setUserBrightness", brightness); |
587 | +} |
588 | + |
589 | +void PowerdMediator::change_backlight_state(BacklightState new_state) |
590 | +{ |
591 | + if (backlight_state == new_state) |
592 | + return; |
593 | + |
594 | + if (new_state == BacklightState::automatic) |
595 | + { |
596 | + powerd_interface->call("userAutobrightnessEnable", true); |
597 | + backlight_state = BacklightState::automatic; |
598 | + return; |
599 | + } |
600 | + |
601 | + switch (new_state) |
602 | + { |
603 | + case BacklightState::normal: |
604 | + current_brightness = normal_brightness; |
605 | + break; |
606 | + case BacklightState::off: |
607 | + current_brightness = 0; |
608 | + break; |
609 | + case BacklightState::dim: |
610 | + current_brightness = dim_brightness; |
611 | + break; |
612 | + default: |
613 | + std::cerr << "unknown backlight state" << std::endl; |
614 | + break; |
615 | + } |
616 | + |
617 | + powerd_interface->call("setUserBrightness", current_brightness); |
618 | + backlight_state = new_state; |
619 | +} |
620 | + |
621 | +void PowerdMediator::set_sys_state_for(MirPowerMode mode) |
622 | +{ |
623 | + if (mode == MirPowerMode::mir_power_mode_off) |
624 | + release_sys_state(); |
625 | + else |
626 | + acquire_sys_state(); |
627 | +} |
628 | + |
629 | +void PowerdMediator::release_sys_state() |
630 | +{ |
631 | + if (acquired_sys_state) |
632 | + powerd_interface->call("clearSysState", sys_state_cookie); |
633 | + acquired_sys_state = false; |
634 | +} |
635 | + |
636 | +void PowerdMediator::acquire_sys_state() |
637 | +{ |
638 | + if (!acquired_sys_state) |
639 | + { |
640 | + QDBusReply<QString> reply = powerd_interface->call("requestSysState", "com.canonical.Unity.Screen", 1); |
641 | + if (reply.isValid()) |
642 | + { |
643 | + sys_state_cookie = reply.value(); |
644 | + acquired_sys_state = true; |
645 | + } |
646 | + } |
647 | +} |
648 | + |
649 | +void PowerdMediator::init_brightness_params() |
650 | +{ |
651 | + QDBusReply<BrightnessParams> reply = powerd_interface->call("getBrightnessParams"); |
652 | + if (reply.isValid()) |
653 | + { |
654 | + auto const& params = reply.value(); |
655 | + dim_brightness = params.dim_brightness; |
656 | + normal_brightness = params.default_brightness; |
657 | + min_brightness_ = params.min_brightness; |
658 | + max_brightness_ = params.max_brightness; |
659 | + auto_brightness_supported_ = params.auto_brightness_supported; |
660 | + std::cerr << "initialized brightness parameters" << std::endl; |
661 | + } |
662 | + else |
663 | + { |
664 | + std::cerr << "getBrightnessParams call failed with: "; |
665 | + std::cerr << reply.error().message().toStdString() << std::endl; |
666 | + } |
667 | +} |
668 | |
669 | === added file 'src/powerd_mediator.h' |
670 | --- src/powerd_mediator.h 1970-01-01 00:00:00 +0000 |
671 | +++ src/powerd_mediator.h 2014-06-25 14:46:51 +0000 |
672 | @@ -0,0 +1,87 @@ |
673 | +/* |
674 | + * Copyright © 2014 Canonical Ltd. |
675 | + * |
676 | + * This program is free software: you can redistribute it and/or modify |
677 | + * it under the terms of the GNU General Public License version 3 as |
678 | + * published by the Free Software Foundation. |
679 | + * |
680 | + * This program is distributed in the hope that it will be useful, |
681 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
682 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
683 | + * GNU General Public License for more details. |
684 | + * |
685 | + * You should have received a copy of the GNU General Public License |
686 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
687 | + */ |
688 | + |
689 | +#ifndef POWERD_MEDIATOR_ |
690 | +#define POWERD_MEDIATOR_ |
691 | + |
692 | +#include <mir_toolkit/common.h> |
693 | + |
694 | +#include <QString> |
695 | +#include <QObject> |
696 | + |
697 | +#include <memory> |
698 | +#include <mutex> |
699 | + |
700 | +class QDBusInterface; |
701 | +class QDBusServiceWatcher; |
702 | + |
703 | +/* |
704 | + * A Proxy to powerd. Note this class is not thread-safe, |
705 | + * synchronization should be done externally. |
706 | + */ |
707 | +class PowerdMediator : public QObject |
708 | +{ |
709 | + Q_OBJECT |
710 | +public: |
711 | + PowerdMediator(); |
712 | + ~PowerdMediator(); |
713 | + |
714 | + void set_dim_backlight(); |
715 | + void set_normal_backlight(); |
716 | + void turn_off_backlight(); |
717 | + void set_sys_state_for(MirPowerMode mode); |
718 | + |
719 | + void change_backlight_values(int dim_brightness, int normal_brightness); |
720 | + void enable_auto_brightness(bool flag); |
721 | + |
722 | + bool auto_brightness_supported(); |
723 | + int min_brightness(); |
724 | + int max_brightness(); |
725 | + |
726 | + void set_brightness(int brightness); |
727 | + |
728 | +private Q_SLOTS: |
729 | + void powerd_registered(); |
730 | + |
731 | +private: |
732 | + enum BacklightState |
733 | + { |
734 | + off, |
735 | + dim, |
736 | + normal, |
737 | + automatic |
738 | + }; |
739 | + void change_backlight_state(BacklightState state); |
740 | + void release_sys_state(); |
741 | + void acquire_sys_state(); |
742 | + void init_brightness_params(); |
743 | + |
744 | + int dim_brightness; |
745 | + int normal_brightness; |
746 | + int current_brightness; |
747 | + int min_brightness_; |
748 | + int max_brightness_; |
749 | + bool auto_brightness_supported_; |
750 | + bool auto_brightness_requested; |
751 | + BacklightState backlight_state; |
752 | + |
753 | + QString sys_state_cookie; |
754 | + bool acquired_sys_state; |
755 | + |
756 | + std::unique_ptr<QDBusInterface> powerd_interface; |
757 | + std::unique_ptr<QDBusServiceWatcher> service_watcher; |
758 | +}; |
759 | +#endif |
760 | |
761 | === added file 'src/powerkey_handler.cpp' |
762 | --- src/powerkey_handler.cpp 1970-01-01 00:00:00 +0000 |
763 | +++ src/powerkey_handler.cpp 2014-06-25 14:46:51 +0000 |
764 | @@ -0,0 +1,84 @@ |
765 | +/* |
766 | + * Copyright © 2014 Canonical Ltd. |
767 | + * |
768 | + * This program is free software: you can redistribute it and/or modify |
769 | + * it under the terms of the GNU General Public License version 3 as |
770 | + * published by the Free Software Foundation. |
771 | + * |
772 | + * This program is distributed in the hope that it will be useful, |
773 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
774 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
775 | + * GNU General Public License for more details. |
776 | + * |
777 | + * You should have received a copy of the GNU General Public License |
778 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
779 | + */ |
780 | + |
781 | +#include "powerkey_handler.h" |
782 | +#include "screen_state_handler.h" |
783 | +#include "power_state_change_reason.h" |
784 | + |
785 | +#include <mir/time/timer.h> |
786 | + |
787 | +#include <cstdio> |
788 | +#include "dbus_screen.h" |
789 | +#include "powerd_mediator.h" |
790 | + |
791 | +namespace mi = mir::input; |
792 | + |
793 | +PowerKeyHandler::PowerKeyHandler(mir::time::Timer& timer, |
794 | + std::chrono::milliseconds power_key_ignore_timeout, |
795 | + std::chrono::milliseconds shutdown_timeout, |
796 | + ScreenStateHandler& screen_state_handler) |
797 | + : long_press_detected{false}, |
798 | + screen_state_handler{&screen_state_handler}, |
799 | + power_key_ignore_timeout{power_key_ignore_timeout}, |
800 | + shutdown_timeout{shutdown_timeout}, |
801 | + shutdown_alarm{timer.create_alarm([this]{ shutdown_alarm_notification(); })}, |
802 | + long_press_alarm{timer.create_alarm([this]{ long_press_detected = true; })} |
803 | +{ |
804 | +} |
805 | + |
806 | +PowerKeyHandler::~PowerKeyHandler() = default; |
807 | + |
808 | +bool PowerKeyHandler::handle(MirEvent const& event) |
809 | +{ |
810 | + static const int32_t POWER_KEY_CODE = 26; |
811 | + |
812 | + if (event.type == mir_event_type_key && |
813 | + event.key.key_code == POWER_KEY_CODE) |
814 | + { |
815 | + if (event.key.action == mir_key_action_down) |
816 | + power_key_down(); |
817 | + else if (event.key.action == mir_key_action_up) |
818 | + power_key_up(); |
819 | + } |
820 | + return false; |
821 | +} |
822 | + |
823 | +void PowerKeyHandler::power_key_down() |
824 | +{ |
825 | + std::lock_guard<std::mutex> lock{guard}; |
826 | + screen_state_handler->enable_inactivity_timers(false); |
827 | + long_press_detected = false; |
828 | + long_press_alarm->reschedule_in(power_key_ignore_timeout); |
829 | + shutdown_alarm->reschedule_in(shutdown_timeout); |
830 | +} |
831 | + |
832 | +void PowerKeyHandler::power_key_up() |
833 | +{ |
834 | + std::lock_guard<std::mutex> lock{guard}; |
835 | + shutdown_alarm->cancel(); |
836 | + long_press_alarm->cancel(); |
837 | + if (!long_press_detected) |
838 | + { |
839 | + screen_state_handler->toggle_screen_power_mode(PowerStateChangeReason::power_key); |
840 | + } |
841 | +} |
842 | + |
843 | +void PowerKeyHandler::shutdown_alarm_notification() |
844 | +{ |
845 | + screen_state_handler->set_screen_power_mode( |
846 | + MirPowerMode::mir_power_mode_off, PowerStateChangeReason::power_key); |
847 | + system("shutdown -P now"); |
848 | +} |
849 | |
850 | === added file 'src/powerkey_handler.h' |
851 | --- src/powerkey_handler.h 1970-01-01 00:00:00 +0000 |
852 | +++ src/powerkey_handler.h 2014-06-25 14:46:51 +0000 |
853 | @@ -0,0 +1,69 @@ |
854 | +/* |
855 | + * Copyright © 2014 Canonical Ltd. |
856 | + * |
857 | + * This program is free software: you can redistribute it and/or modify |
858 | + * it under the terms of the GNU General Public License version 3 as |
859 | + * published by the Free Software Foundation. |
860 | + * |
861 | + * This program is distributed in the hope that it will be useful, |
862 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
863 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
864 | + * GNU General Public License for more details. |
865 | + * |
866 | + * You should have received a copy of the GNU General Public License |
867 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
868 | + */ |
869 | + |
870 | +#ifndef POWERKEY_HANDLER_H_ |
871 | +#define POWERKEY_HANDLER_H_ |
872 | + |
873 | +#include "mir/input/event_filter.h" |
874 | + |
875 | +#include <mutex> |
876 | +#include <memory> |
877 | +#include <atomic> |
878 | +#include <chrono> |
879 | + |
880 | +namespace mir |
881 | +{ |
882 | +class DefaultServerConfiguration; |
883 | +namespace time |
884 | +{ |
885 | +class Alarm; |
886 | +class Timer; |
887 | +} |
888 | +} |
889 | + |
890 | +class ScreenStateHandler; |
891 | + |
892 | +class PowerKeyHandler : public mir::input::EventFilter |
893 | +{ |
894 | +public: |
895 | + PowerKeyHandler(mir::time::Timer& timer, |
896 | + std::chrono::milliseconds power_key_ignore_timeout, |
897 | + std::chrono::milliseconds shutdown_timeout, |
898 | + ScreenStateHandler& screen_state_handler); |
899 | + |
900 | + ~PowerKeyHandler(); |
901 | + |
902 | + bool handle(MirEvent const& event) override; |
903 | + |
904 | +private: |
905 | + void power_key_up(); |
906 | + void power_key_down(); |
907 | + void shutdown_alarm_notification(); |
908 | + |
909 | + std::mutex guard; |
910 | + std::atomic<bool> long_press_detected; |
911 | + |
912 | + ScreenStateHandler* screen_state_handler; |
913 | + |
914 | + std::chrono::milliseconds power_key_ignore_timeout; |
915 | + std::chrono::milliseconds shutdown_timeout; |
916 | + |
917 | + std::unique_ptr<mir::time::Alarm> shutdown_alarm; |
918 | + std::unique_ptr<mir::time::Alarm> long_press_alarm; |
919 | + |
920 | +}; |
921 | + |
922 | +#endif |
923 | |
924 | === added file 'src/screen_state_handler.cpp' |
925 | --- src/screen_state_handler.cpp 1970-01-01 00:00:00 +0000 |
926 | +++ src/screen_state_handler.cpp 2014-06-25 14:46:51 +0000 |
927 | @@ -0,0 +1,201 @@ |
928 | +/* |
929 | + * Copyright © 2014 Canonical Ltd. |
930 | + * |
931 | + * This program is free software: you can redistribute it and/or modify |
932 | + * it under the terms of the GNU General Public License version 3 as |
933 | + * published by the Free Software Foundation. |
934 | + * |
935 | + * This program is distributed in the hope that it will be useful, |
936 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
937 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
938 | + * GNU General Public License for more details. |
939 | + * |
940 | + * You should have received a copy of the GNU General Public License |
941 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
942 | + */ |
943 | + |
944 | +#include "screen_state_handler.h" |
945 | + |
946 | +#include <mir/main_loop.h> |
947 | +#include <mir/time/timer.h> |
948 | +#include <mir/compositor/compositor.h> |
949 | +#include <mir/default_server_configuration.h> |
950 | +#include <mir/graphics/display.h> |
951 | +#include <mir/graphics/display_configuration.h> |
952 | + |
953 | +#include <cstdio> |
954 | +#include "dbus_screen.h" |
955 | +#include "dbus_screen_observer.h" |
956 | +#include "powerd_mediator.h" |
957 | +#include "power_state_change_reason.h" |
958 | + |
959 | +namespace mi = mir::input; |
960 | +namespace mc = mir::compositor; |
961 | +namespace mg = mir::graphics; |
962 | + |
963 | +ScreenStateHandler::ScreenStateHandler(std::shared_ptr<mir::DefaultServerConfiguration> const& config, |
964 | + std::chrono::milliseconds power_off_timeout, |
965 | + std::chrono::milliseconds dimmer_timeout) |
966 | + : current_power_mode{MirPowerMode::mir_power_mode_on}, |
967 | + restart_timers{true}, |
968 | + power_off_timeout{power_off_timeout}, |
969 | + dimming_timeout{dimmer_timeout}, |
970 | + powerd_mediator{new PowerdMediator()}, |
971 | + config{config}, |
972 | + power_off_alarm{config->the_main_loop()->notify_in(power_off_timeout, |
973 | + std::bind(&ScreenStateHandler::power_off_alarm_notification, this))}, |
974 | + dimmer_alarm{config->the_main_loop()->notify_in(dimming_timeout, |
975 | + std::bind(&ScreenStateHandler::dimmer_alarm_notification, this))}, |
976 | + dbus_screen{new DBusScreen(*this)} |
977 | +{ |
978 | +} |
979 | + |
980 | +ScreenStateHandler::~ScreenStateHandler() = default; |
981 | + |
982 | +bool ScreenStateHandler::handle(MirEvent const& event) |
983 | +{ |
984 | + if (event.type == mir_event_type_motion) |
985 | + { |
986 | + std::lock_guard<std::mutex> lock{guard}; |
987 | + reset_timers_l(); |
988 | + powerd_mediator->set_normal_backlight(); |
989 | + } |
990 | + return false; |
991 | +} |
992 | + |
993 | +void ScreenStateHandler::set_timeouts(std::chrono::milliseconds the_power_off_timeout, |
994 | + std::chrono::milliseconds the_dimming_timeout) |
995 | +{ |
996 | + std::lock_guard<std::mutex> lock{guard}; |
997 | + power_off_timeout = the_power_off_timeout; |
998 | + dimming_timeout = the_dimming_timeout; |
999 | + reset_timers_l(); |
1000 | +} |
1001 | + |
1002 | +void ScreenStateHandler::enable_inactivity_timers(bool enable) |
1003 | +{ |
1004 | + std::lock_guard<std::mutex> lock{guard}; |
1005 | + enable_inactivity_timers_l(enable); |
1006 | +} |
1007 | + |
1008 | +void ScreenStateHandler::toggle_screen_power_mode(PowerStateChangeReason reason) |
1009 | +{ |
1010 | + std::lock_guard<std::mutex> lock{guard}; |
1011 | + MirPowerMode new_mode = (current_power_mode == MirPowerMode::mir_power_mode_on) ? |
1012 | + MirPowerMode::mir_power_mode_off : MirPowerMode::mir_power_mode_on; |
1013 | + |
1014 | + set_screen_power_mode_l(new_mode, reason); |
1015 | +} |
1016 | + |
1017 | +void ScreenStateHandler::set_screen_power_mode(MirPowerMode mode, PowerStateChangeReason reason) |
1018 | +{ |
1019 | + std::lock_guard<std::mutex> lock{guard}; |
1020 | + set_screen_power_mode_l(mode, reason); |
1021 | +} |
1022 | + |
1023 | +void ScreenStateHandler::keep_display_on(bool on) |
1024 | +{ |
1025 | + std::lock_guard<std::mutex> lock{guard}; |
1026 | + restart_timers = !on; |
1027 | + enable_inactivity_timers_l(!on); |
1028 | + |
1029 | + if (on) |
1030 | + set_screen_power_mode_l(MirPowerMode::mir_power_mode_on, PowerStateChangeReason::unknown); |
1031 | +} |
1032 | + |
1033 | +void ScreenStateHandler::set_brightness(int brightness) |
1034 | +{ |
1035 | + std::lock_guard<std::mutex> lock{guard}; |
1036 | + powerd_mediator->set_brightness(brightness); |
1037 | +} |
1038 | + |
1039 | +void ScreenStateHandler::enable_auto_brightness(bool enable) |
1040 | +{ |
1041 | + std::lock_guard<std::mutex> lock{guard}; |
1042 | + powerd_mediator->enable_auto_brightness(enable); |
1043 | +} |
1044 | + |
1045 | +void ScreenStateHandler::set_screen_power_mode_l(MirPowerMode mode, PowerStateChangeReason reason) |
1046 | +{ |
1047 | + if (mode == MirPowerMode::mir_power_mode_on) |
1048 | + { |
1049 | + /* The screen may be dim, but on - make sure to reset backlight */ |
1050 | + if (current_power_mode == MirPowerMode::mir_power_mode_on) |
1051 | + powerd_mediator->set_normal_backlight(); |
1052 | + configure_display_l(mode, reason); |
1053 | + reset_timers_l(); |
1054 | + } |
1055 | + else |
1056 | + { |
1057 | + cancel_timers_l(); |
1058 | + configure_display_l(mode, reason); |
1059 | + } |
1060 | +} |
1061 | + |
1062 | +void ScreenStateHandler::configure_display_l(MirPowerMode mode, PowerStateChangeReason reason) |
1063 | +{ |
1064 | + if (current_power_mode == mode) |
1065 | + return; |
1066 | + |
1067 | + std::shared_ptr<mg::Display> display = config->the_display(); |
1068 | + std::shared_ptr<mg::DisplayConfiguration> displayConfig = display->configuration(); |
1069 | + std::shared_ptr<mc::Compositor> compositor = config->the_compositor(); |
1070 | + |
1071 | + displayConfig->for_each_output( |
1072 | + [&](const mg::UserDisplayConfigurationOutput displayConfigOutput) { |
1073 | + displayConfigOutput.power_mode = mode; |
1074 | + } |
1075 | + ); |
1076 | + |
1077 | + compositor->stop(); |
1078 | + display->configure(*displayConfig.get()); |
1079 | + |
1080 | + if (mode == MirPowerMode::mir_power_mode_on) |
1081 | + { |
1082 | + compositor->start(); |
1083 | + powerd_mediator->set_normal_backlight(); |
1084 | + } |
1085 | + else |
1086 | + { |
1087 | + powerd_mediator->turn_off_backlight(); |
1088 | + } |
1089 | + |
1090 | + current_power_mode = mode; |
1091 | + powerd_mediator->set_sys_state_for(mode); |
1092 | + dbus_screen->emit_power_state_change(mode, reason); |
1093 | +} |
1094 | + |
1095 | +void ScreenStateHandler::cancel_timers_l() |
1096 | +{ |
1097 | + power_off_alarm->cancel(); |
1098 | + dimmer_alarm->cancel(); |
1099 | +} |
1100 | + |
1101 | +void ScreenStateHandler::reset_timers_l() |
1102 | +{ |
1103 | + if (restart_timers && current_power_mode != MirPowerMode::mir_power_mode_off) |
1104 | + { |
1105 | + power_off_alarm->reschedule_in(power_off_timeout); |
1106 | + dimmer_alarm->reschedule_in(dimming_timeout); |
1107 | + } |
1108 | +} |
1109 | + |
1110 | +void ScreenStateHandler::enable_inactivity_timers_l(bool enable) |
1111 | +{ |
1112 | + if (enable) |
1113 | + reset_timers_l(); |
1114 | + else |
1115 | + cancel_timers_l(); |
1116 | +} |
1117 | + |
1118 | +void ScreenStateHandler::power_off_alarm_notification() |
1119 | +{ |
1120 | + std::lock_guard<std::mutex> lock{guard}; |
1121 | + configure_display_l(MirPowerMode::mir_power_mode_off, PowerStateChangeReason::inactivity); |
1122 | +} |
1123 | + |
1124 | +void ScreenStateHandler::dimmer_alarm_notification() |
1125 | +{ |
1126 | + std::lock_guard<std::mutex> lock{guard}; |
1127 | + powerd_mediator->set_dim_backlight(); |
1128 | +} |
1129 | |
1130 | === added file 'src/screen_state_handler.h' |
1131 | --- src/screen_state_handler.h 1970-01-01 00:00:00 +0000 |
1132 | +++ src/screen_state_handler.h 2014-06-25 14:46:51 +0000 |
1133 | @@ -0,0 +1,92 @@ |
1134 | +/* |
1135 | + * Copyright © 2014 Canonical Ltd. |
1136 | + * |
1137 | + * This program is free software: you can redistribute it and/or modify |
1138 | + * it under the terms of the GNU General Public License version 3 as |
1139 | + * published by the Free Software Foundation. |
1140 | + * |
1141 | + * This program is distributed in the hope that it will be useful, |
1142 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1143 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1144 | + * GNU General Public License for more details. |
1145 | + * |
1146 | + * You should have received a copy of the GNU General Public License |
1147 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1148 | + */ |
1149 | + |
1150 | +#ifndef SCREEN_STATE_HANDLER_ |
1151 | +#define SCREEN_STATE_HANDLER_ |
1152 | + |
1153 | +#include "mir/input/event_filter.h" |
1154 | +#include "dbus_screen_observer.h" |
1155 | + |
1156 | +#include <chrono> |
1157 | +#include <memory> |
1158 | +#include <mutex> |
1159 | + |
1160 | +class DBusScreen; |
1161 | +class PowerdMediator; |
1162 | +enum class PowerStateChangeReason; |
1163 | + |
1164 | +namespace mir |
1165 | +{ |
1166 | +class DefaultServerConfiguration; |
1167 | +namespace time |
1168 | +{ |
1169 | +class Alarm; |
1170 | +class Timer; |
1171 | +} |
1172 | +} |
1173 | + |
1174 | +class ScreenStateHandler: public mir::input::EventFilter, public DBusScreenObserver |
1175 | +{ |
1176 | +public: |
1177 | + ScreenStateHandler(std::shared_ptr<mir::DefaultServerConfiguration> const& config, |
1178 | + std::chrono::milliseconds power_off_timeout, |
1179 | + std::chrono::milliseconds dimmer_timeout); |
1180 | + virtual ~ScreenStateHandler(); |
1181 | + |
1182 | + //from EventFilter |
1183 | + bool handle(MirEvent const& event) override; |
1184 | + |
1185 | + void set_timeouts(std::chrono::milliseconds power_off_timeout, |
1186 | + std::chrono::milliseconds dimmer_timeout); |
1187 | + |
1188 | + void enable_inactivity_timers(bool enable); |
1189 | + void toggle_screen_power_mode(PowerStateChangeReason reason); |
1190 | + |
1191 | + void set_screen_power_mode(MirPowerMode mode, PowerStateChangeReason reason) override; |
1192 | + void keep_display_on(bool on) override; |
1193 | + void set_brightness(int brightness) override; |
1194 | + void enable_auto_brightness(bool enable) override; |
1195 | + |
1196 | +private: |
1197 | + void set_screen_power_mode_l(MirPowerMode mode, PowerStateChangeReason reason); |
1198 | + void configure_display_l(MirPowerMode mode, PowerStateChangeReason reason); |
1199 | + |
1200 | + void cancel_timers_l(); |
1201 | + void reset_timers_l(); |
1202 | + void enable_inactivity_timers_l(bool flag); |
1203 | + |
1204 | + void power_off_alarm_notification(); |
1205 | + void dimmer_alarm_notification(); |
1206 | + void long_press_alarm_notification(); |
1207 | + |
1208 | + std::mutex guard; |
1209 | + |
1210 | + MirPowerMode current_power_mode; |
1211 | + bool restart_timers; |
1212 | + |
1213 | + std::chrono::milliseconds power_off_timeout; |
1214 | + std::chrono::milliseconds dimming_timeout; |
1215 | + |
1216 | + std::unique_ptr<PowerdMediator> powerd_mediator; |
1217 | + std::shared_ptr<mir::DefaultServerConfiguration> config; |
1218 | + |
1219 | + std::unique_ptr<mir::time::Alarm> power_off_alarm; |
1220 | + std::unique_ptr<mir::time::Alarm> dimmer_alarm; |
1221 | + |
1222 | + std::unique_ptr<DBusScreen> dbus_screen; |
1223 | +}; |
1224 | + |
1225 | +#endif |
1226 | |
1227 | === modified file 'src/system_compositor.cpp' |
1228 | --- src/system_compositor.cpp 2014-06-19 22:03:22 +0000 |
1229 | +++ src/system_compositor.cpp 2014-06-25 14:46:51 +0000 |
1230 | @@ -16,8 +16,15 @@ |
1231 | * Authored by: Robert Ancell <robert.ancell@canonical.com> |
1232 | */ |
1233 | |
1234 | -#include "dbus_screen.h" |
1235 | + |
1236 | #include "system_compositor.h" |
1237 | +#include "screen_state_handler.h" |
1238 | +#include "powerkey_handler.h" |
1239 | + |
1240 | +// Qt headers will introduce a #define of "signals" |
1241 | +// but some mir headers use "signals" as a variable name in |
1242 | +// method declarations |
1243 | +#undef signals |
1244 | |
1245 | #include <mir/run_mir.h> |
1246 | #include <mir/abnormal_exit.h> |
1247 | @@ -31,6 +38,8 @@ |
1248 | #include <mir/server_status_listener.h> |
1249 | #include <mir/shell/focus_controller.h> |
1250 | #include <mir/input/cursor_listener.h> |
1251 | +#include <mir/input/composite_event_filter.h> |
1252 | +#include <mir/main_loop.h> |
1253 | |
1254 | #include <cerrno> |
1255 | #include <iostream> |
1256 | @@ -499,11 +508,26 @@ |
1257 | return the_options()->is_set("version"); |
1258 | } |
1259 | |
1260 | - int power_off_delay() |
1261 | - { |
1262 | - return the_options()->get("power-off-delay", 0); |
1263 | - } |
1264 | - |
1265 | + int inactivity_display_off_timeout() |
1266 | + { |
1267 | + return the_options()->get("inactivity-display-off-timeout", 60); |
1268 | + } |
1269 | + |
1270 | + int inactivity_display_dim_timeout() |
1271 | + { |
1272 | + return the_options()->get("inactivity-display-dim-timeout", 45); |
1273 | + } |
1274 | + |
1275 | + int shutdown_timeout() |
1276 | + { |
1277 | + return the_options()->get("shutdown-timeout", 5000); |
1278 | + } |
1279 | + |
1280 | + int power_key_ignore_timeout() |
1281 | + { |
1282 | + return the_options()->get("power-key-ignore-timeout", 1500); |
1283 | + } |
1284 | + |
1285 | bool enable_hardware_cursor() |
1286 | { |
1287 | return the_options()->get("enable-hardware-cursor", false); |
1288 | @@ -538,7 +562,7 @@ |
1289 | { |
1290 | } |
1291 | }; |
1292 | - |
1293 | + |
1294 | // This is a workaround for u8 desktop preview in 14.04 for the lack of client cursor API. |
1295 | // We need to disable the cursor for XMir but leave it on for the desktop preview. |
1296 | // Luckily as it stands they run inside seperate instances of USC. ~racarr |
1297 | @@ -633,8 +657,11 @@ |
1298 | ("version", "Show version of Unity System Compositor") |
1299 | ("spinner", po::value<std::string>(), "Path to spinner executable") |
1300 | ("public-socket", po::value<bool>(), "Make the socket file publicly writable") |
1301 | - ("power-off-delay", po::value<int>(), "Delay in milliseconds before powering off screen [int]") |
1302 | - ("enable-hardware-cursor", po::value<bool>(), "Enable the hardware cursor (disabled by default)"); |
1303 | + ("enable-hardware-cursor", po::value<bool>(), "Enable the hardware cursor (disabled by default)") |
1304 | + ("inactivity-display-off-timeout", po::value<int>(), "The time in seconds before the screen is turned off when there are no active sessions") |
1305 | + ("inactivity-display-dim-timeout", po::value<int>(), "The time in seconds before the screen is dimmed when there are no active sessions") |
1306 | + ("shutdown-timeout", po::value<int>(), "The time in milli-seconds the power key must be held to initiate a clean system shutdown") |
1307 | + ("power-key-ignore-timeout", po::value<int>(), "The time in milli-seconds the power key must be held to ignore - must be less than shutdown-timeout"); |
1308 | } |
1309 | |
1310 | void parse_config_file( |
1311 | @@ -794,7 +821,25 @@ |
1312 | void SystemCompositor::qt_main(int argc, char **argv) |
1313 | { |
1314 | QCoreApplication app(argc, argv); |
1315 | - DBusScreen dbus_screen(config, config->power_off_delay()); |
1316 | + |
1317 | + std::chrono::seconds inactivity_display_off_timeout{config->inactivity_display_off_timeout()}; |
1318 | + std::chrono::seconds inactivity_display_dim_timeout{config->inactivity_display_dim_timeout()}; |
1319 | + std::chrono::milliseconds power_key_ignore_timeout{config->power_key_ignore_timeout()}; |
1320 | + std::chrono::milliseconds shutdown_timeout{config->shutdown_timeout()}; |
1321 | + |
1322 | + screen_state_handler = std::make_shared<ScreenStateHandler>(config, |
1323 | + std::chrono::duration_cast<std::chrono::milliseconds>(inactivity_display_off_timeout), |
1324 | + std::chrono::duration_cast<std::chrono::milliseconds>(inactivity_display_dim_timeout)); |
1325 | + |
1326 | + power_key_handler = std::make_shared<PowerKeyHandler>(*(config->the_main_loop()), |
1327 | + power_key_ignore_timeout, |
1328 | + shutdown_timeout, |
1329 | + *screen_state_handler); |
1330 | + |
1331 | + auto composite_filter = config->the_composite_event_filter(); |
1332 | + composite_filter->append(screen_state_handler); |
1333 | + composite_filter->append(power_key_handler); |
1334 | + |
1335 | ensure_spinner(); |
1336 | app.exec(); |
1337 | } |
1338 | |
1339 | === modified file 'src/system_compositor.h' |
1340 | --- src/system_compositor.h 2014-06-19 22:03:22 +0000 |
1341 | +++ src/system_compositor.h 2014-06-25 14:46:51 +0000 |
1342 | @@ -26,6 +26,8 @@ |
1343 | |
1344 | class SystemCompositorShell; |
1345 | class SystemCompositorServerConfiguration; |
1346 | +class ScreenStateHandler; |
1347 | +class PowerKeyHandler; |
1348 | |
1349 | class SystemCompositor : public DMMessageHandler |
1350 | { |
1351 | @@ -42,6 +44,8 @@ |
1352 | std::shared_ptr<SystemCompositorShell> shell; |
1353 | boost::asio::io_service io_service; |
1354 | std::shared_ptr<DMConnection> dm_connection; |
1355 | + std::shared_ptr<ScreenStateHandler> screen_state_handler; |
1356 | + std::shared_ptr<PowerKeyHandler> power_key_handler; |
1357 | QProcess spinner_process; |
1358 | |
1359 | void set_active_session(std::string client_name); |
PASSED: Continuous integration, rev:127 jenkins. qa.ubuntu. com/job/ unity-system- compositor- ci/99/ jenkins. qa.ubuntu. com/job/ unity-system- compositor- trusty- amd64-ci/ 51 jenkins. qa.ubuntu. com/job/ unity-system- compositor- trusty- armhf-ci/ 51
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/unity- system- compositor- ci/99/rebuild
http://