Merge lp:~albaguirre/unity-system-compositor/screen-power-state-handling into lp:unity-system-compositor

Proposed by Alberto Aguirre on 2014-04-03
Status: Merged
Approved by: kevin gunn on 2014-06-25
Approved revision: 157
Merged at revision: 143
Proposed branch: lp:~albaguirre/unity-system-compositor/screen-power-state-handling
Merge into: lp:unity-system-compositor
Diff against target: 1359 lines (+1057/-84)
16 files modified
debian/changelog (+6/-0)
debian/control (+1/-0)
src/CMakeLists.txt (+5/-0)
src/com.canonical.Unity.Screen.conf (+4/-0)
src/dbus_screen.cpp (+119/-58)
src/dbus_screen.h (+28/-16)
src/dbus_screen_observer.h (+38/-0)
src/power_state_change_reason.h (+28/-0)
src/powerd_mediator.cpp (+236/-0)
src/powerd_mediator.h (+87/-0)
src/powerkey_handler.cpp (+84/-0)
src/powerkey_handler.h (+69/-0)
src/screen_state_handler.cpp (+201/-0)
src/screen_state_handler.h (+92/-0)
src/system_compositor.cpp (+55/-10)
src/system_compositor.h (+4/-0)
To merge this branch: bzr merge lp:~albaguirre/unity-system-compositor/screen-power-state-handling
Reviewer Review Type Date Requested Status
Michael Terry (community) Approve on 2014-06-25
PS Jenkins bot (community) continuous-integration Approve on 2014-06-25
Ricardo Mendoza (community) 2014-04-03 Approve on 2014-06-25
Ricardo Salveti (community) Needs Information on 2014-06-18
Review via email: mp+213957@code.launchpad.net

Commit message

Migrate display power state handling from powerd to usc

Description of the change

Migrate display power state handling from powerd to usc

This is mainly an effort to remove all input event processing from powerd. Since the mir server already handles input and manages display power states - any screen power state or inactivity timer logic is better suited to reside in USC.

Depends on:
https://code.launchpad.net/~albaguirre/powerd/remove-input-inactivity-handling/+merge/219449

To post a comment you must log in.
Ricardo Salveti (rsalveti) wrote :

MR that exports the dim value:
https://code.launchpad.net/~rsalveti/powerd/export_dim_brightness_value/+merge/216805

To land this MR, besides the need of another clean-up in powerd (to remove the screen states), we also need a clear way for the apps to request something similar to the powerd display state (probably just asking display to be on/off). Do you know if we already have a dbus interface for that?

We also need to coordinate and land changes for all apps that are currently using the powerd requestDisplayState dbus api, as that will be removed as well.

Alberto Aguirre (albaguirre) wrote :

"we also need a clear way for the apps to request something similar to the powerd display state (probably just asking display to be on/off). Do you know if we already have a dbus interface for that?"

This MR keeps the com.canonical.Unity.Screen setScreenPowerMode Dbus interface to turn on/off the display.

128. By Alberto Aguirre on 2014-04-25

Use powerd's dim value now that is exposed

Ricardo Mendoza (ricmm) wrote :

As mentioned in the email, we need to sync with Unity8 regarding long-press for the power button, as this MR as-is would always turn off on power key up.

Also introduced conflict text in:

715 +<<<<<<< TREE
716 ("public-socket", po::value<bool>(), "Make the socket file publicly writable")
717 ("power-off-delay", po::value<int>(), "Delay in milliseconds before powering off screen [int]")
718 ("enable-hardware-cursor", po::value<bool>(), "Enable the hardware cursor (disabled by default)");
719 +=======
720 + ("power-off-timeout", po::value<int>(), "The time in seconds before the screen is turned off when there are no active sessions")
721 + ("dimmer-timeout", po::value<int>(), "The time in seconds before the screen is dimmed when there are no active sessions")
722 + ("public-socket", po::value<bool>(), "Make the socket file publicly writable");
723 +>>>>>>> MERGE-SOURCE

