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

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: 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
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 namespace ash { 17 namespace ash {
17 18
18 namespace { 19 PowerButtonController::PowerButtonController(SessionStateController* controller)
19 20 : power_button_down_(false),
20 // Amount of time that the power button needs to be held before we lock the
21 // screen.
22 const int kLockTimeoutMs = 400;
23
24 // Amount of time that the power button needs to be held before we shut down.
25 const int kShutdownTimeoutMs = 400;
26
27 // Amount of time to wait for our lock requests to be honored before giving up.
28 const int kLockFailTimeoutMs = 4000;
29
30 // When the button has been held continuously from the unlocked state, amount of
31 // time that we wait after the screen locker window is shown before starting the
32 // pre-shutdown animation.
33 const int kLockToShutdownTimeoutMs = 150;
34
35 // Amount of time taken to scale the snapshot of the screen down to a
36 // slightly-smaller size once the user starts holding the power button. Used
37 // for both the pre-lock and pre-shutdown animations.
38 const int kSlowCloseAnimMs = 400;
39
40 // Amount of time taken to scale the snapshot of the screen back to its original
41 // size when the button is released.
42 const int kUndoSlowCloseAnimMs = 100;
43
44 // Amount of time taken to scale the snapshot down to a point in the center of
45 // the screen once the screen has been locked or we've been notified that the
46 // system is shutting down.
47 const int kFastCloseAnimMs = 150;
48
49 // Additional time (beyond kFastCloseAnimMs) to wait after starting the
50 // fast-close shutdown animation before actually requesting shutdown, to give
51 // the animation time to finish.
52 const int kShutdownRequestDelayMs = 50;
53
54 } // namespace
55
56 PowerButtonController::TestApi::TestApi(PowerButtonController* controller)
57 : controller_(controller),
58 animator_api_(new internal::SessionStateAnimator::TestApi(
59 controller->animator_.get())) {
60 }
61
62 PowerButtonController::TestApi::~TestApi() {
63 }
64
65 PowerButtonController::PowerButtonController()
66 : login_status_(user::LOGGED_IN_NONE),
67 unlocked_login_status_(user::LOGGED_IN_NONE),
68 power_button_down_(false),
69 lock_button_down_(false), 21 lock_button_down_(false),
70 screen_is_off_(false), 22 screen_is_off_(false),
71 shutting_down_(false),
72 has_legacy_power_button_( 23 has_legacy_power_button_(
73 CommandLine::ForCurrentProcess()->HasSwitch( 24 CommandLine::ForCurrentProcess()->HasSwitch(
74 switches::kAuraLegacyPowerButton)), 25 switches::kAuraLegacyPowerButton)),
75 animator_(new internal::SessionStateAnimator()) { 26 controller_(controller) {
76 Shell::GetPrimaryRootWindow()->AddRootWindowObserver(this);
77 } 27 }
78 28
79 PowerButtonController::~PowerButtonController() { 29 PowerButtonController::~PowerButtonController() {
80 Shell::GetPrimaryRootWindow()->RemoveRootWindowObserver(this);
81 }
82
83 void PowerButtonController::OnLoginStateChanged(user::LoginStatus status) {
84 login_status_ = status;
85 unlocked_login_status_ = user::LOGGED_IN_NONE;
86 }
87
88 void PowerButtonController::OnAppTerminating() {
89 // If we hear that Chrome is exiting but didn't request it ourselves, all we
90 // can really hope for is that we'll have time to clear the screen.
91 if (!shutting_down_) {
92 shutting_down_ = true;
93 Shell* shell = ash::Shell::GetInstance();
94 shell->env_filter()->set_cursor_hidden_by_filter(false);
95 shell->cursor_manager()->ShowCursor(false);
96 animator_->ShowBlackLayer();
97 animator_->StartAnimation(
98 internal::SessionStateAnimator::kAllContainersMask,
99 internal::SessionStateAnimator::ANIMATION_HIDE);
100 }
101 }
102
103 void PowerButtonController::OnLockStateChanged(bool locked) {
104 if (shutting_down_ || (login_status_ == user::LOGGED_IN_LOCKED) == locked)
105 return;
106
107 if (!locked && login_status_ == user::LOGGED_IN_LOCKED) {
108 login_status_ = unlocked_login_status_;
109 unlocked_login_status_ = user::LOGGED_IN_NONE;
110 } else {
111 unlocked_login_status_ = login_status_;
112 login_status_ = user::LOGGED_IN_LOCKED;
113 }
114
115 if (locked) {
116 animator_->StartAnimation(
117 internal::SessionStateAnimator::LOCK_SCREEN_CONTAINERS,
118 internal::SessionStateAnimator::ANIMATION_FADE_IN);
119 lock_timer_.Stop();
120 lock_fail_timer_.Stop();
121
122 if (!has_legacy_power_button_ && power_button_down_) {
123 lock_to_shutdown_timer_.Stop();
124 lock_to_shutdown_timer_.Start(
125 FROM_HERE,
126 base::TimeDelta::FromMilliseconds(kLockToShutdownTimeoutMs),
127 this, &PowerButtonController::OnLockToShutdownTimeout);
128 }
129 } else {
130 animator_->StartAnimation(
131 internal::SessionStateAnimator::DESKTOP_BACKGROUND |
132 internal::SessionStateAnimator::LAUNCHER |
133 internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
134 internal::SessionStateAnimator::ANIMATION_RESTORE);
135 animator_->DropBlackLayer();
136 }
137 } 30 }
138 31
139 void PowerButtonController::OnScreenBrightnessChanged(double percent) { 32 void PowerButtonController::OnScreenBrightnessChanged(double percent) {
140 screen_is_off_ = percent <= 0.001; 33 screen_is_off_ = percent <= 0.001;
141 } 34 }
142 35
143 void PowerButtonController::OnStartingLock() {
144 if (shutting_down_ || login_status_ == user::LOGGED_IN_LOCKED)
145 return;
146
147 // Ensure that the black layer is visible -- if the screen was locked via
148 // the wrench menu, we won't have already shown the black background
149 // as part of the slow-close animation.
150 animator_->ShowBlackLayer();
151
152 animator_->StartAnimation(
153 internal::SessionStateAnimator::LAUNCHER,
154 internal::SessionStateAnimator::ANIMATION_HIDE);
155
156 animator_->StartAnimation(
157 internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
158 internal::SessionStateAnimator::ANIMATION_FAST_CLOSE);
159
160 // Hide the screen locker containers so we can make them fade in later.
161 animator_->StartAnimation(
162 internal::SessionStateAnimator::LOCK_SCREEN_CONTAINERS,
163 internal::SessionStateAnimator::ANIMATION_HIDE);
164 }
165
166 void PowerButtonController::OnPowerButtonEvent( 36 void PowerButtonController::OnPowerButtonEvent(
167 bool down, const base::TimeTicks& timestamp) { 37 bool down, const base::TimeTicks& timestamp) {
168 power_button_down_ = down; 38 power_button_down_ = down;
169 39
170 if (shutting_down_) 40 if (controller_->IsShuttingDown())
171 return; 41 return;
172 42
173 // 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
174 // while the screen is off (http://crbug.com/128451). 44 // while the screen is off (http://crbug.com/128451).
175 if (screen_is_off_) 45 if (screen_is_off_)
176 return; 46 return;
177 47
178 if (has_legacy_power_button_) { 48 if (has_legacy_power_button_) {
179 // 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
180 // running on official hardware, just lock the screen or shut down 50 // running on official hardware, just lock the screen or shut down
181 // immediately. 51 // immediately.
182 if (down) { 52 if (down) {
183 animator_->ShowBlackLayer(); 53 if (controller_->IsEligibleForLock()) {
Nikita (slow) 2012/10/09 18:30:06 nit: Drop {} here now that each block is exactly 1
Denis Kuznetsov (DE-MUC) 2012/10/11 11:37:12 Done.
184 if (LoggedInAsNonGuest() && login_status_ != user::LOGGED_IN_LOCKED) { 54 controller_->StartLockAnimationButLockImmediately();
185 animator_->StartAnimation(
186 internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
187 internal::SessionStateAnimator::ANIMATION_SLOW_CLOSE);
188 OnLockTimeout();
189 } else { 55 } else {
190 OnShutdownTimeout(); 56 controller_->ShutdownImmediately();
191 } 57 }
192 } 58 }
193 } else { // !has_legacy_power_button_ 59 } else { // !has_legacy_power_button_
194 if (down) { 60 if (down) {
195 // If we already have a pending request to lock the screen, wait. 61 // If we already have a pending request to lock the screen, wait.
196 if (lock_fail_timer_.IsRunning()) 62 if (controller_->IsTryingToLock())
197 return; 63 return;
198 64
199 if (LoggedInAsNonGuest() && login_status_ != user::LOGGED_IN_LOCKED) 65 if (controller_->IsEligibleForLock())
200 StartLockTimer(); 66 controller_->StartCancellableLock();
201 else 67 else
202 StartShutdownTimer(); 68 controller_->StartCancellableShutdown();
203 } else { // Button is up. 69 } else { // Button is up.
204 if (lock_timer_.IsRunning() || shutdown_timer_.IsRunning()) { 70 if (controller_->CanCancelLock())
205 if (login_status_ == user::LOGGED_IN_LOCKED) { 71 controller_->CancelLock();
206 // If we've already started shutdown transition at lock screen 72 else if (controller_->CanCancelShutdown())
207 // desktop background needs to be restored immediately. 73 controller_->CancelShutdown();
208 animator_->StartAnimation(
209 internal::SessionStateAnimator::DESKTOP_BACKGROUND,
210 internal::SessionStateAnimator::ANIMATION_RESTORE);
211 }
212 animator_->StartAnimation(
213 (login_status_ == user::LOGGED_IN_LOCKED) ?
214 internal::SessionStateAnimator::kAllLockScreenContainersMask :
215 internal::SessionStateAnimator::kAllContainersMask,
216 internal::SessionStateAnimator::ANIMATION_UNDO_SLOW_CLOSE);
217 }
218
219 // Drop the black layer after the undo animation finishes.
220 if (lock_timer_.IsRunning() ||
221 (shutdown_timer_.IsRunning() && !LoggedInAsNonGuest())) {
222 animator_->ScheduleDropBlackLayer();
223 }
224
225 lock_timer_.Stop();
226 shutdown_timer_.Stop();
227 lock_to_shutdown_timer_.Stop();
228 } 74 }
229 } 75 }
230 } 76 }
231 77
232 void PowerButtonController::OnLockButtonEvent( 78 void PowerButtonController::OnLockButtonEvent(
233 bool down, const base::TimeTicks& timestamp) { 79 bool down, const base::TimeTicks& timestamp) {
234 lock_button_down_ = down; 80 lock_button_down_ = down;
235 81
236 if (shutting_down_ || !LoggedInAsNonGuest()) 82 if (controller_->IsShuttingDown() || !controller_->IsEligibleForLock())
237 return; 83 return;
238 84
239 // Bail if we're already locked or are in the process of locking. Also give 85 // Bail if we're already locked or are in the process of locking. Also give
240 // the power button precedence over the lock button (we don't expect both 86 // the power button precedence over the lock button (we don't expect both
241 // buttons to be present, so this is just making sure that we don't do 87 // buttons to be present, so this is just making sure that we don't do
242 // something completely stupid if that assumption changes later). 88 // something completely stupid if that assumption changes later).
243 if (login_status_ == user::LOGGED_IN_LOCKED || 89 if (power_button_down_)
244 lock_fail_timer_.IsRunning() || power_button_down_) 90 return;
91
92 if (controller_->IsLocked() ||
Nikita (slow) 2012/10/09 18:30:06 nit: Fit condition on one line.
Denis Kuznetsov (DE-MUC) 2012/10/11 11:37:12 Done.
93 controller_->IsTryingToLock())
245 return; 94 return;
246 95
247 if (down) { 96 if (down) {
Nikita (slow) 2012/10/09 18:30:06 nit: Please drop {} here.
Denis Kuznetsov (DE-MUC) 2012/10/11 11:37:12 Done.
248 StartLockTimer(); 97 controller_->StartCancellableLock();
249 } else { 98 } else {
250 if (lock_timer_.IsRunning()) { 99 controller_->CancelLockWithOtherAnimation();
251 animator_->StartAnimation(
252 internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
253 internal::SessionStateAnimator::ANIMATION_UNDO_SLOW_CLOSE);
254 animator_->ScheduleDropBlackLayer();
255 lock_timer_.Stop();
256 }
257 } 100 }
258 } 101 }
259 102
260 void PowerButtonController::RequestShutdown() {
261 if (!shutting_down_)
262 StartShutdownAnimationAndRequestShutdown();
263 }
264
265 void PowerButtonController::OnRootWindowHostCloseRequested(
266 const aura::RootWindow*) {
267 if(Shell::GetInstance() && Shell::GetInstance()->delegate())
268 Shell::GetInstance()->delegate()->Exit();
269 }
270
271 bool PowerButtonController::LoggedInAsNonGuest() const {
272 if (login_status_ == user::LOGGED_IN_NONE)
273 return false;
274 if (login_status_ == user::LOGGED_IN_GUEST)
275 return false;
276 // TODO(mukai): think about kiosk mode.
277 return true;
278 }
279
280 void PowerButtonController::OnLockTimeout() {
281 delegate_->RequestLockScreen();
282 lock_fail_timer_.Start(
283 FROM_HERE,
284 base::TimeDelta::FromMilliseconds(kLockFailTimeoutMs),
285 this, &PowerButtonController::OnLockFailTimeout);
286 }
287
288 void PowerButtonController::OnLockFailTimeout() {
289 DCHECK_NE(login_status_, user::LOGGED_IN_LOCKED);
290 LOG(ERROR) << "Screen lock request timed out";
291 animator_->StartAnimation(
292 internal::SessionStateAnimator::LAUNCHER |
293 internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
294 internal::SessionStateAnimator::ANIMATION_RESTORE);
295 animator_->DropBlackLayer();
296 }
297
298 void PowerButtonController::OnLockToShutdownTimeout() {
299 DCHECK_EQ(login_status_, user::LOGGED_IN_LOCKED);
300 StartShutdownTimer();
301 }
302
303 void PowerButtonController::OnShutdownTimeout() {
304 if (!shutting_down_)
305 StartShutdownAnimationAndRequestShutdown();
306 }
307
308 void PowerButtonController::OnRealShutdownTimeout() {
309 DCHECK(shutting_down_);
310 delegate_->RequestShutdown();
311 }
312
313 void PowerButtonController::StartLockTimer() {
314 animator_->ShowBlackLayer();
315 animator_->StartAnimation(
316 internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS,
317 internal::SessionStateAnimator::ANIMATION_SLOW_CLOSE);
318 lock_timer_.Stop();
319 lock_timer_.Start(FROM_HERE,
320 base::TimeDelta::FromMilliseconds(kSlowCloseAnimMs),
321 this, &PowerButtonController::OnLockTimeout);
322 }
323
324 void PowerButtonController::StartShutdownTimer() {
325 animator_->ShowBlackLayer();
326 animator_->StartAnimation(
327 internal::SessionStateAnimator::kAllContainersMask,
328 internal::SessionStateAnimator::ANIMATION_SLOW_CLOSE);
329 shutdown_timer_.Stop();
330 shutdown_timer_.Start(
331 FROM_HERE,
332 base::TimeDelta::FromMilliseconds(kShutdownTimeoutMs),
333 this, &PowerButtonController::OnShutdownTimeout);
334 }
335
336 void PowerButtonController::StartShutdownAnimationAndRequestShutdown() {
337 DCHECK(!shutting_down_);
338 shutting_down_ = true;
339
340 Shell* shell = ash::Shell::GetInstance();
341 shell->env_filter()->set_cursor_hidden_by_filter(false);
342 shell->cursor_manager()->ShowCursor(false);
343
344 animator_->ShowBlackLayer();
345 if (login_status_ != user::LOGGED_IN_NONE) {
346 // Hide the other containers before starting the animation.
347 // ANIMATION_FAST_CLOSE will make the screen locker windows partially
348 // transparent, and we don't want the other windows to show through.
349 animator_->StartAnimation(
350 internal::SessionStateAnimator::NON_LOCK_SCREEN_CONTAINERS |
351 internal::SessionStateAnimator::LAUNCHER,
352 internal::SessionStateAnimator::ANIMATION_HIDE);
353 animator_->StartAnimation(
354 internal::SessionStateAnimator::kAllLockScreenContainersMask,
355 internal::SessionStateAnimator::ANIMATION_FAST_CLOSE);
356 } else {
357 animator_->StartAnimation(
358 internal::SessionStateAnimator::kAllContainersMask,
359 internal::SessionStateAnimator::ANIMATION_FAST_CLOSE);
360 }
361
362 real_shutdown_timer_.Start(
363 FROM_HERE,
364 base::TimeDelta::FromMilliseconds(
365 kFastCloseAnimMs + kShutdownRequestDelayMs),
366 this, &PowerButtonController::OnRealShutdownTimeout);
367 }
368
369 } // namespace ash 103 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698