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

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

Issue 196413017: Auto rotate on lid rotation changes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Merge with master and update class comment. Created 6 years, 8 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 | Annotate | Revision Log
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/accelerometer/accelerometer_controller.h" 7 #include "ash/accelerometer/accelerometer_controller.h"
8 #include "ash/display/display_manager.h"
8 #include "ash/shell.h" 9 #include "ash/shell.h"
9 #include "ui/gfx/vector3d_f.h" 10 #include "ui/gfx/vector3d_f.h"
10 11
11 namespace ash { 12 namespace ash {
12 13
13 namespace { 14 namespace {
14 15
15 // The hinge angle at which to enter maximize mode. 16 // The hinge angle at which to enter maximize mode.
16 const float kEnterMaximizeModeAngle = 200.0f; 17 const float kEnterMaximizeModeAngle = 200.0f;
17 18
18 // The angle at which to exit maximize mode, this is specifically less than the 19 // 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 // angle to enter maximize mode to prevent rapid toggling when near the angle.
20 const float kExitMaximizeModeAngle = 160.0f; 21 const float kExitMaximizeModeAngle = 160.0f;
21 22
22 // When the lid is fully open 360 degrees, the accelerometer readings can 23 // 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 // 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 // near closed but the device is on we assume it is an erroneous reading from
25 // it being open 360 degrees. 26 // it being open 360 degrees.
26 const float kFullyOpenAngleErrorTolerance = 10.0f; 27 const float kFullyOpenAngleErrorTolerance = 10.0f;
27 28
28 // When the device approaches vertical orientation (i.e. portrait orientation) 29 // 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 // 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 // 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 // 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 // This is the angle from vertical under which we will not compute a hinge
33 // angle. 34 // angle.
34 const float kHingeAxisAlignedThreshold = 15.0f; 35 const float kHingeAxisAlignedThreshold = 15.0f;
35 36
37 // The angle which the screen has to be rotated past before the display will
38 // rotate to match it (i.e. 45.0f is no stickiness).
39 const float kDisplayRotationStickyAngleDegrees = 60.0f;
40
41 // The minimum acceleration in a direction required to trigger screen rotation.
42 // This prevents rapid toggling of rotation when the device is near flat and
43 // there is very little screen aligned force on it.
44 const float kMinimumAccelerationScreenRotation = 0.3f;
45
36 const float kRadiansToDegrees = 180.0f / 3.14159265f; 46 const float kRadiansToDegrees = 180.0f / 3.14159265f;
37 47
38 // Returns the angle between |base| and |other| in degrees. 48 // Returns the angle between |base| and |other| in degrees.
39 float AngleBetweenVectorsInDegrees(const gfx::Vector3dF& base, 49 float AngleBetweenVectorsInDegrees(const gfx::Vector3dF& base,
40 const gfx::Vector3dF& other) { 50 const gfx::Vector3dF& other) {
41 return acos(gfx::DotProduct(base, other) / 51 return acos(gfx::DotProduct(base, other) /
42 base.Length() / other.Length()) * kRadiansToDegrees; 52 base.Length() / other.Length()) * kRadiansToDegrees;
43 } 53 }
44 54
45 // Returns the clockwise angle between |base| and |other| where |normal| is the 55 // Returns the clockwise angle between |base| and |other| where |normal| is the
(...skipping 18 matching lines...) Expand all
64 Shell::GetInstance()->accelerometer_controller()->AddObserver(this); 74 Shell::GetInstance()->accelerometer_controller()->AddObserver(this);
65 } 75 }
66 76
67 MaximizeModeController::~MaximizeModeController() { 77 MaximizeModeController::~MaximizeModeController() {
68 Shell::GetInstance()->accelerometer_controller()->RemoveObserver(this); 78 Shell::GetInstance()->accelerometer_controller()->RemoveObserver(this);
69 } 79 }
70 80
71 void MaximizeModeController::OnAccelerometerUpdated( 81 void MaximizeModeController::OnAccelerometerUpdated(
72 const gfx::Vector3dF& base, 82 const gfx::Vector3dF& base,
73 const gfx::Vector3dF& lid) { 83 const gfx::Vector3dF& lid) {
84 // Responding to the hinge rotation can change the maximize mode state which
85 // affects screen rotation, so we handle hinge rotation first.
86 HandleHingeRotation(base, lid);
87 HandleScreenRotation(lid);
88 }
89
90 void MaximizeModeController::HandleHingeRotation(const gfx::Vector3dF& base,
91 const gfx::Vector3dF& lid) {
74 static const gfx::Vector3dF hinge_vector(0.0f, 1.0f, 0.0f); 92 static const gfx::Vector3dF hinge_vector(0.0f, 1.0f, 0.0f);
93 bool maximize_mode_engaged =
94 Shell::GetInstance()->IsMaximizeModeWindowManagerEnabled();
75 95
76 // As the hinge approaches a vertical angle, the base and lid accelerometers 96 // As the hinge approaches a vertical angle, the base and lid accelerometers
77 // approach the same values making any angle calculations highly inaccurate. 97 // approach the same values making any angle calculations highly inaccurate.
78 // Bail out early when it is too close. 98 // Bail out early when it is too close.
79 float hinge_angle = AngleBetweenVectorsInDegrees(base, hinge_vector); 99 float hinge_angle = AngleBetweenVectorsInDegrees(base, hinge_vector);
80 if (hinge_angle < kHingeAxisAlignedThreshold || 100 if (hinge_angle < kHingeAxisAlignedThreshold ||
81 hinge_angle > 180.0f - kHingeAxisAlignedThreshold) 101 hinge_angle > 180.0f - kHingeAxisAlignedThreshold) {
82 return; 102 return;
103 }
83 104
84 // Compute the angle between the base and the lid. 105 // Compute the angle between the base and the lid.
85 float angle = ClockwiseAngleBetweenVectorsInDegrees(base, lid, hinge_vector); 106 float angle = ClockwiseAngleBetweenVectorsInDegrees(base, lid, hinge_vector);
86 107
87 // Toggle maximize mode on or off when corresponding thresholds are passed. 108 // Toggle maximize mode on or off when corresponding thresholds are passed.
88 // TODO(flackr): Make MaximizeModeController own the MaximizeModeWindowManager 109 // TODO(flackr): Make MaximizeModeController own the MaximizeModeWindowManager
89 // such that observations of state changes occur after the change and shell 110 // such that observations of state changes occur after the change and shell
90 // has fewer states to track. 111 // has fewer states to track.
91 bool maximize_mode_engaged =
92 Shell::GetInstance()->IsMaximizeModeWindowManagerEnabled();
93 if (maximize_mode_engaged && 112 if (maximize_mode_engaged &&
94 angle > kFullyOpenAngleErrorTolerance && 113 angle > kFullyOpenAngleErrorTolerance &&
95 angle < kExitMaximizeModeAngle) { 114 angle < kExitMaximizeModeAngle) {
96 Shell::GetInstance()->EnableMaximizeModeWindowManager(false); 115 Shell::GetInstance()->EnableMaximizeModeWindowManager(false);
97 } else if (!maximize_mode_engaged && 116 } else if (!maximize_mode_engaged &&
98 angle > kEnterMaximizeModeAngle) { 117 angle > kEnterMaximizeModeAngle) {
99 Shell::GetInstance()->EnableMaximizeModeWindowManager(true); 118 Shell::GetInstance()->EnableMaximizeModeWindowManager(true);
100 } 119 }
101 } 120 }
102 121
122 void MaximizeModeController::HandleScreenRotation(const gfx::Vector3dF& lid) {
123 bool maximize_mode_engaged =
124 Shell::GetInstance()->IsMaximizeModeWindowManagerEnabled();
125
126 internal::DisplayManager* display_manager =
127 Shell::GetInstance()->display_manager();
128 gfx::Display::Rotation current_rotation = display_manager->GetDisplayInfo(
129 gfx::Display::InternalDisplayId()).rotation();
130
131 // If maximize mode is not engaged, ensure the screen is not rotated and
132 // do not rotate to match the current device orientation.
133 if (!maximize_mode_engaged) {
134 if (current_rotation != gfx::Display::ROTATE_0) {
135 // TODO(flackr): Currently this will prevent setting a manual rotation on
136 // the screen of a device with an accelerometer, this should only set it
137 // back to ROTATE_0 if it was last set by the accelerometer.
oshima 2014/04/03 19:19:49 SetDisplayRotation will save the setting to the lo
flackr 2014/04/03 19:43:46 Done.
138 display_manager->SetDisplayRotation(gfx::Display::InternalDisplayId(),
139 gfx::Display::ROTATE_0);
140 }
141 return;
142 }
143
144 // After determining maximize mode state, determine if the screen should
145 // be rotated.
146 gfx::Vector3dF lid_flattened(lid.x(), lid.y(), 0.0f);
147 float lid_flattened_length = lid_flattened.Length();
148 // When the lid is close to being flat, don't change rotation as it is too
149 // sensitive to slight movements.
150 if (lid_flattened_length < kMinimumAccelerationScreenRotation)
151 return;
152
153 // The reference vector is the angle of gravity when the device is rotated
154 // clockwise by 45 degrees. Computing the angle between this vector and
155 // gravity we can easily determine the expected display rotation.
156 static gfx::Vector3dF rotation_reference(-1.0f, 1.0f, 0.0f);
157
158 // Set the down vector to match the expected direction of gravity given the
159 // last configured rotation. This is used to enforce a stickiness that the
160 // user must overcome to rotate the display and prevents frequent rotations
161 // when holding the device near 45 degrees.
162 gfx::Vector3dF down(0.0f, 0.0f, 0.0f);
163 if (current_rotation == gfx::Display::ROTATE_0)
164 down.set_x(-1.0f);
165 else if (current_rotation == gfx::Display::ROTATE_90)
166 down.set_y(1.0f);
167 else if (current_rotation == gfx::Display::ROTATE_180)
168 down.set_x(1.0f);
169 else
170 down.set_y(-1.0f);
171
172 // Don't rotate if the screen has not passed the threshold.
173 if (AngleBetweenVectorsInDegrees(down, lid_flattened) <
174 kDisplayRotationStickyAngleDegrees) {
175 return;
176 }
177
178 float angle = ClockwiseAngleBetweenVectorsInDegrees(rotation_reference,
179 lid_flattened, gfx::Vector3dF(0.0f, 0.0f, -1.0f));
180
181 gfx::Display::Rotation new_rotation = gfx::Display::ROTATE_90;
182 if (angle < 90.0f)
183 new_rotation = gfx::Display::ROTATE_0;
184 else if (angle < 180.0f)
185 new_rotation = gfx::Display::ROTATE_270;
186 else if (angle < 270.0f)
187 new_rotation = gfx::Display::ROTATE_180;
188
189 // When exiting maximize mode return rotation to 0. When entering, rotate to
190 // match screen orientation.
191 if (new_rotation == gfx::Display::ROTATE_0 ||
192 maximize_mode_engaged) {
193 display_manager->SetDisplayRotation(gfx::Display::InternalDisplayId(),
194 new_rotation);
195 }
196 }
197
103 } // namespace ash 198 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698