OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "ash/wm/maximize_mode/maximize_mode_controller.h" |
| 6 |
| 7 #include "ash/accelerometer/accelerometer_controller.h" |
| 8 #include "ash/shell.h" |
| 9 #include "ui/gfx/vector3d_f.h" |
| 10 |
| 11 namespace ash { |
| 12 |
| 13 namespace { |
| 14 |
| 15 // The hinge angle at which to enter maximize mode. |
| 16 const float kEnterMaximizeModeAngle = 200.0f; |
| 17 |
| 18 // The angle at which to exit maximize mode, this is specifically less than the |
| 19 // angle to enter maximize mode to prevent rapid toggling when near the angle. |
| 20 const float kExitMaximizeModeAngle = 160.0f; |
| 21 |
| 22 // When the lid is fully open 360 degrees, the accelerometer readings can |
| 23 // occasionally appear as though the lid is almost closed. If the lid appears |
| 24 // near closed but the device is on we assume it is an erroneous reading from |
| 25 // it being open 360 degrees. |
| 26 const float kFullyOpenAngleErrorTolerance = 10.0f; |
| 27 |
| 28 // When the device approaches vertical orientation (i.e. portrait orientation) |
| 29 // the accelerometers for the base and lid approach the same values (i.e. |
| 30 // gravity pointing in the direction of the hinge). When this happens we cannot |
| 31 // compute the hinge angle reliably and must turn ignore accelerometer readings. |
| 32 // This is the angle from vertical under which we will not compute a hinge |
| 33 // angle. |
| 34 const float kHingeAxisAlignedThreshold = 15.0f; |
| 35 |
| 36 const float kRadiansToDegrees = 180.0f / 3.14159265f; |
| 37 |
| 38 // Returns the angle between |base| and |other| in degrees. |
| 39 float AngleBetweenVectorsInDegrees(const gfx::Vector3dF& base, |
| 40 const gfx::Vector3dF& other) { |
| 41 return acos(gfx::DotProduct(base, other) / |
| 42 base.Length() / other.Length()) * kRadiansToDegrees; |
| 43 } |
| 44 |
| 45 // Returns the clockwise angle between |base| and |other| where |normal| is the |
| 46 // normal of the virtual surface to measure clockwise according to. |
| 47 float ClockwiseAngleBetweenVectorsInDegrees(const gfx::Vector3dF& base, |
| 48 const gfx::Vector3dF& other, |
| 49 const gfx::Vector3dF& normal) { |
| 50 float angle = AngleBetweenVectorsInDegrees(base, other); |
| 51 gfx::Vector3dF cross(base); |
| 52 cross.Cross(other); |
| 53 // If the dot product of this cross product is normal, it means that the |
| 54 // shortest angle between |base| and |other| was counterclockwise with respect |
| 55 // to the surface represented by |normal| and this angle must be reversed. |
| 56 if (gfx::DotProduct(cross, normal) > 0.0f) |
| 57 angle = 360.0f - angle; |
| 58 return angle; |
| 59 } |
| 60 |
| 61 } // namespace |
| 62 |
| 63 MaximizeModeController::MaximizeModeController() { |
| 64 Shell::GetInstance()->accelerometer_controller()->AddObserver(this); |
| 65 } |
| 66 |
| 67 MaximizeModeController::~MaximizeModeController() { |
| 68 Shell::GetInstance()->accelerometer_controller()->RemoveObserver(this); |
| 69 } |
| 70 |
| 71 void MaximizeModeController::OnAccelerometerUpdated( |
| 72 const gfx::Vector3dF& base, |
| 73 const gfx::Vector3dF& lid) { |
| 74 static const gfx::Vector3dF hinge_vector(0.0f, 1.0f, 0.0f); |
| 75 |
| 76 // As the hinge approaches a vertical angle, the base and lid accelerometers |
| 77 // approach the same values making any angle calculations highly inaccurate. |
| 78 // Bail out early when it is too close. |
| 79 float hinge_angle = AngleBetweenVectorsInDegrees(base, hinge_vector); |
| 80 if (hinge_angle < kHingeAxisAlignedThreshold || |
| 81 hinge_angle > 180.0f - kHingeAxisAlignedThreshold) |
| 82 return; |
| 83 |
| 84 // Compute the angle between the base and the lid. |
| 85 float angle = ClockwiseAngleBetweenVectorsInDegrees(base, lid, hinge_vector); |
| 86 |
| 87 // Toggle maximize mode on or off when corresponding thresholds are passed. |
| 88 // TODO(flackr): Make MaximizeModeController own the MaximizeModeWindowManager |
| 89 // such that observations of state changes occur after the change and shell |
| 90 // has fewer states to track. |
| 91 bool maximize_mode_engaged = |
| 92 Shell::GetInstance()->IsMaximizeModeWindowManagerEnabled(); |
| 93 if (maximize_mode_engaged && |
| 94 angle > kFullyOpenAngleErrorTolerance && |
| 95 angle < kExitMaximizeModeAngle) { |
| 96 Shell::GetInstance()->EnableMaximizeModeWindowManager(false); |
| 97 } else if (!maximize_mode_engaged && |
| 98 angle > kEnterMaximizeModeAngle) { |
| 99 Shell::GetInstance()->EnableMaximizeModeWindowManager(true); |
| 100 } |
| 101 } |
| 102 |
| 103 } // namespace ash |
OLD | NEW |