review: Needs Information
129. By Alberto Aguirre on 2014-05-02

merge main branch

130. By Alberto Aguirre on 2014-05-02

merge main branch

131. By Alberto Aguirre on 2014-05-13

Use mir timer support

Cleanup ScreenStateHandler
Make ScreenStateHandler state changes thread safe
Add long power key press detection
Emit DBus signal during after detecting long power press

Alberto Aguirre (albaguirre) wrote :

> As mentioned in the email, we need to sync with Unity8 regarding long-press
> for the power button, as this MR as-is would always turn off on power key up.
>
> Also introduced conflict text in:
>

Fixed the conflicts and implemented the long-press detection.

132. By Alberto Aguirre on 2014-05-21

Remove emitting signal on long press of power key
Change default timeout for long press detection of power key to 5secs
Initiate a system shutdown when detecting long press of power key
Emit and accept reasons for display power state changes

133. By Alberto Aguirre on 2014-05-21

Reset backlight to normal brightness when screen is already on and a power on state change is requested

134. By Alberto Aguirre on 2014-05-21

Remove powerkey dbus conf install step

135. By Alberto Aguirre on 2014-05-21

Remove power key dbus conf install from debin install rules

136. By Alberto Aguirre on 2014-05-21

Add headers to source list

137. By Alberto Aguirre on 2014-05-28

Avoid turning off display when power key is held on a short time.

The shell may want to show a dialog under such conditions.

138. By Alberto Aguirre on 2014-05-30

Add support for keeping display on

139. By Alberto Aguirre on 2014-06-16

merge trunk

140. By Alberto Aguirre on 2014-06-16

Add console dbus access policy as in powerd

141. By Alberto Aguirre on 2014-06-16

Add some logging

142. By Alberto Aguirre on 2014-06-17

Proxy brightness and auto brightness parameters.

143. By Alberto Aguirre on 2014-06-17

fix auto_brightness state machine

144. By Alberto Aguirre on 2014-06-17

Change default inactivity timeouts

145. By Alberto Aguirre on 2014-06-17

Refactor backlight state machine

146. By Alberto Aguirre on 2014-06-17

Turn on screen when a keepDisplayOn request is received

147. By Alberto Aguirre on 2014-06-17

Reset timers when changing timeout values.

Ricardo Salveti (rsalveti) wrote :

Comments inline.

review: Needs Information
Alberto Aguirre (albaguirre) wrote :

Responded to inline comment.

148. By Alberto Aguirre on 2014-06-19

merge trunk

149. By Alberto Aguirre on 2014-06-19

Use new create_alarm api

150. By Alberto Aguirre on 2014-06-19

Only start compositor when turning on screen.

With the new swap unblock solution in mir, its no longer necessary to start the compositor while the screen is off.

151. By Alberto Aguirre on 2014-06-19

Add powerd to Recommends

152. By Alberto Aguirre on 2014-06-20

merge trunk - fix simple conflict

153. By Alberto Aguirre on 2014-06-20

Update changelog

154. By Alberto Aguirre on 2014-06-23

Turn off screen during clean shutdown

155. By Alberto Aguirre on 2014-06-24

Add dbus watcher to wait for powerd to become available if its DBus interface is not available when usc starts.

Ricardo Mendoza (ricmm) wrote :

Looks fine for me so far, I dont see any obvious issues in the code. Works as expected on device.

review: Approve
Michael Terry (mterry) wrote :

I didn't test all the features, since this has already been reviewed. But I wanted to give a few cents, comments inline using this fancy new LP feature.

156. By Alberto Aguirre on 2014-06-25

Rename is_invalid_reason to avoid double negatives.

157. By Alberto Aguirre on 2014-06-25

Always watch for powerd interface restart

Michael Terry (mterry) wrote :

Looks good to me, thanks!

review: Approve

Preview Diff

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

Subscribers

People subscribed via source and target branches