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.
7 #include "ash/ash_switches.h"
8 #include "ash/content/display/screen_orientation_controller_chromeos.h"
9 #include "ash/display/display_info.h"
10 #include "ash/display/display_manager.h"
11 #include "ash/shell.h"
12 #include "ash/test/ash_test_base.h"
13 #include "ash/test/ash_test_helper.h"
14 #include "ash/test/display_manager_test_api.h"
15 #include "ash/test/test_shell_delegate.h"
16 #include "ash/test/test_system_tray_delegate.h"
17 #include "ash/wm/maximize_mode/maximize_mode_controller.h"
18 #include "base/command_line.h"
19 #include "base/memory/scoped_ptr.h"
20 #include "chromeos/accelerometer/accelerometer_reader.h"
21 #include "chromeos/accelerometer/accelerometer_types.h"
22 #include "content/public/browser/browser_context.h"
23 #include "content/public/browser/web_contents.h"
24 #include "content/public/test/test_browser_context.h"
25 #include "third_party/WebKit/public/platform/modules/screen_orientation/WebScreenOrientationLockType.h"
26 #include "ui/aura/window.h"
27 #include "ui/gfx/display.h"
28 #include "ui/message_center/message_center.h"
29 #include "ui/views/test/webview_test_helper.h"
30 #include "ui/views/view.h"
31 #include "ui/views/views_delegate.h"
32 #include "ui/wm/public/activation_client.h"
38 const float kDegreesToRadians
= 3.1415926f
/ 180.0f
;
39 const float kMeanGravity
= 9.8066f
;
41 DisplayInfo
CreateDisplayInfo(int64 id
, const gfx::Rect
& bounds
) {
42 DisplayInfo
info(id
, "dummy", false);
43 info
.SetBounds(bounds
);
47 void EnableMaximizeMode(bool enable
) {
49 ->maximize_mode_controller()
50 ->EnableMaximizeModeWindowManager(enable
);
53 bool RotationLocked() {
54 return Shell::GetInstance()
55 ->screen_orientation_controller()
59 void SetDisplayRotationById(int64 display_id
, gfx::Display::Rotation rotation
) {
60 Shell::GetInstance()->display_manager()->SetDisplayRotation(
61 display_id
, rotation
, gfx::Display::ROTATION_SOURCE_USER
);
64 void SetInternalDisplayRotation(gfx::Display::Rotation rotation
) {
65 SetDisplayRotationById(gfx::Display::InternalDisplayId(), rotation
);
68 void SetRotationLocked(bool rotation_locked
) {
69 Shell::GetInstance()->screen_orientation_controller()->SetRotationLocked(
73 void TriggerLidUpdate(const gfx::Vector3dF
& lid
) {
74 scoped_refptr
<chromeos::AccelerometerUpdate
> update(
75 new chromeos::AccelerometerUpdate());
76 update
->Set(chromeos::ACCELEROMETER_SOURCE_SCREEN
, lid
.x(), lid
.y(), lid
.z());
77 Shell::GetInstance()->screen_orientation_controller()->OnAccelerometerUpdated(
81 // Attaches the NativeView of |web_contents| to |parent| without changing the
82 // currently active window.
83 void AttachWebContents(content::WebContents
* web_contents
,
84 aura::Window
* parent
) {
85 aura::Window
* window
= web_contents
->GetNativeView();
87 parent
->AddChild(window
);
90 // Attaches the NativeView of |web_contents| to |parent|, ensures that it is
91 // visible, and activates the parent window.
92 void AttachAndActivateWebContents(content::WebContents
* web_contents
,
93 aura::Window
* parent
) {
94 AttachWebContents(web_contents
, parent
);
95 Shell::GetInstance()->activation_client()->ActivateWindow(parent
);
100 class ScreenOrientationControllerTest
: public test::AshTestBase
{
102 ScreenOrientationControllerTest();
103 ~ScreenOrientationControllerTest() override
;
105 ScreenOrientationController
* delegate() {
106 return screen_orientation_controller_
;
109 // Creates and initializes and empty content::WebContents that is backed by a
110 // content::BrowserContext and that has an aura::Window.
111 content::WebContents
* CreateWebContents();
113 // Creates a secondary content::WebContents, with a separate
114 // content::BrowserContext.
115 content::WebContents
* CreateSecondaryWebContents();
117 // test::AshTestBase:
118 void SetUp() override
;
121 ScreenOrientationController
* screen_orientation_controller_
;
123 // Optional content::BrowserContext used for two window tests.
124 scoped_ptr
<content::BrowserContext
> secondary_browser_context_
;
126 // Setups underlying content layer so that content::WebContents can be
128 scoped_ptr
<views::WebViewTestHelper
> webview_test_helper_
;
130 DISALLOW_COPY_AND_ASSIGN(ScreenOrientationControllerTest
);
133 ScreenOrientationControllerTest::ScreenOrientationControllerTest() {
134 webview_test_helper_
.reset(new views::WebViewTestHelper());
137 ScreenOrientationControllerTest::~ScreenOrientationControllerTest() {
140 content::WebContents
* ScreenOrientationControllerTest::CreateWebContents() {
141 return views::ViewsDelegate::GetInstance()->CreateWebContents(
142 ash_test_helper()->test_shell_delegate()->GetActiveBrowserContext(),
146 content::WebContents
*
147 ScreenOrientationControllerTest::CreateSecondaryWebContents() {
148 secondary_browser_context_
.reset(new content::TestBrowserContext());
149 return views::ViewsDelegate::GetInstance()->CreateWebContents(
150 secondary_browser_context_
.get(), nullptr);
153 void ScreenOrientationControllerTest::SetUp() {
154 base::CommandLine::ForCurrentProcess()->AppendSwitch(
155 switches::kAshUseFirstDisplayAsInternal
);
156 base::CommandLine::ForCurrentProcess()->AppendSwitch(
157 switches::kAshEnableTouchViewTesting
);
158 test::AshTestBase::SetUp();
159 screen_orientation_controller_
=
160 Shell::GetInstance()->screen_orientation_controller();
163 // Tests that a content::WebContents can lock rotation.
164 TEST_F(ScreenOrientationControllerTest
, LockOrientation
) {
165 scoped_ptr
<content::WebContents
> content(CreateWebContents());
166 scoped_ptr
<aura::Window
> focus_window(CreateTestWindowInShellWithId(0));
167 ASSERT_NE(nullptr, content
->GetNativeView());
168 ASSERT_EQ(gfx::Display::ROTATE_0
, GetCurrentInternalDisplayRotation());
169 ASSERT_FALSE(RotationLocked());
171 AttachAndActivateWebContents(content
.get(), focus_window
.get());
172 delegate()->Lock(content
.get(), blink::WebScreenOrientationLockLandscape
);
173 EXPECT_EQ(gfx::Display::ROTATE_0
, GetCurrentInternalDisplayRotation());
174 EXPECT_TRUE(RotationLocked());
177 // Tests that a content::WebContents can unlock rotation.
178 TEST_F(ScreenOrientationControllerTest
, Unlock
) {
179 scoped_ptr
<content::WebContents
> content(CreateWebContents());
180 scoped_ptr
<aura::Window
> focus_window(CreateTestWindowInShellWithId(0));
181 ASSERT_NE(nullptr, content
->GetNativeView());
182 ASSERT_EQ(gfx::Display::ROTATE_0
, GetCurrentInternalDisplayRotation());
183 ASSERT_FALSE(RotationLocked());
185 AttachAndActivateWebContents(content
.get(), focus_window
.get());
186 delegate()->Lock(content
.get(), blink::WebScreenOrientationLockLandscape
);
187 EXPECT_EQ(gfx::Display::ROTATE_0
, GetCurrentInternalDisplayRotation());
188 EXPECT_TRUE(RotationLocked());
190 delegate()->Unlock(content
.get());
191 EXPECT_FALSE(RotationLocked());
194 // Tests that a content::WebContents is able to change the orientation of the
195 // display after having locked rotation.
196 TEST_F(ScreenOrientationControllerTest
, OrientationChanges
) {
197 scoped_ptr
<content::WebContents
> content(CreateWebContents());
198 scoped_ptr
<aura::Window
> focus_window(CreateTestWindowInShellWithId(0));
199 ASSERT_NE(nullptr, content
->GetNativeView());
200 ASSERT_EQ(gfx::Display::ROTATE_0
, GetCurrentInternalDisplayRotation());
201 ASSERT_FALSE(RotationLocked());
203 AttachAndActivateWebContents(content
.get(), focus_window
.get());
204 delegate()->Lock(content
.get(), blink::WebScreenOrientationLockPortrait
);
205 EXPECT_EQ(gfx::Display::ROTATE_90
, GetCurrentInternalDisplayRotation());
206 EXPECT_TRUE(RotationLocked());
208 delegate()->Lock(content
.get(), blink::WebScreenOrientationLockLandscape
);
209 EXPECT_EQ(gfx::Display::ROTATE_0
, GetCurrentInternalDisplayRotation());
212 // Tests that orientation can only be set by the first content::WebContents that
213 // has set a rotation lock.
214 TEST_F(ScreenOrientationControllerTest
, SecondContentCannotChangeOrientation
) {
215 scoped_ptr
<content::WebContents
> content1(CreateWebContents());
216 scoped_ptr
<content::WebContents
> content2(CreateSecondaryWebContents());
217 scoped_ptr
<aura::Window
> focus_window1(CreateTestWindowInShellWithId(0));
218 scoped_ptr
<aura::Window
> focus_window2(CreateTestWindowInShellWithId(1));
219 ASSERT_NE(content1
->GetNativeView(), content2
->GetNativeView());
221 AttachAndActivateWebContents(content1
.get(), focus_window1
.get());
222 AttachWebContents(content2
.get(), focus_window2
.get());
223 delegate()->Lock(content1
.get(), blink::WebScreenOrientationLockLandscape
);
224 delegate()->Lock(content2
.get(), blink::WebScreenOrientationLockPortrait
);
225 EXPECT_EQ(gfx::Display::ROTATE_0
, GetCurrentInternalDisplayRotation());
228 // Tests that only the content::WebContents that set a rotation lock can perform
230 TEST_F(ScreenOrientationControllerTest
, SecondContentCannotUnlock
) {
231 scoped_ptr
<content::WebContents
> content1(CreateWebContents());
232 scoped_ptr
<content::WebContents
> content2(CreateSecondaryWebContents());
233 scoped_ptr
<aura::Window
> focus_window1(CreateTestWindowInShellWithId(0));
234 scoped_ptr
<aura::Window
> focus_window2(CreateTestWindowInShellWithId(1));
235 ASSERT_NE(content1
->GetNativeView(), content2
->GetNativeView());
237 AttachAndActivateWebContents(content1
.get(), focus_window1
.get());
238 AttachWebContents(content2
.get(), focus_window2
.get());
239 delegate()->Lock(content1
.get(), blink::WebScreenOrientationLockLandscape
);
240 delegate()->Unlock(content2
.get());
241 EXPECT_TRUE(RotationLocked());
244 // Tests that a rotation lock is applied only while the content::WebContents are
245 // a part of the active window.
246 TEST_F(ScreenOrientationControllerTest
, ActiveWindowChangesUpdateLock
) {
247 scoped_ptr
<content::WebContents
> content(CreateWebContents());
248 scoped_ptr
<aura::Window
> focus_window1(CreateTestWindowInShellWithId(0));
249 scoped_ptr
<aura::Window
> focus_window2(CreateTestWindowInShellWithId(1));
251 AttachAndActivateWebContents(content
.get(), focus_window1
.get());
252 delegate()->Lock(content
.get(), blink::WebScreenOrientationLockLandscape
);
253 ASSERT_TRUE(RotationLocked());
255 aura::client::ActivationClient
* activation_client
=
256 Shell::GetInstance()->activation_client();
257 activation_client
->ActivateWindow(focus_window2
.get());
258 EXPECT_FALSE(RotationLocked());
260 activation_client
->ActivateWindow(focus_window1
.get());
261 EXPECT_TRUE(RotationLocked());
264 // Tests that switching between windows with different orientation locks change
266 TEST_F(ScreenOrientationControllerTest
, ActiveWindowChangesUpdateOrientation
) {
267 scoped_ptr
<content::WebContents
> content1(CreateWebContents());
268 scoped_ptr
<content::WebContents
> content2(CreateSecondaryWebContents());
269 scoped_ptr
<aura::Window
> focus_window1(CreateTestWindowInShellWithId(0));
270 scoped_ptr
<aura::Window
> focus_window2(CreateTestWindowInShellWithId(1));
271 AttachAndActivateWebContents(content1
.get(), focus_window1
.get());
272 AttachWebContents(content2
.get(), focus_window2
.get());
274 delegate()->Lock(content1
.get(), blink::WebScreenOrientationLockLandscape
);
275 delegate()->Lock(content2
.get(), blink::WebScreenOrientationLockPortrait
);
276 EXPECT_EQ(gfx::Display::ROTATE_0
, GetCurrentInternalDisplayRotation());
278 aura::client::ActivationClient
* activation_client
=
279 Shell::GetInstance()->activation_client();
280 activation_client
->ActivateWindow(focus_window2
.get());
281 EXPECT_TRUE(RotationLocked());
282 EXPECT_EQ(gfx::Display::ROTATE_90
, GetCurrentInternalDisplayRotation());
284 activation_client
->ActivateWindow(focus_window1
.get());
285 EXPECT_TRUE(RotationLocked());
286 EXPECT_EQ(gfx::Display::ROTATE_0
, GetCurrentInternalDisplayRotation());
289 // Tests that a rotation lock is removed when the setting window is hidden, and
290 // that it is reapplied when the window becomes visible.
291 TEST_F(ScreenOrientationControllerTest
, VisibilityChangesLock
) {
292 scoped_ptr
<content::WebContents
> content(CreateWebContents());
293 scoped_ptr
<aura::Window
> focus_window(CreateTestWindowInShellWithId(0));
294 AttachAndActivateWebContents(content
.get(), focus_window
.get());
295 delegate()->Lock(content
.get(), blink::WebScreenOrientationLockLandscape
);
296 EXPECT_TRUE(RotationLocked());
298 aura::Window
* window
= content
->GetNativeView();
300 EXPECT_FALSE(RotationLocked());
303 EXPECT_TRUE(RotationLocked());
306 // Tests that when a window is destroyed that its rotation lock is removed, and
307 // window activations no longer change the lock
308 TEST_F(ScreenOrientationControllerTest
, WindowDestructionRemovesLock
) {
309 scoped_ptr
<content::WebContents
> content(CreateWebContents());
310 scoped_ptr
<aura::Window
> focus_window1(CreateTestWindowInShellWithId(0));
311 scoped_ptr
<aura::Window
> focus_window2(CreateTestWindowInShellWithId(1));
313 AttachAndActivateWebContents(content
.get(), focus_window1
.get());
314 delegate()->Lock(content
.get(), blink::WebScreenOrientationLockLandscape
);
315 ASSERT_TRUE(RotationLocked());
317 focus_window1
->RemoveChild(content
->GetNativeView());
319 EXPECT_FALSE(RotationLocked());
321 aura::client::ActivationClient
* activation_client
=
322 Shell::GetInstance()->activation_client();
323 activation_client
->ActivateWindow(focus_window2
.get());
324 EXPECT_FALSE(RotationLocked());
326 activation_client
->ActivateWindow(focus_window1
.get());
327 EXPECT_FALSE(RotationLocked());
330 // Tests that accelerometer readings in each of the screen angles will trigger a
331 // rotation of the internal display.
332 TEST_F(ScreenOrientationControllerTest
, DisplayRotation
) {
333 EnableMaximizeMode(true);
334 // Now test rotating in all directions.
335 TriggerLidUpdate(gfx::Vector3dF(-kMeanGravity
, 0.0f
, 0.0f
));
336 EXPECT_EQ(gfx::Display::ROTATE_90
, GetCurrentInternalDisplayRotation());
337 TriggerLidUpdate(gfx::Vector3dF(0.0f
, kMeanGravity
, 0.0f
));
338 EXPECT_EQ(gfx::Display::ROTATE_180
, GetCurrentInternalDisplayRotation());
339 TriggerLidUpdate(gfx::Vector3dF(kMeanGravity
, 0.0f
, 0.0f
));
340 EXPECT_EQ(gfx::Display::ROTATE_270
, GetCurrentInternalDisplayRotation());
341 TriggerLidUpdate(gfx::Vector3dF(0.0f
, -kMeanGravity
, 0.0f
));
342 EXPECT_EQ(gfx::Display::ROTATE_0
, GetCurrentInternalDisplayRotation());
345 // Tests that low angles are ignored by the accelerometer (i.e. when the device
346 // is almost laying flat).
347 TEST_F(ScreenOrientationControllerTest
, RotationIgnoresLowAngles
) {
348 EnableMaximizeMode(true);
349 TriggerLidUpdate(gfx::Vector3dF(0.0f
, -kMeanGravity
, -kMeanGravity
));
350 EXPECT_EQ(gfx::Display::ROTATE_0
, GetCurrentInternalDisplayRotation());
351 TriggerLidUpdate(gfx::Vector3dF(-2.0f
, 0.0f
, -kMeanGravity
));
352 EXPECT_EQ(gfx::Display::ROTATE_0
, GetCurrentInternalDisplayRotation());
353 TriggerLidUpdate(gfx::Vector3dF(0.0f
, 2.0f
, -kMeanGravity
));
354 EXPECT_EQ(gfx::Display::ROTATE_0
, GetCurrentInternalDisplayRotation());
355 TriggerLidUpdate(gfx::Vector3dF(2.0f
, 0.0f
, -kMeanGravity
));
356 EXPECT_EQ(gfx::Display::ROTATE_0
, GetCurrentInternalDisplayRotation());
357 TriggerLidUpdate(gfx::Vector3dF(0.0f
, -2.0f
, -kMeanGravity
));
358 EXPECT_EQ(gfx::Display::ROTATE_0
, GetCurrentInternalDisplayRotation());
361 // Tests that the display will stick to the current orientation beyond the
362 // halfway point, preventing frequent updates back and forth.
363 TEST_F(ScreenOrientationControllerTest
, RotationSticky
) {
364 EnableMaximizeMode(true);
365 gfx::Vector3dF
gravity(0.0f
, -kMeanGravity
, 0.0f
);
366 TriggerLidUpdate(gravity
);
367 EXPECT_EQ(gfx::Display::ROTATE_0
, GetCurrentInternalDisplayRotation());
369 // Turn past half-way point to next direction and rotation should remain
371 float degrees
= 50.0;
372 gravity
.set_x(-sin(degrees
* kDegreesToRadians
) * kMeanGravity
);
373 gravity
.set_y(-cos(degrees
* kDegreesToRadians
) * kMeanGravity
);
374 TriggerLidUpdate(gravity
);
375 EXPECT_EQ(gfx::Display::ROTATE_0
, GetCurrentInternalDisplayRotation());
377 // Turn more and the screen should rotate.
379 gravity
.set_x(-sin(degrees
* kDegreesToRadians
) * kMeanGravity
);
380 gravity
.set_y(-cos(degrees
* kDegreesToRadians
) * kMeanGravity
);
381 TriggerLidUpdate(gravity
);
382 EXPECT_EQ(gfx::Display::ROTATE_90
, GetCurrentInternalDisplayRotation());
384 // Turn back just beyond the half-way point and the new rotation should
385 // still be in effect.
387 gravity
.set_x(-sin(degrees
* kDegreesToRadians
) * kMeanGravity
);
388 gravity
.set_y(-cos(degrees
* kDegreesToRadians
) * kMeanGravity
);
389 TriggerLidUpdate(gravity
);
390 EXPECT_EQ(gfx::Display::ROTATE_90
, GetCurrentInternalDisplayRotation());
393 // Tests that the display will stick to its current orientation when the
394 // rotation lock has been set.
395 TEST_F(ScreenOrientationControllerTest
, RotationLockPreventsRotation
) {
396 EnableMaximizeMode(true);
397 SetRotationLocked(true);
399 // Turn past the threshold for rotation.
400 float degrees
= 90.0;
401 gfx::Vector3dF
gravity(-sin(degrees
* kDegreesToRadians
) * kMeanGravity
,
402 -cos(degrees
* kDegreesToRadians
) * kMeanGravity
,
404 TriggerLidUpdate(gravity
);
405 EXPECT_EQ(gfx::Display::ROTATE_0
, GetCurrentInternalDisplayRotation());
407 SetRotationLocked(false);
408 TriggerLidUpdate(gravity
);
409 EXPECT_EQ(gfx::Display::ROTATE_90
, GetCurrentInternalDisplayRotation());
412 // The TrayDisplay class that is responsible for adding/updating MessageCenter
413 // notifications is only added to the SystemTray on ChromeOS.
414 // Tests that the screen rotation notifications are suppressed when
415 // triggered by the accelerometer.
416 TEST_F(ScreenOrientationControllerTest
, BlockRotationNotifications
) {
417 EnableMaximizeMode(true);
418 test::TestSystemTrayDelegate
* tray_delegate
=
419 static_cast<test::TestSystemTrayDelegate
*>(
420 Shell::GetInstance()->system_tray_delegate());
421 tray_delegate
->set_should_show_display_notification(true);
422 test::DisplayManagerTestApi(Shell::GetInstance()->display_manager())
423 .SetFirstDisplayAsInternalDisplay();
425 message_center::MessageCenter
* message_center
=
426 message_center::MessageCenter::Get();
428 EXPECT_EQ(0u, message_center
->NotificationCount());
429 EXPECT_FALSE(message_center
->HasPopupNotifications());
431 // Make sure notifications are still displayed when
432 // adjusting the screen rotation directly when in maximize mode
433 ASSERT_NE(gfx::Display::ROTATE_270
, GetCurrentInternalDisplayRotation());
434 SetInternalDisplayRotation(gfx::Display::ROTATE_270
);
435 SetRotationLocked(false);
436 EXPECT_EQ(gfx::Display::ROTATE_270
, GetCurrentInternalDisplayRotation());
437 EXPECT_EQ(1u, message_center
->NotificationCount());
438 EXPECT_TRUE(message_center
->HasPopupNotifications());
440 // Clear all notifications
441 message_center
->RemoveAllNotifications(false);
442 EXPECT_EQ(0u, message_center
->NotificationCount());
443 EXPECT_FALSE(message_center
->HasPopupNotifications());
445 // Make sure notifications are blocked when adjusting the screen rotation
446 // via the accelerometer while in maximize mode
447 // Rotate the screen 90 degrees
448 ASSERT_NE(gfx::Display::ROTATE_90
, GetCurrentInternalDisplayRotation());
449 TriggerLidUpdate(gfx::Vector3dF(-kMeanGravity
, 0.0f
, 0.0f
));
450 ASSERT_EQ(gfx::Display::ROTATE_90
, GetCurrentInternalDisplayRotation());
451 EXPECT_EQ(0u, message_center
->NotificationCount());
452 EXPECT_FALSE(message_center
->HasPopupNotifications());
454 // Make sure notifications are still displayed when
455 // adjusting the screen rotation directly when not in maximize mode
456 EnableMaximizeMode(false);
457 // Reset the screen rotation.
458 SetInternalDisplayRotation(gfx::Display::ROTATE_0
);
459 // Clear all notifications
460 message_center
->RemoveAllNotifications(false);
461 ASSERT_NE(gfx::Display::ROTATE_180
, GetCurrentInternalDisplayRotation());
462 ASSERT_EQ(0u, message_center
->NotificationCount());
463 ASSERT_FALSE(message_center
->HasPopupNotifications());
464 SetInternalDisplayRotation(gfx::Display::ROTATE_180
);
465 EXPECT_EQ(gfx::Display::ROTATE_180
, GetCurrentInternalDisplayRotation());
466 EXPECT_EQ(1u, message_center
->NotificationCount());
467 EXPECT_TRUE(message_center
->HasPopupNotifications());
470 // Tests that if a user has set a display rotation that it is restored upon
471 // exiting maximize mode.
472 TEST_F(ScreenOrientationControllerTest
, ResetUserRotationUponExit
) {
473 test::DisplayManagerTestApi(Shell::GetInstance()->display_manager())
474 .SetFirstDisplayAsInternalDisplay();
476 SetInternalDisplayRotation(gfx::Display::ROTATE_90
);
477 EnableMaximizeMode(true);
479 TriggerLidUpdate(gfx::Vector3dF(0.0f
, kMeanGravity
, 0.0f
));
480 EXPECT_EQ(gfx::Display::ROTATE_180
, GetCurrentInternalDisplayRotation());
482 EnableMaximizeMode(false);
483 EXPECT_EQ(gfx::Display::ROTATE_90
, GetCurrentInternalDisplayRotation());
486 // Tests that if a user sets a display rotation that accelerometer rotation
488 TEST_F(ScreenOrientationControllerTest
,
489 NonAccelerometerRotationChangesLockRotation
) {
490 EnableMaximizeMode(true);
491 ASSERT_FALSE(RotationLocked());
492 SetInternalDisplayRotation(gfx::Display::ROTATE_270
);
493 EXPECT_TRUE(RotationLocked());
496 // Tests that if a user changes the display rotation, while rotation is locked,
497 // that the updates are recorded. Upon exiting maximize mode the latest user
498 // rotation should be applied.
499 TEST_F(ScreenOrientationControllerTest
, UpdateUserRotationWhileRotationLocked
) {
500 EnableMaximizeMode(true);
501 SetInternalDisplayRotation(gfx::Display::ROTATE_270
);
502 // User sets rotation to the same rotation that the display was at when
503 // maximize mode was activated.
504 SetInternalDisplayRotation(gfx::Display::ROTATE_0
);
505 EnableMaximizeMode(false);
506 EXPECT_EQ(gfx::Display::ROTATE_0
, GetCurrentInternalDisplayRotation());
509 // Tests that when the orientation lock is set to Landscape, that rotation can
510 // be done between the two angles of the orientation.
511 TEST_F(ScreenOrientationControllerTest
, LandscapeOrientationAllowsRotation
) {
512 scoped_ptr
<content::WebContents
> content(CreateWebContents());
513 scoped_ptr
<aura::Window
> focus_window(CreateTestWindowInShellWithId(0));
514 EnableMaximizeMode(true);
516 AttachAndActivateWebContents(content
.get(), focus_window
.get());
517 delegate()->Lock(content
.get(), blink::WebScreenOrientationLockLandscape
);
518 EXPECT_EQ(gfx::Display::ROTATE_0
, GetCurrentInternalDisplayRotation());
519 EXPECT_TRUE(RotationLocked());
521 // Inverse of orientation is allowed
522 TriggerLidUpdate(gfx::Vector3dF(0.0f
, kMeanGravity
, 0.0f
));
523 EXPECT_EQ(gfx::Display::ROTATE_180
, GetCurrentInternalDisplayRotation());
525 // Display rotations between are not allowed
526 TriggerLidUpdate(gfx::Vector3dF(kMeanGravity
, 0.0f
, 0.0f
));
527 EXPECT_EQ(gfx::Display::ROTATE_180
, GetCurrentInternalDisplayRotation());
528 TriggerLidUpdate(gfx::Vector3dF(-kMeanGravity
, 0.0f
, 0.0f
));
529 EXPECT_EQ(gfx::Display::ROTATE_180
, GetCurrentInternalDisplayRotation());
532 // Tests that when the orientation lock is set to Portrait, that rotaiton can be
533 // done between the two angles of the orientation.
534 TEST_F(ScreenOrientationControllerTest
, PortraitOrientationAllowsRotation
) {
535 scoped_ptr
<content::WebContents
> content(CreateWebContents());
536 scoped_ptr
<aura::Window
> focus_window(CreateTestWindowInShellWithId(0));
537 EnableMaximizeMode(true);
539 AttachAndActivateWebContents(content
.get(), focus_window
.get());
540 delegate()->Lock(content
.get(), blink::WebScreenOrientationLockPortrait
);
541 EXPECT_EQ(gfx::Display::ROTATE_90
, GetCurrentInternalDisplayRotation());
542 EXPECT_TRUE(RotationLocked());
544 // Inverse of orientation is allowed
545 TriggerLidUpdate(gfx::Vector3dF(kMeanGravity
, 0.0f
, 0.0f
));
546 EXPECT_EQ(gfx::Display::ROTATE_270
, GetCurrentInternalDisplayRotation());
548 // Display rotations between are not allowed
549 TriggerLidUpdate(gfx::Vector3dF(0.0f
, kMeanGravity
, 0.0f
));
550 EXPECT_EQ(gfx::Display::ROTATE_270
, GetCurrentInternalDisplayRotation());
551 TriggerLidUpdate(gfx::Vector3dF(0.0f
, -kMeanGravity
, 0.0f
));
552 EXPECT_EQ(gfx::Display::ROTATE_270
, GetCurrentInternalDisplayRotation());
555 // Tests that for an orientation lock which does not allow rotation, that the
556 // display rotation remains constant.
557 TEST_F(ScreenOrientationControllerTest
, OrientationLockDisallowsRotation
) {
558 scoped_ptr
<content::WebContents
> content(CreateWebContents());
559 scoped_ptr
<aura::Window
> focus_window(CreateTestWindowInShellWithId(0));
560 EnableMaximizeMode(true);
562 AttachAndActivateWebContents(content
.get(), focus_window
.get());
563 delegate()->Lock(content
.get(),
564 blink::WebScreenOrientationLockPortraitPrimary
);
565 EXPECT_EQ(gfx::Display::ROTATE_90
, GetCurrentInternalDisplayRotation());
566 EXPECT_TRUE(RotationLocked());
568 // Rotation does not change.
569 TriggerLidUpdate(gfx::Vector3dF(kMeanGravity
, 0.0f
, 0.0f
));
570 EXPECT_EQ(gfx::Display::ROTATE_90
, GetCurrentInternalDisplayRotation());
571 TriggerLidUpdate(gfx::Vector3dF(0.0f
, kMeanGravity
, 0.0f
));
572 EXPECT_EQ(gfx::Display::ROTATE_90
, GetCurrentInternalDisplayRotation());
573 TriggerLidUpdate(gfx::Vector3dF(0.0f
, -kMeanGravity
, 0.0f
));
574 EXPECT_EQ(gfx::Display::ROTATE_90
, GetCurrentInternalDisplayRotation());
577 // Tests that after a content::WebContents has applied an orientation lock which
578 // supports rotation, that a user rotation lock does not allow rotation.
579 TEST_F(ScreenOrientationControllerTest
, UserRotationLockDisallowsRotation
) {
580 scoped_ptr
<content::WebContents
> content(CreateWebContents());
581 scoped_ptr
<aura::Window
> focus_window(CreateTestWindowInShellWithId(0));
582 EnableMaximizeMode(true);
584 AttachAndActivateWebContents(content
.get(), focus_window
.get());
585 delegate()->Lock(content
.get(), blink::WebScreenOrientationLockLandscape
);
586 delegate()->Unlock(content
.get());
588 SetRotationLocked(true);
589 EXPECT_TRUE(RotationLocked());
590 EXPECT_EQ(gfx::Display::ROTATE_0
, GetCurrentInternalDisplayRotation());
592 TriggerLidUpdate(gfx::Vector3dF(0.0f
, kMeanGravity
, 0.0f
));
593 EXPECT_EQ(gfx::Display::ROTATE_0
, GetCurrentInternalDisplayRotation());
596 // Tests that when MaximizeMode is triggered before the internal display is
597 // ready, that ScreenOrientationController still begins listening to events,
598 // which require an internal display to be acted upon.
599 TEST_F(ScreenOrientationControllerTest
, InternalDisplayNotAvailableAtStartup
) {
600 test::DisplayManagerTestApi(Shell::GetInstance()->display_manager())
601 .SetFirstDisplayAsInternalDisplay();
603 int64 internal_display_id
= gfx::Display::InternalDisplayId();
604 gfx::Display::SetInternalDisplayId(gfx::Display::kInvalidDisplayID
);
606 EnableMaximizeMode(true);
608 // Should not crash, even though there is no internal display.
609 SetDisplayRotationById(internal_display_id
, gfx::Display::ROTATE_180
);
610 EXPECT_FALSE(RotationLocked());
612 // Should not crash, even though the invalid display id is requested.
613 SetDisplayRotationById(gfx::Display::kInvalidDisplayID
,
614 gfx::Display::ROTATE_180
);
615 EXPECT_FALSE(RotationLocked());
617 // With an internal display now available, functionality should resume.
618 gfx::Display::SetInternalDisplayId(internal_display_id
);
619 SetInternalDisplayRotation(gfx::Display::ROTATE_90
);
620 EXPECT_TRUE(RotationLocked());
623 // Verifies rotating an inactive Display is sucessful.
624 TEST_F(ScreenOrientationControllerTest
, RotateInactiveDisplay
) {
625 const int64 kInternalDisplayId
= 9;
626 const int64 kExternalDisplayId
= 10;
627 const gfx::Display::Rotation kNewRotation
= gfx::Display::ROTATE_180
;
629 DisplayManager
* display_manager
= Shell::GetInstance()->display_manager();
631 const DisplayInfo internal_display_info
=
632 CreateDisplayInfo(kInternalDisplayId
, gfx::Rect(0, 0, 500, 500));
633 const DisplayInfo external_display_info
=
634 CreateDisplayInfo(kExternalDisplayId
, gfx::Rect(1, 1, 500, 500));
636 std::vector
<DisplayInfo
> display_info_list_two_active
;
637 display_info_list_two_active
.push_back(internal_display_info
);
638 display_info_list_two_active
.push_back(external_display_info
);
640 std::vector
<DisplayInfo
> display_info_list_one_active
;
641 display_info_list_one_active
.push_back(external_display_info
);
643 // The DisplayInfo list with two active displays needs to be added first so
644 // that the DisplayManager can track the |internal_display_info| as inactive
645 // instead of non-existent.
646 ash::Shell::GetInstance()->display_manager()->UpdateDisplays(
647 display_info_list_two_active
);
648 ash::Shell::GetInstance()->display_manager()->UpdateDisplays(
649 display_info_list_one_active
);
651 test::DisplayManagerTestApi(display_manager
)
652 .SetInternalDisplayId(kInternalDisplayId
);
654 ASSERT_NE(kNewRotation
, display_manager
->GetDisplayInfo(kInternalDisplayId
)
655 .GetActiveRotation());
657 delegate()->SetDisplayRotation(kNewRotation
,
658 gfx::Display::ROTATION_SOURCE_ACTIVE
);
660 EXPECT_EQ(kNewRotation
, display_manager
->GetDisplayInfo(kInternalDisplayId
)
661 .GetActiveRotation());