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 <math.h> 6 7 #include "ash/wm/maximize_mode/maximize_mode_controller.h" 8 9 #include "ash/accelerometer/accelerometer_controller.h" 10 #include "ash/display/display_manager.h" 11 #include "ash/shell.h" 12 #include "ash/system/tray/system_tray_delegate.h" 13 #include "ash/test/ash_test_base.h" 14 #include "ash/test/display_manager_test_api.h" 15 #include "ash/test/test_system_tray_delegate.h" 16 #include "ash/test/test_volume_control_delegate.h" 17 #include "base/test/simple_test_tick_clock.h" 18 #include "ui/accelerometer/accelerometer_types.h" 19 #include "ui/events/event_handler.h" 20 #include "ui/events/test/event_generator.h" 21 #include "ui/gfx/vector3d_f.h" 22 #include "ui/message_center/message_center.h" 23 24 #if defined(USE_X11) 25 #include "ui/events/test/events_test_utils_x11.h" 26 #endif 27 28 namespace ash { 29 30 namespace { 31 32 const float kDegreesToRadians = 3.1415926f / 180.0f; 33 const float kMeanGravity = 9.8066f; 34 35 } // namespace 36 37 // Test accelerometer data taken with the lid at less than 180 degrees while 38 // shaking the device around. The data is to be interpreted in groups of 6 where 39 // each 6 values corresponds to the X, Y, and Z readings from the base and lid 40 // accelerometers in this order. 41 extern const float kAccelerometerLaptopModeTestData[]; 42 extern const size_t kAccelerometerLaptopModeTestDataLength; 43 44 // Test accelerometer data taken with the lid open 360 degrees while 45 // shaking the device around. The data is to be interpreted in groups of 6 where 46 // each 6 values corresponds to the X, Y, and Z readings from the base and lid 47 // accelerometers in this order. 48 extern const float kAccelerometerFullyOpenTestData[]; 49 extern const size_t kAccelerometerFullyOpenTestDataLength; 50 51 class MaximizeModeControllerTest : public test::AshTestBase { 52 public: 53 MaximizeModeControllerTest() {} 54 virtual ~MaximizeModeControllerTest() {} 55 56 virtual void SetUp() OVERRIDE { 57 test::AshTestBase::SetUp(); 58 Shell::GetInstance()->accelerometer_controller()->RemoveObserver( 59 maximize_mode_controller()); 60 61 // Set the first display to be the internal display for the accelerometer 62 // screen rotation tests. 63 test::DisplayManagerTestApi(Shell::GetInstance()->display_manager()). 64 SetFirstDisplayAsInternalDisplay(); 65 } 66 67 virtual void TearDown() OVERRIDE { 68 Shell::GetInstance()->accelerometer_controller()->AddObserver( 69 maximize_mode_controller()); 70 test::AshTestBase::TearDown(); 71 } 72 73 MaximizeModeController* maximize_mode_controller() { 74 return Shell::GetInstance()->maximize_mode_controller(); 75 } 76 77 void TriggerAccelerometerUpdate(const gfx::Vector3dF& base, 78 const gfx::Vector3dF& lid) { 79 ui::AccelerometerUpdate update; 80 update.Set(ui::ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD, 81 base.x(), base.y(), base.z()); 82 update.Set(ui::ACCELEROMETER_SOURCE_SCREEN, 83 lid.x(), lid.y(), lid.z()); 84 maximize_mode_controller()->OnAccelerometerUpdated(update); 85 } 86 87 bool IsMaximizeModeStarted() { 88 return maximize_mode_controller()->IsMaximizeModeWindowManagerEnabled(); 89 } 90 91 gfx::Display::Rotation GetInternalDisplayRotation() const { 92 return Shell::GetInstance()->display_manager()->GetDisplayInfo( 93 gfx::Display::InternalDisplayId()).rotation(); 94 } 95 96 void SetInternalDisplayRotation(gfx::Display::Rotation rotation) const { 97 Shell::GetInstance()->display_manager()-> 98 SetDisplayRotation(gfx::Display::InternalDisplayId(), rotation); 99 } 100 101 // Attaches a SimpleTestTickClock to the MaximizeModeController with a non 102 // null value initial value. 103 void AttachTickClockForTest() { 104 scoped_ptr<base::TickClock> tick_clock( 105 test_tick_clock_ = new base::SimpleTestTickClock()); 106 test_tick_clock_->Advance(base::TimeDelta::FromSeconds(1)); 107 maximize_mode_controller()->SetTickClockForTest(tick_clock.Pass()); 108 } 109 110 void AdvanceTickClock(const base::TimeDelta& delta) { 111 DCHECK(test_tick_clock_); 112 test_tick_clock_->Advance(delta); 113 } 114 115 void OpenLidToAngle(float degrees) { 116 DCHECK(degrees >= 0.0f); 117 DCHECK(degrees <= 360.0f); 118 119 float radians = degrees * kDegreesToRadians; 120 gfx::Vector3dF base_vector(0.0f, -kMeanGravity, 0.0f); 121 gfx::Vector3dF lid_vector(0.0f, 122 kMeanGravity * cos(radians), 123 kMeanGravity * sin(radians)); 124 TriggerAccelerometerUpdate(base_vector, lid_vector); 125 } 126 127 #if defined(OS_CHROMEOS) 128 void OpenLid() { 129 maximize_mode_controller()->LidEventReceived(true /* open */, 130 maximize_mode_controller()->tick_clock_->NowTicks()); 131 } 132 133 void CloseLid() { 134 maximize_mode_controller()->LidEventReceived(false /* open */, 135 maximize_mode_controller()->tick_clock_->NowTicks()); 136 } 137 #endif // OS_CHROMEOS 138 139 bool WasLidOpenedRecently() { 140 return maximize_mode_controller()->WasLidOpenedRecently(); 141 } 142 143 private: 144 base::SimpleTestTickClock* test_tick_clock_; 145 146 DISALLOW_COPY_AND_ASSIGN(MaximizeModeControllerTest); 147 }; 148 149 #if defined(OS_CHROMEOS) 150 151 // Verify that closing the lid will exit maximize mode. 152 TEST_F(MaximizeModeControllerTest, CloseLidWhileInMaximizeMode) { 153 OpenLidToAngle(315.0f); 154 ASSERT_TRUE(IsMaximizeModeStarted()); 155 156 CloseLid(); 157 EXPECT_FALSE(IsMaximizeModeStarted()); 158 } 159 160 // Verify that maximize mode will not be entered when the lid is closed. 161 TEST_F(MaximizeModeControllerTest, 162 HingeAnglesWithLidClosed) { 163 AttachTickClockForTest(); 164 165 CloseLid(); 166 167 OpenLidToAngle(270.0f); 168 EXPECT_FALSE(IsMaximizeModeStarted()); 169 170 OpenLidToAngle(315.0f); 171 EXPECT_FALSE(IsMaximizeModeStarted()); 172 173 OpenLidToAngle(355.0f); 174 EXPECT_FALSE(IsMaximizeModeStarted()); 175 } 176 177 // Verify the maximize mode state for unstable hinge angles when the lid was 178 // recently open. 179 TEST_F(MaximizeModeControllerTest, 180 UnstableHingeAnglesWhenLidRecentlyOpened) { 181 AttachTickClockForTest(); 182 183 OpenLid(); 184 ASSERT_TRUE(WasLidOpenedRecently()); 185 186 OpenLidToAngle(5.0f); 187 EXPECT_FALSE(IsMaximizeModeStarted()); 188 189 OpenLidToAngle(355.0f); 190 EXPECT_FALSE(IsMaximizeModeStarted()); 191 192 // This is a stable reading and should clear the last lid opened time. 193 OpenLidToAngle(45.0f); 194 EXPECT_FALSE(IsMaximizeModeStarted()); 195 EXPECT_FALSE(WasLidOpenedRecently()); 196 197 OpenLidToAngle(355.0f); 198 EXPECT_TRUE(IsMaximizeModeStarted()); 199 } 200 201 #endif // OS_CHROMEOS 202 203 // Verify the WasLidOpenedRecently signal with respect to time. 204 TEST_F(MaximizeModeControllerTest, WasLidOpenedRecentlyOverTime) { 205 #if defined(OS_CHROMEOS) 206 207 AttachTickClockForTest(); 208 209 // No lid open time initially. 210 ASSERT_FALSE(WasLidOpenedRecently()); 211 212 CloseLid(); 213 EXPECT_FALSE(WasLidOpenedRecently()); 214 215 OpenLid(); 216 EXPECT_TRUE(WasLidOpenedRecently()); 217 218 // 1 second after lid open. 219 AdvanceTickClock(base::TimeDelta::FromSeconds(1)); 220 EXPECT_TRUE(WasLidOpenedRecently()); 221 222 // 3 seconds after lid open. 223 AdvanceTickClock(base::TimeDelta::FromSeconds(2)); 224 EXPECT_FALSE(WasLidOpenedRecently()); 225 226 #else 227 228 EXPECT_FALSE(WasLidOpenedRecently()); 229 230 #endif // OS_CHROMEOS 231 } 232 233 // Verify the maximize mode enter/exit thresholds for stable angles. 234 TEST_F(MaximizeModeControllerTest, StableHingeAnglesWithLidOpened) { 235 ASSERT_FALSE(IsMaximizeModeStarted()); 236 ASSERT_FALSE(WasLidOpenedRecently()); 237 238 OpenLidToAngle(180.0f); 239 EXPECT_FALSE(IsMaximizeModeStarted()); 240 241 OpenLidToAngle(315.0f); 242 EXPECT_TRUE(IsMaximizeModeStarted()); 243 244 OpenLidToAngle(180.0f); 245 EXPECT_TRUE(IsMaximizeModeStarted()); 246 247 OpenLidToAngle(45.0f); 248 EXPECT_FALSE(IsMaximizeModeStarted()); 249 250 OpenLidToAngle(270.0f); 251 EXPECT_TRUE(IsMaximizeModeStarted()); 252 253 OpenLidToAngle(90.0f); 254 EXPECT_FALSE(IsMaximizeModeStarted()); 255 } 256 257 // Verify the maximize mode state for unstable hinge angles when the lid is open 258 // but not recently. 259 TEST_F(MaximizeModeControllerTest, UnstableHingeAnglesWithLidOpened) { 260 AttachTickClockForTest(); 261 262 ASSERT_FALSE(WasLidOpenedRecently()); 263 ASSERT_FALSE(IsMaximizeModeStarted()); 264 265 OpenLidToAngle(5.0f); 266 EXPECT_FALSE(IsMaximizeModeStarted()); 267 268 OpenLidToAngle(355.0f); 269 EXPECT_TRUE(IsMaximizeModeStarted()); 270 271 OpenLidToAngle(5.0f); 272 EXPECT_TRUE(IsMaximizeModeStarted()); 273 } 274 275 // Tests that when the hinge is nearly vertically aligned, the current state 276 // persists as the computed angle is highly inaccurate in this orientation. 277 TEST_F(MaximizeModeControllerTest, HingeAligned) { 278 // Laptop in normal orientation lid open 90 degrees. 279 TriggerAccelerometerUpdate(gfx::Vector3dF(0.0f, 0.0f, -kMeanGravity), 280 gfx::Vector3dF(0.0f, -kMeanGravity, 0.0f)); 281 EXPECT_FALSE(IsMaximizeModeStarted()); 282 283 // Completely vertical. 284 TriggerAccelerometerUpdate(gfx::Vector3dF(kMeanGravity, 0.0f, 0.0f), 285 gfx::Vector3dF(kMeanGravity, 0.0f, 0.0f)); 286 EXPECT_FALSE(IsMaximizeModeStarted()); 287 288 // Close to vertical but with hinge appearing to be open 270 degrees. 289 TriggerAccelerometerUpdate(gfx::Vector3dF(kMeanGravity, 0.0f, -0.1f), 290 gfx::Vector3dF(kMeanGravity, 0.1f, 0.0f)); 291 EXPECT_FALSE(IsMaximizeModeStarted()); 292 293 // Flat and open 270 degrees should start maximize mode. 294 TriggerAccelerometerUpdate(gfx::Vector3dF(0.0f, 0.0f, -kMeanGravity), 295 gfx::Vector3dF(0.0f, kMeanGravity, 0.0f)); 296 EXPECT_TRUE(IsMaximizeModeStarted()); 297 298 // Normal 90 degree orientation but near vertical should stay in maximize 299 // mode. 300 TriggerAccelerometerUpdate(gfx::Vector3dF(kMeanGravity, 0.0f, -0.1f), 301 gfx::Vector3dF(kMeanGravity, -0.1f, 0.0f)); 302 EXPECT_TRUE(IsMaximizeModeStarted()); 303 } 304 305 // Tests that accelerometer readings in each of the screen angles will trigger a 306 // rotation of the internal display. 307 TEST_F(MaximizeModeControllerTest, DisplayRotation) { 308 // Trigger maximize mode by opening to 270. 309 TriggerAccelerometerUpdate(gfx::Vector3dF(0.0f, 0.0f, kMeanGravity), 310 gfx::Vector3dF(0.0f, -kMeanGravity, 0.0f)); 311 ASSERT_TRUE(IsMaximizeModeStarted()); 312 313 // Now test rotating in all directions. 314 TriggerAccelerometerUpdate(gfx::Vector3dF(-kMeanGravity, 0.0f, 0.0f), 315 gfx::Vector3dF(-kMeanGravity, 0.0f, 0.0f)); 316 EXPECT_EQ(gfx::Display::ROTATE_90, GetInternalDisplayRotation()); 317 TriggerAccelerometerUpdate(gfx::Vector3dF(0.0f, -kMeanGravity, 0.0f), 318 gfx::Vector3dF(0.0f, kMeanGravity, 0.0f)); 319 EXPECT_EQ(gfx::Display::ROTATE_180, GetInternalDisplayRotation()); 320 TriggerAccelerometerUpdate(gfx::Vector3dF(kMeanGravity, 0.0f, 0.0f), 321 gfx::Vector3dF(kMeanGravity, 0.0f, 0.0f)); 322 EXPECT_EQ(gfx::Display::ROTATE_270, GetInternalDisplayRotation()); 323 TriggerAccelerometerUpdate(gfx::Vector3dF(0.0f, kMeanGravity, 0.0f), 324 gfx::Vector3dF(0.0f, -kMeanGravity, 0.0f)); 325 EXPECT_EQ(gfx::Display::ROTATE_0, GetInternalDisplayRotation()); 326 } 327 328 // Tests that low angles are ignored by the accelerometer (i.e. when the device 329 // is almost laying flat). 330 TEST_F(MaximizeModeControllerTest, RotationIgnoresLowAngles) { 331 // Trigger maximize mode by opening to 270. 332 TriggerAccelerometerUpdate(gfx::Vector3dF(0.0f, 0.0f, kMeanGravity), 333 gfx::Vector3dF(0.0f, -kMeanGravity, 0.0f)); 334 ASSERT_TRUE(IsMaximizeModeStarted()); 335 336 TriggerAccelerometerUpdate( 337 gfx::Vector3dF(0.0f, kMeanGravity, kMeanGravity), 338 gfx::Vector3dF(0.0f, -kMeanGravity, -kMeanGravity)); 339 EXPECT_EQ(gfx::Display::ROTATE_0, GetInternalDisplayRotation()); 340 TriggerAccelerometerUpdate(gfx::Vector3dF(-2.0f, 0.0f, kMeanGravity), 341 gfx::Vector3dF(-2.0f, 0.0f, -kMeanGravity)); 342 EXPECT_EQ(gfx::Display::ROTATE_0, GetInternalDisplayRotation()); 343 TriggerAccelerometerUpdate(gfx::Vector3dF(0.0f, -2.0f, kMeanGravity), 344 gfx::Vector3dF(0.0f, 2.0f, -kMeanGravity)); 345 EXPECT_EQ(gfx::Display::ROTATE_0, GetInternalDisplayRotation()); 346 TriggerAccelerometerUpdate(gfx::Vector3dF(2.0f, 0.0f, kMeanGravity), 347 gfx::Vector3dF(2.0f, 0.0f, -kMeanGravity)); 348 EXPECT_EQ(gfx::Display::ROTATE_0, GetInternalDisplayRotation()); 349 TriggerAccelerometerUpdate(gfx::Vector3dF(0.0f, 2.0f, kMeanGravity), 350 gfx::Vector3dF(0.0f, -2.0f, -kMeanGravity)); 351 EXPECT_EQ(gfx::Display::ROTATE_0, GetInternalDisplayRotation()); 352 } 353 354 // Tests that the display will stick to the current orientation beyond the 355 // halfway point, preventing frequent updates back and forth. 356 TEST_F(MaximizeModeControllerTest, RotationSticky) { 357 // Trigger maximize mode by opening to 270. 358 TriggerAccelerometerUpdate(gfx::Vector3dF(0.0f, 0.0f, kMeanGravity), 359 gfx::Vector3dF(0.0f, -kMeanGravity, 0.0f)); 360 ASSERT_TRUE(IsMaximizeModeStarted()); 361 362 gfx::Vector3dF gravity(0.0f, -kMeanGravity, 0.0f); 363 TriggerAccelerometerUpdate(gravity, gravity); 364 EXPECT_EQ(gfx::Display::ROTATE_0, GetInternalDisplayRotation()); 365 366 // Turn past half-way point to next direction and rotation should remain 367 // the same. 368 float degrees = 50.0; 369 gravity.set_x(-sin(degrees * kDegreesToRadians) * kMeanGravity); 370 gravity.set_y(-cos(degrees * kDegreesToRadians) * kMeanGravity); 371 TriggerAccelerometerUpdate(gravity, gravity); 372 EXPECT_EQ(gfx::Display::ROTATE_0, GetInternalDisplayRotation()); 373 374 // Turn more and the screen should rotate. 375 degrees = 70.0; 376 gravity.set_x(-sin(degrees * kDegreesToRadians) * kMeanGravity); 377 gravity.set_y(-cos(degrees * kDegreesToRadians) * kMeanGravity); 378 TriggerAccelerometerUpdate(gravity, gravity); 379 EXPECT_EQ(gfx::Display::ROTATE_90, GetInternalDisplayRotation()); 380 381 // Turn back just beyond the half-way point and the new rotation should 382 // still be in effect. 383 degrees = 40.0; 384 gravity.set_x(-sin(degrees * kDegreesToRadians) * kMeanGravity); 385 gravity.set_y(-cos(degrees * kDegreesToRadians) * kMeanGravity); 386 TriggerAccelerometerUpdate(gravity, gravity); 387 EXPECT_EQ(gfx::Display::ROTATE_90, GetInternalDisplayRotation()); 388 } 389 390 // Tests that the screen only rotates when maximize mode is engaged, and will 391 // return to the standard orientation on exiting maximize mode. 392 TEST_F(MaximizeModeControllerTest, RotationOnlyInMaximizeMode) { 393 // Rotate on side with lid only open 90 degrees. 394 TriggerAccelerometerUpdate(gfx::Vector3dF(-9.5f, 0.0f, -3.5f), 395 gfx::Vector3dF(-9.5f, -3.5f, 0.0f)); 396 ASSERT_FALSE(IsMaximizeModeStarted()); 397 EXPECT_EQ(gfx::Display::ROTATE_0, GetInternalDisplayRotation()); 398 399 // Open lid, screen should now rotate to match orientation. 400 TriggerAccelerometerUpdate(gfx::Vector3dF(-9.5f, 0.0f, 3.5f), 401 gfx::Vector3dF(-9.5f, -3.5f, 0.0f)); 402 ASSERT_TRUE(IsMaximizeModeStarted()); 403 EXPECT_EQ(gfx::Display::ROTATE_90, GetInternalDisplayRotation()); 404 405 // Close lid back to 90, screen should rotate back. 406 TriggerAccelerometerUpdate(gfx::Vector3dF(-9.5f, 0.0f, -3.5f), 407 gfx::Vector3dF(-9.5f, -3.5f, 0.0f)); 408 ASSERT_FALSE(IsMaximizeModeStarted()); 409 EXPECT_EQ(gfx::Display::ROTATE_0, GetInternalDisplayRotation()); 410 } 411 412 413 TEST_F(MaximizeModeControllerTest, LaptopTest) { 414 // Feeds in sample accelerometer data and verifies that there are no 415 // transitions into touchview / maximize mode while shaking the device around 416 // with the hinge at less than 180 degrees. Note the conversion from device 417 // data to accelerometer updates consistent with accelerometer_reader.cc. 418 ASSERT_EQ(0u, kAccelerometerLaptopModeTestDataLength % 6); 419 for (size_t i = 0; i < kAccelerometerLaptopModeTestDataLength / 6; ++i) { 420 gfx::Vector3dF base(-kAccelerometerLaptopModeTestData[i * 6 + 1], 421 -kAccelerometerLaptopModeTestData[i * 6], 422 -kAccelerometerLaptopModeTestData[i * 6 + 2]); 423 base.Scale(kMeanGravity); 424 gfx::Vector3dF lid(-kAccelerometerLaptopModeTestData[i * 6 + 4], 425 kAccelerometerLaptopModeTestData[i * 6 + 3], 426 kAccelerometerLaptopModeTestData[i * 6 + 5]); 427 lid.Scale(kMeanGravity); 428 TriggerAccelerometerUpdate(base, lid); 429 // There are a lot of samples, so ASSERT rather than EXPECT to only generate 430 // one failure rather than potentially hundreds. 431 ASSERT_FALSE(IsMaximizeModeStarted()); 432 } 433 } 434 435 TEST_F(MaximizeModeControllerTest, MaximizeModeTest) { 436 // Trigger maximize mode by opening to 270 to begin the test in maximize mode. 437 TriggerAccelerometerUpdate(gfx::Vector3dF(0.0f, 0.0f, kMeanGravity), 438 gfx::Vector3dF(0.0f, -kMeanGravity, 0.0f)); 439 ASSERT_TRUE(IsMaximizeModeStarted()); 440 441 // Feeds in sample accelerometer data and verifies that there are no 442 // transitions out of touchview / maximize mode while shaking the device 443 // around. Note the conversion from device data to accelerometer updates 444 // consistent with accelerometer_reader.cc. 445 ASSERT_EQ(0u, kAccelerometerFullyOpenTestDataLength % 6); 446 for (size_t i = 0; i < kAccelerometerFullyOpenTestDataLength / 6; ++i) { 447 gfx::Vector3dF base(-kAccelerometerFullyOpenTestData[i * 6 + 1], 448 -kAccelerometerFullyOpenTestData[i * 6], 449 -kAccelerometerFullyOpenTestData[i * 6 + 2]); 450 base.Scale(kMeanGravity); 451 gfx::Vector3dF lid(-kAccelerometerFullyOpenTestData[i * 6 + 4], 452 kAccelerometerFullyOpenTestData[i * 6 + 3], 453 kAccelerometerFullyOpenTestData[i * 6 + 5]); 454 lid.Scale(kMeanGravity); 455 TriggerAccelerometerUpdate(base, lid); 456 // There are a lot of samples, so ASSERT rather than EXPECT to only generate 457 // one failure rather than potentially hundreds. 458 ASSERT_TRUE(IsMaximizeModeStarted()); 459 } 460 } 461 462 // Tests that the display will stick to its current orientation when the 463 // rotation lock has been set. 464 TEST_F(MaximizeModeControllerTest, RotationLockPreventsRotation) { 465 // Trigger maximize mode by opening to 270. 466 TriggerAccelerometerUpdate(gfx::Vector3dF(0.0f, 0.0f, kMeanGravity), 467 gfx::Vector3dF(0.0f, -kMeanGravity, 0.0f)); 468 ASSERT_TRUE(IsMaximizeModeStarted()); 469 470 gfx::Vector3dF gravity(-kMeanGravity, 0.0f, 0.0f); 471 472 maximize_mode_controller()->SetRotationLocked(true); 473 474 // Turn past the threshold for rotation. 475 float degrees = 90.0; 476 gravity.set_x(-sin(degrees * kDegreesToRadians) * kMeanGravity); 477 gravity.set_y(-cos(degrees * kDegreesToRadians) * kMeanGravity); 478 TriggerAccelerometerUpdate(gravity, gravity); 479 EXPECT_EQ(gfx::Display::ROTATE_0, GetInternalDisplayRotation()); 480 481 maximize_mode_controller()->SetRotationLocked(false); 482 TriggerAccelerometerUpdate(gravity, gravity); 483 EXPECT_EQ(gfx::Display::ROTATE_90, GetInternalDisplayRotation()); 484 } 485 486 // Tests that when MaximizeModeController turns off MaximizeMode that on the 487 // next accelerometer update the rotation lock is cleared. 488 TEST_F(MaximizeModeControllerTest, ExitingMaximizeModeClearRotationLock) { 489 // Trigger maximize mode by opening to 270. 490 OpenLidToAngle(270.0f); 491 ASSERT_TRUE(IsMaximizeModeStarted()); 492 493 maximize_mode_controller()->SetRotationLocked(true); 494 495 OpenLidToAngle(90.0f); 496 EXPECT_FALSE(IsMaximizeModeStarted()); 497 498 // Send an update that would not relaunch MaximizeMode. 499 OpenLidToAngle(90.0f); 500 EXPECT_FALSE(maximize_mode_controller()->rotation_locked()); 501 } 502 503 // The TrayDisplay class that is responsible for adding/updating MessageCenter 504 // notifications is only added to the SystemTray on ChromeOS. 505 #if defined(OS_CHROMEOS) 506 // Tests that the screen rotation notifications are suppressed when 507 // triggered by the accelerometer. 508 TEST_F(MaximizeModeControllerTest, BlockRotationNotifications) { 509 test::TestSystemTrayDelegate* tray_delegate = 510 static_cast<test::TestSystemTrayDelegate*>( 511 Shell::GetInstance()->system_tray_delegate()); 512 tray_delegate->set_should_show_display_notification(true); 513 514 message_center::MessageCenter* message_center = 515 message_center::MessageCenter::Get(); 516 517 // Make sure notifications are still displayed when 518 // adjusting the screen rotation directly when not in maximize mode 519 ASSERT_FALSE(IsMaximizeModeStarted()); 520 ASSERT_NE(gfx::Display::ROTATE_180, GetInternalDisplayRotation()); 521 ASSERT_EQ(0u, message_center->NotificationCount()); 522 ASSERT_FALSE(message_center->HasPopupNotifications()); 523 SetInternalDisplayRotation(gfx::Display::ROTATE_180); 524 EXPECT_EQ(gfx::Display::ROTATE_180, GetInternalDisplayRotation()); 525 EXPECT_EQ(1u, message_center->NotificationCount()); 526 EXPECT_TRUE(message_center->HasPopupNotifications()); 527 528 // Reset the screen rotation. 529 SetInternalDisplayRotation(gfx::Display::ROTATE_0); 530 // Clear all notifications 531 message_center->RemoveAllNotifications(false); 532 // Trigger maximize mode by opening to 270. 533 TriggerAccelerometerUpdate(gfx::Vector3dF(0.0f, 0.0f, kMeanGravity), 534 gfx::Vector3dF(0.0f, -kMeanGravity, 0.0f)); 535 EXPECT_TRUE(IsMaximizeModeStarted()); 536 EXPECT_EQ(0u, message_center->NotificationCount()); 537 EXPECT_FALSE(message_center->HasPopupNotifications()); 538 539 // Make sure notifications are still displayed when 540 // adjusting the screen rotation directly when in maximize mode 541 ASSERT_NE(gfx::Display::ROTATE_270, GetInternalDisplayRotation()); 542 SetInternalDisplayRotation(gfx::Display::ROTATE_270); 543 maximize_mode_controller()->SetRotationLocked(false); 544 EXPECT_EQ(gfx::Display::ROTATE_270, GetInternalDisplayRotation()); 545 EXPECT_EQ(1u, message_center->NotificationCount()); 546 EXPECT_TRUE(message_center->HasPopupNotifications()); 547 548 // Clear all notifications 549 message_center->RemoveAllNotifications(false); 550 EXPECT_EQ(0u, message_center->NotificationCount()); 551 EXPECT_FALSE(message_center->HasPopupNotifications()); 552 553 // Make sure notifications are blocked when adjusting the screen rotation 554 // via the accelerometer while in maximize mode 555 // Rotate the screen 90 degrees 556 ASSERT_NE(gfx::Display::ROTATE_90, GetInternalDisplayRotation()); 557 TriggerAccelerometerUpdate(gfx::Vector3dF(-kMeanGravity, 0.0f, 0.0f), 558 gfx::Vector3dF(-kMeanGravity, 0.0f, 0.0f)); 559 ASSERT_EQ(gfx::Display::ROTATE_90, GetInternalDisplayRotation()); 560 EXPECT_EQ(0u, message_center->NotificationCount()); 561 EXPECT_FALSE(message_center->HasPopupNotifications()); 562 } 563 #endif 564 565 // Tests that if a user has set a display rotation that it is restored upon 566 // exiting maximize mode. 567 TEST_F(MaximizeModeControllerTest, ResetUserRotationUponExit) { 568 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); 569 display_manager->SetDisplayRotation(gfx::Display::InternalDisplayId(), 570 gfx::Display::ROTATE_90); 571 572 // Trigger maximize mode 573 TriggerAccelerometerUpdate(gfx::Vector3dF(0.0f, 0.0f, kMeanGravity), 574 gfx::Vector3dF(0.0f, -kMeanGravity, 0.0f)); 575 ASSERT_TRUE(IsMaximizeModeStarted()); 576 577 TriggerAccelerometerUpdate(gfx::Vector3dF(0.0f, -kMeanGravity, 0.0f), 578 gfx::Vector3dF(0.0f, kMeanGravity, 0.0f)); 579 EXPECT_EQ(gfx::Display::ROTATE_180, GetInternalDisplayRotation()); 580 581 // Exit maximize mode 582 TriggerAccelerometerUpdate(gfx::Vector3dF(0.0f, 0.0f, -kMeanGravity), 583 gfx::Vector3dF(0.0f, -kMeanGravity, 0.0f)); 584 EXPECT_FALSE(IsMaximizeModeStarted()); 585 EXPECT_EQ(gfx::Display::ROTATE_90, GetInternalDisplayRotation()); 586 } 587 588 // Tests that if a user sets a display rotation that accelerometer rotation 589 // becomes locked. 590 TEST_F(MaximizeModeControllerTest, 591 NonAccelerometerRotationChangesLockRotation) { 592 // Trigger maximize mode by opening to 270. 593 TriggerAccelerometerUpdate(gfx::Vector3dF(0.0f, 0.0f, kMeanGravity), 594 gfx::Vector3dF(0.0f, -kMeanGravity, 0.0f)); 595 ASSERT_FALSE(maximize_mode_controller()->rotation_locked()); 596 SetInternalDisplayRotation(gfx::Display::ROTATE_270); 597 EXPECT_TRUE(maximize_mode_controller()->rotation_locked()); 598 } 599 600 // Tests that if a user changes the display rotation, while rotation is locked, 601 // that the updates are recorded. Upon exiting maximize mode the latest user 602 // rotation should be applied. 603 TEST_F(MaximizeModeControllerTest, UpdateUserRotationWhileRotationLocked) { 604 // Trigger maximize mode by opening to 270. 605 TriggerAccelerometerUpdate(gfx::Vector3dF(0.0f, 0.0f, kMeanGravity), 606 gfx::Vector3dF(0.0f, -kMeanGravity, 0.0f)); 607 SetInternalDisplayRotation(gfx::Display::ROTATE_270); 608 // User sets rotation to the same rotation that the display was at when 609 // maximize mode was activated. 610 SetInternalDisplayRotation(gfx::Display::ROTATE_0); 611 // Exit maximize mode 612 TriggerAccelerometerUpdate(gfx::Vector3dF(0.0f, 0.0f, -kMeanGravity), 613 gfx::Vector3dF(0.0f, -kMeanGravity, 0.0f)); 614 EXPECT_EQ(gfx::Display::ROTATE_0, GetInternalDisplayRotation()); 615 } 616 617 } // namespace ash 618