Merge lp:~andreas-pokorny/unity-system-compositor/expose-powerkey-state-and-screen-toggle-controller-interface into lp:unity-system-compositor
- expose-powerkey-state-and-screen-toggle-controller-interface
- Merge into trunk
Status: | Work in progress |
---|---|
Proposed branch: | lp:~andreas-pokorny/unity-system-compositor/expose-powerkey-state-and-screen-toggle-controller-interface |
Merge into: | lp:unity-system-compositor |
Diff against target: |
1777 lines (+1239/-102) 25 files modified
CMakeLists.txt (+9/-9) src/CMakeLists.txt (+2/-0) src/dbus_screen.cpp (+56/-16) src/dbus_screen.h (+26/-8) src/dbus_screen_observer.h (+3/-0) src/inactivty_tracker.h (+34/-0) src/powerkey_handler.cpp (+63/-46) src/powerkey_handler.h (+19/-7) src/powerkey_mediator.cpp (+68/-0) src/powerkey_mediator.h (+55/-0) src/powerkey_state_listener.h (+40/-0) src/screen_power_state_listener.h (+40/-0) src/screen_state_handler.cpp (+8/-7) src/screen_state_handler.h (+10/-6) src/screen_toggle_controller.h (+38/-0) src/system.h (+37/-0) src/system_compositor.cpp (+16/-2) src/system_compositor.h (+9/-1) src/system_impl.cpp (+25/-0) src/system_impl.h (+31/-0) tests/unit-tests/CMakeLists.txt (+2/-0) tests/unit-tests/gmock-fixes.h (+106/-0) tests/unit-tests/mock_dbus_screen_observer.h (+38/-0) tests/unit-tests/test_powerkey_handler.cpp (+366/-0) tests/unit-tests/test_powerkey_mediator.cpp (+138/-0) |
To merge this branch: | bzr merge lp:~andreas-pokorny/unity-system-compositor/expose-powerkey-state-and-screen-toggle-controller-interface |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alan Griffiths | Needs Fixing | ||
Alberto Aguirre (community) | Needs Information | ||
PS Jenkins bot (community) | continuous-integration | Approve | |
Review via email: mp+240834@code.launchpad.net |
Commit message
Add enablePowerMode
Description of the change
Adds two new interface parts to com.canonical.
DBus methods for controlling wither power button toggles screen power mode:
* enablePowerMode
* disablePowerMod
DBus signals for power key down/up sequences:
* powerKeyUp
* powerKeyDown
Note that most LOC of the diff are caused due to the decomposition necessary to unit test the new logic.
- 191. By Andreas Pokorny
-
Remove debug output
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:191
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Alberto Aguirre (albaguirre) wrote : | # |
DBus methods for controlling wither power button toggles screen power mode:
* enablePowerMode
* disablePowerMod
Umm I wonder if this should be exposed. We certainly don't want just any client to override this policy - say what if the client requesting this crashed and never restored the power key policy?
The user now can't get the screen to shut off.
Maybe a request like in keepDisplayOn is needed, at least if the requesting client dies the power key policy can go back to default.
I guess an apparmor policy would be needed to access those controls so that they are not abused either.
Andreas Pokorny (andreas-pokorny) wrote : | # |
> DBus methods for controlling wither power button toggles screen power mode:
> * enablePowerMode
> * disablePowerMod
>
> Umm I wonder if this should be exposed. We certainly don't want just any
> client to override this policy - say what if the client requesting this
> crashed and never restored the power key policy?
> The user now can't get the screen to shut off.
>
> Maybe a request like in keepDisplayOn is needed, at least if the requesting
> client dies the power key policy can go back to default.
>
> I guess an apparmor policy would be needed to access those controls so that
> they are not abused either.
ok, good idea.
Robert Carr (robertcarr) wrote : | # |
What's going on here? Looks like the bug is still open to some extent (read the final comment on the remaining error states).
I'm not sure this is the correct approach...shoul the telephony service be listening to the powerKey event or rather should it be listening to the power state change event from powerd or whomever
Andreas Pokorny (andreas-pokorny) wrote : | # |
> What's going on here? Looks like the bug is still open to some extent (read
> the final comment on the remaining error states).
>
> I'm not sure this is the correct approach...shoul the telephony service be
> listening to the powerKey event or rather should it be listening to the power
> state change event from powerd or whomever
For RTM a simpler solution was used that would still results into the power state being toggled.
The expected behavior is that on an incoming call pressing the power key is consumed by rejecting/silencing the call, so without turning the display off or on in that case.
And yes the approach outlined here is ugly too.
Alan Griffiths (alan-griffiths) wrote : | # |
Text conflict in src/CMakeLists.txt
Contents conflict in src/dbus_screen.cpp
Contents conflict in src/dbus_screen.h
Text conflict in src/mir_screen.cpp
Text conflict in src/mir_screen.h
Text conflict in src/screen_
Text conflict in src/screen_
Text conflict in src/system_
Text conflict in src/system_
Text conflict in tests/unit-
10 conflicts encountered.
Unmerged revisions
- 191. By Andreas Pokorny
-
Remove debug output
- 190. By Andreas Pokorny
-
missing initialization
- 189. By Andreas Pokorny
-
Adds enable/disable interface for screen toggle
- 188. By Andreas Pokorny
-
dropping voice call tracking and manual dbus signaling again
- 187. By Andreas Pokorny
-
fixed and reduced call_added and call_removed signature
- 186. By Andreas Pokorny
-
Adds an ofono call state observer
During a call the screen toggle through the power key is disabled. The powerkey is supposed to be processed by telephony-service to silence and/or terminate the call.
- 185. By Andreas Pokorny
-
moving gmock utitlity for unique_ptr to separate file
- 184. By Andreas Pokorny
-
Make PowerKey handling and related parts unit-testable
This change does not change any of the existing behavior. It just moves calls to system()
or other parts of the unity system compositor behind interfaces.
Preview Diff
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2014-08-14 19:42:15 +0000 |
3 | +++ CMakeLists.txt 2014-11-06 10:16:42 +0000 |
4 | @@ -53,12 +53,12 @@ |
5 | add_subdirectory(spinner/) |
6 | add_subdirectory(src/) |
7 | |
8 | -#enable_testing() |
9 | - |
10 | -#option(MIR_ENABLE_TESTS "Build tests" ON) |
11 | - |
12 | -#if (MIR_ENABLE_TESTS) |
13 | -# find_package(Gtest REQUIRED) |
14 | -# include_directories(${GMOCK_INCLUDE_DIR} ${GTEST_INCLUDE_DIR}) |
15 | -# add_subdirectory(tests/) |
16 | -#endif () |
17 | +enable_testing() |
18 | + |
19 | +option(MIR_ENABLE_TESTS "Build tests" ON) |
20 | + |
21 | +if (MIR_ENABLE_TESTS) |
22 | + find_package(Gtest REQUIRED) |
23 | + include_directories(${GMOCK_INCLUDE_DIR} ${GTEST_INCLUDE_DIR}) |
24 | + add_subdirectory(tests/) |
25 | +endif () |
26 | |
27 | === modified file 'src/CMakeLists.txt' |
28 | --- src/CMakeLists.txt 2014-09-16 00:20:05 +0000 |
29 | +++ src/CMakeLists.txt 2014-11-06 10:16:42 +0000 |
30 | @@ -20,12 +20,14 @@ |
31 | external_spinner.cpp |
32 | powerd_mediator.cpp |
33 | powerkey_handler.cpp |
34 | + powerkey_mediator.cpp |
35 | screen_state_handler.cpp |
36 | server_configuration.cpp |
37 | session_coordinator.cpp |
38 | session_switcher.cpp |
39 | surface_coordinator.cpp |
40 | system_compositor.cpp |
41 | + system_impl.cpp |
42 | worker_thread.cpp |
43 | ) |
44 | |
45 | |
46 | === modified file 'src/dbus_screen.cpp' |
47 | --- src/dbus_screen.cpp 2014-10-10 22:43:34 +0000 |
48 | +++ src/dbus_screen.cpp 2014-11-06 10:16:42 +0000 |
49 | @@ -18,6 +18,7 @@ |
50 | #include "dbus_screen_adaptor.h" |
51 | #include "dbus_screen_observer.h" |
52 | #include "power_state_change_reason.h" |
53 | +#include "screen_toggle_controller.h" |
54 | #include "worker_thread.h" |
55 | |
56 | #include <atomic> |
57 | @@ -53,11 +54,12 @@ |
58 | } |
59 | |
60 | |
61 | -DBusScreen::DBusScreen(DBusScreenObserver& observer, QObject *parent) |
62 | +DBusScreen::DBusScreen(QObject *parent) |
63 | : QObject(parent), |
64 | dbus_adaptor{new DBusScreenAdaptor(this)}, |
65 | service_watcher{new QDBusServiceWatcher()}, |
66 | - observer{&observer}, |
67 | + observer{nullptr}, |
68 | + controller{nullptr}, |
69 | worker_thread{new usc::WorkerThread("USC/DBusHandler")} |
70 | { |
71 | QDBusConnection bus = QDBusConnection::systemBus(); |
72 | @@ -78,6 +80,38 @@ |
73 | |
74 | DBusScreen::~DBusScreen() = default; |
75 | |
76 | +void DBusScreen::set_dbus_observer(DBusScreenObserver *obs) |
77 | +{ |
78 | + observer = obs; |
79 | +} |
80 | + |
81 | +void DBusScreen::set_screen_toggle_controller(usc::ScreenToggleController *ctrl) |
82 | +{ |
83 | + controller = ctrl; |
84 | +} |
85 | + |
86 | +void DBusScreen::power_key_up() |
87 | +{ |
88 | + emit powerKeyUp(); |
89 | +} |
90 | + |
91 | +void DBusScreen::power_key_short() |
92 | +{ |
93 | +} |
94 | + |
95 | +void DBusScreen::power_key_long() |
96 | +{ |
97 | +} |
98 | + |
99 | +void DBusScreen::power_key_very_long() |
100 | +{ |
101 | +} |
102 | + |
103 | +void DBusScreen::power_key_down() |
104 | +{ |
105 | + emit powerKeyDown(); |
106 | +} |
107 | + |
108 | bool DBusScreen::setScreenPowerMode(const QString &mode, int reason) |
109 | { |
110 | if (!is_valid_reason(reason)) |
111 | @@ -107,21 +141,11 @@ |
112 | return true; |
113 | } |
114 | |
115 | -void DBusScreen::emit_power_state_change(MirPowerMode power_mode, PowerStateChangeReason reason) |
116 | +void DBusScreen::power_state_change(MirPowerMode power_mode, PowerStateChangeReason reason) |
117 | { |
118 | - QDBusMessage message = QDBusMessage::createSignal("/com/canonical/Unity/Screen", |
119 | - "com.canonical.Unity.Screen", "DisplayPowerStateChange"); |
120 | - |
121 | - int power_state = (power_mode == MirPowerMode::mir_power_mode_off) ? 0 : 1; |
122 | - |
123 | - QVariant state(power_state); |
124 | - QList<QVariant> arguments; |
125 | - arguments.append(state); |
126 | - arguments.append(static_cast<int>(reason)); |
127 | - message.setArguments(arguments); |
128 | - |
129 | - QDBusConnection bus = QDBusConnection::systemBus(); |
130 | - bus.send(message); |
131 | + emit DisplayPowerStateChange( |
132 | + (power_mode == MirPowerMode::mir_power_mode_off) ? 0 : 1, |
133 | + static_cast<int>(reason)); |
134 | } |
135 | |
136 | int DBusScreen::keepDisplayOn() |
137 | @@ -175,6 +199,22 @@ |
138 | remove_requestor(requestor, lock); |
139 | } |
140 | |
141 | +void DBusScreen::enablePowerModeToggle() |
142 | +{ |
143 | + std::cout << "enablePowerModeToggle" << std::endl; |
144 | + if (!controller) |
145 | + return; |
146 | + controller->enable_screen_toggle(); |
147 | +} |
148 | + |
149 | +void DBusScreen::disablePowerModeToggle() |
150 | +{ |
151 | + std::cout << "disablePowerModeToggle" << std::endl; |
152 | + if (!controller) |
153 | + return; |
154 | + controller->disable_screen_toggle(); |
155 | +} |
156 | + |
157 | void DBusScreen::remove_display_on_requestor(QString const& requestor) |
158 | { |
159 | std::lock_guard<decltype(guard)> lock{guard}; |
160 | |
161 | === modified file 'src/dbus_screen.h' |
162 | --- src/dbus_screen.h 2014-09-22 17:19:52 +0000 |
163 | +++ src/dbus_screen.h 2014-11-06 10:16:42 +0000 |
164 | @@ -17,7 +17,8 @@ |
165 | #ifndef DBUS_SCREEN_H_ |
166 | #define DBUS_SCREEN_H_ |
167 | |
168 | -#include <mir_toolkit/common.h> |
169 | +#include "screen_power_state_listener.h" |
170 | +#include "powerkey_state_listener.h" |
171 | |
172 | #include <memory> |
173 | #include <mutex> |
174 | @@ -28,38 +29,54 @@ |
175 | #include <QtCore> |
176 | #include <QDBusContext> |
177 | |
178 | -namespace usc {class WorkerThread;} |
179 | +namespace usc { |
180 | +class WorkerThread; |
181 | +class ScreenToggleController; |
182 | +} |
183 | |
184 | class DBusScreenAdaptor; |
185 | class DBusScreenObserver; |
186 | class QDBusInterface; |
187 | class QDBusServiceWatcher; |
188 | -enum class PowerStateChangeReason; |
189 | |
190 | -class DBusScreen : public QObject, protected QDBusContext |
191 | +class DBusScreen : public QObject, protected QDBusContext, public usc::PowerKeyStateListener, public usc::ScreenPowerStateListener |
192 | { |
193 | Q_OBJECT |
194 | Q_CLASSINFO("D-Bus Interface", "com.canonical.Unity.Screen") |
195 | |
196 | public: |
197 | - explicit DBusScreen(DBusScreenObserver& observer, QObject *parent = 0); |
198 | + explicit DBusScreen(QObject *parent = 0); |
199 | virtual ~DBusScreen(); |
200 | |
201 | - void emit_power_state_change(MirPowerMode mode, PowerStateChangeReason reason); |
202 | + void set_dbus_observer(DBusScreenObserver *observer); |
203 | + void set_screen_toggle_controller(usc::ScreenToggleController *controller); |
204 | + void power_state_change(MirPowerMode mode, PowerStateChangeReason reason) override; |
205 | + void power_key_down() override; |
206 | + void power_key_short() override; |
207 | + void power_key_long() override; |
208 | + void power_key_very_long() override; |
209 | + void power_key_up() override; |
210 | |
211 | public Q_SLOTS: |
212 | bool setScreenPowerMode(const QString &mode, int reason); |
213 | int keepDisplayOn(); |
214 | void removeDisplayOnRequest(int id); |
215 | + void enablePowerModeToggle(); |
216 | + void disablePowerModeToggle(); |
217 | |
218 | //TODO: Expose same DBus powerd interface for now |
219 | void setUserBrightness(int brightness); |
220 | void userAutobrightnessEnable(bool enable); |
221 | |
222 | void setInactivityTimeouts(int poweroff_timeout, int dimmer_timeout); |
223 | - |
224 | + |
225 | void setTouchVisualizationEnabled(bool enabled); |
226 | |
227 | +Q_SIGNALS: |
228 | + void powerKeyUp(); |
229 | + void powerKeyDown(); |
230 | + void DisplayPowerStateChange(int power_state, int reason); |
231 | + |
232 | private Q_SLOTS: |
233 | void remove_display_on_requestor(QString const& requestor); |
234 | |
235 | @@ -70,7 +87,8 @@ |
236 | std::unique_ptr<DBusScreenAdaptor> dbus_adaptor; |
237 | std::unique_ptr<QDBusServiceWatcher> service_watcher; |
238 | std::unordered_map<std::string, std::unordered_set<int>> display_requests; |
239 | - DBusScreenObserver* const observer; |
240 | + DBusScreenObserver* observer; |
241 | + usc::ScreenToggleController* controller; |
242 | std::unique_ptr<usc::WorkerThread> worker_thread; |
243 | }; |
244 | |
245 | |
246 | === modified file 'src/dbus_screen_observer.h' |
247 | --- src/dbus_screen_observer.h 2014-09-04 22:30:24 +0000 |
248 | +++ src/dbus_screen_observer.h 2014-11-06 10:16:42 +0000 |
249 | @@ -17,6 +17,8 @@ |
250 | #ifndef DBUS_SCREEN_OBSERVER_H_ |
251 | #define DBUS_SCREEN_OBSERVER_H_ |
252 | |
253 | +#include "mir_toolkit/common.h" |
254 | + |
255 | enum class PowerStateChangeReason; |
256 | |
257 | class DBusScreenObserver |
258 | @@ -25,6 +27,7 @@ |
259 | virtual ~DBusScreenObserver() = default; |
260 | |
261 | virtual void set_screen_power_mode(MirPowerMode mode, PowerStateChangeReason reason) = 0; |
262 | + virtual void toggle_screen_power_mode(PowerStateChangeReason reason) = 0; |
263 | virtual void keep_display_on(bool on) = 0; |
264 | virtual void set_brightness(int brightness) = 0; |
265 | virtual void enable_auto_brightness(bool enable) = 0; |
266 | |
267 | === added file 'src/inactivty_tracker.h' |
268 | --- src/inactivty_tracker.h 1970-01-01 00:00:00 +0000 |
269 | +++ src/inactivty_tracker.h 2014-11-06 10:16:42 +0000 |
270 | @@ -0,0 +1,34 @@ |
271 | +/* |
272 | + * Copyright © 2014 Canonical Ltd. |
273 | + * |
274 | + * This program is free software: you can redistribute it and/or modify |
275 | + * it under the terms of the GNU General Public License version 3 as |
276 | + * published by the Free Software Foundation. |
277 | + * |
278 | + * This program is distributed in the hope that it will be useful, |
279 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
280 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
281 | + * GNU General Public License for more details. |
282 | + * |
283 | + * You should have received a copy of the GNU General Public License |
284 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
285 | + * |
286 | + * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com> |
287 | + */ |
288 | + |
289 | +#ifndef INACTIVITY_TRACKER_H_ |
290 | +#define INACTIVITY_TRACKER_H_ |
291 | + |
292 | +class InactivtyTracker |
293 | +{ |
294 | +public: |
295 | + InactivtyTracker() = default; |
296 | + virtual ~InactivtyTracker() = default; |
297 | + virtual void enable_inactivity_timers(bool enable) = 0; |
298 | +protected: |
299 | + InactivtyTracker(InactivtyTracker const&) = delete; |
300 | + InactivtyTracker& operator=(InactivtyTracker const&) = delete; |
301 | +}; |
302 | + |
303 | +#endif |
304 | + |
305 | |
306 | === modified file 'src/powerkey_handler.cpp' |
307 | --- src/powerkey_handler.cpp 2014-07-21 21:33:35 +0000 |
308 | +++ src/powerkey_handler.cpp 2014-11-06 10:16:42 +0000 |
309 | @@ -15,36 +15,37 @@ |
310 | */ |
311 | |
312 | #include "powerkey_handler.h" |
313 | -#include "screen_state_handler.h" |
314 | -#include "power_state_change_reason.h" |
315 | +#include "powerkey_state_listener.h" |
316 | |
317 | #include <mir/time/timer.h> |
318 | |
319 | -#include <cstdio> |
320 | -#include "dbus_screen.h" |
321 | -#include "powerd_mediator.h" |
322 | +#include <chrono> |
323 | +#include <algorithm> |
324 | |
325 | namespace mi = mir::input; |
326 | |
327 | -PowerKeyHandler::PowerKeyHandler(mir::time::Timer& timer, |
328 | +usc::PowerKeyHandler::PowerKeyHandler(mir::time::Timer& timer, |
329 | std::chrono::milliseconds power_key_ignore_timeout, |
330 | std::chrono::milliseconds shutdown_timeout, |
331 | - ScreenStateHandler& screen_state_handler) |
332 | - : long_press_detected{false}, |
333 | - screen_state_handler{&screen_state_handler}, |
334 | + std::initializer_list<usc::PowerKeyStateListener*> listener) |
335 | + : power_key{KeyState::Released}, |
336 | power_key_ignore_timeout{power_key_ignore_timeout}, |
337 | shutdown_timeout{shutdown_timeout}, |
338 | shutdown_alarm{timer.create_alarm([this]{ shutdown_alarm_notification(); })}, |
339 | - long_press_alarm{timer.create_alarm([this]{ long_press_notification(); })} |
340 | + long_press_alarm{timer.create_alarm([this]{ long_press_notification(); })}, |
341 | + key_state_listener{listener} |
342 | { |
343 | + if (power_key_ignore_timeout > shutdown_timeout) |
344 | + throw std::invalid_argument("shutdown timeout must be larger than power key ignore timeout"); |
345 | + if (power_key_ignore_timeout.count() == 0 || |
346 | + shutdown_timeout.count() == 0) |
347 | + throw std::invalid_argument("timeouts must be non-zero"); |
348 | } |
349 | |
350 | -PowerKeyHandler::~PowerKeyHandler() = default; |
351 | +usc::PowerKeyHandler::~PowerKeyHandler() = default; |
352 | |
353 | -bool PowerKeyHandler::handle(MirEvent const& event) |
354 | +bool usc::PowerKeyHandler::handle(MirEvent const& event) |
355 | { |
356 | - static const int32_t POWER_KEY_CODE = 26; |
357 | - |
358 | if (event.type == mir_event_type_key && |
359 | event.key.key_code == POWER_KEY_CODE) |
360 | { |
361 | @@ -56,36 +57,52 @@ |
362 | return false; |
363 | } |
364 | |
365 | -void PowerKeyHandler::power_key_down() |
366 | -{ |
367 | - std::lock_guard<std::mutex> lock{guard}; |
368 | - screen_state_handler->enable_inactivity_timers(false); |
369 | - long_press_detected = false; |
370 | - long_press_alarm->reschedule_in(power_key_ignore_timeout); |
371 | - shutdown_alarm->reschedule_in(shutdown_timeout); |
372 | -} |
373 | - |
374 | -void PowerKeyHandler::power_key_up() |
375 | -{ |
376 | - std::lock_guard<std::mutex> lock{guard}; |
377 | - shutdown_alarm->cancel(); |
378 | - long_press_alarm->cancel(); |
379 | - if (!long_press_detected) |
380 | - { |
381 | - screen_state_handler->toggle_screen_power_mode(PowerStateChangeReason::power_key); |
382 | - } |
383 | -} |
384 | - |
385 | -void PowerKeyHandler::shutdown_alarm_notification() |
386 | -{ |
387 | - screen_state_handler->set_screen_power_mode( |
388 | - MirPowerMode::mir_power_mode_off, PowerStateChangeReason::power_key); |
389 | - system("shutdown -P now"); |
390 | -} |
391 | - |
392 | -void PowerKeyHandler::long_press_notification() |
393 | -{ |
394 | - screen_state_handler->set_screen_power_mode( |
395 | - MirPowerMode::mir_power_mode_on, PowerStateChangeReason::power_key); |
396 | - long_press_detected = true; |
397 | +void usc::PowerKeyHandler::power_key_down() |
398 | +{ |
399 | + if (try_transistion(KeyState::Released, KeyState::Pressed)) |
400 | + { |
401 | + long_press_alarm->reschedule_in(power_key_ignore_timeout); |
402 | + shutdown_alarm->reschedule_in(shutdown_timeout); |
403 | + std::for_each(begin(key_state_listener), end(key_state_listener), [](usc::PowerKeyStateListener* item){item->power_key_down();}); |
404 | + } |
405 | +} |
406 | + |
407 | +void usc::PowerKeyHandler::power_key_up() |
408 | +{ |
409 | + if (try_transistion(KeyState::Pressed, KeyState::Released)) |
410 | + { |
411 | + shutdown_alarm->cancel(); |
412 | + long_press_alarm->cancel(); |
413 | + std::for_each(begin(key_state_listener), end(key_state_listener), [](usc::PowerKeyStateListener* item){item->power_key_short();}); |
414 | + } |
415 | + else if (try_transistion(KeyState::LongPressed, KeyState::Released)) |
416 | + { |
417 | + shutdown_alarm->cancel(); |
418 | + } |
419 | + else if (try_transistion(KeyState::VeryLongPressed, KeyState::Released)) |
420 | + { |
421 | + // both alarms already fired |
422 | + } |
423 | + std::for_each(begin(key_state_listener), end(key_state_listener), [](usc::PowerKeyStateListener* item){item->power_key_up();}); |
424 | +} |
425 | + |
426 | +void usc::PowerKeyHandler::shutdown_alarm_notification() |
427 | +{ |
428 | + if (try_transistion(KeyState::LongPressed, KeyState::VeryLongPressed)) |
429 | + { |
430 | + std::for_each(begin(key_state_listener), end(key_state_listener), [](usc::PowerKeyStateListener* item){item->power_key_very_long();}); |
431 | + } |
432 | +} |
433 | + |
434 | +void usc::PowerKeyHandler::long_press_notification() |
435 | +{ |
436 | + if (try_transistion(KeyState::Pressed, KeyState::LongPressed)) |
437 | + { |
438 | + std::for_each(begin(key_state_listener), end(key_state_listener), [](usc::PowerKeyStateListener* item){item->power_key_long();}); |
439 | + } |
440 | +} |
441 | + |
442 | +bool usc::PowerKeyHandler::try_transistion(KeyState from, KeyState to) |
443 | +{ |
444 | + return std::atomic_compare_exchange_strong(&power_key, &from, to); |
445 | } |
446 | |
447 | === modified file 'src/powerkey_handler.h' |
448 | --- src/powerkey_handler.h 2014-07-21 21:33:35 +0000 |
449 | +++ src/powerkey_handler.h 2014-11-06 10:16:42 +0000 |
450 | @@ -22,11 +22,12 @@ |
451 | #include <mutex> |
452 | #include <memory> |
453 | #include <atomic> |
454 | +#include <vector> |
455 | #include <chrono> |
456 | +#include <initializer_list> |
457 | |
458 | namespace mir |
459 | { |
460 | -class DefaultServerConfiguration; |
461 | namespace time |
462 | { |
463 | class Alarm; |
464 | @@ -34,7 +35,9 @@ |
465 | } |
466 | } |
467 | |
468 | -class ScreenStateHandler; |
469 | +namespace usc |
470 | +{ |
471 | +class PowerKeyStateListener; |
472 | |
473 | class PowerKeyHandler : public mir::input::EventFilter |
474 | { |
475 | @@ -42,29 +45,38 @@ |
476 | PowerKeyHandler(mir::time::Timer& timer, |
477 | std::chrono::milliseconds power_key_ignore_timeout, |
478 | std::chrono::milliseconds shutdown_timeout, |
479 | - ScreenStateHandler& screen_state_handler); |
480 | + std::initializer_list<PowerKeyStateListener*> listener); |
481 | |
482 | ~PowerKeyHandler(); |
483 | |
484 | bool handle(MirEvent const& event) override; |
485 | |
486 | + static const int32_t POWER_KEY_CODE = 26; |
487 | + |
488 | private: |
489 | void power_key_up(); |
490 | void power_key_down(); |
491 | void shutdown_alarm_notification(); |
492 | void long_press_notification(); |
493 | |
494 | - std::mutex guard; |
495 | - std::atomic<bool> long_press_detected; |
496 | + enum class KeyState |
497 | + { |
498 | + Released, |
499 | + Pressed, |
500 | + LongPressed, |
501 | + VeryLongPressed |
502 | + }; |
503 | + bool try_transistion(KeyState from, KeyState to); |
504 | |
505 | - ScreenStateHandler* screen_state_handler; |
506 | + std::atomic<KeyState> power_key; |
507 | |
508 | std::chrono::milliseconds power_key_ignore_timeout; |
509 | std::chrono::milliseconds shutdown_timeout; |
510 | |
511 | std::unique_ptr<mir::time::Alarm> shutdown_alarm; |
512 | std::unique_ptr<mir::time::Alarm> long_press_alarm; |
513 | - |
514 | + std::vector<PowerKeyStateListener*> const key_state_listener; |
515 | }; |
516 | +} |
517 | |
518 | #endif |
519 | |
520 | === added file 'src/powerkey_mediator.cpp' |
521 | --- src/powerkey_mediator.cpp 1970-01-01 00:00:00 +0000 |
522 | +++ src/powerkey_mediator.cpp 2014-11-06 10:16:42 +0000 |
523 | @@ -0,0 +1,68 @@ |
524 | +/* |
525 | + * Copyright © 2014 Canonical Ltd. |
526 | + * |
527 | + * This program is free software: you can redistribute it and/or modify |
528 | + * it under the terms of the GNU General Public License version 3 as |
529 | + * published by the Free Software Foundation. |
530 | + * |
531 | + * This program is distributed in the hope that it will be useful, |
532 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
533 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
534 | + * GNU General Public License for more details. |
535 | + * |
536 | + * You should have received a copy of the GNU General Public License |
537 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
538 | + * |
539 | + * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com> |
540 | + */ |
541 | + |
542 | +#include "powerkey_mediator.h" |
543 | +#include "dbus_screen_observer.h" |
544 | +#include "power_state_change_reason.h" |
545 | +#include "inactivty_tracker.h" |
546 | +#include "system.h" |
547 | + |
548 | +usc::PowerKeyMediator::PowerKeyMediator(DBusScreenObserver & observer, InactivtyTracker & tracker, System& sys) |
549 | + : screen_observer{observer}, inactivity_tracker(tracker), sys(sys) |
550 | +{ |
551 | +} |
552 | + |
553 | +void usc::PowerKeyMediator::power_key_down() |
554 | +{ |
555 | + inactivity_tracker.enable_inactivity_timers(false); |
556 | +} |
557 | + |
558 | +void usc::PowerKeyMediator::power_key_short() |
559 | +{ |
560 | + if (screen_toggle_enabled) |
561 | + screen_observer.toggle_screen_power_mode(PowerStateChangeReason::power_key); |
562 | +} |
563 | + |
564 | +void usc::PowerKeyMediator::power_key_long() |
565 | +{ |
566 | + // screen is turned on so that the shutdown/restart/cancel dialog that is displayed |
567 | + // by the shell can be seen |
568 | + screen_observer.set_screen_power_mode( |
569 | + MirPowerMode::mir_power_mode_on, PowerStateChangeReason::power_key); |
570 | +} |
571 | + |
572 | +void usc::PowerKeyMediator::power_key_very_long() |
573 | +{ |
574 | + screen_observer.set_screen_power_mode( |
575 | + MirPowerMode::mir_power_mode_off, PowerStateChangeReason::power_key); |
576 | + sys.shutdown(); |
577 | +} |
578 | + |
579 | +void usc::PowerKeyMediator::power_key_up() |
580 | +{ |
581 | +} |
582 | + |
583 | +void usc::PowerKeyMediator::enable_screen_toggle() |
584 | +{ |
585 | + screen_toggle_enabled = true; |
586 | +} |
587 | + |
588 | +void usc::PowerKeyMediator::disable_screen_toggle() |
589 | +{ |
590 | + screen_toggle_enabled = false; |
591 | +} |
592 | |
593 | === added file 'src/powerkey_mediator.h' |
594 | --- src/powerkey_mediator.h 1970-01-01 00:00:00 +0000 |
595 | +++ src/powerkey_mediator.h 2014-11-06 10:16:42 +0000 |
596 | @@ -0,0 +1,55 @@ |
597 | +/* |
598 | + * Copyright © 2014 Canonical Ltd. |
599 | + * |
600 | + * This program is free software: you can redistribute it and/or modify |
601 | + * it under the terms of the GNU General Public License version 3 as |
602 | + * published by the Free Software Foundation. |
603 | + * |
604 | + * This program is distributed in the hope that it will be useful, |
605 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
606 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
607 | + * GNU General Public License for more details. |
608 | + * |
609 | + * You should have received a copy of the GNU General Public License |
610 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
611 | + * |
612 | + * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com> |
613 | + */ |
614 | + |
615 | +#ifndef POWER_KEY_MEDIATOR_ |
616 | +#define POWER_KEY_MEDIATOR_ |
617 | + |
618 | +#include "powerkey_state_listener.h" |
619 | +#include "screen_toggle_controller.h" |
620 | + |
621 | +#include <atomic> |
622 | + |
623 | +class InactivtyTracker; |
624 | +class DBusScreenObserver; |
625 | +class System; |
626 | + |
627 | +namespace usc |
628 | +{ |
629 | + |
630 | +class PowerKeyMediator : public PowerKeyStateListener, public ScreenToggleController |
631 | +{ |
632 | +public: |
633 | + PowerKeyMediator(DBusScreenObserver& observer, InactivtyTracker& handler, System& sys); |
634 | + void power_key_down() override; |
635 | + void power_key_short() override; |
636 | + void power_key_long() override; |
637 | + void power_key_very_long() override; |
638 | + void power_key_up() override; |
639 | + |
640 | + void enable_screen_toggle() override; |
641 | + void disable_screen_toggle() override; |
642 | +private: |
643 | + DBusScreenObserver& screen_observer; |
644 | + InactivtyTracker& inactivity_tracker; |
645 | + System& sys; |
646 | + std::atomic<bool> screen_toggle_enabled{true}; |
647 | +}; |
648 | + |
649 | +} |
650 | + |
651 | +#endif |
652 | |
653 | === added file 'src/powerkey_state_listener.h' |
654 | --- src/powerkey_state_listener.h 1970-01-01 00:00:00 +0000 |
655 | +++ src/powerkey_state_listener.h 2014-11-06 10:16:42 +0000 |
656 | @@ -0,0 +1,40 @@ |
657 | +/* |
658 | + * Copyright © 2014 Canonical Ltd. |
659 | + * |
660 | + * This program is free software: you can redistribute it and/or modify |
661 | + * it under the terms of the GNU General Public License version 3 as |
662 | + * published by the Free Software Foundation. |
663 | + * |
664 | + * This program is distributed in the hope that it will be useful, |
665 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
666 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
667 | + * GNU General Public License for more details. |
668 | + * |
669 | + * You should have received a copy of the GNU General Public License |
670 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
671 | + */ |
672 | + |
673 | +#ifndef POWER_KEY_STATE_LISTENER_ |
674 | +#define POWER_KEY_STATE_LISTENER_ |
675 | + |
676 | +namespace usc |
677 | +{ |
678 | + |
679 | +class PowerKeyStateListener |
680 | +{ |
681 | +public: |
682 | + PowerKeyStateListener() = default; |
683 | + virtual ~PowerKeyStateListener() = default; |
684 | + virtual void power_key_down() = 0; |
685 | + virtual void power_key_short() = 0; |
686 | + virtual void power_key_long() = 0; |
687 | + virtual void power_key_very_long() = 0; |
688 | + virtual void power_key_up() = 0; |
689 | +protected: |
690 | + PowerKeyStateListener(PowerKeyStateListener const&) = delete; |
691 | + PowerKeyStateListener& operator=(PowerKeyStateListener const&) = delete; |
692 | +}; |
693 | + |
694 | +} |
695 | + |
696 | +#endif |
697 | |
698 | === added file 'src/screen_power_state_listener.h' |
699 | --- src/screen_power_state_listener.h 1970-01-01 00:00:00 +0000 |
700 | +++ src/screen_power_state_listener.h 2014-11-06 10:16:42 +0000 |
701 | @@ -0,0 +1,40 @@ |
702 | +/* |
703 | + * Copyright © 2013-2014 Canonical Ltd. |
704 | + * |
705 | + * This program is free software: you can redistribute it and/or modify |
706 | + * it under the terms of the GNU General Public License version 3 as |
707 | + * published by the Free Software Foundation. |
708 | + * |
709 | + * This program is distributed in the hope that it will be useful, |
710 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
711 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
712 | + * GNU General Public License for more details. |
713 | + * |
714 | + * You should have received a copy of the GNU General Public License |
715 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
716 | + */ |
717 | + |
718 | +#ifndef USC_SCREEN_POWER_STATE_LISTENER_H_ |
719 | +#define USC_SCREEN_POWER_STATE_LISTENER_H_ |
720 | + |
721 | +#include <mir_toolkit/common.h> |
722 | + |
723 | +enum class PowerStateChangeReason; |
724 | + |
725 | +namespace usc |
726 | +{ |
727 | + |
728 | +class ScreenPowerStateListener |
729 | +{ |
730 | +public: |
731 | + ScreenPowerStateListener() = default; |
732 | + virtual ~ScreenPowerStateListener() = default; |
733 | + virtual void power_state_change(MirPowerMode mode, PowerStateChangeReason reason) = 0; |
734 | +private: |
735 | + ScreenPowerStateListener(ScreenPowerStateListener const&) = delete; |
736 | + ScreenPowerStateListener& operator=(ScreenPowerStateListener const&) = delete; |
737 | +}; |
738 | + |
739 | +} |
740 | + |
741 | +#endif |
742 | |
743 | === modified file 'src/screen_state_handler.cpp' |
744 | --- src/screen_state_handler.cpp 2014-09-22 17:19:52 +0000 |
745 | +++ src/screen_state_handler.cpp 2014-11-06 10:16:42 +0000 |
746 | @@ -13,8 +13,12 @@ |
747 | * You should have received a copy of the GNU General Public License |
748 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
749 | */ |
750 | +#define QT_NO_KEYWORDS |
751 | |
752 | #include "screen_state_handler.h" |
753 | +#include "powerd_mediator.h" |
754 | +#include "power_state_change_reason.h" |
755 | +#include "screen_power_state_listener.h" |
756 | |
757 | #include <mir/main_loop.h> |
758 | #include <mir/time/timer.h> |
759 | @@ -25,10 +29,6 @@ |
760 | #include <mir/input/touch_visualizer.h> |
761 | |
762 | #include <cstdio> |
763 | -#include "dbus_screen.h" |
764 | -#include "dbus_screen_observer.h" |
765 | -#include "powerd_mediator.h" |
766 | -#include "power_state_change_reason.h" |
767 | |
768 | namespace mi = mir::input; |
769 | namespace mc = mir::compositor; |
770 | @@ -36,7 +36,8 @@ |
771 | |
772 | ScreenStateHandler::ScreenStateHandler(std::shared_ptr<mir::DefaultServerConfiguration> const& config, |
773 | std::chrono::milliseconds poweroff_timeout, |
774 | - std::chrono::milliseconds dimmer_timeout) |
775 | + std::chrono::milliseconds dimmer_timeout, |
776 | + usc::ScreenPowerStateListener & screen_state_listener) |
777 | : current_power_mode{MirPowerMode::mir_power_mode_on}, |
778 | restart_timers{true}, |
779 | power_off_timeout{poweroff_timeout}, |
780 | @@ -47,7 +48,7 @@ |
781 | std::bind(&ScreenStateHandler::power_off_alarm_notification, this))}, |
782 | dimmer_alarm{config->the_main_loop()->create_alarm( |
783 | std::bind(&ScreenStateHandler::dimmer_alarm_notification, this))}, |
784 | - dbus_screen{new DBusScreen(*this)} |
785 | + screen_state_listener{screen_state_listener} |
786 | { |
787 | reset_timers_l(); |
788 | } |
789 | @@ -181,7 +182,7 @@ |
790 | |
791 | current_power_mode = mode; |
792 | |
793 | - dbus_screen->emit_power_state_change(mode, reason); |
794 | + screen_state_listener.power_state_change(mode, reason); |
795 | |
796 | if (!power_on) |
797 | powerd_mediator->allow_suspend(); |
798 | |
799 | === modified file 'src/screen_state_handler.h' |
800 | --- src/screen_state_handler.h 2014-09-04 22:30:24 +0000 |
801 | +++ src/screen_state_handler.h 2014-11-06 10:16:42 +0000 |
802 | @@ -19,6 +19,7 @@ |
803 | |
804 | #include "mir/input/event_filter.h" |
805 | #include "dbus_screen_observer.h" |
806 | +#include "inactivty_tracker.h" |
807 | |
808 | #include <chrono> |
809 | #include <memory> |
810 | @@ -38,26 +39,29 @@ |
811 | } |
812 | } |
813 | |
814 | -class ScreenStateHandler: public mir::input::EventFilter, public DBusScreenObserver |
815 | +namespace usc { class ScreenPowerStateListener;} |
816 | + |
817 | +class ScreenStateHandler: public mir::input::EventFilter, public DBusScreenObserver, public InactivtyTracker |
818 | { |
819 | public: |
820 | ScreenStateHandler(std::shared_ptr<mir::DefaultServerConfiguration> const& config, |
821 | std::chrono::milliseconds power_off_timeout, |
822 | - std::chrono::milliseconds dimmer_timeout); |
823 | + std::chrono::milliseconds dimmer_timeout, |
824 | + usc::ScreenPowerStateListener& screen_state_listener); |
825 | virtual ~ScreenStateHandler(); |
826 | |
827 | //from EventFilter |
828 | bool handle(MirEvent const& event) override; |
829 | |
830 | - void enable_inactivity_timers(bool enable); |
831 | - void toggle_screen_power_mode(PowerStateChangeReason reason); |
832 | + void enable_inactivity_timers(bool enable) override; |
833 | |
834 | void set_screen_power_mode(MirPowerMode mode, PowerStateChangeReason reason) override; |
835 | + void toggle_screen_power_mode(PowerStateChangeReason reason) override; |
836 | void keep_display_on(bool on) override; |
837 | void set_brightness(int brightness) override; |
838 | void enable_auto_brightness(bool enable) override; |
839 | void set_inactivity_timeouts(int power_off_timeout, int dimmer_timeout) override; |
840 | - |
841 | + |
842 | void set_touch_visualization_enabled(bool enabled) override; |
843 | |
844 | private: |
845 | @@ -86,7 +90,7 @@ |
846 | std::unique_ptr<mir::time::Alarm> power_off_alarm; |
847 | std::unique_ptr<mir::time::Alarm> dimmer_alarm; |
848 | |
849 | - std::unique_ptr<DBusScreen> dbus_screen; |
850 | + usc::ScreenPowerStateListener& screen_state_listener; |
851 | }; |
852 | |
853 | #endif |
854 | |
855 | === added file 'src/screen_toggle_controller.h' |
856 | --- src/screen_toggle_controller.h 1970-01-01 00:00:00 +0000 |
857 | +++ src/screen_toggle_controller.h 2014-11-06 10:16:42 +0000 |
858 | @@ -0,0 +1,38 @@ |
859 | +/* |
860 | + * Copyright © 2014 Canonical Ltd. |
861 | + * |
862 | + * This program is free software: you can redistribute it and/or modify |
863 | + * it under the terms of the GNU General Public License version 3 as |
864 | + * published by the Free Software Foundation. |
865 | + * |
866 | + * This program is distributed in the hope that it will be useful, |
867 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
868 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
869 | + * GNU General Public License for more details. |
870 | + * |
871 | + * You should have received a copy of the GNU General Public License |
872 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
873 | + * |
874 | + * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com> |
875 | + */ |
876 | + |
877 | +#ifndef USC_SCREEN_TOGGLE_CONTROLLER_H_ |
878 | +#define USC_SCREEN_TOGGLE_CONTROLLER_H_ |
879 | + |
880 | +namespace usc |
881 | +{ |
882 | + |
883 | +class ScreenToggleController |
884 | +{ |
885 | +public: |
886 | + ScreenToggleController() = default; |
887 | + virtual ~ScreenToggleController() = default; |
888 | + virtual void enable_screen_toggle() = 0; |
889 | + virtual void disable_screen_toggle() = 0; |
890 | +protected: |
891 | + ScreenToggleController(ScreenToggleController const&) = delete; |
892 | + ScreenToggleController& operator=(ScreenToggleController const&) = delete; |
893 | +}; |
894 | +} |
895 | + |
896 | +#endif |
897 | |
898 | === added file 'src/system.h' |
899 | --- src/system.h 1970-01-01 00:00:00 +0000 |
900 | +++ src/system.h 2014-11-06 10:16:42 +0000 |
901 | @@ -0,0 +1,37 @@ |
902 | +/* |
903 | + * Copyright © 2014 Canonical Ltd. |
904 | + * |
905 | + * This program is free software: you can redistribute it and/or modify |
906 | + * it under the terms of the GNU General Public License version 3 as |
907 | + * published by the Free Software Foundation. |
908 | + * |
909 | + * This program is distributed in the hope that it will be useful, |
910 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
911 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
912 | + * GNU General Public License for more details. |
913 | + * |
914 | + * You should have received a copy of the GNU General Public License |
915 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
916 | + * |
917 | + * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com> |
918 | + */ |
919 | + |
920 | +#ifndef UNITY_SYSTEM_COMPOSITOR_SYSTEM_H_ |
921 | +#define UNITY_SYSTEM_COMPOSITOR_SYSTEM_H_ |
922 | + |
923 | +/*! |
924 | + * Interfaces to low level c-library functionality. |
925 | + */ |
926 | +class System |
927 | +{ |
928 | +public: |
929 | + System() = default; |
930 | + virtual ~System() = default; |
931 | + virtual void shutdown() = 0; |
932 | +protected: |
933 | + System(System const&) = delete; |
934 | + System& operator=(System const&) = delete; |
935 | +}; |
936 | + |
937 | +#endif |
938 | + |
939 | |
940 | === modified file 'src/system_compositor.cpp' |
941 | --- src/system_compositor.cpp 2014-07-18 06:37:51 +0000 |
942 | +++ src/system_compositor.cpp 2014-11-06 10:16:42 +0000 |
943 | @@ -24,6 +24,8 @@ |
944 | #include "spinner.h" |
945 | #include "screen_state_handler.h" |
946 | #include "powerkey_handler.h" |
947 | +#include "powerkey_mediator.h" |
948 | +#include "dbus_screen.h" |
949 | |
950 | // Qt headers will introduce a #define of "signals" |
951 | // but some mir headers use "signals" as a variable name in |
952 | @@ -93,6 +95,8 @@ |
953 | { |
954 | } |
955 | |
956 | +usc::SystemCompositor::~SystemCompositor() = default; |
957 | + |
958 | void usc::SystemCompositor::run() |
959 | { |
960 | if (config->show_version()) |
961 | @@ -155,14 +159,24 @@ |
962 | std::chrono::milliseconds power_key_ignore_timeout{config->power_key_ignore_timeout()}; |
963 | std::chrono::milliseconds shutdown_timeout{config->shutdown_timeout()}; |
964 | |
965 | + dbus_screen = std::unique_ptr<DBusScreen>(new DBusScreen); |
966 | screen_state_handler = std::make_shared<ScreenStateHandler>(config, |
967 | std::chrono::duration_cast<std::chrono::milliseconds>(inactivity_display_off_timeout), |
968 | - std::chrono::duration_cast<std::chrono::milliseconds>(inactivity_display_dim_timeout)); |
969 | + std::chrono::duration_cast<std::chrono::milliseconds>(inactivity_display_dim_timeout), |
970 | + *dbus_screen |
971 | + ); |
972 | + |
973 | + dbus_screen->set_dbus_observer(screen_state_handler.get()); |
974 | + |
975 | + power_key_mediator = std::make_shared<PowerKeyMediator>(*screen_state_handler, *screen_state_handler, system_impl); |
976 | + |
977 | + dbus_screen->set_screen_toggle_controller(power_key_mediator.get()); |
978 | |
979 | power_key_handler = std::make_shared<PowerKeyHandler>(*(config->the_main_loop()), |
980 | power_key_ignore_timeout, |
981 | shutdown_timeout, |
982 | - *screen_state_handler); |
983 | + std::initializer_list<PowerKeyStateListener*>{power_key_mediator.get(), dbus_screen.get()} |
984 | + ); |
985 | |
986 | auto composite_filter = config->the_composite_event_filter(); |
987 | composite_filter->append(screen_state_handler); |
988 | |
989 | === modified file 'src/system_compositor.h' |
990 | --- src/system_compositor.h 2014-07-14 14:26:17 +0000 |
991 | +++ src/system_compositor.h 2014-11-06 10:16:42 +0000 |
992 | @@ -22,13 +22,17 @@ |
993 | |
994 | #include <memory> |
995 | |
996 | +#include "system_impl.h" |
997 | + |
998 | class ScreenStateHandler; |
999 | -class PowerKeyHandler; |
1000 | +class DBusScreen; |
1001 | |
1002 | namespace usc |
1003 | { |
1004 | |
1005 | class ServerConfiguration; |
1006 | +class PowerKeyMediator; |
1007 | +class PowerKeyHandler; |
1008 | class DMConnection; |
1009 | class Spinner; |
1010 | |
1011 | @@ -36,6 +40,7 @@ |
1012 | { |
1013 | public: |
1014 | SystemCompositor(std::shared_ptr<ServerConfiguration> const& config); |
1015 | + ~SystemCompositor(); |
1016 | void run(); |
1017 | |
1018 | private: |
1019 | @@ -45,8 +50,11 @@ |
1020 | std::shared_ptr<ServerConfiguration> const config; |
1021 | std::shared_ptr<DMConnection> const dm_connection; |
1022 | std::shared_ptr<Spinner> const spinner; |
1023 | + std::unique_ptr<DBusScreen> dbus_screen; |
1024 | std::shared_ptr<ScreenStateHandler> screen_state_handler; |
1025 | + std::shared_ptr<PowerKeyMediator> power_key_mediator; |
1026 | std::shared_ptr<PowerKeyHandler> power_key_handler; |
1027 | + SystemImpl system_impl; |
1028 | }; |
1029 | |
1030 | } |
1031 | |
1032 | === added file 'src/system_impl.cpp' |
1033 | --- src/system_impl.cpp 1970-01-01 00:00:00 +0000 |
1034 | +++ src/system_impl.cpp 2014-11-06 10:16:42 +0000 |
1035 | @@ -0,0 +1,25 @@ |
1036 | +/* |
1037 | + * Copyright © 2014 Canonical Ltd. |
1038 | + * |
1039 | + * This program is free software: you can redistribute it and/or modify |
1040 | + * it under the terms of the GNU General Public License version 3 as |
1041 | + * published by the Free Software Foundation. |
1042 | + * |
1043 | + * This program is distributed in the hope that it will be useful, |
1044 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1045 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1046 | + * GNU General Public License for more details. |
1047 | + * |
1048 | + * You should have received a copy of the GNU General Public License |
1049 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1050 | + * |
1051 | + * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com> |
1052 | + */ |
1053 | + |
1054 | +#include "system_impl.h" |
1055 | +#include <cstdlib> |
1056 | + |
1057 | +void SystemImpl::shutdown() |
1058 | +{ |
1059 | + std::system("shutdown -P now"); |
1060 | +} |
1061 | |
1062 | === added file 'src/system_impl.h' |
1063 | --- src/system_impl.h 1970-01-01 00:00:00 +0000 |
1064 | +++ src/system_impl.h 2014-11-06 10:16:42 +0000 |
1065 | @@ -0,0 +1,31 @@ |
1066 | +/* |
1067 | + * Copyright © 2014 Canonical Ltd. |
1068 | + * |
1069 | + * This program is free software: you can redistribute it and/or modify |
1070 | + * it under the terms of the GNU General Public License version 3 as |
1071 | + * published by the Free Software Foundation. |
1072 | + * |
1073 | + * This program is distributed in the hope that it will be useful, |
1074 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1075 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1076 | + * GNU General Public License for more details. |
1077 | + * |
1078 | + * You should have received a copy of the GNU General Public License |
1079 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1080 | + * |
1081 | + * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com> |
1082 | + */ |
1083 | + |
1084 | +#ifndef SYSTEM_IMPL_H |
1085 | +#define SYSTEM_IMPL_H |
1086 | + |
1087 | +#include "system.h" |
1088 | + |
1089 | +class SystemImpl : public System |
1090 | +{ |
1091 | +public: |
1092 | + void shutdown() override; |
1093 | +}; |
1094 | + |
1095 | +#endif |
1096 | + |
1097 | |
1098 | === modified file 'tests/unit-tests/CMakeLists.txt' |
1099 | --- tests/unit-tests/CMakeLists.txt 2014-07-09 06:58:05 +0000 |
1100 | +++ tests/unit-tests/CMakeLists.txt 2014-11-06 10:16:42 +0000 |
1101 | @@ -23,6 +23,8 @@ |
1102 | usc_unit_tests |
1103 | |
1104 | test_session_switcher.cpp |
1105 | + test_powerkey_handler.cpp |
1106 | + test_powerkey_mediator.cpp |
1107 | ) |
1108 | |
1109 | target_link_libraries( |
1110 | |
1111 | === added file 'tests/unit-tests/gmock-fixes.h' |
1112 | --- tests/unit-tests/gmock-fixes.h 1970-01-01 00:00:00 +0000 |
1113 | +++ tests/unit-tests/gmock-fixes.h 2014-11-06 10:16:42 +0000 |
1114 | @@ -0,0 +1,106 @@ |
1115 | +/* |
1116 | + * Copyright © 2014 Canonical Ltd. |
1117 | + * |
1118 | + * This program is free software: you can redistribute it and/or modify |
1119 | + * it under the terms of the GNU General Public License version 3 as |
1120 | + * published by the Free Software Foundation. |
1121 | + * |
1122 | + * This program is distributed in the hope that it will be useful, |
1123 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1124 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1125 | + * GNU General Public License for more details. |
1126 | + * |
1127 | + * You should have received a copy of the GNU General Public License |
1128 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1129 | + */ |
1130 | + |
1131 | +#ifndef USC_GMOCK_FIXES_H_ |
1132 | +#define USC_GMOCK_FIXES_H_ |
1133 | +#include <gmock/gmock.h> |
1134 | + |
1135 | +// copied from mir code base |
1136 | +namespace testing |
1137 | +{ |
1138 | +namespace internal |
1139 | +{ |
1140 | + |
1141 | +template<typename T> |
1142 | +class ActionResultHolder<std::unique_ptr<T>> |
1143 | +: public UntypedActionResultHolderBase { |
1144 | + public: |
1145 | + explicit ActionResultHolder(std::unique_ptr<T>&& a_value) : |
1146 | + value_(std::move(a_value)) {} |
1147 | + |
1148 | + // The compiler-generated copy constructor and assignment operator |
1149 | + // are exactly what we need, so we don't need to define them. |
1150 | + |
1151 | + // Returns the held value and deletes this object. |
1152 | + std::unique_ptr<T> GetValueAndDelete() const { |
1153 | + std::unique_ptr<T> retval(std::move(value_)); |
1154 | + delete this; |
1155 | + return std::move(retval); |
1156 | + } |
1157 | + |
1158 | + // Prints the held value as an action's result to os. |
1159 | + virtual void PrintAsActionResult(::std::ostream* os) const { |
1160 | + *os << "\n Returns: "; |
1161 | + // T may be a reference type, so we don't use UniversalPrint(). |
1162 | + UniversalPrinter<std::unique_ptr<T>>::Print(value_, os); |
1163 | + } |
1164 | + |
1165 | + // Performs the given mock function's default action and returns the |
1166 | + // result in a new-ed ActionResultHolder. |
1167 | + template <typename F> |
1168 | + static ActionResultHolder* PerformDefaultAction( |
1169 | + const FunctionMockerBase<F>* func_mocker, |
1170 | + const typename Function<F>::ArgumentTuple& args, |
1171 | + const string& call_description) { |
1172 | + return new ActionResultHolder( |
1173 | + func_mocker->PerformDefaultAction(args, call_description)); |
1174 | + } |
1175 | + |
1176 | + // Performs the given action and returns the result in a new-ed |
1177 | + // ActionResultHolder. |
1178 | + template <typename F> |
1179 | + static ActionResultHolder* |
1180 | + PerformAction(const Action<F>& action, |
1181 | + const typename Function<F>::ArgumentTuple& args) { |
1182 | + return new ActionResultHolder(action.Perform(args)); |
1183 | + } |
1184 | + |
1185 | + private: |
1186 | + std::unique_ptr<T> mutable value_; |
1187 | + |
1188 | + // T could be a reference type, so = isn't supported. |
1189 | + GTEST_DISALLOW_ASSIGN_(ActionResultHolder); |
1190 | +}; |
1191 | + |
1192 | +} |
1193 | + |
1194 | +template<typename T> |
1195 | +class DefaultValue<std::unique_ptr<T>> { |
1196 | + public: |
1197 | + // Unsets the default value for type T. |
1198 | + static void Clear() {} |
1199 | + |
1200 | + // Returns true iff the user has set the default value for type T. |
1201 | + static bool IsSet() { return false; } |
1202 | + |
1203 | + // Returns true if T has a default return value set by the user or there |
1204 | + // exists a built-in default value. |
1205 | + static bool Exists() { |
1206 | + return true; |
1207 | + } |
1208 | + |
1209 | + // Returns the default value for type T if the user has set one; |
1210 | + // otherwise returns the built-in default value if there is one; |
1211 | + // otherwise aborts the process. |
1212 | + static std::unique_ptr<T> Get() { |
1213 | + return std::unique_ptr<T>(); |
1214 | + } |
1215 | +}; |
1216 | + |
1217 | +} |
1218 | + |
1219 | +#endif |
1220 | + |
1221 | |
1222 | === added file 'tests/unit-tests/mock_dbus_screen_observer.h' |
1223 | --- tests/unit-tests/mock_dbus_screen_observer.h 1970-01-01 00:00:00 +0000 |
1224 | +++ tests/unit-tests/mock_dbus_screen_observer.h 2014-11-06 10:16:42 +0000 |
1225 | @@ -0,0 +1,38 @@ |
1226 | +/* |
1227 | + * Copyright © 2014 Canonical Ltd. |
1228 | + * |
1229 | + * This program is free software: you can redistribute it and/or modify |
1230 | + * it under the terms of the GNU General Public License version 3 as |
1231 | + * published by the Free Software Foundation. |
1232 | + * |
1233 | + * This program is distributed in the hope that it will be useful, |
1234 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1235 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1236 | + * GNU General Public License for more details. |
1237 | + * |
1238 | + * You should have received a copy of the GNU General Public License |
1239 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1240 | + * |
1241 | + * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com> |
1242 | + */ |
1243 | + |
1244 | +#ifndef USC_MOCK_DBUS_SCREEN_OBSERER_H_ |
1245 | +#define USC_MOCK_DBUS_SCREEN_OBSERER_H_ |
1246 | + |
1247 | +#include "src/dbus_screen_observer.h" |
1248 | + |
1249 | +#include <gmock/gmock.h> |
1250 | + |
1251 | +class MockDBusScreenObserver : public DBusScreenObserver |
1252 | +{ |
1253 | +public: |
1254 | + MOCK_METHOD2(set_screen_power_mode, void(MirPowerMode, PowerStateChangeReason)); |
1255 | + MOCK_METHOD1(toggle_screen_power_mode, void(PowerStateChangeReason)); |
1256 | + MOCK_METHOD1(keep_display_on, void(bool)); |
1257 | + MOCK_METHOD1(set_brightness, void(int)); |
1258 | + MOCK_METHOD1(enable_auto_brightness, void(bool)); |
1259 | + MOCK_METHOD2(set_inactivity_timeouts, void(int, int)); |
1260 | + MOCK_METHOD1(set_touch_visualization_enabled, void(bool)); |
1261 | +}; |
1262 | + |
1263 | +#endif |
1264 | |
1265 | === added file 'tests/unit-tests/test_powerkey_handler.cpp' |
1266 | --- tests/unit-tests/test_powerkey_handler.cpp 1970-01-01 00:00:00 +0000 |
1267 | +++ tests/unit-tests/test_powerkey_handler.cpp 2014-11-06 10:16:42 +0000 |
1268 | @@ -0,0 +1,366 @@ |
1269 | +/* |
1270 | + * Copyright © 2014 Canonical Ltd. |
1271 | + * |
1272 | + * This program is free software: you can redistribute it and/or modify |
1273 | + * it under the terms of the GNU General Public License version 3 as |
1274 | + * published by the Free Software Foundation. |
1275 | + * |
1276 | + * This program is distributed in the hope that it will be useful, |
1277 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1278 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1279 | + * GNU General Public License for more details. |
1280 | + * |
1281 | + * You should have received a copy of the GNU General Public License |
1282 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1283 | + * |
1284 | + * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com> |
1285 | + */ |
1286 | + |
1287 | +#include "src/powerkey_handler.h" |
1288 | +#include "src/powerkey_state_listener.h" |
1289 | +#include "mir/time/alarm.h" |
1290 | +#include "mir/time/timer.h" |
1291 | + |
1292 | +#include "gmock-fixes.h" |
1293 | +#include <gtest/gtest.h> |
1294 | + |
1295 | +namespace mti = mir::time; |
1296 | + |
1297 | +class MockAlarm : public mir::time::Alarm |
1298 | +{ |
1299 | +public: |
1300 | + std::function<void()> callback; |
1301 | + |
1302 | + MOCK_METHOD0(cancel,bool()); |
1303 | + MOCK_CONST_METHOD0(state, State()); |
1304 | + MOCK_METHOD1(reschedule_in, bool(std::chrono::milliseconds)); |
1305 | + MOCK_METHOD1(reschedule_for, bool(mti::Timestamp)); |
1306 | +}; |
1307 | + |
1308 | +class MockTimer : public mti::Timer |
1309 | +{ |
1310 | +public: |
1311 | + MOCK_METHOD2(notify_in, |
1312 | + std::unique_ptr<mti::Alarm>(std::chrono::milliseconds, |
1313 | + std::function<void()>)); |
1314 | + MOCK_METHOD2(notify_at, std::unique_ptr<mti::Alarm>(mti::Timestamp, |
1315 | + std::function<void()>)); |
1316 | + MOCK_METHOD1(create_alarm, std::unique_ptr<mti::Alarm>(std::function<void()>)); |
1317 | +}; |
1318 | + |
1319 | +class MockPowerKeyStateListener : public usc::PowerKeyStateListener |
1320 | +{ |
1321 | +public: |
1322 | + MOCK_METHOD0(power_key_down,void()); |
1323 | + MOCK_METHOD0(power_key_short, void()); |
1324 | + MOCK_METHOD0(power_key_long, void()); |
1325 | + MOCK_METHOD0(power_key_very_long, void()); |
1326 | + MOCK_METHOD0(power_key_up, void()); |
1327 | +}; |
1328 | + |
1329 | +class TestPowerKeyHandler : public ::testing::Test |
1330 | +{ |
1331 | +public: |
1332 | + TestPowerKeyHandler() |
1333 | + { |
1334 | + using namespace ::testing; |
1335 | + ON_CALL(mock_timer,create_alarm(_)) |
1336 | + .WillByDefault(Invoke([this](std::function<void()> callback) -> std::unique_ptr<mti::Alarm> |
1337 | + {return create_alarm(callback);} ) |
1338 | + ); |
1339 | + |
1340 | + power_key_down_event.key.action = mir_key_action_down; |
1341 | + power_key_down_event.key.key_code = usc::PowerKeyHandler::POWER_KEY_CODE; |
1342 | + |
1343 | + power_key_up_event.key.action = mir_key_action_up; |
1344 | + power_key_up_event.key.key_code = usc::PowerKeyHandler::POWER_KEY_CODE; |
1345 | + |
1346 | + non_power_key.key.action = mir_key_action_down; |
1347 | + non_power_key.key.key_code = usc::PowerKeyHandler::POWER_KEY_CODE + 1; |
1348 | + } |
1349 | + |
1350 | + std::unique_ptr<mti::Alarm> create_alarm(std::function<void()> callback) |
1351 | + { |
1352 | + // TODO find a better way to keep track of alarms created by KeyStateHandler |
1353 | + if (!long_timeout) |
1354 | + { |
1355 | + long_timeout = new ::testing::NiceMock<MockAlarm>; |
1356 | + long_timeout->callback = callback; |
1357 | + // potentially violating against unique_ptr here |
1358 | + return std::unique_ptr<mti::Alarm>(long_timeout); |
1359 | + } |
1360 | + if(!short_timeout) |
1361 | + { |
1362 | + short_timeout = new ::testing::NiceMock<MockAlarm>; |
1363 | + short_timeout->callback = callback; |
1364 | + // potentially violating against unique_ptr here |
1365 | + return std::unique_ptr<mti::Alarm>(short_timeout); |
1366 | + } |
1367 | + return nullptr; |
1368 | + } |
1369 | + |
1370 | + ::testing::NiceMock<MockAlarm> * short_timeout = nullptr; |
1371 | + ::testing::NiceMock<MockAlarm> * long_timeout = nullptr; |
1372 | + ::testing::NiceMock<MockTimer> mock_timer; |
1373 | + ::testing::NiceMock<MockPowerKeyStateListener> mock_key_state_listener; |
1374 | + |
1375 | + std::chrono::milliseconds short_delay{1}; |
1376 | + std::chrono::milliseconds long_delay{2}; |
1377 | + std::chrono::milliseconds zero_timeout{0}; |
1378 | + |
1379 | + MirEvent power_key_down_event{ mir_event_type_key }; |
1380 | + MirEvent power_key_up_event{ mir_event_type_key }; |
1381 | + MirEvent non_power_key{ mir_event_type_key }; |
1382 | +}; |
1383 | + |
1384 | +TEST_F(TestPowerKeyHandler, creates_two_alarms) |
1385 | +{ |
1386 | + using namespace ::testing; |
1387 | + EXPECT_CALL(mock_timer,create_alarm(_)).Times(2); |
1388 | + usc::PowerKeyHandler key_handler(mock_timer, short_delay, long_delay, {&mock_key_state_listener}); |
1389 | +} |
1390 | + |
1391 | +TEST_F(TestPowerKeyHandler, schedules_timers_on_power_key_down) |
1392 | +{ |
1393 | + usc::PowerKeyHandler key_handler(mock_timer, short_delay, long_delay, {&mock_key_state_listener}); |
1394 | + |
1395 | + EXPECT_CALL(*short_timeout,reschedule_in(short_delay)).Times(1); |
1396 | + EXPECT_CALL(*long_timeout,reschedule_in(long_delay)).Times(1); |
1397 | + |
1398 | + key_handler.handle(power_key_down_event); |
1399 | +} |
1400 | + |
1401 | +TEST_F(TestPowerKeyHandler, re_schedules_and_cancel_timers) |
1402 | +{ |
1403 | + using namespace ::testing; |
1404 | + usc::PowerKeyHandler key_handler(mock_timer, short_delay, long_delay, {&mock_key_state_listener}); |
1405 | + |
1406 | + Sequence s; |
1407 | + EXPECT_CALL(*short_timeout,reschedule_in(short_delay)).InSequence(s); |
1408 | + EXPECT_CALL(*long_timeout,reschedule_in(long_delay)).InSequence(s); |
1409 | + EXPECT_CALL(*long_timeout,cancel()).InSequence(s); |
1410 | + EXPECT_CALL(*short_timeout,cancel()).InSequence(s); |
1411 | + EXPECT_CALL(*short_timeout,reschedule_in(short_delay)).InSequence(s); |
1412 | + EXPECT_CALL(*long_timeout,reschedule_in(long_delay)).InSequence(s); |
1413 | + EXPECT_CALL(*long_timeout,cancel()).InSequence(s); |
1414 | + EXPECT_CALL(*short_timeout,cancel()).InSequence(s); |
1415 | + EXPECT_CALL(*short_timeout,reschedule_in(short_delay)).InSequence(s); |
1416 | + EXPECT_CALL(*long_timeout,reschedule_in(long_delay)).InSequence(s); |
1417 | + EXPECT_CALL(*long_timeout,cancel()).InSequence(s); |
1418 | + EXPECT_CALL(*short_timeout,cancel()).InSequence(s); |
1419 | + |
1420 | + key_handler.handle(power_key_down_event); |
1421 | + key_handler.handle(power_key_up_event); |
1422 | + key_handler.handle(power_key_down_event); |
1423 | + key_handler.handle(power_key_up_event); |
1424 | + key_handler.handle(power_key_down_event); |
1425 | + key_handler.handle(power_key_up_event); |
1426 | +} |
1427 | + |
1428 | +TEST_F(TestPowerKeyHandler, never_filters_key_events) |
1429 | +{ |
1430 | + using namespace testing; |
1431 | + usc::PowerKeyHandler key_handler(mock_timer, short_delay, long_delay, {&mock_key_state_listener}); |
1432 | + |
1433 | + EXPECT_THAT(key_handler.handle(power_key_down_event), Eq(false)); |
1434 | + EXPECT_THAT(key_handler.handle(power_key_up_event), Eq(false)); |
1435 | + EXPECT_THAT(key_handler.handle(non_power_key), Eq(false)); |
1436 | +} |
1437 | + |
1438 | +TEST_F(TestPowerKeyHandler, cancels_timers_on_power_key_up) |
1439 | +{ |
1440 | + usc::PowerKeyHandler key_handler(mock_timer, short_delay, long_delay, {&mock_key_state_listener}); |
1441 | + |
1442 | + EXPECT_CALL(*long_timeout,cancel()).Times(1); |
1443 | + EXPECT_CALL(*short_timeout,cancel()).Times(1); |
1444 | + |
1445 | + key_handler.handle(power_key_down_event); |
1446 | + key_handler.handle(power_key_up_event); |
1447 | +} |
1448 | + |
1449 | +TEST_F(TestPowerKeyHandler, throws_on_wrong_timeouts) |
1450 | +{ |
1451 | + EXPECT_THROW({ |
1452 | + usc::PowerKeyHandler key_handler(mock_timer, long_delay, short_delay, {&mock_key_state_listener}); |
1453 | + }, std::invalid_argument); |
1454 | +} |
1455 | + |
1456 | +TEST_F(TestPowerKeyHandler, ignores_spurious_up_down_events) |
1457 | +{ |
1458 | + using namespace ::testing; |
1459 | + usc::PowerKeyHandler key_handler(mock_timer, short_delay, long_delay, {&mock_key_state_listener}); |
1460 | + |
1461 | + Sequence seq; |
1462 | + |
1463 | + EXPECT_CALL(*short_timeout,reschedule_in(short_delay)) |
1464 | + .InSequence(seq); |
1465 | + EXPECT_CALL(*long_timeout,reschedule_in(long_delay)) |
1466 | + .InSequence(seq); |
1467 | + EXPECT_CALL(*long_timeout,cancel()) |
1468 | + .InSequence(seq); |
1469 | + EXPECT_CALL(*short_timeout,cancel()) |
1470 | + .InSequence(seq); |
1471 | + |
1472 | + key_handler.handle(power_key_down_event); |
1473 | + key_handler.handle(power_key_down_event); |
1474 | + key_handler.handle(power_key_down_event); |
1475 | + key_handler.handle(power_key_up_event); |
1476 | + key_handler.handle(power_key_up_event); |
1477 | + key_handler.handle(power_key_up_event); |
1478 | +} |
1479 | + |
1480 | +TEST_F(TestPowerKeyHandler, forwards_down_events_to_key_state_listener) |
1481 | +{ |
1482 | + usc::PowerKeyHandler key_handler(mock_timer, short_delay, long_delay, {&mock_key_state_listener}); |
1483 | + |
1484 | + EXPECT_CALL(mock_key_state_listener, power_key_down()); |
1485 | + key_handler.handle(power_key_down_event); |
1486 | +} |
1487 | + |
1488 | +TEST_F(TestPowerKeyHandler, forwards_up_events_to_key_state_listener) |
1489 | +{ |
1490 | + usc::PowerKeyHandler key_handler(mock_timer, short_delay, long_delay, {&mock_key_state_listener}); |
1491 | + |
1492 | + EXPECT_CALL(mock_key_state_listener, power_key_up()); |
1493 | + key_handler.handle(power_key_down_event); |
1494 | + key_handler.handle(power_key_up_event); |
1495 | +} |
1496 | + |
1497 | +TEST_F(TestPowerKeyHandler, down_short_up_up_comes_in_sequence) |
1498 | +{ |
1499 | + using namespace ::testing; |
1500 | + usc::PowerKeyHandler key_handler(mock_timer, short_delay, long_delay, {&mock_key_state_listener}); |
1501 | + |
1502 | + Sequence s; |
1503 | + |
1504 | + EXPECT_CALL(mock_key_state_listener, power_key_down()).InSequence(s); |
1505 | + EXPECT_CALL(mock_key_state_listener, power_key_short()).InSequence(s); |
1506 | + EXPECT_CALL(mock_key_state_listener, power_key_up()).InSequence(s); |
1507 | + key_handler.handle(power_key_down_event); |
1508 | + key_handler.handle(power_key_up_event); |
1509 | +} |
1510 | + |
1511 | +TEST_F(TestPowerKeyHandler, down_long_up_comes_in_sequence) |
1512 | +{ |
1513 | + using namespace ::testing; |
1514 | + usc::PowerKeyHandler key_handler(mock_timer, short_delay, long_delay, {&mock_key_state_listener}); |
1515 | + |
1516 | + Sequence s; |
1517 | + |
1518 | + EXPECT_CALL(mock_key_state_listener, power_key_down()).InSequence(s); |
1519 | + EXPECT_CALL(mock_key_state_listener, power_key_long()).InSequence(s); |
1520 | + EXPECT_CALL(mock_key_state_listener, power_key_up()).InSequence(s); |
1521 | + |
1522 | + key_handler.handle(power_key_down_event); |
1523 | + short_timeout->callback(); |
1524 | + key_handler.handle(power_key_up_event); |
1525 | +} |
1526 | + |
1527 | +TEST_F(TestPowerKeyHandler, down_very_long_up_comes_in_sequence) |
1528 | +{ |
1529 | + using namespace ::testing; |
1530 | + usc::PowerKeyHandler key_handler(mock_timer, short_delay, long_delay, {&mock_key_state_listener}); |
1531 | + |
1532 | + Sequence s; |
1533 | + |
1534 | + EXPECT_CALL(mock_key_state_listener, power_key_down()).InSequence(s); |
1535 | + EXPECT_CALL(mock_key_state_listener, power_key_long()).InSequence(s); |
1536 | + EXPECT_CALL(mock_key_state_listener, power_key_very_long()).InSequence(s); |
1537 | + EXPECT_CALL(mock_key_state_listener, power_key_up()).InSequence(s); |
1538 | + |
1539 | + key_handler.handle(power_key_down_event); |
1540 | + short_timeout->callback(); |
1541 | + long_timeout->callback(); |
1542 | + key_handler.handle(power_key_up_event); |
1543 | +} |
1544 | + |
1545 | +TEST_F(TestPowerKeyHandler, spurious_alarm_callbacks_dont_cause_calls) |
1546 | +{ |
1547 | + using namespace ::testing; |
1548 | + usc::PowerKeyHandler key_handler(mock_timer, short_delay, long_delay, {&mock_key_state_listener}); |
1549 | + |
1550 | + Sequence s; |
1551 | + |
1552 | + EXPECT_CALL(mock_key_state_listener, power_key_down()).InSequence(s); |
1553 | + EXPECT_CALL(mock_key_state_listener, power_key_short()).InSequence(s); |
1554 | + EXPECT_CALL(mock_key_state_listener, power_key_up()).InSequence(s); |
1555 | + EXPECT_CALL(mock_key_state_listener, power_key_very_long()).Times(0); |
1556 | + EXPECT_CALL(mock_key_state_listener, power_key_long()).Times(0); |
1557 | + |
1558 | + key_handler.handle(power_key_down_event); |
1559 | + key_handler.handle(power_key_up_event); |
1560 | + |
1561 | + long_timeout->callback(); |
1562 | + long_timeout->callback(); |
1563 | + short_timeout->callback(); |
1564 | + short_timeout->callback(); |
1565 | +} |
1566 | + |
1567 | +TEST_F(TestPowerKeyHandler, spurious_alarm_callbacks_dont_cause_calls_after_first_timeout) |
1568 | +{ |
1569 | + using namespace ::testing; |
1570 | + usc::PowerKeyHandler key_handler(mock_timer, short_delay, long_delay, {&mock_key_state_listener}); |
1571 | + |
1572 | + Sequence s; |
1573 | + |
1574 | + EXPECT_CALL(mock_key_state_listener, power_key_down()).InSequence(s); |
1575 | + EXPECT_CALL(mock_key_state_listener, power_key_long()).InSequence(s); |
1576 | + EXPECT_CALL(mock_key_state_listener, power_key_up()).InSequence(s); |
1577 | + EXPECT_CALL(mock_key_state_listener, power_key_very_long()).Times(0); |
1578 | + EXPECT_CALL(mock_key_state_listener, power_key_short()).Times(0); |
1579 | + |
1580 | + key_handler.handle(power_key_down_event); |
1581 | + short_timeout->callback(); |
1582 | + key_handler.handle(power_key_up_event); |
1583 | + |
1584 | + long_timeout->callback(); |
1585 | + long_timeout->callback(); |
1586 | + short_timeout->callback(); |
1587 | + short_timeout->callback(); |
1588 | +} |
1589 | + |
1590 | +TEST_F(TestPowerKeyHandler, multiple_sequences_work) |
1591 | +{ |
1592 | + using namespace ::testing; |
1593 | + usc::PowerKeyHandler key_handler(mock_timer, short_delay, long_delay, {&mock_key_state_listener}); |
1594 | + |
1595 | + Sequence s; |
1596 | + |
1597 | + EXPECT_CALL(mock_key_state_listener, power_key_down()).InSequence(s); |
1598 | + EXPECT_CALL(mock_key_state_listener, power_key_long()).InSequence(s); |
1599 | + EXPECT_CALL(mock_key_state_listener, power_key_up()).InSequence(s); |
1600 | + |
1601 | + EXPECT_CALL(mock_key_state_listener, power_key_down()).InSequence(s); |
1602 | + EXPECT_CALL(mock_key_state_listener, power_key_short()).InSequence(s); |
1603 | + EXPECT_CALL(mock_key_state_listener, power_key_up()).InSequence(s); |
1604 | + |
1605 | + EXPECT_CALL(mock_key_state_listener, power_key_down()).InSequence(s); |
1606 | + EXPECT_CALL(mock_key_state_listener, power_key_long()).InSequence(s); |
1607 | + EXPECT_CALL(mock_key_state_listener, power_key_very_long()).InSequence(s); |
1608 | + EXPECT_CALL(mock_key_state_listener, power_key_up()).InSequence(s); |
1609 | + |
1610 | + key_handler.handle(power_key_down_event); |
1611 | + short_timeout->callback(); |
1612 | + key_handler.handle(power_key_up_event); |
1613 | + |
1614 | + key_handler.handle(power_key_down_event); |
1615 | + key_handler.handle(power_key_up_event); |
1616 | + |
1617 | + key_handler.handle(power_key_down_event); |
1618 | + short_timeout->callback(); |
1619 | + long_timeout->callback(); |
1620 | + key_handler.handle(power_key_up_event); |
1621 | +} |
1622 | + |
1623 | +TEST_F(TestPowerKeyHandler, throws_on_zero_timeouts) |
1624 | +{ |
1625 | + using namespace ::testing; |
1626 | + EXPECT_THROW({ |
1627 | + usc::PowerKeyHandler key_handler(mock_timer, zero_timeout, long_delay, {&mock_key_state_listener}); |
1628 | + }, std::invalid_argument |
1629 | + ); |
1630 | + EXPECT_THROW({ |
1631 | + usc::PowerKeyHandler key_handler(mock_timer, short_delay, zero_timeout, {&mock_key_state_listener}); |
1632 | + }, std::invalid_argument |
1633 | + ); |
1634 | +} |
1635 | |
1636 | === added file 'tests/unit-tests/test_powerkey_mediator.cpp' |
1637 | --- tests/unit-tests/test_powerkey_mediator.cpp 1970-01-01 00:00:00 +0000 |
1638 | +++ tests/unit-tests/test_powerkey_mediator.cpp 2014-11-06 10:16:42 +0000 |
1639 | @@ -0,0 +1,138 @@ |
1640 | +/* |
1641 | + * Copyright © 2014 Canonical Ltd. |
1642 | + * |
1643 | + * This program is free software: you can redistribute it and/or modify |
1644 | + * it under the terms of the GNU General Public License version 3 as |
1645 | + * published by the Free Software Foundation. |
1646 | + * |
1647 | + * This program is distributed in the hope that it will be useful, |
1648 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1649 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1650 | + * GNU General Public License for more details. |
1651 | + * |
1652 | + * You should have received a copy of the GNU General Public License |
1653 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1654 | + * |
1655 | + * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com> |
1656 | + */ |
1657 | + |
1658 | +#include "src/powerkey_mediator.h" |
1659 | +#include "src/inactivty_tracker.h" |
1660 | +#include "src/power_state_change_reason.h" |
1661 | +#include "src/system.h" |
1662 | + |
1663 | +#include "mock_dbus_screen_observer.h" |
1664 | + |
1665 | +#include <gmock/gmock.h> |
1666 | +#include <gtest/gtest.h> |
1667 | + |
1668 | +class MockInactivityTracker : public InactivtyTracker |
1669 | +{ |
1670 | +public: |
1671 | + MOCK_METHOD1(enable_inactivity_timers, void(bool)); |
1672 | +}; |
1673 | + |
1674 | +class MockSystem : public System |
1675 | +{ |
1676 | +public: |
1677 | + MOCK_METHOD0(shutdown,void()); |
1678 | +}; |
1679 | + |
1680 | +class PowerKeyMediatorTest : public ::testing::Test |
1681 | +{ |
1682 | +public: |
1683 | + ::testing::NiceMock<MockInactivityTracker> mock_tracker; |
1684 | + ::testing::NiceMock<MockDBusScreenObserver> mock_screen_observer; |
1685 | + ::testing::NiceMock<MockSystem> mock_system; |
1686 | + usc::PowerKeyMediator key_mediator{mock_screen_observer, mock_tracker, mock_system}; |
1687 | +}; |
1688 | + |
1689 | +TEST_F(PowerKeyMediatorTest, power_key_down_disables_inactivity_timers) |
1690 | +{ |
1691 | + EXPECT_CALL(mock_tracker, enable_inactivity_timers(false)).Times(3); |
1692 | + |
1693 | + key_mediator.power_key_down(); |
1694 | + key_mediator.power_key_short(); |
1695 | + key_mediator.power_key_up(); |
1696 | + |
1697 | + key_mediator.power_key_down(); |
1698 | + key_mediator.power_key_long(); |
1699 | + key_mediator.power_key_up(); |
1700 | + |
1701 | + key_mediator.power_key_down(); |
1702 | + key_mediator.power_key_very_long(); |
1703 | + key_mediator.power_key_up(); |
1704 | +} |
1705 | + |
1706 | +TEST_F(PowerKeyMediatorTest, power_key_short_sequence_toggles_screen_power_state) |
1707 | +{ |
1708 | + EXPECT_CALL(mock_screen_observer, toggle_screen_power_mode(PowerStateChangeReason::power_key)); |
1709 | + |
1710 | + key_mediator.power_key_down(); |
1711 | + key_mediator.power_key_short(); |
1712 | + key_mediator.power_key_up(); |
1713 | +} |
1714 | + |
1715 | +TEST_F(PowerKeyMediatorTest, power_key_long_sequence_forces_power_on_screen_state) |
1716 | +{ |
1717 | + EXPECT_CALL(mock_screen_observer, set_screen_power_mode( |
1718 | + MirPowerMode::mir_power_mode_on, PowerStateChangeReason::power_key)); |
1719 | + |
1720 | + key_mediator.power_key_down(); |
1721 | + key_mediator.power_key_long(); |
1722 | + key_mediator.power_key_up(); |
1723 | +} |
1724 | + |
1725 | +TEST_F(PowerKeyMediatorTest, power_key_very_long_sequence_forces_power_off_screen_state_and_shutdown) |
1726 | +{ |
1727 | + EXPECT_CALL(mock_screen_observer, set_screen_power_mode( |
1728 | + MirPowerMode::mir_power_mode_off, PowerStateChangeReason::power_key)); |
1729 | + EXPECT_CALL(mock_system,shutdown()); |
1730 | + |
1731 | + key_mediator.power_key_down(); |
1732 | + key_mediator.power_key_very_long(); |
1733 | + key_mediator.power_key_up(); |
1734 | +} |
1735 | + |
1736 | +TEST_F(PowerKeyMediatorTest, screen_toggle_can_be_deactivated) |
1737 | +{ |
1738 | + EXPECT_CALL(mock_screen_observer, toggle_screen_power_mode(PowerStateChangeReason::power_key)) |
1739 | + .Times(0); |
1740 | + |
1741 | + key_mediator.disable_screen_toggle(); |
1742 | + |
1743 | + key_mediator.power_key_down(); |
1744 | + key_mediator.power_key_short(); |
1745 | + key_mediator.power_key_up(); |
1746 | +} |
1747 | + |
1748 | +TEST_F(PowerKeyMediatorTest, screen_toggle_can_be_deactivated_during_key_down) |
1749 | +{ |
1750 | + EXPECT_CALL(mock_screen_observer, toggle_screen_power_mode(PowerStateChangeReason::power_key)) |
1751 | + .Times(0); |
1752 | + |
1753 | + key_mediator.power_key_down(); |
1754 | + |
1755 | + key_mediator.disable_screen_toggle(); |
1756 | + |
1757 | + key_mediator.power_key_short(); |
1758 | + key_mediator.power_key_up(); |
1759 | +} |
1760 | + |
1761 | +TEST_F(PowerKeyMediatorTest, screen_toggle_can_be_reactivated) |
1762 | +{ |
1763 | + EXPECT_CALL(mock_screen_observer, toggle_screen_power_mode(PowerStateChangeReason::power_key)) |
1764 | + .Times(1); |
1765 | + |
1766 | + key_mediator.disable_screen_toggle(); |
1767 | + |
1768 | + key_mediator.power_key_down(); |
1769 | + key_mediator.power_key_short(); |
1770 | + key_mediator.power_key_up(); |
1771 | + |
1772 | + key_mediator.enable_screen_toggle(); |
1773 | + |
1774 | + key_mediator.power_key_down(); |
1775 | + key_mediator.power_key_short(); |
1776 | + key_mediator.power_key_up(); |
1777 | +} |
PASSED: Continuous integration, rev:190 jenkins. qa.ubuntu. com/job/ unity-system- compositor- ci/164/ jenkins. qa.ubuntu. com/job/ unity-system- compositor- vivid-amd64- ci/1 jenkins. qa.ubuntu. com/job/ unity-system- compositor- vivid-armhf- ci/1
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/unity- system- compositor- ci/164/ rebuild
http://