Merge lp:~3v1n0/unity/lockscreen-power-keys into lp:unity

Proposed by Marco Trevisan (Treviño) on 2014-05-16
Status: Merged
Approved by: Stephen M. Webb on 2014-06-18
Approved revision: 3818
Merged at revision: 3828
Proposed branch: lp:~3v1n0/unity/lockscreen-power-keys
Merge into: lp:unity
Prerequisite: lp:~brandontschaefer/unity/shutdown-dialog-hi-dpi
Diff against target: 701 lines (+225/-66)
14 files modified
UnityCore/GnomeSessionManager.cpp (+62/-14)
UnityCore/GnomeSessionManager.h (+2/-0)
UnityCore/GnomeSessionManagerImpl.h (+1/-0)
UnityCore/SessionManager.h (+3/-0)
lockscreen/LockScreenAcceleratorController.cpp (+46/-2)
lockscreen/LockScreenAcceleratorController.h (+2/-1)
lockscreen/LockScreenController.cpp (+3/-3)
shutdown/SessionDBusManager.cpp (+23/-9)
shutdown/SessionView.cpp (+49/-30)
shutdown/SessionView.h (+6/-5)
shutdown/StandaloneSession.cpp (+2/-0)
tests/test_mock_session_manager.h (+2/-0)
tests/test_session_controller.cpp (+1/-0)
tests/test_session_view.cpp (+23/-2)
To merge this branch: bzr merge lp:~3v1n0/unity/lockscreen-power-keys
Reviewer Review Type Date Requested Status
Stephen M. Webb (community) Approve on 2014-06-18
PS Jenkins bot (community) continuous-integration Needs Fixing on 2014-06-18
Christopher Townsend 2014-05-16 Approve on 2014-05-16
Review via email: mp+219778@code.launchpad.net

Commit message

LockScreenAcceleratorController: do ther configured action on power special keys press

We finally can suspend, shutdown, hibernate or start the screensaver when the screen is locked, using
the Suspend, Sleep, Hibernate and PowerOff hardware keys.

Also the Shutdown dialog doesn't allow now to lock the session if it is not allowed by settings.

To post a comment you must log in.
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Christopher Townsend (townsend) wrote :

LGTM

Christopher Townsend (townsend) wrote :

Oops, meant to approve

review: Approve
Stephen M. Webb (bregma) wrote :

Merge conflicts when attempting to merge to trunk.

Text conflict in lockscreen/LockScreenController.cpp
Text conflict in shutdown/SessionView.cpp
2 conflicts encountered.

review: Needs Fixing
3818. By Marco Trevisan (Treviño) on 2014-06-18

Merging with trunk

PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Stephen M. Webb (bregma) wrote :

