Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(69)

Side by Side Diff: ash/wm/power_button_controller.cc

Issue 11091023: ash : Decouple power button controller and session state controller. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Fix power button cancel behaviour + unittest Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ash/wm/power_button_controller.h ('k') | ash/wm/power_button_controller_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ash/wm/power_button_controller.h" 5 #include "ash/wm/power_button_controller.h"
6 6
7 #include "ash/ash_switches.h" 7 #include "ash/ash_switches.h"
8 #include "ash/shell.h" 8 #include "ash/shell.h"
9 #include "ash/shell_delegate.h" 9 #include "ash/shell_delegate.h"
10 #include "ash/shell_window_ids.h" 10 #include "ash/shell_window_ids.h"
11 #include "ash/wm/session_state_animator.h" 11 #include "ash/wm/session_state_animator.h"
12 #include "ash/wm/session_state_controller.h"
12 #include "base/command_line.h" 13 #include "base/command_line.h"
13 #include "ui/aura/root_window.h" 14 #include "ui/aura/root_window.h"
14 #include "ui/aura/shared/compound_event_filter.h" 15 #include "ui/aura/shared/compound_event_filter.h"
15 16
16 #if defined(OS_CHROMEOS)
17 #include "base/chromeos/chromeos_version.h"
18 #endif
19
20 namespace ash { 17 namespace ash {
21 18
22 namespace { 19 PowerButtonController::PowerButtonController(SessionStateController* controller)
23 20 : power_button_down_(false),
24 // Amount of time that the power button needs to be held before we lock the
25 // screen.
26 const int kLockTimeoutMs = 400;
27
28 // Amount of time that the power button needs to be held before we shut down.
29 const int kShutdownTimeoutMs = 400;
30
31 // Amount of time to wait for our lock requests to be honored before giving up.
32 const int kLockFailTimeoutMs = 4000;
33
34 // When the button has been held continuously from the unlocked state, amount of
35 // time that we wait after the screen locker window is shown before starting the
36 // pre-shutdown animation.
37 const int kLockToShutdownTimeoutMs = 150;
38
39 // Amount of time taken to scale the snapshot of the screen down to a
40 // slightly-smaller size once the user starts holding the power button. Used
41 // for both the pre-lock and pre-shutdown animations.
42 const int kSlowCloseAnimMs = 400;
43
44 // Amount of time taken to scale the snapshot of the screen back to its original
45 // size when the button is released.
46 const int kUndoSlowCloseAnimMs = 100;
47
48 // Amount of time taken to scale the snapshot down to a point in the center of
49 // the screen once the screen has been locked or we've been notified that the
50 // system is shutting down.
51 const int kFastCloseAnimMs = 150;
52
53 // Additional time (beyond kFastCloseAnimMs) to wait after starting the
54 // fast-close shutdown animation before actually requesting shutdown, to give
55 // the animation time to finish.
56 const int kShutdownRequestDelayMs = 50;
57
58 } // namespace
59
60 PowerButtonController::TestApi::TestApi(PowerButtonController* controller)
61 : controller_(controller),
62 animator_api_(new internal::SessionStateAnimator::TestApi(
63 controller->animator_.get())) {
64 }
65
66 PowerButtonController::TestApi::~TestApi() {
67 }
68
69 PowerButtonController::PowerButtonController()
70 : login_status_(user::LOGGED_IN_NONE),
71 unlocked_login_status_(user::LOGGED_IN_NONE),
72 power_button_down_(false),
73 lock_button_down_(false), 21 lock_button_down_(false),
74 screen_is_off_(false), 22 screen_is_off_(false),
75 shutting_down_(false),
76 has_legacy_power_button_( 23 has_legacy_power_button_(
77 CommandLine::ForCurrentProcess()->HasSwitch( 24 CommandLine::ForCurrentProcess()->HasSwitch(
78 switches::kAuraLegacyPowerButton)), 25 switches::kAuraLegacyPowerButton)),
79 animator_(new internal::SessionStateAnimator()) { 26 controller_(controller) {
80 Shell::GetPrimaryRootWindow()->AddRootWindowObserver(this);
81 } 27 }
82 28
83 PowerButtonController::~PowerButtonController() { 29 PowerButtonController::~PowerButtonController() {
84 Shell::GetPrimaryRootWindow()->RemoveRootWindowObserver(this);
85 }
86
87 void PowerButtonController::OnLoginStateChanged(user::LoginStatus status) {
88 login_status_ = status;
89 unlocked_login_status_ = user::LOGGED_IN_NONE;
90 }
91
92 void PowerButtonController::OnAppTerminating() {
93 // If we hear that Chrome is exiting but didn't request it ourselves, all we
94 // can really hope for is that we'll have time to clear the screen.
95 if (!shutting_down_) {
96 shutting_down_ = true;
97 Shell* shell = ash::Shell::GetInstance();
98 shell->env_filter()->set_cursor_hidden_by_filter(false);
99 shell->cursor_manager()->ShowCursor(false);
100 animator_->ShowBlackLayer();
101 animator_->StartAnimation(
102 internal::SessionStateAnimator::kAllContainersMask,
103 internal::SessionStateAnimator::ANIMATION_HIDE);
104 }
105 }
106
107 void PowerButtonController::OnLockStateChanged(bool locked) {
108 if (shutting_down_ || (login_status_ == user::LOGGED_IN_LOCKED) == locked)
109 return;
110
111 if (!locked && login_status_ == user::LOGGED_IN_LOCKED) {
112 login_status_ = unlocked_login_status_;
113 unlocked_login_status_ = user::LOGGED_IN_NONE;
114 } else {
115 unlocked_login_status_ = login_status_;
116 login_status_ = user::LOGGED_IN_LOCKED;
117 }
118
119 if (locked) {
120 animator_->StartAnimation(
121 internal::SessionStateAnimator::LOCK_SCREEN_CONTAINERS,
122 internal::SessionStateAnimator::ANIMATION_FADE_IN);
123 lock_timer_.Stop();
124 lock_fail_timer_.Stop();
125
126 if (!has_legacy_power_button_ && power_button_down_) {
127 lock_to_shutdown_timer_.Stop();
128 lock_to_shutdown_timer_.Start(
129 FROM_HERE,
130 base::TimeDelta::FromMilliseconds(kLockToShutdownTimeoutMs),
131 this, &PowerButtonController::OnLockToShutdownTimeout);
132 }
133 } else {
134 animator_->StartAnimation(
135 internal::SessionStateAnimator::DESKTOP_BACKGROUND |
136 internal::SessionStateAnimator::LAUNCHER |
137 internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
138 internal::SessionStateAnimator::ANIMATION_RESTORE);
139 animator_->DropBlackLayer();
140 }
141 } 30 }
142 31
143 void PowerButtonController::OnScreenBrightnessChanged(double percent) { 32 void PowerButtonController::OnScreenBrightnessChanged(double percent) {
144 screen_is_off_ = percent <= 0.001; 33 screen_is_off_ = percent <= 0.001;
145 } 34 }
146 35
147 void PowerButtonController::OnStartingLock() {
148 if (shutting_down_ || login_status_ == user::LOGGED_IN_LOCKED)
149 return;
150
151 // Ensure that the black layer is visible -- if the screen was locked via
152 // the wrench menu, we won't have already shown the black background
153 // as part of the slow-close animation.
154 animator_->ShowBlackLayer();
155
156 animator_->StartAnimation(
157 internal::SessionStateAnimator::LAUNCHER,
158 internal::SessionStateAnimator::ANIMATION_HIDE);
159
160 animator_->StartAnimation(
161 internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
162 internal::SessionStateAnimator::ANIMATION_FAST_CLOSE);
163
164 // Hide the screen locker containers so we can make them fade in later.
165 animator_->StartAnimation(
166 internal::SessionStateAnimator::LOCK_SCREEN_CONTAINERS,
167 internal::SessionStateAnimator::ANIMATION_HIDE);
168 }
169
170 void PowerButtonController::OnPowerButtonEvent( 36 void PowerButtonController::OnPowerButtonEvent(
171 bool down, const base::TimeTicks& timestamp) { 37 bool down, const base::TimeTicks& timestamp) {
172 power_button_down_ = down; 38 power_button_down_ = down;
173 39
174 if (shutting_down_) 40 if (controller_->ShutdownRequested())
175 return; 41 return;
176 42
177 // Avoid starting the lock/shutdown sequence if the power button is pressed 43 // Avoid starting the lock/shutdown sequence if the power button is pressed
178 // while the screen is off (http://crbug.com/128451). 44 // while the screen is off (http://crbug.com/128451).
179 if (screen_is_off_) 45 if (screen_is_off_)
180 return; 46 return;
181 47
182 if (has_legacy_power_button_) { 48 if (has_legacy_power_button_) {
183 // If power button releases won't get reported correctly because we're not 49 // If power button releases won't get reported correctly because we're not
184 // running on official hardware, just lock the screen or shut down 50 // running on official hardware, just lock the screen or shut down
185 // immediately. 51 // immediately.
186 if (down) { 52 if (down) {
187 animator_->ShowBlackLayer(); 53 if (controller_->IsEligibleForLock())
188 if (LoggedInAsNonGuest() && login_status_ != user::LOGGED_IN_LOCKED) { 54 controller_->StartLockAnimationAndLockImmediately();
189 animator_->StartAnimation( 55 else
190 internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS, 56 controller_->RequestShutdown();
191 internal::SessionStateAnimator::ANIMATION_SLOW_CLOSE);
192 OnLockTimeout();
193 } else {
194 OnShutdownTimeout();
195 }
196 } 57 }
197 } else { // !has_legacy_power_button_ 58 } else { // !has_legacy_power_button_
198 if (down) { 59 if (down) {
199 // If we already have a pending request to lock the screen, wait. 60 // If we already have a pending request to lock the screen, wait.
200 if (lock_fail_timer_.IsRunning()) 61 if (controller_->LockRequested())
201 return; 62 return;
202 63
203 if (LoggedInAsNonGuest() && login_status_ != user::LOGGED_IN_LOCKED) 64 if (controller_->IsEligibleForLock())
204 StartLockTimer(); 65 controller_->StartLockAnimation();
205 else 66 else
206 StartShutdownTimer(); 67 controller_->StartShutdownAnimation();
207 } else { // Button is up. 68 } else { // Button is up.
208 if (lock_timer_.IsRunning() || shutdown_timer_.IsRunning()) { 69 if (controller_->CanCancelLockAnimation())
209 if (login_status_ == user::LOGGED_IN_LOCKED) { 70 controller_->CancelLockAnimation();
210 // If we've already started shutdown transition at lock screen 71 else if (controller_->CanCancelShutdownAnimation())
211 // desktop background needs to be restored immediately. 72 controller_->CancelShutdownAnimation();
212 animator_->StartAnimation(
213 internal::SessionStateAnimator::DESKTOP_BACKGROUND,
214 internal::SessionStateAnimator::ANIMATION_RESTORE);
215 }
216 animator_->StartAnimation(
217 (login_status_ == user::LOGGED_IN_LOCKED) ?
218 internal::SessionStateAnimator::kAllLockScreenContainersMask :
219 internal::SessionStateAnimator::kAllContainersMask,
220 internal::SessionStateAnimator::ANIMATION_UNDO_SLOW_CLOSE);
221 }
222
223 // Drop the black layer after the undo animation finishes.
224 if (lock_timer_.IsRunning() ||
225 (shutdown_timer_.IsRunning() && !LoggedInAsNonGuest())) {
226 animator_->ScheduleDropBlackLayer();
227 }
228
229 lock_timer_.Stop();
230 shutdown_timer_.Stop();
231 lock_to_shutdown_timer_.Stop();
232 } 73 }
233 } 74 }
234 } 75 }
235 76
236 void PowerButtonController::OnLockButtonEvent( 77 void PowerButtonController::OnLockButtonEvent(
237 bool down, const base::TimeTicks& timestamp) { 78 bool down, const base::TimeTicks& timestamp) {
238 lock_button_down_ = down; 79 lock_button_down_ = down;
239 80
240 if (shutting_down_ || !LoggedInAsNonGuest()) 81 if (controller_->ShutdownRequested() || !controller_->IsEligibleForLock())
241 return; 82 return;
242 83
243 // Bail if we're already locked or are in the process of locking. Also give 84 // Bail if we're already locked or are in the process of locking. Also give
244 // the power button precedence over the lock button (we don't expect both 85 // the power button precedence over the lock button (we don't expect both
245 // buttons to be present, so this is just making sure that we don't do 86 // buttons to be present, so this is just making sure that we don't do
246 // something completely stupid if that assumption changes later). 87 // something completely stupid if that assumption changes later).
247 if (login_status_ == user::LOGGED_IN_LOCKED || 88 if (power_button_down_)
248 lock_fail_timer_.IsRunning() || power_button_down_)
249 return; 89 return;
250 90
251 if (down) { 91 if (controller_->IsLocked() || controller_->LockRequested())
252 StartLockTimer(); 92 return;
253 } else {
254 if (lock_timer_.IsRunning()) {
255 animator_->StartAnimation(
256 internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
257 internal::SessionStateAnimator::ANIMATION_UNDO_SLOW_CLOSE);
258 animator_->ScheduleDropBlackLayer();
259 lock_timer_.Stop();
260 }
261 }
262 }
263 93
264 void PowerButtonController::RequestShutdown() { 94 if (down)
265 if (!shutting_down_) 95 controller_->StartLockAnimation();
266 StartShutdownAnimationAndRequestShutdown(); 96 else
267 } 97 controller_->CancelLockWithOtherAnimation();
268
269 void PowerButtonController::OnRootWindowHostCloseRequested(
270 const aura::RootWindow*) {
271 if(Shell::GetInstance() && Shell::GetInstance()->delegate())
272 Shell::GetInstance()->delegate()->Exit();
273 }
274
275 bool PowerButtonController::LoggedInAsNonGuest() const {
276 if (login_status_ == user::LOGGED_IN_NONE)
277 return false;
278 if (login_status_ == user::LOGGED_IN_GUEST)
279 return false;
280 // TODO(mukai): think about kiosk mode.
281 return true;
282 }
283
284 void PowerButtonController::OnLockTimeout() {
285 delegate_->RequestLockScreen();
286 lock_fail_timer_.Start(
287 FROM_HERE,
288 base::TimeDelta::FromMilliseconds(kLockFailTimeoutMs),
289 this, &PowerButtonController::OnLockFailTimeout);
290 }
291
292 void PowerButtonController::OnLockFailTimeout() {
293 DCHECK_NE(login_status_, user::LOGGED_IN_LOCKED);
294 LOG(ERROR) << "Screen lock request timed out";
295 animator_->StartAnimation(
296 internal::SessionStateAnimator::LAUNCHER |
297 internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
298 internal::SessionStateAnimator::ANIMATION_RESTORE);
299 animator_->DropBlackLayer();
300 }
301
302 void PowerButtonController::OnLockToShutdownTimeout() {
303 DCHECK_EQ(login_status_, user::LOGGED_IN_LOCKED);
304 StartShutdownTimer();
305 }
306
307 void PowerButtonController::OnShutdownTimeout() {
308 if (!shutting_down_)
309 StartShutdownAnimationAndRequestShutdown();
310 }
311
312 void PowerButtonController::OnRealShutdownTimeout() {
313 DCHECK(shutting_down_);
314 #if defined(OS_CHROMEOS)
315 if (!base::chromeos::IsRunningOnChromeOS()) {
316 ShellDelegate* delegate = Shell::GetInstance()->delegate();
317 if (delegate)
318 delegate->Exit();
319 }
320 #endif
321 delegate_->RequestShutdown();
322 }
323
324 void PowerButtonController::StartLockTimer() {
325 animator_->ShowBlackLayer();
326 animator_->StartAnimation(
327 internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
328 internal::SessionStateAnimator::ANIMATION_SLOW_CLOSE);
329 lock_timer_.Stop();
330 lock_timer_.Start(FROM_HERE,
331 base::TimeDelta::FromMilliseconds(kSlowCloseAnimMs),
332 this, &PowerButtonController::OnLockTimeout);
333 }
334
335 void PowerButtonController::StartShutdownTimer() {
336 animator_->ShowBlackLayer();
337 animator_->StartAnimation(
338 internal::SessionStateAnimator::kAllContainersMask,
339 internal::SessionStateAnimator::ANIMATION_SLOW_CLOSE);
340 shutdown_timer_.Stop();
341 shutdown_timer_.Start(
342 FROM_HERE,
343 base::TimeDelta::FromMilliseconds(kShutdownTimeoutMs),
344 this, &PowerButtonController::OnShutdownTimeout);
345 }
346
347 void PowerButtonController::StartShutdownAnimationAndRequestShutdown() {
348 DCHECK(!shutting_down_);
349 shutting_down_ = true;
350
351 Shell* shell = ash::Shell::GetInstance();
352 shell->env_filter()->set_cursor_hidden_by_filter(false);
353 shell->cursor_manager()->ShowCursor(false);
354
355 animator_->ShowBlackLayer();
356 if (login_status_ != user::LOGGED_IN_NONE) {
357 // Hide the other containers before starting the animation.
358 // ANIMATION_FAST_CLOSE will make the screen locker windows partially
359 // transparent, and we don't want the other windows to show through.
360 animator_->StartAnimation(
361 internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS |
362 internal::SessionStateAnimator::LAUNCHER,
363 internal::SessionStateAnimator::ANIMATION_HIDE);
364 animator_->StartAnimation(
365 internal::SessionStateAnimator::kAllLockScreenContainersMask,
366 internal::SessionStateAnimator::ANIMATION_FAST_CLOSE);
367 } else {
368 animator_->StartAnimation(
369 internal::SessionStateAnimator::kAllContainersMask,
370 internal::SessionStateAnimator::ANIMATION_FAST_CLOSE);
371 }
372
373 real_shutdown_timer_.Start(
374 FROM_HERE,
375 base::TimeDelta::FromMilliseconds(
376 kFastCloseAnimMs + kShutdownRequestDelayMs),
377 this, &PowerButtonController::OnRealShutdownTimeout);
378 } 98 }
379 99
380 } // namespace ash 100 } // namespace ash
OLDNEW
« no previous file with comments | « ash/wm/power_button_controller.h ('k') | ash/wm/power_button_controller_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698