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

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

Issue 2474913004: Tablet-like power button behavior on Convertible/Tablet ChromeOS devices (Closed)
Patch Set: Created 4 years, 1 month 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/common/accelerators/accelerator_controller.h" 7 #include "ash/common/accelerators/accelerator_controller.h"
8 #include "ash/common/ash_switches.h" 8 #include "ash/common/ash_switches.h"
9 #include "ash/common/session/session_state_delegate.h" 9 #include "ash/common/session/session_state_delegate.h"
10 #include "ash/common/system/audio/tray_audio.h" 10 #include "ash/common/system/audio/tray_audio.h"
11 #include "ash/common/system/tray/system_tray.h" 11 #include "ash/common/system/tray/system_tray.h"
12 #include "ash/common/wm/maximize_mode/maximize_mode_controller.h" 12 #include "ash/common/wm/maximize_mode/maximize_mode_controller.h"
13 #include "ash/common/wm_shell.h" 13 #include "ash/common/wm_shell.h"
14 #include "ash/public/cpp/shell_window_ids.h" 14 #include "ash/public/cpp/shell_window_ids.h"
15 #include "ash/shell.h" 15 #include "ash/shell.h"
16 #include "ash/wm/lock_state_controller.h" 16 #include "ash/wm/lock_state_controller.h"
17 #include "ash/wm/session_state_animator.h" 17 #include "ash/wm/session_state_animator.h"
18 #include "base/command_line.h" 18 #include "base/command_line.h"
19 #include "ui/aura/window_event_dispatcher.h" 19 #include "ui/aura/window_event_dispatcher.h"
20 #include "ui/display/types/display_snapshot.h" 20 #include "ui/display/types/display_snapshot.h"
21 #include "ui/events/event_handler.h" 21 #include "ui/events/event_handler.h"
22 #include "ui/wm/core/compound_event_filter.h" 22 #include "ui/wm/core/compound_event_filter.h"
23 23
24 #if defined(OS_CHROMEOS) 24 #if defined(OS_CHROMEOS)
25 #include "ash/wm/tablet_power_state_delegate_chromeos.h"
25 #include "chromeos/audio/cras_audio_handler.h" 26 #include "chromeos/audio/cras_audio_handler.h"
26 #include "chromeos/dbus/dbus_thread_manager.h" 27 #include "chromeos/dbus/dbus_thread_manager.h"
27 #endif 28 #endif
28 29
29 namespace ash { 30 namespace ash {
30 31
32 namespace {
33 // 1s timer before starting shutdown animation. If power button released event
34 // is not received before timeout, |controller_| will take the duty to start
35 // shutdown animation.
36 const int kTabletPreStartShutdownAnimationTimeoutMs = 1000;
37 } // namespace
38
39 PowerButtonController::TestApi::TestApi(PowerButtonController* controller)
40 : controller_(controller) {}
41
42 PowerButtonController::TestApi::~TestApi() {}
43
31 PowerButtonController::PowerButtonController(LockStateController* controller) 44 PowerButtonController::PowerButtonController(LockStateController* controller)
32 : power_button_down_(false), 45 : power_button_down_(false),
33 lock_button_down_(false), 46 lock_button_down_(false),
34 volume_down_pressed_(false), 47 volume_down_pressed_(false),
35 #if defined(OS_CHROMEOS) 48 #if defined(OS_CHROMEOS)
36 volume_percent_before_screenshot_(0), 49 volume_percent_before_screenshot_(0),
37 #endif 50 #endif
38 brightness_is_zero_(false), 51 brightness_is_zero_(false),
39 internal_display_off_and_external_display_on_(false), 52 internal_display_off_and_external_display_on_(false),
40 has_legacy_power_button_( 53 has_legacy_power_button_(
41 base::CommandLine::ForCurrentProcess()->HasSwitch( 54 base::CommandLine::ForCurrentProcess()->HasSwitch(
42 switches::kAuraLegacyPowerButton)), 55 switches::kAuraLegacyPowerButton)),
43 #if defined(OS_CHROMEOS) 56 #if defined(OS_CHROMEOS)
44 enable_quick_lock_(base::CommandLine::ForCurrentProcess()->HasSwitch( 57 enable_quick_lock_(base::CommandLine::ForCurrentProcess()->HasSwitch(
45 switches::kAshEnableTouchView)), 58 switches::kAshEnableTouchView)),
46 #else 59 #else
47 enable_quick_lock_(false), 60 enable_quick_lock_(false),
48 #endif 61 #endif
49 controller_(controller) { 62 controller_(controller),
63 pressed_on_screen_off_(false),
64 backlights_forced_off_(false) {
50 #if defined(OS_CHROMEOS) 65 #if defined(OS_CHROMEOS)
51 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->AddObserver( 66 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->AddObserver(
52 this); 67 this);
53 Shell::GetInstance()->display_configurator()->AddObserver(this); 68 Shell::GetInstance()->display_configurator()->AddObserver(this);
54 #endif 69 #endif
55 Shell::GetInstance()->PrependPreTargetHandler(this); 70 Shell::GetInstance()->PrependPreTargetHandler(this);
71 #if defined(OS_CHROMEOS)
72 tablet_power_state_delegate_ =
73 base::MakeUnique<TabletPowerStateDelegateChromeos>();
Daniel Erat 2016/11/03 21:28:08 i don't understand the reason for this delegate.
Qiang(Joe) Xu 2016/11/04 01:14:03 done, thanks. I was thinking using |delegate_| ini
74 #endif
75
76 base::ThreadTaskRunnerHandle::Get()->PostTask(
Daniel Erat 2016/11/03 21:28:08 what's the reason for posting this instead of just
Qiang(Joe) Xu 2016/11/04 01:14:04 I think just GetInitialBacklightsForcedOff should
77 FROM_HERE,
78 base::Bind(&PowerButtonController::GetInitialBacklightsForcedOff,
79 base::Unretained(this)));
56 } 80 }
57 81
58 PowerButtonController::~PowerButtonController() { 82 PowerButtonController::~PowerButtonController() {
83 #if defined(OS_CHROMEOS)
84 tablet_power_state_delegate_.reset();
85 #endif
59 Shell::GetInstance()->RemovePreTargetHandler(this); 86 Shell::GetInstance()->RemovePreTargetHandler(this);
60 #if defined(OS_CHROMEOS) 87 #if defined(OS_CHROMEOS)
61 Shell::GetInstance()->display_configurator()->RemoveObserver(this); 88 Shell::GetInstance()->display_configurator()->RemoveObserver(this);
62 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver( 89 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver(
63 this); 90 this);
64 #endif 91 #endif
65 } 92 }
66 93
67 void PowerButtonController::OnScreenBrightnessChanged(double percent) { 94 void PowerButtonController::OnScreenBrightnessChanged(double percent) {
68 brightness_is_zero_ = percent <= 0.001; 95 brightness_is_zero_ = percent <= 0.001;
69 } 96 }
70 97
71 void PowerButtonController::OnPowerButtonEvent( 98 void PowerButtonController::OnPowerButtonEvent(
72 bool down, 99 bool down,
73 const base::TimeTicks& timestamp) { 100 const base::TimeTicks& timestamp) {
74 power_button_down_ = down; 101 power_button_down_ = down;
75 102
76 if (controller_->ShutdownRequested()) 103 if (controller_->ShutdownRequested())
77 return; 104 return;
78 105
106 if (!has_legacy_power_button_ && !MaybeTakeScreenshot(down) &&
Daniel Erat 2016/11/03 21:28:07 instead of calling this helper method twice, why n
Qiang(Joe) Xu 2016/11/04 01:14:04 Done.
107 WmShell::Get()->maximize_mode_controller()->CanEnterMaximizeMode()) {
108 OnTabletPowerButtonEvent(down, timestamp);
109 return;
110 }
111
79 // Avoid starting the lock/shutdown sequence if the power button is pressed 112 // Avoid starting the lock/shutdown sequence if the power button is pressed
80 // while the screen is off (http://crbug.com/128451), unless an external 113 // while the screen is off (http://crbug.com/128451), unless an external
81 // display is still on (http://crosbug.com/p/24912). 114 // display is still on (http://crosbug.com/p/24912).
82 if (brightness_is_zero_ && !internal_display_off_and_external_display_on_) 115 if (brightness_is_zero_ && !internal_display_off_and_external_display_on_)
83 return; 116 return;
84 117
85 if (volume_down_pressed_ && down && 118 if (MaybeTakeScreenshot(down)) {
86 WmShell::Get()
87 ->maximize_mode_controller()
88 ->IsMaximizeModeWindowManagerEnabled()) {
89 SystemTray* system_tray = Shell::GetInstance()->GetPrimarySystemTray(); 119 SystemTray* system_tray = Shell::GetInstance()->GetPrimarySystemTray();
90 if (system_tray && system_tray->GetTrayAudio()) 120 if (system_tray && system_tray->GetTrayAudio())
91 system_tray->GetTrayAudio()->HideDetailedView(false); 121 system_tray->GetTrayAudio()->HideDetailedView(false);
92 122
93 WmShell::Get()->accelerator_controller()->PerformActionIfEnabled( 123 WmShell::Get()->accelerator_controller()->PerformActionIfEnabled(
94 TAKE_SCREENSHOT); 124 TAKE_SCREENSHOT);
95 125
96 #if defined(OS_CHROMEOS) 126 #if defined(OS_CHROMEOS)
97 // Restore volume. 127 // Restore volume.
98 chromeos::CrasAudioHandler* audio_handler = 128 chromeos::CrasAudioHandler* audio_handler =
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 if (power_button_down_) 193 if (power_button_down_)
164 return; 194 return;
165 195
166 if (down) 196 if (down)
167 controller_->StartLockAnimation(false); 197 controller_->StartLockAnimation(false);
168 else 198 else
169 controller_->CancelLockAnimation(); 199 controller_->CancelLockAnimation();
170 } 200 }
171 201
172 void PowerButtonController::OnKeyEvent(ui::KeyEvent* event) { 202 void PowerButtonController::OnKeyEvent(ui::KeyEvent* event) {
203 WakeOnLaptopMode();
173 if (event->key_code() == ui::VKEY_VOLUME_DOWN) { 204 if (event->key_code() == ui::VKEY_VOLUME_DOWN) {
174 volume_down_pressed_ = event->type() == ui::ET_KEY_PRESSED; 205 volume_down_pressed_ = event->type() == ui::ET_KEY_PRESSED;
175 #if defined(OS_CHROMEOS) 206 #if defined(OS_CHROMEOS)
176 if (!event->is_repeat()) { 207 if (!event->is_repeat()) {
177 chromeos::CrasAudioHandler* audio_handler = 208 chromeos::CrasAudioHandler* audio_handler =
178 chromeos::CrasAudioHandler::Get(); 209 chromeos::CrasAudioHandler::Get();
179 volume_percent_before_screenshot_ = 210 volume_percent_before_screenshot_ =
180 audio_handler->GetOutputVolumePercent(); 211 audio_handler->GetOutputVolumePercent();
181 } 212 }
182 #endif 213 #endif
183 } 214 }
184 } 215 }
185 216
217 void PowerButtonController::OnMouseEvent(ui::MouseEvent* event) {
218 WakeOnLaptopMode();
219 }
220
186 #if defined(OS_CHROMEOS) 221 #if defined(OS_CHROMEOS)
187 void PowerButtonController::OnDisplayModeChanged( 222 void PowerButtonController::OnDisplayModeChanged(
188 const ui::DisplayConfigurator::DisplayStateList& display_states) { 223 const ui::DisplayConfigurator::DisplayStateList& display_states) {
189 bool internal_display_off = false; 224 bool internal_display_off = false;
190 bool external_display_on = false; 225 bool external_display_on = false;
191 for (const ui::DisplaySnapshot* display : display_states) { 226 for (const ui::DisplaySnapshot* display : display_states) {
192 if (display->type() == ui::DISPLAY_CONNECTION_TYPE_INTERNAL) { 227 if (display->type() == ui::DISPLAY_CONNECTION_TYPE_INTERNAL) {
193 if (!display->current_mode()) 228 if (!display->current_mode())
194 internal_display_off = true; 229 internal_display_off = true;
195 } else if (display->current_mode()) { 230 } else if (display->current_mode()) {
196 external_display_on = true; 231 external_display_on = true;
197 } 232 }
198 } 233 }
199 internal_display_off_and_external_display_on_ = 234 internal_display_off_and_external_display_on_ =
200 internal_display_off && external_display_on; 235 internal_display_off && external_display_on;
201 } 236 }
202 237
203 void PowerButtonController::PowerButtonEventReceived( 238 void PowerButtonController::PowerButtonEventReceived(
204 bool down, 239 bool down,
205 const base::TimeTicks& timestamp) { 240 const base::TimeTicks& timestamp) {
206 OnPowerButtonEvent(down, timestamp); 241 OnPowerButtonEvent(down, timestamp);
207 } 242 }
208 #endif // defined(OS_CHROMEOS) 243 #endif // defined(OS_CHROMEOS)
209 244
245 void PowerButtonController::OnTabletPowerButtonEvent(
246 bool down,
247 const base::TimeTicks& timestamp) {
248 if (!tablet_power_state_delegate_)
249 return;
250
251 // When screen is off, SetBacklightsForcedOff(false) takes action on power
252 // button pressed.
253 // When screen is on, SetBacklightsForcedOff(true) takes action when power
254 // button is released before the |tablet_pre_start_shutdown_animation_timer_|
255 // is timeout.
256 if (down) {
257 if (backlights_forced_off_ || brightness_is_zero_) {
258 pressed_on_screen_off_ = true;
Daniel Erat 2016/11/03 21:28:07 it seems a bit safer to set this unconditionally h
Qiang(Joe) Xu 2016/11/04 01:14:03 done. If backlights_forced_off_is true, brightness
Daniel Erat 2016/11/04 16:12:51 i think that 2 is much better, since it ensures th
Qiang(Joe) Xu 2016/11/04 19:29:51 Done.
259 SetBacklightsForcedOff(false);
260 }
261 StartTabletPreStartShutdownAnimationTimer();
262 } else {
263 if (pressed_on_screen_off_) {
264 if (tablet_pre_start_shutdown_animation_timer_.IsRunning())
265 tablet_pre_start_shutdown_animation_timer_.Stop();
266 pressed_on_screen_off_ = false;
267 } else {
268 if (tablet_pre_start_shutdown_animation_timer_.IsRunning()) {
269 tablet_pre_start_shutdown_animation_timer_.Stop();
270 SetBacklightsForcedOff(true);
271 LockScreenIfRequired();
272 }
273 }
274 // When power button is released, Cancel Shutdown animation whenever it is
275 // still cancellable.
276 if (controller_->CanCancelShutdownAnimation())
277 controller_->CancelShutdownAnimation();
278 }
279 }
280
281 void PowerButtonController::SetBacklightsForcedOff(bool forced_off) {
282 if (!tablet_power_state_delegate_ || backlights_forced_off_ == forced_off)
283 return;
284
285 tablet_power_state_delegate_->SetBacklightsForcedOff(forced_off);
286 backlights_forced_off_ = forced_off;
287 }
288
289 void PowerButtonController::GetInitialBacklightsForcedOff() {
290 if (!tablet_power_state_delegate_)
291 return;
292
293 tablet_power_state_delegate_->GetBacklightsForcedOff(
294 base::Bind(&PowerButtonController::HandleInitialBacklightsForcedOff,
295 base::Unretained(this)));
296 }
297
298 void PowerButtonController::HandleInitialBacklightsForcedOff(
299 bool is_forced_off) {
300 backlights_forced_off_ = is_forced_off;
301 if (is_forced_off)
302 SetBacklightsForcedOff(false);
Daniel Erat 2016/11/03 21:28:07 i don't understand why this call is needed. the ba
Qiang(Joe) Xu 2016/11/04 01:14:03 I thought when constructed, user should face non-f
303 }
304
305 void PowerButtonController::StartTabletPreStartShutdownAnimationTimer() {
306 tablet_pre_start_shutdown_animation_timer_.Stop();
Daniel Erat 2016/11/03 21:28:08 you don't need this call to Stop(); Start() alread
Qiang(Joe) Xu 2016/11/04 01:14:03 Done.
307 tablet_pre_start_shutdown_animation_timer_.Start(
308 FROM_HERE, base::TimeDelta::FromMilliseconds(
309 kTabletPreStartShutdownAnimationTimeoutMs),
310 this, &PowerButtonController::OnTabletPreStartShutdownAnimationTimeout);
311 }
312
313 void PowerButtonController::OnTabletPreStartShutdownAnimationTimeout() {
314 controller_->StartShutdownAnimation();
315 }
316
317 void PowerButtonController::LockScreenIfRequired() {
318 SessionStateDelegate* session_state_delegate =
319 WmShell::Get()->GetSessionStateDelegate();
320 if (session_state_delegate->ShouldLockScreenAutomatically() &&
321 session_state_delegate->CanLockScreen() &&
322 !session_state_delegate->IsUserSessionBlocked() &&
323 !controller_->LockRequested()) {
324 session_state_delegate->LockScreen();
325 }
326 }
327
328 void PowerButtonController::WakeOnLaptopMode() {
Daniel Erat 2016/11/03 21:28:07 using the word "wake" here seems a bit inaccurate;
Qiang(Joe) Xu 2016/11/04 01:14:03 Done.
329 MaximizeModeController* maximize_mode_controller =
330 WmShell::Get()->maximize_mode_controller();
331 if (maximize_mode_controller &&
332 maximize_mode_controller->CanEnterMaximizeMode() &&
333 !maximize_mode_controller->IsMaximizeModeWindowManagerEnabled() &&
Daniel Erat 2016/11/03 21:28:07 i find all of these references to MaximizeModeCont
Qiang(Joe) Xu 2016/11/04 01:14:03 Done.
334 (backlights_forced_off_ || brightness_is_zero_)) {
Daniel Erat 2016/11/03 21:28:07 i don't understand the brightness_is_zero_ check h
Qiang(Joe) Xu 2016/11/04 01:14:03 Yes, brightness_is_zero_ is not needed. Thanks!
335 SetBacklightsForcedOff(false);
336 }
337 }
338
339 bool PowerButtonController::MaybeTakeScreenshot(bool power_button_pressed) {
340 return volume_down_pressed_ && power_button_pressed &&
341 WmShell::Get()
342 ->maximize_mode_controller()
343 ->IsMaximizeModeWindowManagerEnabled();
344 }
345
210 } // namespace ash 346 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698