OK, merges cleanly now

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'UnityCore/GnomeSessionManager.cpp'
2--- UnityCore/GnomeSessionManager.cpp 2014-04-16 22:03:41 +0000
3+++ UnityCore/GnomeSessionManager.cpp 2014-06-18 15:11:36 +0000
4@@ -91,6 +91,11 @@
5 shell_object_ = shell_server_.GetObject(shell::DBUS_INTERFACE);
6 shell_object_->SetMethodsCallsHandler(sigc::mem_fun(this, &Impl::OnShellMethodCall));
7
8+ manager_->is_locked = false;
9+ manager_->is_locked.changed.connect([this] (bool locked) {
10+ locked ? manager_->locked.emit() : manager_->unlocked.emit();
11+ });
12+
13 {
14 const char* session_id = test_mode_ ? "id0" : g_getenv("XDG_SESSION_ID");
15
16@@ -421,21 +426,13 @@
17 {
18 EnsureCancelPendingAction();
19
20+ if (!manager_->CanLock())
21+ {
22+ manager_->ScreenSaverActivate();
23+ return;
24+ }
25+
26 // FIXME (andy) we should ask gnome-session to emit the logind signal
27- glib::Object<GSettings> lockdown_settings(g_settings_new(GNOME_LOCKDOWN_OPTIONS.c_str()));
28-
29- if (g_settings_get_boolean(lockdown_settings, DISABLE_LOCKSCREEN_KEY.c_str()))
30- {
31- manager_->ScreenSaverActivate();
32- return;
33- }
34- else if (manager_->UserName().find("guest-") == 0)
35- {
36- LOG_INFO(logger) << "Impossible to lock a guest session";
37- manager_->ScreenSaverActivate();
38- return;
39- }
40-
41 prompt ? manager_->prompt_lock_requested.emit() : manager_->lock_requested.emit();
42 }
43
44@@ -454,6 +451,39 @@
45 });
46 }
47
48+bool GnomeManager::Impl::HasInhibitors()
49+{
50+ glib::Error error;
51+ glib::Object<GDBusConnection> bus(g_bus_get_sync(G_BUS_TYPE_SESSION, nullptr, &error));
52+
53+ if (error)
54+ {
55+ LOG_ERROR(logger) << "Impossible to get the session bus, to fetch the inhibitors: " << error;
56+ return false;
57+ }
58+
59+ enum class Inhibited : unsigned
60+ {
61+ LOGOUT = 1,
62+ USER_SWITCH = 2,
63+ SUSPEND = 4,
64+ IDLE_SET = 8
65+ };
66+
67+ glib::Variant inhibitors(g_dbus_connection_call_sync(bus, test_mode_ ? testing::DBUS_NAME.c_str() : "org.gnome.SessionManager",
68+ "/org/gnome/SessionManager", "org.gnome.SessionManager",
69+ "IsInhibited", g_variant_new("(u)", Inhibited::LOGOUT), nullptr,
70+ G_DBUS_CALL_FLAGS_NONE, 500, nullptr, &error));
71+
72+ if (error)
73+ {
74+ LOG_ERROR(logger) << "Impossible to get the inhibitors: " << error;
75+ return false;
76+ }
77+
78+ return inhibitors.GetBool();
79+}
80+
81 // Public implementation
82
83 GnomeManager::GnomeManager()
84@@ -617,6 +647,19 @@
85 });
86 }
87
88+bool GnomeManager::CanLock() const
89+{
90+ glib::Object<GSettings> lockdown_settings(g_settings_new(GNOME_LOCKDOWN_OPTIONS.c_str()));
91+
92+ if (g_settings_get_boolean(lockdown_settings, DISABLE_LOCKSCREEN_KEY.c_str()) ||
93+ UserName().find("guest-") == 0 || is_locked())
94+ {
95+ return false;
96+ }
97+
98+ return true;
99+}
100+
101 bool GnomeManager::CanShutdown() const
102 {
103 return impl_->can_shutdown_;
104@@ -632,6 +675,11 @@
105 return impl_->can_hibernate_;
106 }
107
108+bool GnomeManager::HasInhibitors() const
109+{
110+ return impl_->HasInhibitors();
111+}
112+
113 void GnomeManager::CancelAction()
114 {
115 impl_->CancelAction();
116
117=== modified file 'UnityCore/GnomeSessionManager.h'
118--- UnityCore/GnomeSessionManager.h 2014-04-10 04:47:58 +0000
119+++ UnityCore/GnomeSessionManager.h 2014-06-18 15:11:36 +0000
120@@ -47,9 +47,11 @@
121 void Suspend();
122 void Hibernate();
123
124+ bool CanLock() const;
125 bool CanShutdown() const;
126 bool CanSuspend() const;
127 bool CanHibernate() const;
128+ bool HasInhibitors() const;
129
130 void CancelAction();
131
132
133=== modified file 'UnityCore/GnomeSessionManagerImpl.h'
134--- UnityCore/GnomeSessionManagerImpl.h 2014-04-16 21:51:45 +0000
135+++ UnityCore/GnomeSessionManagerImpl.h 2014-06-18 15:11:36 +0000
136@@ -51,6 +51,7 @@
137 void ConfirmShutdown();
138 void CancelAction();
139 void ClosedDialog();
140+ bool HasInhibitors();
141 void EnsureCancelPendingAction();
142 void LockScreen(bool prompt);
143
144
145=== modified file 'UnityCore/SessionManager.h'
146--- UnityCore/SessionManager.h 2014-04-16 21:51:45 +0000
147+++ UnityCore/SessionManager.h 2014-06-18 15:11:36 +0000
148@@ -39,6 +39,7 @@
149 virtual ~Manager() = default;
150
151 nux::ROProperty<bool> have_other_open_sessions;
152+ nux::Property<bool> is_locked;
153
154 virtual std::string RealName() const = 0;
155 virtual std::string UserName() const = 0;
156@@ -54,9 +55,11 @@
157 virtual void Suspend() = 0;
158 virtual void Hibernate() = 0;
159
160+ virtual bool CanLock() const = 0;
161 virtual bool CanShutdown() const = 0;
162 virtual bool CanSuspend() const = 0;
163 virtual bool CanHibernate() const = 0;
164+ virtual bool HasInhibitors() const = 0;
165
166 virtual void CancelAction() = 0;
167
168
169=== modified file 'lockscreen/LockScreenAcceleratorController.cpp'
170--- lockscreen/LockScreenAcceleratorController.cpp 2014-04-28 13:09:53 +0000
171+++ lockscreen/LockScreenAcceleratorController.cpp 2014-06-18 15:11:36 +0000
172@@ -32,6 +32,17 @@
173 const char* const MEDIA_KEYS_KEY_VOLUME_MUTE = "volume-mute";
174 const char* const MEDIA_KEYS_KEY_VOLUME_DOWN = "volume-down";
175 const char* const MEDIA_KEYS_KEY_VOLUME_UP = "volume-up";
176+
177+const char* const POWER_SCHEMA = "org.gnome.settings-daemon.plugins.power";
178+const char* const SUSPEND_BUTTON_ACTION_KEY = "button-suspend";
179+const char* const SLEEP_BUTTON_ACTION_KEY = "button-sleep";
180+const char* const HIBERNATE_BUTTON_ACTION_KEY = "button-hibernate";
181+const char* const POWER_BUTTON_ACTION_KEY = "button-power";
182+const char* const POWER_KEY_SUSPEND = "XF86Suspend";
183+const char* const POWER_KEY_SLEEP = "XF86Sleep";
184+const char* const POWER_KEY_HIBERNATE = "XF86Hibernate";
185+const char* const POWER_KEY_POWEROFF = "XF86PowerOff";
186+
187 const char* const INPUT_SWITCH_SCHEMA = "org.gnome.desktop.wm.keybindings";
188 const char* const INPUT_SWITCH_KEY_PREVIOUS_SOURCE = "switch-input-source-backward";
189 const char* const INPUT_SWITCH_KEY_NEXT_SOURCE = "switch-input-source";
190@@ -89,15 +100,32 @@
191 INDICATOR_KEYBOARD_ACTION_SCROLL,
192 g_variant_new_int32(-offset));
193 }
194+
195+void PowerAction(session::Manager::Ptr const& session, const char *action_key)
196+{
197+ glib::Object<GSettings> settings(g_settings_new(POWER_SCHEMA));
198+ auto const& action = glib::String(g_settings_get_string(settings, action_key)).Str();
199+
200+ if (action == "interactive")
201+ session->shutdown_requested.emit(session->HasInhibitors());
202+ else if (action == "shutdown")
203+ session->reboot_requested.emit(session->HasInhibitors());
204+ else if (action == "suspend")
205+ session->Suspend();
206+ else if (action == "hibernate")
207+ session->Hibernate();
208+ else if (action == "blank")
209+ session->ScreenSaverActivate();
210+}
211 } // namespace
212
213-AcceleratorController::AcceleratorController()
214+AcceleratorController::AcceleratorController(session::Manager::Ptr const& session)
215 : accelerators_(new Accelerators)
216 {
217 auto settings = glib::Object<GSettings>(g_settings_new(MEDIA_KEYS_SCHEMA));
218
219 auto accelerator = std::make_shared<Accelerator>(glib::String(g_settings_get_string(settings, MEDIA_KEYS_KEY_VOLUME_MUTE)));
220- accelerator->activated.connect(std::function<void ()>(MuteIndicatorSound));
221+ accelerator->activated.connect(std::function<void()>(MuteIndicatorSound));
222 accelerators_->Add(accelerator);
223
224 accelerator = std::make_shared<Accelerator>(glib::String(g_settings_get_string(settings, MEDIA_KEYS_KEY_VOLUME_DOWN)));
225@@ -108,6 +136,22 @@
226 accelerator->activated.connect(std::bind(ScrollIndicatorSound, +1));
227 accelerators_->Add(accelerator);
228
229+ accelerator = std::make_shared<Accelerator>(POWER_KEY_SUSPEND);
230+ accelerator->activated.connect(std::bind(PowerAction, session, SUSPEND_BUTTON_ACTION_KEY));
231+ accelerators_->Add(accelerator);
232+
233+ accelerator = std::make_shared<Accelerator>(POWER_KEY_SLEEP);
234+ accelerator->activated.connect(std::bind(PowerAction, session, SLEEP_BUTTON_ACTION_KEY));
235+ accelerators_->Add(accelerator);
236+
237+ accelerator = std::make_shared<Accelerator>(POWER_KEY_HIBERNATE);
238+ accelerator->activated.connect(std::bind(PowerAction, session, HIBERNATE_BUTTON_ACTION_KEY));
239+ accelerators_->Add(accelerator);
240+
241+ accelerator = std::make_shared<Accelerator>(POWER_KEY_POWEROFF);
242+ accelerator->activated.connect(std::bind(PowerAction, session, POWER_BUTTON_ACTION_KEY));
243+ accelerators_->Add(accelerator);
244+
245 settings = glib::Object<GSettings>(g_settings_new(INPUT_SWITCH_SCHEMA));
246
247 auto variant = glib::Variant(g_settings_get_value(settings, INPUT_SWITCH_KEY_PREVIOUS_SOURCE), glib::StealRef());
248
249=== modified file 'lockscreen/LockScreenAcceleratorController.h'
250--- lockscreen/LockScreenAcceleratorController.h 2014-04-28 13:09:53 +0000
251+++ lockscreen/LockScreenAcceleratorController.h 2014-06-18 15:11:36 +0000
252@@ -20,6 +20,7 @@
253 #ifndef UNITY_LOCKSCREEN_ACCELERATOR_CONTROLLER
254 #define UNITY_LOCKSCREEN_ACCELERATOR_CONTROLLER
255
256+#include <UnityCore/SessionManager.h>
257 #include "LockScreenAccelerators.h"
258
259 namespace unity
260@@ -32,7 +33,7 @@
261 public:
262 typedef std::shared_ptr<AcceleratorController> Ptr;
263
264- AcceleratorController();
265+ AcceleratorController(session::Manager::Ptr const&);
266
267 Accelerators::Ptr const& GetAccelerators() const;
268
269
270=== modified file 'lockscreen/LockScreenController.cpp'
271--- lockscreen/LockScreenController.cpp 2014-06-07 16:26:59 +0000
272+++ lockscreen/LockScreenController.cpp 2014-06-18 15:11:36 +0000
273@@ -104,7 +104,7 @@
274 key_connection_->disconnect();
275 uscreen_connection_->block();
276 hidden_window_connection_->block();
277- session_manager_->unlocked.emit();
278+ session_manager_->is_locked = false;
279
280 std::for_each(shields_.begin(), shields_.end(), [](nux::ObjectPtr<Shield> const& shield) {
281 shield->RemoveLayout();
282@@ -342,7 +342,7 @@
283 HideBlankWindow();
284
285 LockScreen();
286- session_manager_->locked.emit();
287+ session_manager_->is_locked = true;
288
289 if (prompt_activation_)
290 {
291@@ -403,7 +403,7 @@
292 indicators_ = std::make_shared<indicator::LockScreenDBusIndicators>();
293 upstart_wrapper_->Emit("desktop-lock");
294
295- accelerator_controller_ = std::make_shared<AcceleratorController>();
296+ accelerator_controller_ = std::make_shared<AcceleratorController>(session_manager_);
297 auto activate_key = WindowManager::Default().activate_indicators_key();
298 auto accelerator = std::make_shared<Accelerator>(activate_key.second, 0, activate_key.first);
299 accelerator->activated.connect(std::bind(std::mem_fn(&Controller::ActivatePanel), this));
300
301=== modified file 'shutdown/SessionDBusManager.cpp'
302--- shutdown/SessionDBusManager.cpp 2014-04-10 04:47:58 +0000
303+++ shutdown/SessionDBusManager.cpp 2014-06-18 15:11:36 +0000
304@@ -53,14 +53,20 @@
305 <method name="Suspend" />
306 <method name="Hibernate" />
307 <method name="CancelAction" />
308+ <method name="IsLocked">
309+ <arg type="b" direction="out" name="is_locked" />
310+ </method>
311+ <method name="CanLock">
312+ <arg type="b" direction="out" name="can_lock" />
313+ </method>
314 <method name="CanShutdown">
315- <arg type="b" direction="out" name="canshutdown" />
316+ <arg type="b" direction="out" name="can_shutdown" />
317 </method>
318 <method name="CanSuspend">
319- <arg type="b" direction="out" name="cansuspend" />
320+ <arg type="b" direction="out" name="can_suspend" />
321 </method>
322 <method name="CanHibernate">
323- <arg type="b" direction="out" name="canhibernate" />
324+ <arg type="b" direction="out" name="can_hibernate" />
325 </method>
326
327 <signal name="LockRequested" />
328@@ -121,7 +127,7 @@
329 }
330 else if (method == "RequestLogout")
331 {
332- session_->logout_requested.emit(false);
333+ session_->logout_requested.emit(session_->HasInhibitors());
334 }
335 else if (method == "Reboot")
336 {
337@@ -129,7 +135,7 @@
338 }
339 else if (method == "RequestReboot")
340 {
341- session_->reboot_requested.emit(false);
342+ session_->reboot_requested.emit(session_->HasInhibitors());
343 }
344 else if (method == "Shutdown")
345 {
346@@ -137,7 +143,7 @@
347 }
348 else if (method == "RequestShutdown")
349 {
350- session_->shutdown_requested.emit(false);
351+ session_->shutdown_requested.emit(session_->HasInhibitors());
352 }
353 else if (method == "Suspend")
354 {
355@@ -152,17 +158,25 @@
356 session_->CancelAction();
357 session_->cancel_requested.emit();
358 }
359+ else if (method == "IsLocked")
360+ {
361+ return g_variant_new("(b)", session_->is_locked() != false);
362+ }
363+ else if (method == "CanLock")
364+ {
365+ return g_variant_new("(b)", session_->CanLock() != false);
366+ }
367 else if (method == "CanShutdown")
368 {
369- return g_variant_new("(b)", session_->CanShutdown() != FALSE);
370+ return g_variant_new("(b)", session_->CanShutdown() != false);
371 }
372 else if (method == "CanSuspend")
373 {
374- return g_variant_new("(b)", session_->CanSuspend() != FALSE);
375+ return g_variant_new("(b)", session_->CanSuspend() != false);
376 }
377 else if (method == "CanHibernate")
378 {
379- return g_variant_new("(b)", session_->CanHibernate() != FALSE);
380+ return g_variant_new("(b)", session_->CanHibernate() != false);
381 }
382
383 return nullptr;
384
385=== modified file 'shutdown/SessionView.cpp'
386--- shutdown/SessionView.cpp 2014-06-07 16:26:41 +0000
387+++ shutdown/SessionView.cpp 2014-06-18 15:11:36 +0000
388@@ -91,16 +91,17 @@
389 return false;
390 });
391
392- mode.changed.connect([this] (Mode m) {
393- UpdateText();
394- Populate();
395- });
396-
397+ mode.changed.connect(sigc::hide(sigc::mem_fun(this, &View::UpdateContents)));
398 scale.changed.connect(sigc::hide(sigc::mem_fun(this, &View::UpdateViewSize)));
399+ UpdateContents();
400+}
401
402+void View::UpdateContents()
403+{
404+ SetVisible(true);
405+ PopulateButtons();
406+ UpdateText();
407 UpdateViewSize();
408- UpdateText();
409- Populate();
410 }
411
412 void View::UpdateViewSize()
413@@ -115,11 +116,17 @@
414 ReloadCloseButtonTexture();
415
416 buttons_layout_->SetSpaceBetweenChildren(style::BUTTONS_SPACE.CP(scale()));
417-
418- for (auto* area : buttons_layout_->GetChildren())
419+ auto const& buttons = buttons_layout_->GetChildren();
420+
421+ for (auto* area : buttons)
422+ static_cast<Button*>(area)->scale = scale();
423+
424+ if (buttons.size() == 1)
425 {
426- auto* button = static_cast<Button*>(area);
427- button->scale = scale();
428+ auto* button = buttons.front();
429+ button->ComputeContentSize();
430+ int padding = button->GetWidth()/2 + style::MAIN_SPACE.CP(scale())/2;
431+ buttons_layout_->SetLeftAndRightPadding(padding, padding);
432 }
433 }
434
435@@ -201,20 +208,26 @@
436 subtitle_->SetText(glib::String(g_strdup_printf(message.c_str(), name.c_str())).Str());
437 }
438
439-void View::Populate()
440+void View::PopulateButtons()
441 {
442 debug::Introspectable::RemoveAllChildren();
443 buttons_layout_->Clear();
444+ buttons_layout_->SetLeftAndRightPadding(0, 0);
445 key_focus_area_ = this;
446
447 if (mode() == Mode::LOGOUT)
448 {
449- auto* button = new Button(Button::Action::LOCK, NUX_TRACKER_LOCATION);
450- button->scale = scale();
451- button->activated.connect(sigc::mem_fun(manager_.get(), &Manager::LockScreen));
452- AddButton(button);
453-
454- button = new Button(Button::Action::LOGOUT, NUX_TRACKER_LOCATION);
455+ if (manager_->is_locked())
456+ return;
457+
458+ if (manager_->CanLock())
459+ {
460+ auto* button = new Button(Button::Action::LOCK, NUX_TRACKER_LOCATION);
461+ button->activated.connect(sigc::mem_fun(manager_.get(), &Manager::LockScreen));
462+ AddButton(button);
463+ }
464+
465+ auto* button = new Button(Button::Action::LOGOUT, NUX_TRACKER_LOCATION);
466 button->activated.connect(sigc::mem_fun(manager_.get(), &Manager::Logout));
467 key_focus_area_ = button;
468 AddButton(button);
469@@ -223,23 +236,23 @@
470 {
471 if (mode() == Mode::FULL)
472 {
473- auto* button = new Button(Button::Action::LOCK, NUX_TRACKER_LOCATION);
474- button->scale = scale();
475- button->activated.connect(sigc::mem_fun(manager_.get(), &Manager::LockScreen));
476- AddButton(button);
477+ if (manager_->CanLock())
478+ {
479+ auto* button = new Button(Button::Action::LOCK, NUX_TRACKER_LOCATION);
480+ button->activated.connect(sigc::mem_fun(manager_.get(), &Manager::LockScreen));
481+ AddButton(button);
482+ }
483
484 if (manager_->CanSuspend())
485 {
486- button = new Button(Button::Action::SUSPEND, NUX_TRACKER_LOCATION);
487- button->scale = scale();
488+ auto* button = new Button(Button::Action::SUSPEND, NUX_TRACKER_LOCATION);
489 button->activated.connect(sigc::mem_fun(manager_.get(), &Manager::Suspend));
490 AddButton(button);
491 }
492
493 if (manager_->CanHibernate())
494 {
495- button = new Button(Button::Action::HIBERNATE, NUX_TRACKER_LOCATION);
496- button->scale = scale();
497+ auto* button = new Button(Button::Action::HIBERNATE, NUX_TRACKER_LOCATION);
498 button->activated.connect(sigc::mem_fun(manager_.get(), &Manager::Hibernate));
499 AddButton(button);
500 }
501@@ -248,28 +261,34 @@
502 if (manager_->CanShutdown())
503 {
504 auto *button = new Button(Button::Action::REBOOT, NUX_TRACKER_LOCATION);
505- button->scale = scale();
506 button->activated.connect(sigc::mem_fun(manager_.get(), &Manager::Reboot));
507 AddButton(button);
508
509 button = new Button(Button::Action::SHUTDOWN, NUX_TRACKER_LOCATION);
510- button->scale = scale();
511 button->activated.connect(sigc::mem_fun(manager_.get(), &Manager::Shutdown));
512 key_focus_area_ = (mode() == Mode::SHUTDOWN) ? button : key_focus_area_;
513 AddButton(button);
514 }
515- else if (mode() == Mode::FULL)
516+ else if (mode() == Mode::FULL && !manager_->is_locked())
517 {
518 auto* button = new Button(Button::Action::LOGOUT, NUX_TRACKER_LOCATION);
519- button->scale = scale();
520 button->activated.connect(sigc::mem_fun(manager_.get(), &Manager::Logout));
521 AddButton(button);
522 }
523 }
524+
525+ cancel_idle_.reset();
526+ if (buttons_layout_->GetChildren().empty())
527+ {
528+ // There's nothing to show here, let's cancel the action and hide
529+ SetVisible(false);
530+ cancel_idle_.reset(new glib::Idle([this] { request_close.emit(); return false; }));
531+ }
532 }
533
534 void View::AddButton(Button* button)
535 {
536+ button->scale = scale();
537 button->activated.connect([this] {request_hide.emit();});
538 buttons_layout_->AddView(button);
539 debug::Introspectable::AddChild(button);
540
541=== modified file 'shutdown/SessionView.h'
542--- shutdown/SessionView.h 2014-04-25 18:12:48 +0000
543+++ shutdown/SessionView.h 2014-06-18 15:11:36 +0000
544@@ -25,10 +25,10 @@
545 #include <Nux/VLayout.h>
546 #include <Nux/HLayout.h>
547
548-#include "UnityCore/SessionManager.h"
549+#include <UnityCore/GLibSource.h>
550+#include <UnityCore/SessionManager.h>
551 #include "unity-shared/EMConverter.h"
552 #include "unity-shared/UnityWindowView.h"
553-#include "UnityCore/SessionManager.h"
554
555 namespace unity
556 {
557@@ -73,10 +73,10 @@
558 private:
559 friend class TestSessionView;
560
561+ void PopulateButtons();
562+ void UpdateText();
563+ void UpdateContents();
564 void UpdateViewSize();
565-
566- void UpdateText();
567- void Populate();
568 void AddButton(Button*);
569
570 Manager::Ptr manager_;
571@@ -85,6 +85,7 @@
572 nux::VLayout* main_layout_;
573 nux::HLayout* buttons_layout_;
574 nux::InputArea* key_focus_area_;
575+ glib::Source::UniquePtr cancel_idle_;
576 };
577
578 } // namespace session
579
580=== modified file 'shutdown/StandaloneSession.cpp'
581--- shutdown/StandaloneSession.cpp 2014-04-10 04:47:58 +0000
582+++ shutdown/StandaloneSession.cpp 2014-06-18 15:11:36 +0000
583@@ -52,9 +52,11 @@
584
585 void CancelAction() { std::cout << "CancelAction" << std::endl; }
586
587+ bool CanLock() const {return true;}
588 bool CanShutdown() const {return true;}
589 bool CanSuspend() const {return true;}
590 bool CanHibernate() const {return true;}
591+ bool HasInhibitors() const {return false;}
592 };
593
594 struct SessionWindow
595
596=== modified file 'tests/test_mock_session_manager.h'
597--- tests/test_mock_session_manager.h 2014-04-10 04:47:58 +0000
598+++ tests/test_mock_session_manager.h 2014-06-18 15:11:36 +0000
599@@ -44,9 +44,11 @@
600 MOCK_METHOD0(Hibernate, void());
601 MOCK_METHOD0(CancelAction, void());
602
603+ MOCK_CONST_METHOD0(CanLock, bool());
604 MOCK_CONST_METHOD0(CanShutdown, bool());
605 MOCK_CONST_METHOD0(CanSuspend, bool());
606 MOCK_CONST_METHOD0(CanHibernate, bool());
607+ MOCK_CONST_METHOD0(HasInhibitors, bool());
608 };
609
610 } // session
611
612=== modified file 'tests/test_session_controller.cpp'
613--- tests/test_session_controller.cpp 2014-04-30 15:33:43 +0000
614+++ tests/test_session_controller.cpp 2014-06-18 15:11:36 +0000
615@@ -41,6 +41,7 @@
616 , manager(std::make_shared<testing::NiceMock<MockManager>>())
617 , controller(manager)
618 {
619+ ON_CALL(*manager, CanLock()).WillByDefault(testing::Return(true));
620 ON_CALL(*manager, CanShutdown()).WillByDefault(testing::Return(true));
621 }
622
623
624=== modified file 'tests/test_session_view.cpp'
625--- tests/test_session_view.cpp 2014-03-21 04:40:12 +0000
626+++ tests/test_session_view.cpp 2014-06-18 15:11:36 +0000
627@@ -137,6 +137,7 @@
628
629 TEST_F(TestSessionView, FullModeButtons)
630 {
631+ ON_CALL(*manager, CanLock()).WillByDefault(testing::Return(true));
632 ON_CALL(*manager, CanShutdown()).WillByDefault(testing::Return(true));
633 ON_CALL(*manager, CanSuspend()).WillByDefault(testing::Return(true));
634 ON_CALL(*manager, CanHibernate()).WillByDefault(testing::Return(true));
635@@ -166,6 +167,11 @@
636 view.mode.changed.emit(View::Mode::FULL);
637
638 EXPECT_EQ(view.GetButtonByAction(Button::Action::HIBERNATE), nullptr);
639+
640+ ON_CALL(*manager, CanLock()).WillByDefault(testing::Return(false));
641+ view.mode.changed.emit(View::Mode::FULL);
642+
643+ EXPECT_EQ(view.GetButtonByAction(Button::Action::LOCK), nullptr);
644 }
645
646 TEST_F(TestSessionView, ShutdownModeButtons)
647@@ -181,6 +187,7 @@
648
649 TEST_F(TestSessionView, LogoutModeButtons)
650 {
651+ ON_CALL(*manager, CanLock()).WillByDefault(testing::Return(true));
652 view.mode = View::Mode::LOGOUT;
653
654 EXPECT_EQ(view.GetButtons().size(), 2);
655@@ -189,6 +196,16 @@
656 EXPECT_EQ(view.key_focus_area(), view.GetButtonByAction(Button::Action::LOGOUT));
657 }
658
659+TEST_F(TestSessionView, LogoutLightModeButtons)
660+{
661+ ON_CALL(*manager, CanLock()).WillByDefault(testing::Return(false));
662+ view.mode = View::Mode::LOGOUT;
663+
664+ EXPECT_EQ(view.GetButtons().size(), 1);
665+ EXPECT_EQ(view.GetButtonPosition(Button::Action::LOGOUT), 0);
666+ EXPECT_EQ(view.key_focus_area(), view.GetButtonByAction(Button::Action::LOGOUT));
667+}
668+
669 TEST_F(TestSessionView, FullModeTitle)
670 {
671 EXPECT_TRUE(view.GetTitle().empty());
672@@ -213,8 +230,9 @@
673 {
674 bool request_hide = false;
675 view.request_hide.connect([&request_hide] { request_hide = true; });
676+ view.mode = View::Mode::LOGOUT;
677
678- auto button = view.GetButtonByAction(Button::Action::LOCK);
679+ auto button = view.GetButtonByAction(Button::Action::LOGOUT);
680 ASSERT_NE(button, nullptr);
681 button->activated.emit();
682
683@@ -223,7 +241,8 @@
684
685 TEST_F(TestSessionView, ButtonsActivateDeselectButton)
686 {
687- auto button = view.GetButtonByAction(Button::Action::LOCK);
688+ view.mode = View::Mode::LOGOUT;
689+ auto button = view.GetButtonByAction(Button::Action::LOGOUT);
690 ASSERT_NE(button, nullptr);
691 button->highlighted = true;
692 button->activated.emit();
693@@ -233,6 +252,8 @@
694
695 TEST_F(TestSessionView, LockButtonActivateLocks)
696 {
697+ ON_CALL(*manager, CanLock()).WillByDefault(testing::Return(true));
698+ view.mode = View::Mode::LOGOUT;
699 EXPECT_CALL(*manager, LockScreen());
700 auto button = view.GetButtonByAction(Button::Action::LOCK);
701 ASSERT_NE(button, nullptr);