OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/maximize_mode/maximize_mode_controller.h" | 5 #include "ash/wm/maximize_mode/maximize_mode_controller.h" |
6 | 6 |
7 #include "ash/accelerators/accelerator_controller.h" | 7 #include "ash/accelerators/accelerator_controller.h" |
8 #include "ash/accelerators/accelerator_table.h" | 8 #include "ash/accelerators/accelerator_table.h" |
9 #include "ash/accelerometer/accelerometer_controller.h" | 9 #include "ash/accelerometer/accelerometer_controller.h" |
10 #include "ash/ash_switches.h" | 10 #include "ash/ash_switches.h" |
11 #include "ash/display/display_manager.h" | 11 #include "ash/display/display_manager.h" |
12 #include "ash/shell.h" | 12 #include "ash/shell.h" |
13 #include "ash/wm/maximize_mode/maximize_mode_window_manager.h" | 13 #include "ash/wm/maximize_mode/maximize_mode_window_manager.h" |
14 #include "ash/wm/maximize_mode/scoped_disable_internal_mouse_and_keyboard.h" | 14 #include "ash/wm/maximize_mode/scoped_disable_internal_mouse_and_keyboard.h" |
15 #include "base/auto_reset.h" | 15 #include "base/auto_reset.h" |
16 #include "base/command_line.h" | 16 #include "base/command_line.h" |
17 #include "base/metrics/histogram.h" | 17 #include "base/metrics/histogram.h" |
18 #include "chromeos/dbus/dbus_thread_manager.h" | |
jonross
2014/07/24 14:22:00
Can you confirm via gyp files that this will alway
bruthig
2014/07/24 19:57:06
Done.
| |
18 #include "ui/base/accelerators/accelerator.h" | 19 #include "ui/base/accelerators/accelerator.h" |
19 #include "ui/events/event.h" | 20 #include "ui/events/event.h" |
20 #include "ui/events/event_handler.h" | 21 #include "ui/events/event_handler.h" |
21 #include "ui/events/keycodes/keyboard_codes.h" | 22 #include "ui/events/keycodes/keyboard_codes.h" |
22 #include "ui/gfx/vector3d_f.h" | 23 #include "ui/gfx/vector3d_f.h" |
23 | 24 |
24 #if defined(USE_X11) | 25 #if defined(USE_X11) |
25 #include "ash/wm/maximize_mode/scoped_disable_internal_mouse_and_keyboard_x11.h" | 26 #include "ash/wm/maximize_mode/scoped_disable_internal_mouse_and_keyboard_x11.h" |
26 #endif | 27 #endif |
27 | 28 |
28 namespace ash { | 29 namespace ash { |
29 | 30 |
30 namespace { | 31 namespace { |
31 | 32 |
32 // The hinge angle at which to enter maximize mode. | 33 // The hinge angle at which to enter maximize mode. |
33 const float kEnterMaximizeModeAngle = 200.0f; | 34 const float kEnterMaximizeModeAngle = 200.0f; |
34 | 35 |
35 // The angle at which to exit maximize mode, this is specifically less than the | 36 // The angle at which to exit maximize mode, this is specifically less than the |
36 // angle to enter maximize mode to prevent rapid toggling when near the angle. | 37 // angle to enter maximize mode to prevent rapid toggling when near the angle. |
37 const float kExitMaximizeModeAngle = 160.0f; | 38 const float kExitMaximizeModeAngle = 160.0f; |
38 | 39 |
39 // When the lid is fully open 360 degrees, the accelerometer readings can | 40 // Defines a range for which accelerometer readings are considered accurate. |
40 // occasionally appear as though the lid is almost closed. If the lid appears | 41 // When the lid is near open (or near closed) the acceleromter readings may be |
41 // near closed but the device is on we assume it is an erroneous reading from | 42 // inaccurate and a lid that is fully open may appear to be near closed (and |
42 // it being open 360 degrees. | 43 // vice versa). |
43 const float kFullyOpenAngleErrorTolerance = 20.0f; | 44 const float kMinStableAngle = 20.0f; |
45 const float kMaxStableAngle = 340.0f; | |
46 | |
47 // The time in seconds to consider the lid to be recently opened. | |
48 // This is used to prevent entering maximize mode if an erroneous accelerometer | |
49 // reading makes the lid appear to be fully open when the user is opening the | |
50 // lid from a closed position. | |
51 const int kLidRecentlyOpenedTolerance = 2; | |
jonross
2014/07/24 14:22:00
For constants representing a time duration we appe
bruthig
2014/07/24 19:57:06
Done.
| |
44 | 52 |
45 // When the device approaches vertical orientation (i.e. portrait orientation) | 53 // When the device approaches vertical orientation (i.e. portrait orientation) |
46 // the accelerometers for the base and lid approach the same values (i.e. | 54 // the accelerometers for the base and lid approach the same values (i.e. |
47 // gravity pointing in the direction of the hinge). When this happens we cannot | 55 // gravity pointing in the direction of the hinge). When this happens we cannot |
48 // compute the hinge angle reliably and must turn ignore accelerometer readings. | 56 // compute the hinge angle reliably and must turn ignore accelerometer readings. |
49 // This is the minimum acceleration perpendicular to the hinge under which to | 57 // This is the minimum acceleration perpendicular to the hinge under which to |
50 // detect hinge angle. | 58 // detect hinge angle. |
51 const float kHingeAngleDetectionThreshold = 0.25f; | 59 const float kHingeAngleDetectionThreshold = 0.25f; |
52 | 60 |
53 // The maximum deviation from the acceleration expected due to gravity under | 61 // The maximum deviation from the acceleration expected due to gravity under |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
132 event->type() == ui::ET_KEY_PRESSED) { | 140 event->type() == ui::ET_KEY_PRESSED) { |
133 Shell::GetInstance()->accelerator_controller()->PerformAction( | 141 Shell::GetInstance()->accelerator_controller()->PerformAction( |
134 ash::TAKE_SCREENSHOT, ui::Accelerator()); | 142 ash::TAKE_SCREENSHOT, ui::Accelerator()); |
135 } | 143 } |
136 } | 144 } |
137 | 145 |
138 #endif // OS_CHROMEOS | 146 #endif // OS_CHROMEOS |
139 | 147 |
140 } // namespace | 148 } // namespace |
141 | 149 |
150 base::TimeTicks MaximizeModeController::TimeTickProviderImpl::Now() const { | |
151 return base::TimeTicks::Now(); | |
152 } | |
153 | |
142 MaximizeModeController::MaximizeModeController() | 154 MaximizeModeController::MaximizeModeController() |
143 : rotation_locked_(false), | 155 : rotation_locked_(false), |
144 have_seen_accelerometer_data_(false), | 156 have_seen_accelerometer_data_(false), |
145 in_set_screen_rotation_(false), | 157 in_set_screen_rotation_(false), |
146 user_rotation_(gfx::Display::ROTATE_0), | 158 user_rotation_(gfx::Display::ROTATE_0), |
147 last_touchview_transition_time_(base::Time::Now()) { | 159 last_touchview_transition_time_(base::Time::Now()), |
160 last_lid_open_time_(), | |
161 time_tick_provider_(new TimeTickProviderImpl()), | |
162 lid_is_closed_(false) { | |
148 Shell::GetInstance()->accelerometer_controller()->AddObserver(this); | 163 Shell::GetInstance()->accelerometer_controller()->AddObserver(this); |
149 Shell::GetInstance()->AddShellObserver(this); | 164 Shell::GetInstance()->AddShellObserver(this); |
165 chromeos::DBusThreadManager::Get()-> | |
166 GetPowerManagerClient()->AddObserver(this); | |
150 } | 167 } |
151 | 168 |
152 MaximizeModeController::~MaximizeModeController() { | 169 MaximizeModeController::~MaximizeModeController() { |
153 Shell::GetInstance()->RemoveShellObserver(this); | 170 Shell::GetInstance()->RemoveShellObserver(this); |
154 Shell::GetInstance()->accelerometer_controller()->RemoveObserver(this); | 171 Shell::GetInstance()->accelerometer_controller()->RemoveObserver(this); |
172 chromeos::DBusThreadManager::Get()-> | |
173 GetPowerManagerClient()->RemoveObserver(this); | |
155 } | 174 } |
156 | 175 |
157 void MaximizeModeController::SetRotationLocked(bool rotation_locked) { | 176 void MaximizeModeController::SetRotationLocked(bool rotation_locked) { |
158 if (rotation_locked_ == rotation_locked) | 177 if (rotation_locked_ == rotation_locked) |
159 return; | 178 return; |
160 rotation_locked_ = rotation_locked; | 179 rotation_locked_ = rotation_locked; |
161 FOR_EACH_OBSERVER(Observer, observers_, | 180 FOR_EACH_OBSERVER(Observer, observers_, |
162 OnRotationLockChanged(rotation_locked_)); | 181 OnRotationLockChanged(rotation_locked_)); |
163 } | 182 } |
164 | 183 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
232 if (user_rotation != current_rotation_) { | 251 if (user_rotation != current_rotation_) { |
233 // A user may change other display configuration settings. When the user | 252 // A user may change other display configuration settings. When the user |
234 // does change the rotation setting, then lock rotation to prevent the | 253 // does change the rotation setting, then lock rotation to prevent the |
235 // accelerometer from erasing their change. | 254 // accelerometer from erasing their change. |
236 SetRotationLocked(true); | 255 SetRotationLocked(true); |
237 user_rotation_ = user_rotation; | 256 user_rotation_ = user_rotation; |
238 current_rotation_ = user_rotation; | 257 current_rotation_ = user_rotation; |
239 } | 258 } |
240 } | 259 } |
241 | 260 |
261 void MaximizeModeController::LidEventReceived(bool open, | |
262 const base::TimeTicks& time) { | |
263 if (open) | |
264 last_lid_open_time_ = time; | |
265 lid_is_closed_ = !open; | |
266 LeaveMaximizeMode(); | |
267 } | |
268 | |
269 void MaximizeModeController::SuspendImminent() { | |
270 RecordTouchViewStateTransition(); | |
271 } | |
272 | |
273 void MaximizeModeController::SuspendDone( | |
274 const base::TimeDelta& sleep_duration) { | |
275 last_touchview_transition_time_ = base::Time::Now(); | |
276 // A lid open event won't always occur when coming out of a suspend state. | |
jonross
2014/07/24 14:22:00
If it does not, is there a way to poll lid state u
bruthig
2014/07/24 19:57:06
I'm not sure if there is a way or not but I don't
jonross
2014/07/25 13:39:06
Acknowledged.
| |
277 lid_is_closed_ = false; | |
278 } | |
279 | |
242 void MaximizeModeController::HandleHingeRotation(const gfx::Vector3dF& base, | 280 void MaximizeModeController::HandleHingeRotation(const gfx::Vector3dF& base, |
243 const gfx::Vector3dF& lid) { | 281 const gfx::Vector3dF& lid) { |
244 static const gfx::Vector3dF hinge_vector(0.0f, 1.0f, 0.0f); | 282 static const gfx::Vector3dF hinge_vector(0.0f, 1.0f, 0.0f); |
245 bool maximize_mode_engaged = IsMaximizeModeWindowManagerEnabled(); | |
246 // Ignore the component of acceleration parallel to the hinge for the purposes | 283 // Ignore the component of acceleration parallel to the hinge for the purposes |
247 // of hinge angle calculation. | 284 // of hinge angle calculation. |
248 gfx::Vector3dF base_flattened(base); | 285 gfx::Vector3dF base_flattened(base); |
249 gfx::Vector3dF lid_flattened(lid); | 286 gfx::Vector3dF lid_flattened(lid); |
250 base_flattened.set_y(0.0f); | 287 base_flattened.set_y(0.0f); |
251 lid_flattened.set_y(0.0f); | 288 lid_flattened.set_y(0.0f); |
252 | 289 |
253 // As the hinge approaches a vertical angle, the base and lid accelerometers | 290 // As the hinge approaches a vertical angle, the base and lid accelerometers |
254 // approach the same values making any angle calculations highly inaccurate. | 291 // approach the same values making any angle calculations highly inaccurate. |
255 // Bail out early when it is too close. | 292 // Bail out early when it is too close. |
256 if (base_flattened.Length() < kHingeAngleDetectionThreshold || | 293 if (base_flattened.Length() < kHingeAngleDetectionThreshold || |
257 lid_flattened.Length() < kHingeAngleDetectionThreshold) { | 294 lid_flattened.Length() < kHingeAngleDetectionThreshold) { |
258 return; | 295 return; |
259 } | 296 } |
260 | 297 |
261 // Compute the angle between the base and the lid. | 298 // Compute the angle between the base and the lid. |
262 float angle = ClockwiseAngleBetweenVectorsInDegrees(base_flattened, | 299 float angle = ClockwiseAngleBetweenVectorsInDegrees(base_flattened, |
263 lid_flattened, hinge_vector); | 300 lid_flattened, hinge_vector); |
264 | |
265 // Toggle maximize mode on or off when corresponding thresholds are passed. | 301 // Toggle maximize mode on or off when corresponding thresholds are passed. |
266 // TODO(flackr): Make MaximizeModeController own the MaximizeModeWindowManager | 302 // TODO(flackr): Make MaximizeModeController own the MaximizeModeWindowManager |
267 // such that observations of state changes occur after the change and shell | 303 // such that observations of state changes occur after the change and shell |
268 // has fewer states to track. | 304 // has fewer states to track. |
269 if (maximize_mode_engaged && | 305 if (lid_is_closed_) { |
270 angle > kFullyOpenAngleErrorTolerance && | |
271 angle < kExitMaximizeModeAngle) { | |
272 LeaveMaximizeMode(); | 306 LeaveMaximizeMode(); |
273 } else if (!maximize_mode_engaged && | 307 } else if (angle > kMinStableAngle && |
jonross
2014/07/24 14:22:00
Should we exit MaximizeMode if angle <kMinStableAn
bruthig
2014/07/24 19:57:06
No we don't want to exit MaximizeMode in this case
jonross
2014/07/25 13:39:06
Acknowledged.
| |
274 angle > kEnterMaximizeModeAngle) { | 308 angle < kMaxStableAngle) { |
275 EnterMaximizeMode(); | 309 // Clear the last_lid_open_time_ for a stable reading so that there is less |
310 // chance of a delay if the lid is moved from the close state to the fully | |
311 // open state very quickly. | |
312 last_lid_open_time_ = base::TimeTicks(); | |
jonross
2014/07/24 14:22:00
This moves the lid open time to be later than when
bruthig
2014/07/24 19:57:06
I don't think this is doing what you think. It's
jonross
2014/07/25 13:39:06
My misreading.
| |
313 if (angle < kExitMaximizeModeAngle) { | |
314 LeaveMaximizeMode(); | |
315 } else if (angle > kEnterMaximizeModeAngle) { | |
316 EnterMaximizeMode(); | |
317 } | |
318 } else if (angle > kMaxStableAngle) { | |
319 if (WasLidOpenedRecently()) { | |
320 LeaveMaximizeMode(); | |
321 } else { | |
322 EnterMaximizeMode(); | |
323 } | |
276 } | 324 } |
277 } | 325 } |
278 | 326 |
279 void MaximizeModeController::HandleScreenRotation(const gfx::Vector3dF& lid) { | 327 void MaximizeModeController::HandleScreenRotation(const gfx::Vector3dF& lid) { |
280 bool maximize_mode_engaged = IsMaximizeModeWindowManagerEnabled(); | 328 bool maximize_mode_engaged = IsMaximizeModeWindowManagerEnabled(); |
281 | 329 |
282 // TODO(jonross): track the updated rotation angle even when locked. So that | 330 // TODO(jonross): track the updated rotation angle even when locked. So that |
283 // when rotation lock is removed the accelerometer rotation can be applied | 331 // when rotation lock is removed the accelerometer rotation can be applied |
284 // without waiting for the next update. | 332 // without waiting for the next update. |
285 if (!maximize_mode_engaged || rotation_locked_) | 333 if (!maximize_mode_engaged || rotation_locked_) |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
343 DisplayManager* display_manager, | 391 DisplayManager* display_manager, |
344 gfx::Display::Rotation rotation) { | 392 gfx::Display::Rotation rotation) { |
345 base::AutoReset<bool> auto_in_set_screen_rotation( | 393 base::AutoReset<bool> auto_in_set_screen_rotation( |
346 &in_set_screen_rotation_, true); | 394 &in_set_screen_rotation_, true); |
347 current_rotation_ = rotation; | 395 current_rotation_ = rotation; |
348 display_manager->SetDisplayRotation(gfx::Display::InternalDisplayId(), | 396 display_manager->SetDisplayRotation(gfx::Display::InternalDisplayId(), |
349 rotation); | 397 rotation); |
350 } | 398 } |
351 | 399 |
352 void MaximizeModeController::EnterMaximizeMode() { | 400 void MaximizeModeController::EnterMaximizeMode() { |
401 if (IsMaximizeModeWindowManagerEnabled()) | |
jonross
2014/07/24 14:22:00
We should stop calling this twice.
bruthig
2014/07/24 19:57:06
In order to stop calling it twice each spot that c
| |
402 return; | |
353 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); | 403 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); |
354 current_rotation_ = user_rotation_ = display_manager-> | 404 current_rotation_ = user_rotation_ = display_manager-> |
355 GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation(); | 405 GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation(); |
356 EnableMaximizeModeWindowManager(true); | 406 EnableMaximizeModeWindowManager(true); |
357 #if defined(USE_X11) | 407 #if defined(USE_X11) |
358 event_blocker_.reset(new ScopedDisableInternalMouseAndKeyboardX11); | 408 event_blocker_.reset(new ScopedDisableInternalMouseAndKeyboardX11); |
359 #endif | 409 #endif |
360 #if defined(OS_CHROMEOS) | 410 #if defined(OS_CHROMEOS) |
361 event_handler_.reset(new ScreenshotActionHandler); | 411 event_handler_.reset(new ScreenshotActionHandler); |
362 #endif | 412 #endif |
363 Shell::GetInstance()->display_controller()->AddObserver(this); | 413 Shell::GetInstance()->display_controller()->AddObserver(this); |
364 } | 414 } |
365 | 415 |
366 void MaximizeModeController::LeaveMaximizeMode() { | 416 void MaximizeModeController::LeaveMaximizeMode() { |
417 if (!IsMaximizeModeWindowManagerEnabled()) | |
418 return; | |
367 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); | 419 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); |
368 gfx::Display::Rotation current_rotation = display_manager-> | 420 gfx::Display::Rotation current_rotation = display_manager-> |
369 GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation(); | 421 GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation(); |
370 if (current_rotation != user_rotation_) | 422 if (current_rotation != user_rotation_) |
371 SetDisplayRotation(display_manager, user_rotation_); | 423 SetDisplayRotation(display_manager, user_rotation_); |
372 rotation_locked_ = false; | 424 rotation_locked_ = false; |
373 EnableMaximizeModeWindowManager(false); | 425 EnableMaximizeModeWindowManager(false); |
374 event_blocker_.reset(); | 426 event_blocker_.reset(); |
375 event_handler_.reset(); | 427 event_handler_.reset(); |
376 } | 428 Shell::GetInstance()->display_controller()->RemoveObserver(this); |
jonross
2014/07/24 14:22:00
Nice fix.
| |
377 | |
378 void MaximizeModeController::OnSuspend() { | |
379 RecordTouchViewStateTransition(); | |
380 } | |
381 | |
382 void MaximizeModeController::OnResume() { | |
383 last_touchview_transition_time_ = base::Time::Now(); | |
384 } | 429 } |
385 | 430 |
386 // Called after maximize mode has started, windows might still animate though. | 431 // Called after maximize mode has started, windows might still animate though. |
387 void MaximizeModeController::OnMaximizeModeStarted() { | 432 void MaximizeModeController::OnMaximizeModeStarted() { |
388 RecordTouchViewStateTransition(); | 433 RecordTouchViewStateTransition(); |
389 } | 434 } |
390 | 435 |
391 // Called after maximize mode has ended, windows might still be returning to | 436 // Called after maximize mode has ended, windows might still be returning to |
392 // their original position. | 437 // their original position. |
393 void MaximizeModeController::OnMaximizeModeEnded() { | 438 void MaximizeModeController::OnMaximizeModeEnded() { |
(...skipping 27 matching lines...) Expand all Loading... | |
421 base::TimeDelta total_runtime = total_touchview_time_ + | 466 base::TimeDelta total_runtime = total_touchview_time_ + |
422 total_non_touchview_time_; | 467 total_non_touchview_time_; |
423 if (total_runtime.InSeconds() > 0) { | 468 if (total_runtime.InSeconds() > 0) { |
424 UMA_HISTOGRAM_PERCENTAGE("Ash.TouchView.TouchViewActivePercentage", | 469 UMA_HISTOGRAM_PERCENTAGE("Ash.TouchView.TouchViewActivePercentage", |
425 100 * total_touchview_time_.InSeconds() / total_runtime.InSeconds()); | 470 100 * total_touchview_time_.InSeconds() / total_runtime.InSeconds()); |
426 } | 471 } |
427 } | 472 } |
428 Shell::GetInstance()->display_controller()->RemoveObserver(this); | 473 Shell::GetInstance()->display_controller()->RemoveObserver(this); |
429 } | 474 } |
430 | 475 |
476 bool MaximizeModeController::WasLidOpenedRecently() const { | |
477 bool was_lid_recently_opened = false; | |
478 if (!last_lid_open_time_.is_null()) { | |
jonross
2014/07/24 14:22:00
Quick exits are prefered.
if (last_lid_open_time_
bruthig
2014/07/24 19:57:06
Done.
| |
479 base::TimeTicks now = time_tick_provider_->Now(); | |
480 DCHECK(now >= last_lid_open_time_); | |
481 base::TimeDelta elapsed_time = now - last_lid_open_time_; | |
482 was_lid_recently_opened = | |
483 elapsed_time <= base::TimeDelta::FromSeconds(kLidRecentlyOpenedTolerance); | |
484 } | |
485 return was_lid_recently_opened; | |
486 } | |
487 | |
488 void MaximizeModeController::SetTimeTickProviderForTest( | |
489 TimeTickProvider* provider) { | |
490 DCHECK(provider); | |
491 time_tick_provider_.reset(provider); | |
492 } | |
493 | |
431 } // namespace ash | 494 } // namespace ash |
OLD | NEW |