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/ash_switches.h" | 9 #include "ash/ash_switches.h" |
10 #include "ash/display/display_manager.h" | 10 #include "ash/display/display_manager.h" |
11 #include "ash/shell.h" | 11 #include "ash/shell.h" |
12 #include "ash/wm/maximize_mode/maximize_mode_window_manager.h" | 12 #include "ash/wm/maximize_mode/maximize_mode_window_manager.h" |
13 #include "ash/wm/maximize_mode/scoped_disable_internal_mouse_and_keyboard.h" | 13 #include "ash/wm/maximize_mode/scoped_disable_internal_mouse_and_keyboard.h" |
14 #include "base/auto_reset.h" | |
15 #include "base/command_line.h" | 14 #include "base/command_line.h" |
16 #include "base/metrics/histogram.h" | 15 #include "base/metrics/histogram.h" |
17 #include "base/time/default_tick_clock.h" | 16 #include "base/time/default_tick_clock.h" |
18 #include "base/time/tick_clock.h" | 17 #include "base/time/tick_clock.h" |
19 #include "ui/base/accelerators/accelerator.h" | 18 #include "ui/base/accelerators/accelerator.h" |
20 #include "ui/events/event.h" | 19 #include "ui/events/event.h" |
21 #include "ui/events/keycodes/keyboard_codes.h" | 20 #include "ui/events/keycodes/keyboard_codes.h" |
22 #include "ui/gfx/geometry/vector3d_f.h" | 21 #include "ui/gfx/geometry/vector3d_f.h" |
23 | 22 |
24 #if defined(USE_X11) | 23 #if defined(USE_X11) |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 | 55 |
57 // When the device approaches vertical orientation (i.e. portrait orientation) | 56 // When the device approaches vertical orientation (i.e. portrait orientation) |
58 // the accelerometers for the base and lid approach the same values (i.e. | 57 // the accelerometers for the base and lid approach the same values (i.e. |
59 // gravity pointing in the direction of the hinge). When this happens we cannot | 58 // gravity pointing in the direction of the hinge). When this happens we cannot |
60 // compute the hinge angle reliably and must turn ignore accelerometer readings. | 59 // compute the hinge angle reliably and must turn ignore accelerometer readings. |
61 // This is the minimum acceleration perpendicular to the hinge under which to | 60 // This is the minimum acceleration perpendicular to the hinge under which to |
62 // detect hinge angle in m/s^2. | 61 // detect hinge angle in m/s^2. |
63 const float kHingeAngleDetectionThreshold = 2.5f; | 62 const float kHingeAngleDetectionThreshold = 2.5f; |
64 | 63 |
65 #if defined(OS_CHROMEOS) | 64 #if defined(OS_CHROMEOS) |
66 // The mean acceleration due to gravity on Earth in m/s^2. | |
67 const float kMeanGravity = 9.80665f; | |
68 | |
69 // The maximum deviation from the acceleration expected due to gravity under | |
70 // which to detect hinge angle and screen rotation in m/s^2 | |
71 const float kDeviationFromGravityThreshold = 1.0f; | |
72 | |
73 // The maximum deviation between the magnitude of the two accelerometers under | 65 // The maximum deviation between the magnitude of the two accelerometers under |
74 // which to detect hinge angle and screen rotation in m/s^2. These | 66 // which to detect hinge angle and screen rotation in m/s^2. These |
75 // accelerometers are attached to the same physical device and so should be | 67 // accelerometers are attached to the same physical device and so should be |
76 // under the same acceleration. | 68 // under the same acceleration. |
77 const float kNoisyMagnitudeDeviation = 1.0f; | 69 const float kNoisyMagnitudeDeviation = 1.0f; |
78 #endif | 70 #endif |
79 | 71 |
80 // The angle which the screen has to be rotated past before the display will | |
81 // rotate to match it (i.e. 45.0f is no stickiness). | |
82 const float kDisplayRotationStickyAngleDegrees = 60.0f; | |
83 | |
84 // The minimum acceleration in m/s^2 in a direction required to trigger screen | |
85 // rotation. This prevents rapid toggling of rotation when the device is near | |
86 // flat and there is very little screen aligned force on it. The value is | |
87 // effectively the sine of the rise angle required times the acceleration due | |
88 // to gravity, with the current value requiring at least a 25 degree rise. | |
89 const float kMinimumAccelerationScreenRotation = 4.2f; | |
90 | |
91 const float kRadiansToDegrees = 180.0f / 3.14159265f; | |
92 | |
93 // Returns the angle between |base| and |other| in degrees. | |
94 float AngleBetweenVectorsInDegrees(const gfx::Vector3dF& base, | |
95 const gfx::Vector3dF& other) { | |
96 return acos(gfx::DotProduct(base, other) / | |
97 base.Length() / other.Length()) * kRadiansToDegrees; | |
98 } | |
99 | |
100 // Returns the clockwise angle between |base| and |other| where |normal| is the | |
101 // normal of the virtual surface to measure clockwise according to. | |
102 float ClockwiseAngleBetweenVectorsInDegrees(const gfx::Vector3dF& base, | |
103 const gfx::Vector3dF& other, | |
104 const gfx::Vector3dF& normal) { | |
105 float angle = AngleBetweenVectorsInDegrees(base, other); | |
106 gfx::Vector3dF cross(base); | |
107 cross.Cross(other); | |
108 // If the dot product of this cross product is normal, it means that the | |
109 // shortest angle between |base| and |other| was counterclockwise with respect | |
110 // to the surface represented by |normal| and this angle must be reversed. | |
111 if (gfx::DotProduct(cross, normal) > 0.0f) | |
112 angle = 360.0f - angle; | |
113 return angle; | |
114 } | |
115 | |
116 } // namespace | 72 } // namespace |
117 | 73 |
118 MaximizeModeController::MaximizeModeController() | 74 MaximizeModeController::MaximizeModeController() |
119 : rotation_locked_(false), | 75 : have_seen_accelerometer_data_(false), |
120 have_seen_accelerometer_data_(false), | |
121 ignore_display_configuration_updates_(false), | |
122 lid_open_past_180_(false), | 76 lid_open_past_180_(false), |
123 shutting_down_(false), | |
124 user_rotation_(gfx::Display::ROTATE_0), | |
125 last_touchview_transition_time_(base::Time::Now()), | 77 last_touchview_transition_time_(base::Time::Now()), |
126 tick_clock_(new base::DefaultTickClock()), | 78 tick_clock_(new base::DefaultTickClock()), |
127 lid_is_closed_(false) { | 79 lid_is_closed_(false) { |
128 Shell::GetInstance()->AddShellObserver(this); | 80 Shell::GetInstance()->AddShellObserver(this); |
129 #if defined(OS_CHROMEOS) | 81 #if defined(OS_CHROMEOS) |
130 Shell::GetInstance()->accelerometer_reader()->AddObserver(this); | 82 Shell::GetInstance()->accelerometer_reader()->AddObserver(this); |
131 chromeos::DBusThreadManager::Get()-> | 83 chromeos::DBusThreadManager::Get()-> |
132 GetPowerManagerClient()->AddObserver(this); | 84 GetPowerManagerClient()->AddObserver(this); |
133 #endif // OS_CHROMEOS | 85 #endif // OS_CHROMEOS |
134 } | 86 } |
135 | 87 |
136 MaximizeModeController::~MaximizeModeController() { | 88 MaximizeModeController::~MaximizeModeController() { |
137 Shell::GetInstance()->RemoveShellObserver(this); | 89 Shell::GetInstance()->RemoveShellObserver(this); |
138 #if defined(OS_CHROMEOS) | 90 #if defined(OS_CHROMEOS) |
139 Shell::GetInstance()->accelerometer_reader()->RemoveObserver(this); | 91 Shell::GetInstance()->accelerometer_reader()->RemoveObserver(this); |
140 chromeos::DBusThreadManager::Get()-> | 92 chromeos::DBusThreadManager::Get()-> |
141 GetPowerManagerClient()->RemoveObserver(this); | 93 GetPowerManagerClient()->RemoveObserver(this); |
142 #endif // OS_CHROMEOS | 94 #endif // OS_CHROMEOS |
143 } | 95 } |
144 | 96 |
145 void MaximizeModeController::SetRotationLocked(bool rotation_locked) { | |
146 if (rotation_locked_ == rotation_locked) | |
147 return; | |
148 base::AutoReset<bool> auto_ignore_display_configuration_updates( | |
149 &ignore_display_configuration_updates_, true); | |
150 rotation_locked_ = rotation_locked; | |
151 Shell::GetInstance()->display_manager()-> | |
152 RegisterDisplayRotationProperties(rotation_locked_, current_rotation_); | |
153 FOR_EACH_OBSERVER(Observer, observers_, | |
154 OnRotationLockChanged(rotation_locked_)); | |
155 } | |
156 | |
157 void MaximizeModeController::LockRotation(gfx::Display::Rotation rotation) { | |
158 SetRotationLocked(true); | |
159 SetDisplayRotation(Shell::GetInstance()->display_manager(), rotation); | |
160 } | |
161 | |
162 void MaximizeModeController::AddObserver(Observer* observer) { | |
163 observers_.AddObserver(observer); | |
164 } | |
165 | |
166 void MaximizeModeController::RemoveObserver(Observer* observer) { | |
167 observers_.RemoveObserver(observer); | |
168 } | |
169 | |
170 bool MaximizeModeController::CanEnterMaximizeMode() { | 97 bool MaximizeModeController::CanEnterMaximizeMode() { |
171 // If we have ever seen accelerometer data, then HandleHingeRotation may | 98 // If we have ever seen accelerometer data, then HandleHingeRotation may |
172 // trigger maximize mode at some point in the future. | 99 // trigger maximize mode at some point in the future. |
173 // The --enable-touch-view-testing switch can also mean that we may enter | 100 // The --enable-touch-view-testing switch can also mean that we may enter |
174 // maximize mode. | 101 // maximize mode. |
175 return have_seen_accelerometer_data_ || | 102 return have_seen_accelerometer_data_ || |
176 base::CommandLine::ForCurrentProcess()->HasSwitch( | 103 base::CommandLine::ForCurrentProcess()->HasSwitch( |
177 switches::kAshEnableTouchViewTesting); | 104 switches::kAshEnableTouchViewTesting); |
178 } | 105 } |
179 | 106 |
(...skipping 11 matching lines...) Expand all Loading... |
191 | 118 |
192 bool MaximizeModeController::IsMaximizeModeWindowManagerEnabled() const { | 119 bool MaximizeModeController::IsMaximizeModeWindowManagerEnabled() const { |
193 return maximize_mode_window_manager_.get() != NULL; | 120 return maximize_mode_window_manager_.get() != NULL; |
194 } | 121 } |
195 | 122 |
196 void MaximizeModeController::AddWindow(aura::Window* window) { | 123 void MaximizeModeController::AddWindow(aura::Window* window) { |
197 if (IsMaximizeModeWindowManagerEnabled()) | 124 if (IsMaximizeModeWindowManagerEnabled()) |
198 maximize_mode_window_manager_->AddWindow(window); | 125 maximize_mode_window_manager_->AddWindow(window); |
199 } | 126 } |
200 | 127 |
201 void MaximizeModeController::Shutdown() { | |
202 shutting_down_ = true; | |
203 LeaveMaximizeMode(); | |
204 } | |
205 | |
206 void MaximizeModeController::OnDisplayConfigurationChanged() { | |
207 if (ignore_display_configuration_updates_) | |
208 return; | |
209 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); | |
210 gfx::Display::Rotation user_rotation = | |
211 display_manager->GetDisplayInfo(gfx::Display::InternalDisplayId()) | |
212 .rotation(); | |
213 if (user_rotation != current_rotation_) { | |
214 // A user may change other display configuration settings. When the user | |
215 // does change the rotation setting, then lock rotation to prevent the | |
216 // accelerometer from erasing their change. | |
217 SetRotationLocked(true); | |
218 user_rotation_ = user_rotation; | |
219 current_rotation_ = user_rotation; | |
220 } | |
221 } | |
222 | |
223 #if defined(OS_CHROMEOS) | 128 #if defined(OS_CHROMEOS) |
224 void MaximizeModeController::OnAccelerometerUpdated( | 129 void MaximizeModeController::OnAccelerometerUpdated( |
225 const ui::AccelerometerUpdate& update) { | 130 const ui::AccelerometerUpdate& update) { |
226 bool first_accelerometer_update = !have_seen_accelerometer_data_; | 131 bool first_accelerometer_update = !have_seen_accelerometer_data_; |
227 have_seen_accelerometer_data_ = true; | 132 have_seen_accelerometer_data_ = true; |
228 | 133 |
229 // Ignore the reading if it appears unstable. The reading is considered | 134 if (!update.has(ui::ACCELEROMETER_SOURCE_SCREEN)) |
230 // unstable if it deviates too much from gravity and/or the magnitude of the | 135 return; |
231 // reading from the lid differs too much from the reading from the base. | |
232 float lid_magnitude = update.has(ui::ACCELEROMETER_SOURCE_SCREEN) ? | |
233 update.get(ui::ACCELEROMETER_SOURCE_SCREEN).Length() : 0.0f; | |
234 bool lid_stable = update.has(ui::ACCELEROMETER_SOURCE_SCREEN) && | |
235 std::abs(lid_magnitude - kMeanGravity) <= kDeviationFromGravityThreshold; | |
236 | 136 |
237 // Whether or not we enter maximize mode affects whether we handle screen | 137 // Whether or not we enter maximize mode affects whether we handle screen |
238 // rotation, so determine whether to enter maximize mode first. | 138 // rotation, so determine whether to enter maximize mode first. |
239 if (!update.has(ui::ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD)) { | 139 if (!update.has(ui::ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD)) { |
240 if (first_accelerometer_update && | 140 if (first_accelerometer_update) |
241 update.has(ui::ACCELEROMETER_SOURCE_SCREEN)) { | |
242 EnterMaximizeMode(); | 141 EnterMaximizeMode(); |
243 } | 142 } else if (chromeos::AccelerometerReader::IsReadingStable( |
244 } else { // update.has(ui::ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD) | 143 update, ui::ACCELEROMETER_SOURCE_SCREEN) && |
245 float base_magnitude = | 144 chromeos::AccelerometerReader::IsReadingStable( |
246 update.get(ui::ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD).Length(); | 145 update, ui::ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD) && |
247 bool base_angle_stable = lid_stable && | 146 std::abs(update.get(ui::ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD) |
248 std::abs(base_magnitude - lid_magnitude) <= kNoisyMagnitudeDeviation && | 147 .Length() - |
249 std::abs(base_magnitude - kMeanGravity) <= | 148 update.get(ui::ACCELEROMETER_SOURCE_SCREEN).Length()) <= |
250 kDeviationFromGravityThreshold; | 149 kNoisyMagnitudeDeviation) { |
251 if (base_angle_stable) { | 150 // update.has(ui::ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD) |
252 HandleHingeRotation( | 151 // Ignore the reading if it appears unstable. The reading is considered |
253 update.get(ui::ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD), | 152 // unstable if it deviates too much from gravity and/or the magnitude of the |
254 update.get(ui::ACCELEROMETER_SOURCE_SCREEN)); | 153 // reading from the lid differs too much from the reading from the base. |
255 } | 154 HandleHingeRotation(update.get(ui::ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD), |
256 } | 155 update.get(ui::ACCELEROMETER_SOURCE_SCREEN)); |
257 | |
258 if (lid_stable) | |
259 HandleScreenRotation(update.get(ui::ACCELEROMETER_SOURCE_SCREEN)); | |
260 | |
261 if (first_accelerometer_update) { | |
262 // On the first accelerometer update we will know if we have entered | |
263 // maximize mode or not. Update the preferences to reflect the current | |
264 // state. | |
265 Shell::GetInstance()->display_manager()-> | |
266 RegisterDisplayRotationProperties(rotation_locked_, current_rotation_); | |
267 } | 156 } |
268 } | 157 } |
269 | 158 |
270 void MaximizeModeController::LidEventReceived(bool open, | 159 void MaximizeModeController::LidEventReceived(bool open, |
271 const base::TimeTicks& time) { | 160 const base::TimeTicks& time) { |
272 if (open) | 161 if (open) |
273 last_lid_open_time_ = time; | 162 last_lid_open_time_ = time; |
274 lid_is_closed_ = !open; | 163 lid_is_closed_ = !open; |
275 LeaveMaximizeMode(); | 164 LeaveMaximizeMode(); |
276 } | 165 } |
(...skipping 20 matching lines...) Expand all Loading... |
297 | 186 |
298 // As the hinge approaches a vertical angle, the base and lid accelerometers | 187 // As the hinge approaches a vertical angle, the base and lid accelerometers |
299 // approach the same values making any angle calculations highly inaccurate. | 188 // approach the same values making any angle calculations highly inaccurate. |
300 // Bail out early when it is too close. | 189 // Bail out early when it is too close. |
301 if (base_flattened.Length() < kHingeAngleDetectionThreshold || | 190 if (base_flattened.Length() < kHingeAngleDetectionThreshold || |
302 lid_flattened.Length() < kHingeAngleDetectionThreshold) { | 191 lid_flattened.Length() < kHingeAngleDetectionThreshold) { |
303 return; | 192 return; |
304 } | 193 } |
305 | 194 |
306 // Compute the angle between the base and the lid. | 195 // Compute the angle between the base and the lid. |
307 float lid_angle = 180.0f - ClockwiseAngleBetweenVectorsInDegrees( | 196 float lid_angle = 180.0f - gfx::ClockwiseAngleBetweenVectorsInDegrees( |
308 base_flattened, lid_flattened, hinge_vector); | 197 base_flattened, lid_flattened, hinge_vector); |
309 if (lid_angle < 0.0f) | 198 if (lid_angle < 0.0f) |
310 lid_angle += 360.0f; | 199 lid_angle += 360.0f; |
311 | 200 |
312 bool is_angle_stable = lid_angle >= kMinStableAngle && | 201 bool is_angle_stable = lid_angle >= kMinStableAngle && |
313 lid_angle <= kMaxStableAngle; | 202 lid_angle <= kMaxStableAngle; |
314 | 203 |
315 // Clear the last_lid_open_time_ for a stable reading so that there is less | 204 // Clear the last_lid_open_time_ for a stable reading so that there is less |
316 // chance of a delay if the lid is moved from the close state to the fully | 205 // chance of a delay if the lid is moved from the close state to the fully |
317 // open state very quickly. | 206 // open state very quickly. |
318 if (is_angle_stable) | 207 if (is_angle_stable) |
(...skipping 15 matching lines...) Expand all Loading... |
334 if (!base::CommandLine::ForCurrentProcess()-> | 223 if (!base::CommandLine::ForCurrentProcess()-> |
335 HasSwitch(switches::kAshEnableTouchViewTesting)) { | 224 HasSwitch(switches::kAshEnableTouchViewTesting)) { |
336 EnterMaximizeMode(); | 225 EnterMaximizeMode(); |
337 } | 226 } |
338 #if defined(USE_X11) | 227 #if defined(USE_X11) |
339 event_blocker_.reset(new ScopedDisableInternalMouseAndKeyboardX11); | 228 event_blocker_.reset(new ScopedDisableInternalMouseAndKeyboardX11); |
340 #endif | 229 #endif |
341 } | 230 } |
342 } | 231 } |
343 | 232 |
344 void MaximizeModeController::HandleScreenRotation(const gfx::Vector3dF& lid) { | |
345 bool maximize_mode_engaged = IsMaximizeModeWindowManagerEnabled(); | |
346 | |
347 // TODO(jonross): track the updated rotation angle even when locked. So that | |
348 // when rotation lock is removed the accelerometer rotation can be applied | |
349 // without waiting for the next update. | |
350 if (!maximize_mode_engaged || rotation_locked_) | |
351 return; | |
352 | |
353 DisplayManager* display_manager = | |
354 Shell::GetInstance()->display_manager(); | |
355 gfx::Display::Rotation current_rotation = display_manager->GetDisplayInfo( | |
356 gfx::Display::InternalDisplayId()).rotation(); | |
357 | |
358 // After determining maximize mode state, determine if the screen should | |
359 // be rotated. | |
360 gfx::Vector3dF lid_flattened(lid.x(), lid.y(), 0.0f); | |
361 float lid_flattened_length = lid_flattened.Length(); | |
362 // When the lid is close to being flat, don't change rotation as it is too | |
363 // sensitive to slight movements. | |
364 if (lid_flattened_length < kMinimumAccelerationScreenRotation) | |
365 return; | |
366 | |
367 // The reference vector is the angle of gravity when the device is rotated | |
368 // clockwise by 45 degrees. Computing the angle between this vector and | |
369 // gravity we can easily determine the expected display rotation. | |
370 static const gfx::Vector3dF rotation_reference(-1.0f, -1.0f, 0.0f); | |
371 | |
372 // Set the down vector to match the expected direction of gravity given the | |
373 // last configured rotation. This is used to enforce a stickiness that the | |
374 // user must overcome to rotate the display and prevents frequent rotations | |
375 // when holding the device near 45 degrees. | |
376 gfx::Vector3dF down(0.0f, 0.0f, 0.0f); | |
377 if (current_rotation == gfx::Display::ROTATE_0) | |
378 down.set_y(-1.0f); | |
379 else if (current_rotation == gfx::Display::ROTATE_90) | |
380 down.set_x(-1.0f); | |
381 else if (current_rotation == gfx::Display::ROTATE_180) | |
382 down.set_y(1.0f); | |
383 else | |
384 down.set_x(1.0f); | |
385 | |
386 // Don't rotate if the screen has not passed the threshold. | |
387 if (AngleBetweenVectorsInDegrees(down, lid_flattened) < | |
388 kDisplayRotationStickyAngleDegrees) { | |
389 return; | |
390 } | |
391 | |
392 float angle = ClockwiseAngleBetweenVectorsInDegrees(rotation_reference, | |
393 lid_flattened, gfx::Vector3dF(0.0f, 0.0f, -1.0f)); | |
394 | |
395 gfx::Display::Rotation new_rotation = gfx::Display::ROTATE_90; | |
396 if (angle < 90.0f) | |
397 new_rotation = gfx::Display::ROTATE_0; | |
398 else if (angle < 180.0f) | |
399 new_rotation = gfx::Display::ROTATE_270; | |
400 else if (angle < 270.0f) | |
401 new_rotation = gfx::Display::ROTATE_180; | |
402 | |
403 if (new_rotation != current_rotation) | |
404 SetDisplayRotation(display_manager, new_rotation); | |
405 } | |
406 | |
407 void MaximizeModeController::SetDisplayRotation( | |
408 DisplayManager* display_manager, | |
409 gfx::Display::Rotation rotation) { | |
410 base::AutoReset<bool> auto_ignore_display_configuration_updates( | |
411 &ignore_display_configuration_updates_, true); | |
412 current_rotation_ = rotation; | |
413 display_manager->SetDisplayRotation(gfx::Display::InternalDisplayId(), | |
414 rotation); | |
415 } | |
416 | |
417 void MaximizeModeController::EnterMaximizeMode() { | 233 void MaximizeModeController::EnterMaximizeMode() { |
418 if (IsMaximizeModeWindowManagerEnabled()) | 234 if (IsMaximizeModeWindowManagerEnabled()) |
419 return; | 235 return; |
420 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); | |
421 if (display_manager->HasInternalDisplay()) { | |
422 current_rotation_ = user_rotation_ = display_manager-> | |
423 GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation(); | |
424 LoadDisplayRotationProperties(); | |
425 } | |
426 EnableMaximizeModeWindowManager(true); | 236 EnableMaximizeModeWindowManager(true); |
427 Shell::GetInstance()->display_controller()->AddObserver(this); | |
428 } | 237 } |
429 | 238 |
430 void MaximizeModeController::LeaveMaximizeMode() { | 239 void MaximizeModeController::LeaveMaximizeMode() { |
431 if (!IsMaximizeModeWindowManagerEnabled()) | 240 if (!IsMaximizeModeWindowManagerEnabled()) |
432 return; | 241 return; |
433 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); | |
434 if (display_manager->HasInternalDisplay()) { | |
435 gfx::Display::Rotation current_rotation = display_manager-> | |
436 GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation(); | |
437 if (current_rotation != user_rotation_) | |
438 SetDisplayRotation(display_manager, user_rotation_); | |
439 } | |
440 if (!shutting_down_) | |
441 SetRotationLocked(false); | |
442 EnableMaximizeModeWindowManager(false); | 242 EnableMaximizeModeWindowManager(false); |
443 Shell::GetInstance()->display_controller()->RemoveObserver(this); | |
444 } | 243 } |
445 | 244 |
446 // Called after maximize mode has started, windows might still animate though. | 245 // Called after maximize mode has started, windows might still animate though. |
447 void MaximizeModeController::OnMaximizeModeStarted() { | 246 void MaximizeModeController::OnMaximizeModeStarted() { |
448 RecordTouchViewStateTransition(); | 247 RecordTouchViewStateTransition(); |
449 } | 248 } |
450 | 249 |
451 // Called after maximize mode has ended, windows might still be returning to | 250 // Called after maximize mode has ended, windows might still be returning to |
452 // their original position. | 251 // their original position. |
453 void MaximizeModeController::OnMaximizeModeEnded() { | 252 void MaximizeModeController::OnMaximizeModeEnded() { |
454 RecordTouchViewStateTransition(); | 253 RecordTouchViewStateTransition(); |
455 } | 254 } |
456 | 255 |
457 void MaximizeModeController::RecordTouchViewStateTransition() { | 256 void MaximizeModeController::RecordTouchViewStateTransition() { |
458 if (CanEnterMaximizeMode()) { | 257 if (CanEnterMaximizeMode()) { |
459 base::Time current_time = base::Time::Now(); | 258 base::Time current_time = base::Time::Now(); |
460 base::TimeDelta delta = current_time - last_touchview_transition_time_; | 259 base::TimeDelta delta = current_time - last_touchview_transition_time_; |
461 if (IsMaximizeModeWindowManagerEnabled()) { | 260 if (IsMaximizeModeWindowManagerEnabled()) { |
462 UMA_HISTOGRAM_LONG_TIMES("Ash.TouchView.TouchViewInactive", delta); | 261 UMA_HISTOGRAM_LONG_TIMES("Ash.TouchView.TouchViewInactive", delta); |
463 total_non_touchview_time_ += delta; | 262 total_non_touchview_time_ += delta; |
464 } else { | 263 } else { |
465 UMA_HISTOGRAM_LONG_TIMES("Ash.TouchView.TouchViewActive", delta); | 264 UMA_HISTOGRAM_LONG_TIMES("Ash.TouchView.TouchViewActive", delta); |
466 total_touchview_time_ += delta; | 265 total_touchview_time_ += delta; |
467 } | 266 } |
468 last_touchview_transition_time_ = current_time; | 267 last_touchview_transition_time_ = current_time; |
469 } | 268 } |
470 } | 269 } |
471 | 270 |
472 void MaximizeModeController::LoadDisplayRotationProperties() { | |
473 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); | |
474 if (!display_manager->registered_internal_display_rotation_lock()) | |
475 return; | |
476 | |
477 SetDisplayRotation(display_manager, | |
478 display_manager->registered_internal_display_rotation()); | |
479 SetRotationLocked(true); | |
480 } | |
481 | |
482 void MaximizeModeController::OnAppTerminating() { | 271 void MaximizeModeController::OnAppTerminating() { |
483 if (CanEnterMaximizeMode()) { | 272 if (CanEnterMaximizeMode()) { |
484 RecordTouchViewStateTransition(); | 273 RecordTouchViewStateTransition(); |
485 UMA_HISTOGRAM_CUSTOM_COUNTS("Ash.TouchView.TouchViewActiveTotal", | 274 UMA_HISTOGRAM_CUSTOM_COUNTS("Ash.TouchView.TouchViewActiveTotal", |
486 total_touchview_time_.InMinutes(), | 275 total_touchview_time_.InMinutes(), |
487 1, base::TimeDelta::FromDays(7).InMinutes(), 50); | 276 1, base::TimeDelta::FromDays(7).InMinutes(), 50); |
488 UMA_HISTOGRAM_CUSTOM_COUNTS("Ash.TouchView.TouchViewInactiveTotal", | 277 UMA_HISTOGRAM_CUSTOM_COUNTS("Ash.TouchView.TouchViewInactiveTotal", |
489 total_non_touchview_time_.InMinutes(), | 278 total_non_touchview_time_.InMinutes(), |
490 1, base::TimeDelta::FromDays(7).InMinutes(), 50); | 279 1, base::TimeDelta::FromDays(7).InMinutes(), 50); |
491 base::TimeDelta total_runtime = total_touchview_time_ + | 280 base::TimeDelta total_runtime = total_touchview_time_ + |
492 total_non_touchview_time_; | 281 total_non_touchview_time_; |
493 if (total_runtime.InSeconds() > 0) { | 282 if (total_runtime.InSeconds() > 0) { |
494 UMA_HISTOGRAM_PERCENTAGE("Ash.TouchView.TouchViewActivePercentage", | 283 UMA_HISTOGRAM_PERCENTAGE("Ash.TouchView.TouchViewActivePercentage", |
495 100 * total_touchview_time_.InSeconds() / total_runtime.InSeconds()); | 284 100 * total_touchview_time_.InSeconds() / total_runtime.InSeconds()); |
496 } | 285 } |
497 } | 286 } |
498 Shell::GetInstance()->display_controller()->RemoveObserver(this); | |
499 } | 287 } |
500 | 288 |
501 bool MaximizeModeController::WasLidOpenedRecently() const { | 289 bool MaximizeModeController::WasLidOpenedRecently() const { |
502 if (last_lid_open_time_.is_null()) | 290 if (last_lid_open_time_.is_null()) |
503 return false; | 291 return false; |
504 | 292 |
505 base::TimeTicks now = tick_clock_->NowTicks(); | 293 base::TimeTicks now = tick_clock_->NowTicks(); |
506 DCHECK(now >= last_lid_open_time_); | 294 DCHECK(now >= last_lid_open_time_); |
507 base::TimeDelta elapsed_time = now - last_lid_open_time_; | 295 base::TimeDelta elapsed_time = now - last_lid_open_time_; |
508 return elapsed_time <= kLidRecentlyOpenedDuration; | 296 return elapsed_time <= kLidRecentlyOpenedDuration; |
509 } | 297 } |
510 | 298 |
511 void MaximizeModeController::SetTickClockForTest( | 299 void MaximizeModeController::SetTickClockForTest( |
512 scoped_ptr<base::TickClock> tick_clock) { | 300 scoped_ptr<base::TickClock> tick_clock) { |
513 DCHECK(tick_clock_); | 301 DCHECK(tick_clock_); |
514 tick_clock_ = tick_clock.Pass(); | 302 tick_clock_ = tick_clock.Pass(); |
515 } | 303 } |
516 | 304 |
517 } // namespace ash | 305 } // namespace ash |
OLD | NEW |