Merge lp:~andreas-pokorny/unity-system-compositor/expose-powerkey-state-and-screen-toggle-controller-interface into lp:unity-system-compositor

Proposed by Andreas Pokorny
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
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 enablePowerModeToggle, disablePowerModeToggle and power key signals to com.canonical.Unity.Screen

Description of the change

Adds two new interface parts to com.canonical.Unity.Screen:

DBus methods for controlling wither power button toggles screen power mode:
  * enablePowerModeToggle
  * disablePowerModeToggle

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.

To post a comment you must log in.
191. By Andreas Pokorny

Remove debug output

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alberto Aguirre (albaguirre) wrote :

DBus methods for controlling wither power button toggles screen power mode:
  * enablePowerModeToggle
  * disablePowerModeToggle

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.

review: Needs Information
Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

> DBus methods for controlling wither power button toggles screen power mode:
> * enablePowerModeToggle
> * disablePowerModeToggle
>
> 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.

Revision history for this message
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

Revision history for this message
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.

Revision history for this message
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_event_handler.cpp
Text conflict in src/screen_event_handler.h
Text conflict in src/system_compositor.cpp
Text conflict in src/system_compositor.h
Text conflict in tests/unit-tests/CMakeLists.txt
10 conflicts encountered.

review: Needs Fixing

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

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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+}

Subscribers

People subscribed via source and target branches