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

Side by Side Diff: ash/wm/maximize_mode/maximize_mode_controller.cc

Issue 500613003: Use standardized and extendable accelerometer update type. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Merge and remove unused Vector3dF reference. Created 6 years, 3 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 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"
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 const float kMinStableAngle = 20.0f; 49 const float kMinStableAngle = 20.0f;
50 const float kMaxStableAngle = 340.0f; 50 const float kMaxStableAngle = 340.0f;
51 51
52 // The time duration to consider the lid to be recently opened. 52 // The time duration to consider the lid to be recently opened.
53 // This is used to prevent entering maximize mode if an erroneous accelerometer 53 // This is used to prevent entering maximize mode if an erroneous accelerometer
54 // reading makes the lid appear to be fully open when the user is opening the 54 // reading makes the lid appear to be fully open when the user is opening the
55 // lid from a closed position. 55 // lid from a closed position.
56 const base::TimeDelta kLidRecentlyOpenedDuration = 56 const base::TimeDelta kLidRecentlyOpenedDuration =
57 base::TimeDelta::FromSeconds(2); 57 base::TimeDelta::FromSeconds(2);
58 58
59 // The mean acceleration due to gravity on Earth in m/s^2.
60 const float kMeanGravity = 9.80665f;
61
59 // When the device approaches vertical orientation (i.e. portrait orientation) 62 // When the device approaches vertical orientation (i.e. portrait orientation)
60 // the accelerometers for the base and lid approach the same values (i.e. 63 // the accelerometers for the base and lid approach the same values (i.e.
61 // gravity pointing in the direction of the hinge). When this happens we cannot 64 // gravity pointing in the direction of the hinge). When this happens we cannot
62 // compute the hinge angle reliably and must turn ignore accelerometer readings. 65 // compute the hinge angle reliably and must turn ignore accelerometer readings.
63 // This is the minimum acceleration perpendicular to the hinge under which to 66 // This is the minimum acceleration perpendicular to the hinge under which to
64 // detect hinge angle. 67 // detect hinge angle in m/s^2.
65 const float kHingeAngleDetectionThreshold = 0.25f; 68 const float kHingeAngleDetectionThreshold = 2.5f;
66 69
67 // The maximum deviation from the acceleration expected due to gravity under 70 // The maximum deviation from the acceleration expected due to gravity under
68 // which to detect hinge angle and screen rotation. 71 // which to detect hinge angle and screen rotation in m/s^2
69 const float kDeviationFromGravityThreshold = 0.1f; 72 const float kDeviationFromGravityThreshold = 1.0f;
70 73
71 // The maximum deviation between the magnitude of the two accelerometers under 74 // The maximum deviation between the magnitude of the two accelerometers under
72 // which to detect hinge angle and screen rotation. These accelerometers are 75 // which to detect hinge angle and screen rotation in m/s^2. These
73 // attached to the same physical device and so should be under the same 76 // accelerometers are attached to the same physical device and so should be
74 // acceleration. 77 // under the same acceleration.
75 const float kNoisyMagnitudeDeviation = 0.1f; 78 const float kNoisyMagnitudeDeviation = 1.0f;
76 79
77 // The angle which the screen has to be rotated past before the display will 80 // The angle which the screen has to be rotated past before the display will
78 // rotate to match it (i.e. 45.0f is no stickiness). 81 // rotate to match it (i.e. 45.0f is no stickiness).
79 const float kDisplayRotationStickyAngleDegrees = 60.0f; 82 const float kDisplayRotationStickyAngleDegrees = 60.0f;
80 83
81 // The minimum acceleration in a direction required to trigger screen rotation. 84 // The minimum acceleration in m/s^2 in a direction required to trigger screen
82 // This prevents rapid toggling of rotation when the device is near flat and 85 // rotation. This prevents rapid toggling of rotation when the device is near
83 // there is very little screen aligned force on it. The value is effectively the 86 // flat and there is very little screen aligned force on it. The value is
84 // sine of the rise angle required, with the current value requiring at least a 87 // effectively the sine of the rise angle required times the acceleration due
85 // 25 degree rise. 88 // to gravity, with the current value requiring at least a 25 degree rise.
86 const float kMinimumAccelerationScreenRotation = 0.42f; 89 const float kMinimumAccelerationScreenRotation = 4.2f;
87 90
88 const float kRadiansToDegrees = 180.0f / 3.14159265f; 91 const float kRadiansToDegrees = 180.0f / 3.14159265f;
89 92
90 // Returns the angle between |base| and |other| in degrees. 93 // Returns the angle between |base| and |other| in degrees.
91 float AngleBetweenVectorsInDegrees(const gfx::Vector3dF& base, 94 float AngleBetweenVectorsInDegrees(const gfx::Vector3dF& base,
92 const gfx::Vector3dF& other) { 95 const gfx::Vector3dF& other) {
93 return acos(gfx::DotProduct(base, other) / 96 return acos(gfx::DotProduct(base, other) /
94 base.Length() / other.Length()) * kRadiansToDegrees; 97 base.Length() / other.Length()) * kRadiansToDegrees;
95 } 98 }
96 99
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 if (IsMaximizeModeWindowManagerEnabled()) 232 if (IsMaximizeModeWindowManagerEnabled())
230 maximize_mode_window_manager_->AddWindow(window); 233 maximize_mode_window_manager_->AddWindow(window);
231 } 234 }
232 235
233 void MaximizeModeController::Shutdown() { 236 void MaximizeModeController::Shutdown() {
234 shutting_down_ = true; 237 shutting_down_ = true;
235 LeaveMaximizeMode(); 238 LeaveMaximizeMode();
236 } 239 }
237 240
238 void MaximizeModeController::OnAccelerometerUpdated( 241 void MaximizeModeController::OnAccelerometerUpdated(
239 const gfx::Vector3dF& base, 242 const ui::AccelerometerUpdate& update) {
240 const gfx::Vector3dF& lid) {
241 bool first_accelerometer_update = !have_seen_accelerometer_data_; 243 bool first_accelerometer_update = !have_seen_accelerometer_data_;
242 have_seen_accelerometer_data_ = true; 244 have_seen_accelerometer_data_ = true;
243 245
244 // Ignore the reading if it appears unstable. The reading is considered 246 // Ignore the reading if it appears unstable. The reading is considered
245 // unstable if it deviates too much from gravity and/or the magnitude of the 247 // unstable if it deviates too much from gravity and/or the magnitude of the
246 // reading from the lid differs too much from the reading from the base. 248 // reading from the lid differs too much from the reading from the base.
247 float base_magnitude = base.Length(); 249 float base_magnitude =
248 float lid_magnitude = lid.Length(); 250 update.has(ui::ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD) ?
249 if (std::abs(base_magnitude - lid_magnitude) > kNoisyMagnitudeDeviation || 251 update.get(ui::ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD).Length() :
250 std::abs(base_magnitude - 1.0f) > kDeviationFromGravityThreshold || 252 0.0f;
251 std::abs(lid_magnitude - 1.0f) > kDeviationFromGravityThreshold) { 253 float lid_magnitude = update.has(ui::ACCELEROMETER_SOURCE_SCREEN) ?
252 return; 254 update.get(ui::ACCELEROMETER_SOURCE_SCREEN).Length() : 0.0f;
255 bool lid_stable = update.has(ui::ACCELEROMETER_SOURCE_SCREEN) &&
256 std::abs(lid_magnitude - kMeanGravity) <= kDeviationFromGravityThreshold;
257 bool base_angle_stable = lid_stable &&
258 update.has(ui::ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD) &&
259 std::abs(base_magnitude - lid_magnitude) <= kNoisyMagnitudeDeviation &&
260 std::abs(base_magnitude - kMeanGravity) <= kDeviationFromGravityThreshold;
261
262 if (base_angle_stable) {
263 // Responding to the hinge rotation can change the maximize mode state which
264 // affects screen rotation, so we handle hinge rotation first.
265 HandleHingeRotation(
266 update.get(ui::ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD),
267 update.get(ui::ACCELEROMETER_SOURCE_SCREEN));
253 } 268 }
254 269 if (lid_stable)
255 // Responding to the hinge rotation can change the maximize mode state which 270 HandleScreenRotation(update.get(ui::ACCELEROMETER_SOURCE_SCREEN));
256 // affects screen rotation, so we handle hinge rotation first.
257 HandleHingeRotation(base, lid);
258 HandleScreenRotation(lid);
259 271
260 if (first_accelerometer_update) { 272 if (first_accelerometer_update) {
261 // On the first accelerometer update we will know if we have entered 273 // On the first accelerometer update we will know if we have entered
262 // maximize mode or not. Update the preferences to reflect the current 274 // maximize mode or not. Update the preferences to reflect the current
263 // state. 275 // state.
264 Shell::GetInstance()->display_manager()-> 276 Shell::GetInstance()->display_manager()->
265 RegisterDisplayRotationProperties(rotation_locked_, current_rotation_); 277 RegisterDisplayRotationProperties(rotation_locked_, current_rotation_);
266 } 278 }
267 } 279 }
268 280
(...skipping 27 matching lines...) Expand all
296 } 308 }
297 309
298 void MaximizeModeController::SuspendDone( 310 void MaximizeModeController::SuspendDone(
299 const base::TimeDelta& sleep_duration) { 311 const base::TimeDelta& sleep_duration) {
300 last_touchview_transition_time_ = base::Time::Now(); 312 last_touchview_transition_time_ = base::Time::Now();
301 } 313 }
302 #endif // OS_CHROMEOS 314 #endif // OS_CHROMEOS
303 315
304 void MaximizeModeController::HandleHingeRotation(const gfx::Vector3dF& base, 316 void MaximizeModeController::HandleHingeRotation(const gfx::Vector3dF& base,
305 const gfx::Vector3dF& lid) { 317 const gfx::Vector3dF& lid) {
306 static const gfx::Vector3dF hinge_vector(0.0f, 1.0f, 0.0f); 318 static const gfx::Vector3dF hinge_vector(1.0f, 0.0f, 0.0f);
307 bool maximize_mode_engaged = IsMaximizeModeWindowManagerEnabled(); 319 bool maximize_mode_engaged = IsMaximizeModeWindowManagerEnabled();
308 // Ignore the component of acceleration parallel to the hinge for the purposes 320 // Ignore the component of acceleration parallel to the hinge for the purposes
309 // of hinge angle calculation. 321 // of hinge angle calculation.
310 gfx::Vector3dF base_flattened(base); 322 gfx::Vector3dF base_flattened(base);
311 gfx::Vector3dF lid_flattened(lid); 323 gfx::Vector3dF lid_flattened(lid);
312 base_flattened.set_y(0.0f); 324 base_flattened.set_x(0.0f);
313 lid_flattened.set_y(0.0f); 325 lid_flattened.set_x(0.0f);
314 326
315 // As the hinge approaches a vertical angle, the base and lid accelerometers 327 // As the hinge approaches a vertical angle, the base and lid accelerometers
316 // approach the same values making any angle calculations highly inaccurate. 328 // approach the same values making any angle calculations highly inaccurate.
317 // Bail out early when it is too close. 329 // Bail out early when it is too close.
318 if (base_flattened.Length() < kHingeAngleDetectionThreshold || 330 if (base_flattened.Length() < kHingeAngleDetectionThreshold ||
319 lid_flattened.Length() < kHingeAngleDetectionThreshold) { 331 lid_flattened.Length() < kHingeAngleDetectionThreshold) {
320 return; 332 return;
321 } 333 }
322 334
323 // Compute the angle between the base and the lid. 335 // Compute the angle between the base and the lid.
324 float angle = ClockwiseAngleBetweenVectorsInDegrees(base_flattened, 336 float lid_angle = 180.0f - ClockwiseAngleBetweenVectorsInDegrees(
325 lid_flattened, hinge_vector); 337 base_flattened, lid_flattened, hinge_vector);
338 if (lid_angle < 0.0f)
339 lid_angle += 360.0f;
326 340
327 bool is_angle_stable = angle > kMinStableAngle && angle < kMaxStableAngle; 341 bool is_angle_stable = lid_angle >= kMinStableAngle &&
342 lid_angle <= kMaxStableAngle;
328 343
329 // Clear the last_lid_open_time_ for a stable reading so that there is less 344 // Clear the last_lid_open_time_ for a stable reading so that there is less
330 // chance of a delay if the lid is moved from the close state to the fully 345 // chance of a delay if the lid is moved from the close state to the fully
331 // open state very quickly. 346 // open state very quickly.
332 if (is_angle_stable) 347 if (is_angle_stable)
333 last_lid_open_time_ = base::TimeTicks(); 348 last_lid_open_time_ = base::TimeTicks();
334 349
335 // Toggle maximize mode on or off when corresponding thresholds are passed. 350 // Toggle maximize mode on or off when corresponding thresholds are passed.
336 // TODO(flackr): Make MaximizeModeController own the MaximizeModeWindowManager 351 // TODO(flackr): Make MaximizeModeController own the MaximizeModeWindowManager
337 // such that observations of state changes occur after the change and shell 352 // such that observations of state changes occur after the change and shell
338 // has fewer states to track. 353 // has fewer states to track.
339 if (maximize_mode_engaged && is_angle_stable && 354 if (maximize_mode_engaged && is_angle_stable &&
340 angle < kExitMaximizeModeAngle) { 355 lid_angle <= kExitMaximizeModeAngle) {
341 LeaveMaximizeMode(); 356 LeaveMaximizeMode();
342 } else if (!lid_is_closed_ && !maximize_mode_engaged && 357 } else if (!lid_is_closed_ && !maximize_mode_engaged &&
343 angle > kEnterMaximizeModeAngle && 358 lid_angle >= kEnterMaximizeModeAngle &&
344 (is_angle_stable || !WasLidOpenedRecently())) { 359 (is_angle_stable || !WasLidOpenedRecently())) {
345 EnterMaximizeMode(); 360 EnterMaximizeMode();
346 } 361 }
347 } 362 }
348 363
349 void MaximizeModeController::HandleScreenRotation(const gfx::Vector3dF& lid) { 364 void MaximizeModeController::HandleScreenRotation(const gfx::Vector3dF& lid) {
350 bool maximize_mode_engaged = IsMaximizeModeWindowManagerEnabled(); 365 bool maximize_mode_engaged = IsMaximizeModeWindowManagerEnabled();
351 366
352 // TODO(jonross): track the updated rotation angle even when locked. So that 367 // TODO(jonross): track the updated rotation angle even when locked. So that
353 // when rotation lock is removed the accelerometer rotation can be applied 368 // when rotation lock is removed the accelerometer rotation can be applied
(...skipping 11 matching lines...) Expand all
365 gfx::Vector3dF lid_flattened(lid.x(), lid.y(), 0.0f); 380 gfx::Vector3dF lid_flattened(lid.x(), lid.y(), 0.0f);
366 float lid_flattened_length = lid_flattened.Length(); 381 float lid_flattened_length = lid_flattened.Length();
367 // When the lid is close to being flat, don't change rotation as it is too 382 // When the lid is close to being flat, don't change rotation as it is too
368 // sensitive to slight movements. 383 // sensitive to slight movements.
369 if (lid_flattened_length < kMinimumAccelerationScreenRotation) 384 if (lid_flattened_length < kMinimumAccelerationScreenRotation)
370 return; 385 return;
371 386
372 // The reference vector is the angle of gravity when the device is rotated 387 // The reference vector is the angle of gravity when the device is rotated
373 // clockwise by 45 degrees. Computing the angle between this vector and 388 // clockwise by 45 degrees. Computing the angle between this vector and
374 // gravity we can easily determine the expected display rotation. 389 // gravity we can easily determine the expected display rotation.
375 static gfx::Vector3dF rotation_reference(-1.0f, 1.0f, 0.0f); 390 static const gfx::Vector3dF rotation_reference(-1.0f, -1.0f, 0.0f);
376 391
377 // Set the down vector to match the expected direction of gravity given the 392 // Set the down vector to match the expected direction of gravity given the
378 // last configured rotation. This is used to enforce a stickiness that the 393 // last configured rotation. This is used to enforce a stickiness that the
379 // user must overcome to rotate the display and prevents frequent rotations 394 // user must overcome to rotate the display and prevents frequent rotations
380 // when holding the device near 45 degrees. 395 // when holding the device near 45 degrees.
381 gfx::Vector3dF down(0.0f, 0.0f, 0.0f); 396 gfx::Vector3dF down(0.0f, 0.0f, 0.0f);
382 if (current_rotation == gfx::Display::ROTATE_0) 397 if (current_rotation == gfx::Display::ROTATE_0)
398 down.set_y(-1.0f);
399 else if (current_rotation == gfx::Display::ROTATE_90)
383 down.set_x(-1.0f); 400 down.set_x(-1.0f);
384 else if (current_rotation == gfx::Display::ROTATE_90) 401 else if (current_rotation == gfx::Display::ROTATE_180)
385 down.set_y(1.0f); 402 down.set_y(1.0f);
386 else if (current_rotation == gfx::Display::ROTATE_180) 403 else
387 down.set_x(1.0f); 404 down.set_x(1.0f);
388 else
389 down.set_y(-1.0f);
390 405
391 // Don't rotate if the screen has not passed the threshold. 406 // Don't rotate if the screen has not passed the threshold.
392 if (AngleBetweenVectorsInDegrees(down, lid_flattened) < 407 if (AngleBetweenVectorsInDegrees(down, lid_flattened) <
393 kDisplayRotationStickyAngleDegrees) { 408 kDisplayRotationStickyAngleDegrees) {
394 return; 409 return;
395 } 410 }
396 411
397 float angle = ClockwiseAngleBetweenVectorsInDegrees(rotation_reference, 412 float angle = ClockwiseAngleBetweenVectorsInDegrees(rotation_reference,
398 lid_flattened, gfx::Vector3dF(0.0f, 0.0f, -1.0f)); 413 lid_flattened, gfx::Vector3dF(0.0f, 0.0f, -1.0f));
399 414
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
521 return elapsed_time <= kLidRecentlyOpenedDuration; 536 return elapsed_time <= kLidRecentlyOpenedDuration;
522 } 537 }
523 538
524 void MaximizeModeController::SetTickClockForTest( 539 void MaximizeModeController::SetTickClockForTest(
525 scoped_ptr<base::TickClock> tick_clock) { 540 scoped_ptr<base::TickClock> tick_clock) {
526 DCHECK(tick_clock_); 541 DCHECK(tick_clock_);
527 tick_clock_ = tick_clock.Pass(); 542 tick_clock_ = tick_clock.Pass();
528 } 543 }
529 544
530 } // namespace ash 545 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698