1 // Copyright (c) 2012 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.
5 #include "chrome/browser/chromeos/display/display_preferences.h"
10 #include "ash/content/display/screen_orientation_controller_chromeos.h"
11 #include "ash/display/display_controller.h"
12 #include "ash/display/display_layout_store.h"
13 #include "ash/display/display_manager.h"
14 #include "ash/display/resolution_notification_controller.h"
15 #include "ash/screen_util.h"
16 #include "ash/shell.h"
17 #include "ash/test/ash_test_base.h"
18 #include "ash/test/display_manager_test_api.h"
19 #include "ash/wm/maximize_mode/maximize_mode_controller.h"
20 #include "base/memory/ref_counted.h"
21 #include "base/prefs/scoped_user_pref_update.h"
22 #include "base/prefs/testing_pref_service.h"
23 #include "base/strings/string_number_conversions.h"
24 #include "base/values.h"
25 #include "chrome/browser/chromeos/display/display_configuration_observer.h"
26 #include "chrome/browser/chromeos/login/users/mock_user_manager.h"
27 #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h"
28 #include "chrome/common/pref_names.h"
29 #include "chrome/test/base/testing_browser_process.h"
30 #include "ui/display/chromeos/display_configurator.h"
31 #include "ui/gfx/geometry/vector3d_f.h"
32 #include "ui/message_center/message_center.h"
34 using ash::ResolutionNotificationController
;
38 const char kPrimaryIdKey
[] = "primary-id";
39 const char kMirroredKey
[] = "mirrored";
40 const char kPositionKey
[] = "position";
41 const char kOffsetKey
[] = "offset";
43 // The mean acceleration due to gravity on Earth in m/s^2.
44 const float kMeanGravity
= 9.80665f
;
46 bool IsRotationLocked() {
47 return ash::Shell::GetInstance()
48 ->screen_orientation_controller()
52 class DisplayPreferencesTest
: public ash::test::AshTestBase
{
54 DisplayPreferencesTest()
55 : mock_user_manager_(new MockUserManager
),
56 user_manager_enabler_(mock_user_manager_
) {
59 ~DisplayPreferencesTest() override
{}
61 void SetUp() override
{
62 EXPECT_CALL(*mock_user_manager_
, IsUserLoggedIn())
63 .WillRepeatedly(testing::Return(false));
64 EXPECT_CALL(*mock_user_manager_
, Shutdown());
65 ash::test::AshTestBase::SetUp();
66 RegisterDisplayLocalStatePrefs(local_state_
.registry());
67 TestingBrowserProcess::GetGlobal()->SetLocalState(&local_state_
);
68 observer_
.reset(new DisplayConfigurationObserver());
71 void TearDown() override
{
73 TestingBrowserProcess::GetGlobal()->SetLocalState(NULL
);
74 ash::test::AshTestBase::TearDown();
77 void LoggedInAsUser() {
78 EXPECT_CALL(*mock_user_manager_
, IsUserLoggedIn())
79 .WillRepeatedly(testing::Return(true));
80 EXPECT_CALL(*mock_user_manager_
, IsLoggedInAsUserWithGaiaAccount())
81 .WillRepeatedly(testing::Return(true));
84 void LoggedInAsGuest() {
85 EXPECT_CALL(*mock_user_manager_
, IsUserLoggedIn())
86 .WillRepeatedly(testing::Return(true));
87 EXPECT_CALL(*mock_user_manager_
, IsLoggedInAsUserWithGaiaAccount())
88 .WillRepeatedly(testing::Return(false));
89 EXPECT_CALL(*mock_user_manager_
, IsLoggedInAsSupervisedUser())
90 .WillRepeatedly(testing::Return(false));
93 // Do not use the implementation of display_preferences.cc directly to avoid
94 // notifying the update to the system.
95 void StoreDisplayLayoutPrefForName(const std::string
& name
,
96 ash::DisplayLayout::Position layout
,
99 DictionaryPrefUpdate
update(&local_state_
, prefs::kSecondaryDisplays
);
100 ash::DisplayLayout
display_layout(layout
, offset
);
101 display_layout
.primary_id
= primary_id
;
103 DCHECK(!name
.empty());
105 base::DictionaryValue
* pref_data
= update
.Get();
106 scoped_ptr
<base::Value
>layout_value(new base::DictionaryValue());
107 if (pref_data
->HasKey(name
)) {
108 base::Value
* value
= NULL
;
109 if (pref_data
->Get(name
, &value
) && value
!= NULL
)
110 layout_value
.reset(value
->DeepCopy());
112 if (ash::DisplayLayout::ConvertToValue(display_layout
, layout_value
.get()))
113 pref_data
->Set(name
, layout_value
.release());
116 void StoreDisplayLayoutPrefForPair(int64 id1
,
118 ash::DisplayLayout::Position layout
,
120 StoreDisplayLayoutPrefForName(
121 base::Int64ToString(id1
) + "," + base::Int64ToString(id2
),
122 layout
, offset
, id1
);
125 void StoreDisplayLayoutPrefForSecondary(int64 id
,
126 ash::DisplayLayout::Position layout
,
129 StoreDisplayLayoutPrefForName(
130 base::Int64ToString(id
), layout
, offset
, primary_id
);
133 void StoreDisplayOverscan(int64 id
, const gfx::Insets
& insets
) {
134 DictionaryPrefUpdate
update(&local_state_
, prefs::kDisplayProperties
);
135 const std::string name
= base::Int64ToString(id
);
137 base::DictionaryValue
* pref_data
= update
.Get();
138 base::DictionaryValue
* insets_value
= new base::DictionaryValue();
139 insets_value
->SetInteger("insets_top", insets
.top());
140 insets_value
->SetInteger("insets_left", insets
.left());
141 insets_value
->SetInteger("insets_bottom", insets
.bottom());
142 insets_value
->SetInteger("insets_right", insets
.right());
143 pref_data
->Set(name
, insets_value
);
146 void StoreColorProfile(int64 id
, const std::string
& profile
) {
147 DictionaryPrefUpdate
update(&local_state_
, prefs::kDisplayProperties
);
148 const std::string name
= base::Int64ToString(id
);
150 base::DictionaryValue
* pref_data
= update
.Get();
151 base::DictionaryValue
* property
= new base::DictionaryValue();
152 property
->SetString("color_profile_name", profile
);
153 pref_data
->Set(name
, property
);
156 void StoreDisplayRotationPrefsForTest(bool rotation_lock
,
157 gfx::Display::Rotation rotation
) {
158 DictionaryPrefUpdate
update(local_state(), prefs::kDisplayRotationLock
);
159 base::DictionaryValue
* pref_data
= update
.Get();
160 pref_data
->SetBoolean("lock", rotation_lock
);
161 pref_data
->SetInteger("orientation", static_cast<int>(rotation
));
164 std::string
GetRegisteredDisplayLayoutStr(int64 id1
, int64 id2
) {
165 ash::DisplayIdPair pair
;
168 return ash::Shell::GetInstance()->display_manager()->layout_store()->
169 GetRegisteredDisplayLayout(pair
).ToString();
172 PrefService
* local_state() { return &local_state_
; }
175 MockUserManager
* mock_user_manager_
; // Not owned.
176 ScopedUserManagerEnabler user_manager_enabler_
;
177 TestingPrefServiceSimple local_state_
;
178 scoped_ptr
<DisplayConfigurationObserver
> observer_
;
180 DISALLOW_COPY_AND_ASSIGN(DisplayPreferencesTest
);
185 TEST_F(DisplayPreferencesTest
, PairedLayoutOverrides
) {
186 UpdateDisplay("100x100,200x200");
187 int64 id1
= gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id();
188 int64 id2
= ash::ScreenUtil::GetSecondaryDisplay().id();
189 int64 dummy_id
= id2
+ 1;
190 ASSERT_NE(id1
, dummy_id
);
192 StoreDisplayLayoutPrefForPair(id1
, id2
, ash::DisplayLayout::TOP
, 20);
193 StoreDisplayLayoutPrefForPair(id1
, dummy_id
, ash::DisplayLayout::LEFT
, 30);
194 StoreDisplayPowerStateForTest(
195 chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON
);
197 ash::Shell
* shell
= ash::Shell::GetInstance();
199 LoadDisplayPreferences(true);
200 // DisplayPowerState should be ignored at boot.
201 EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON
,
202 shell
->display_configurator()->requested_power_state());
204 shell
->display_manager()->UpdateDisplays();
205 // Check if the layout settings are notified to the system properly.
206 // The paired layout overrides old layout.
207 // Inverted one of for specified pair (id1, id2). Not used for the pair
208 // (id1, dummy_id) since dummy_id is not connected right now.
210 shell
->display_manager()->GetCurrentDisplayLayout().ToString());
211 EXPECT_EQ("top, 20", GetRegisteredDisplayLayoutStr(id1
, id2
));
212 EXPECT_EQ("left, 30", GetRegisteredDisplayLayoutStr(id1
, dummy_id
));
215 TEST_F(DisplayPreferencesTest
, BasicStores
) {
216 ash::DisplayController
* display_controller
=
217 ash::Shell::GetInstance()->display_controller();
218 ash::DisplayManager
* display_manager
=
219 ash::Shell::GetInstance()->display_manager();
221 UpdateDisplay("200x200*2, 400x300#400x400|300x200*1.25");
222 int64 id1
= gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id();
223 ash::test::DisplayManagerTestApi
test_api(display_manager
);
224 test_api
.SetInternalDisplayId(id1
);
225 int64 id2
= ash::ScreenUtil::GetSecondaryDisplay().id();
226 int64 dummy_id
= id2
+ 1;
227 ASSERT_NE(id1
, dummy_id
);
228 std::vector
<ui::ColorCalibrationProfile
> profiles
;
229 profiles
.push_back(ui::COLOR_PROFILE_STANDARD
);
230 profiles
.push_back(ui::COLOR_PROFILE_DYNAMIC
);
231 profiles
.push_back(ui::COLOR_PROFILE_MOVIE
);
232 profiles
.push_back(ui::COLOR_PROFILE_READING
);
233 // Allows only |id1|.
234 test_api
.SetAvailableColorProfiles(id1
, profiles
);
235 display_manager
->SetColorCalibrationProfile(id1
, ui::COLOR_PROFILE_DYNAMIC
);
236 display_manager
->SetColorCalibrationProfile(id2
, ui::COLOR_PROFILE_DYNAMIC
);
239 ash::DisplayLayout
layout(ash::DisplayLayout::TOP
, 10);
240 SetCurrentDisplayLayout(layout
);
241 StoreDisplayLayoutPrefForTest(
242 id1
, dummy_id
, ash::DisplayLayout(ash::DisplayLayout::LEFT
, 20));
243 // Can't switch to a display that does not exist.
244 display_controller
->SetPrimaryDisplayId(dummy_id
);
245 EXPECT_NE(dummy_id
, ash::Shell::GetScreen()->GetPrimaryDisplay().id());
247 display_controller
->SetOverscanInsets(id1
, gfx::Insets(10, 11, 12, 13));
248 display_manager
->SetDisplayRotation(id1
, gfx::Display::ROTATE_90
);
249 EXPECT_TRUE(display_manager
->SetDisplayUIScale(id1
, 1.25f
));
250 EXPECT_FALSE(display_manager
->SetDisplayUIScale(id2
, 1.25f
));
252 const base::DictionaryValue
* displays
=
253 local_state()->GetDictionary(prefs::kSecondaryDisplays
);
254 const base::DictionaryValue
* layout_value
= NULL
;
255 std::string key
= base::Int64ToString(id1
) + "," + base::Int64ToString(id2
);
256 EXPECT_TRUE(displays
->GetDictionary(key
, &layout_value
));
258 ash::DisplayLayout stored_layout
;
259 EXPECT_TRUE(ash::DisplayLayout::ConvertFromValue(*layout_value
,
261 EXPECT_EQ(layout
.position
, stored_layout
.position
);
262 EXPECT_EQ(layout
.offset
, stored_layout
.offset
);
264 bool mirrored
= true;
265 EXPECT_TRUE(layout_value
->GetBoolean(kMirroredKey
, &mirrored
));
266 EXPECT_FALSE(mirrored
);
268 const base::DictionaryValue
* properties
=
269 local_state()->GetDictionary(prefs::kDisplayProperties
);
270 const base::DictionaryValue
* property
= NULL
;
271 EXPECT_TRUE(properties
->GetDictionary(base::Int64ToString(id1
), &property
));
274 EXPECT_TRUE(property
->GetInteger("rotation", &rotation
));
275 EXPECT_TRUE(property
->GetInteger("ui-scale", &ui_scale
));
276 EXPECT_EQ(1, rotation
);
277 EXPECT_EQ(1250, ui_scale
);
279 // Internal display never registered the resolution.
280 int width
= 0, height
= 0;
281 EXPECT_FALSE(property
->GetInteger("width", &width
));
282 EXPECT_FALSE(property
->GetInteger("height", &height
));
284 int top
= 0, left
= 0, bottom
= 0, right
= 0;
285 EXPECT_TRUE(property
->GetInteger("insets_top", &top
));
286 EXPECT_TRUE(property
->GetInteger("insets_left", &left
));
287 EXPECT_TRUE(property
->GetInteger("insets_bottom", &bottom
));
288 EXPECT_TRUE(property
->GetInteger("insets_right", &right
));
291 EXPECT_EQ(12, bottom
);
292 EXPECT_EQ(13, right
);
294 std::string color_profile
;
295 EXPECT_TRUE(property
->GetString("color_profile_name", &color_profile
));
296 EXPECT_EQ("dynamic", color_profile
);
298 EXPECT_TRUE(properties
->GetDictionary(base::Int64ToString(id2
), &property
));
299 EXPECT_TRUE(property
->GetInteger("rotation", &rotation
));
300 EXPECT_TRUE(property
->GetInteger("ui-scale", &ui_scale
));
301 EXPECT_EQ(0, rotation
);
302 // ui_scale works only on 2x scale factor/1st display.
303 EXPECT_EQ(1000, ui_scale
);
304 EXPECT_FALSE(property
->GetInteger("insets_top", &top
));
305 EXPECT_FALSE(property
->GetInteger("insets_left", &left
));
306 EXPECT_FALSE(property
->GetInteger("insets_bottom", &bottom
));
307 EXPECT_FALSE(property
->GetInteger("insets_right", &right
));
309 // |id2| doesn't have the color_profile because it doesn't have 'dynamic' in
310 // its available list.
311 EXPECT_FALSE(property
->GetString("color_profile_name", &color_profile
));
313 // Resolution is saved only when the resolution is set
314 // by DisplayManager::SetDisplayMode
317 EXPECT_FALSE(property
->GetInteger("width", &width
));
318 EXPECT_FALSE(property
->GetInteger("height", &height
));
320 ash::DisplayMode
mode(gfx::Size(300, 200), 60.0f
, false, true);
321 mode
.device_scale_factor
= 1.25f
;
322 display_manager
->SetDisplayMode(id2
, mode
);
324 display_controller
->SetPrimaryDisplayId(id2
);
326 EXPECT_TRUE(properties
->GetDictionary(base::Int64ToString(id1
), &property
));
329 // Internal display shouldn't store its resolution.
330 EXPECT_FALSE(property
->GetInteger("width", &width
));
331 EXPECT_FALSE(property
->GetInteger("height", &height
));
333 // External display's resolution must be stored this time because
335 int device_scale_factor
= 0;
336 EXPECT_TRUE(properties
->GetDictionary(base::Int64ToString(id2
), &property
));
337 EXPECT_TRUE(property
->GetInteger("width", &width
));
338 EXPECT_TRUE(property
->GetInteger("height", &height
));
339 EXPECT_TRUE(property
->GetInteger(
340 "device-scale-factor", &device_scale_factor
));
341 EXPECT_EQ(300, width
);
342 EXPECT_EQ(200, height
);
343 EXPECT_EQ(1250, device_scale_factor
);
345 // The layout remains the same.
346 EXPECT_TRUE(displays
->GetDictionary(key
, &layout_value
));
347 EXPECT_TRUE(ash::DisplayLayout::ConvertFromValue(*layout_value
,
349 EXPECT_EQ(layout
.position
, stored_layout
.position
);
350 EXPECT_EQ(layout
.offset
, stored_layout
.offset
);
351 EXPECT_EQ(id2
, stored_layout
.primary_id
);
354 EXPECT_TRUE(layout_value
->GetBoolean(kMirroredKey
, &mirrored
));
355 EXPECT_FALSE(mirrored
);
356 std::string primary_id_str
;
357 EXPECT_TRUE(layout_value
->GetString(kPrimaryIdKey
, &primary_id_str
));
358 EXPECT_EQ(base::Int64ToString(id2
), primary_id_str
);
360 SetCurrentDisplayLayout(
361 ash::DisplayLayout(ash::DisplayLayout::BOTTOM
, 20));
363 UpdateDisplay("1+0-200x200*2,1+0-200x200");
366 std::string position
;
367 EXPECT_TRUE(displays
->GetDictionary(key
, &layout_value
));
368 EXPECT_TRUE(layout_value
->GetString(kPositionKey
, &position
));
369 EXPECT_EQ("top", position
);
370 EXPECT_TRUE(layout_value
->GetInteger(kOffsetKey
, &offset
));
371 EXPECT_EQ(-20, offset
);
373 EXPECT_TRUE(layout_value
->GetBoolean(kMirroredKey
, &mirrored
));
374 EXPECT_TRUE(mirrored
);
375 EXPECT_TRUE(layout_value
->GetString(kPrimaryIdKey
, &primary_id_str
));
376 EXPECT_EQ(base::Int64ToString(id2
), primary_id_str
);
378 EXPECT_TRUE(properties
->GetDictionary(base::Int64ToString(id1
), &property
));
379 EXPECT_FALSE(property
->GetInteger("width", &width
));
380 EXPECT_FALSE(property
->GetInteger("height", &height
));
382 // External display's selected resolution must not change
384 EXPECT_TRUE(properties
->GetDictionary(base::Int64ToString(id2
), &property
));
385 EXPECT_TRUE(property
->GetInteger("width", &width
));
386 EXPECT_TRUE(property
->GetInteger("height", &height
));
387 EXPECT_EQ(300, width
);
388 EXPECT_EQ(200, height
);
390 // Set new display's selected resolution.
391 display_manager
->RegisterDisplayProperty(
392 id2
+ 1, gfx::Display::ROTATE_0
, 1.0f
, NULL
, gfx::Size(500, 400), 1.0f
,
393 ui::COLOR_PROFILE_STANDARD
);
395 UpdateDisplay("200x200*2, 600x500#600x500|500x400");
397 // Update key as the 2nd display gets new id.
398 id2
= ash::ScreenUtil::GetSecondaryDisplay().id();
399 key
= base::Int64ToString(id1
) + "," + base::Int64ToString(id2
);
400 EXPECT_TRUE(displays
->GetDictionary(key
, &layout_value
));
401 EXPECT_TRUE(layout_value
->GetString(kPositionKey
, &position
));
402 EXPECT_EQ("right", position
);
403 EXPECT_TRUE(layout_value
->GetInteger(kOffsetKey
, &offset
));
404 EXPECT_EQ(0, offset
);
406 EXPECT_TRUE(layout_value
->GetBoolean(kMirroredKey
, &mirrored
));
407 EXPECT_FALSE(mirrored
);
408 EXPECT_TRUE(layout_value
->GetString(kPrimaryIdKey
, &primary_id_str
));
409 EXPECT_EQ(base::Int64ToString(id1
), primary_id_str
);
411 // Best resolution should not be saved.
412 EXPECT_TRUE(properties
->GetDictionary(base::Int64ToString(id2
), &property
));
413 EXPECT_FALSE(property
->GetInteger("width", &width
));
414 EXPECT_FALSE(property
->GetInteger("height", &height
));
416 // Set yet another new display's selected resolution.
417 display_manager
->RegisterDisplayProperty(
418 id2
+ 1, gfx::Display::ROTATE_0
, 1.0f
, NULL
, gfx::Size(500, 400), 1.0f
,
419 ui::COLOR_PROFILE_STANDARD
);
420 // Disconnect 2nd display first to generate new id for external display.
421 UpdateDisplay("200x200*2");
422 UpdateDisplay("200x200*2, 500x400#600x500|500x400%60.0f");
423 // Update key as the 2nd display gets new id.
424 id2
= ash::ScreenUtil::GetSecondaryDisplay().id();
425 key
= base::Int64ToString(id1
) + "," + base::Int64ToString(id2
);
426 EXPECT_TRUE(displays
->GetDictionary(key
, &layout_value
));
427 EXPECT_TRUE(layout_value
->GetString(kPositionKey
, &position
));
428 EXPECT_EQ("right", position
);
429 EXPECT_TRUE(layout_value
->GetInteger(kOffsetKey
, &offset
));
430 EXPECT_EQ(0, offset
);
432 EXPECT_TRUE(layout_value
->GetBoolean(kMirroredKey
, &mirrored
));
433 EXPECT_FALSE(mirrored
);
434 EXPECT_TRUE(layout_value
->GetString(kPrimaryIdKey
, &primary_id_str
));
435 EXPECT_EQ(base::Int64ToString(id1
), primary_id_str
);
437 // External display's selected resolution must be updated.
438 EXPECT_TRUE(properties
->GetDictionary(base::Int64ToString(id2
), &property
));
439 EXPECT_TRUE(property
->GetInteger("width", &width
));
440 EXPECT_TRUE(property
->GetInteger("height", &height
));
441 EXPECT_EQ(500, width
);
442 EXPECT_EQ(400, height
);
445 TEST_F(DisplayPreferencesTest
, PreventStore
) {
446 ResolutionNotificationController::SuppressTimerForTest();
448 UpdateDisplay("400x300#500x400|400x300|300x200");
449 int64 id
= ash::Shell::GetScreen()->GetPrimaryDisplay().id();
450 // Set display's resolution in single display. It creates the notification and
451 // display preferences should not stored meanwhile.
452 ash::Shell
* shell
= ash::Shell::GetInstance();
453 ash::DisplayMode old_mode
;
454 ash::DisplayMode new_mode
;
455 old_mode
.size
= gfx::Size(400, 300);
456 new_mode
.size
= gfx::Size(500, 400);
457 if (shell
->display_manager()->SetDisplayMode(id
, new_mode
)) {
458 shell
->resolution_notification_controller()->PrepareNotification(
459 id
, old_mode
, new_mode
, base::Closure());
461 UpdateDisplay("500x400#500x400|400x300|300x200");
463 const base::DictionaryValue
* properties
=
464 local_state()->GetDictionary(prefs::kDisplayProperties
);
465 const base::DictionaryValue
* property
= NULL
;
466 EXPECT_TRUE(properties
->GetDictionary(base::Int64ToString(id
), &property
));
467 int width
= 0, height
= 0;
468 EXPECT_FALSE(property
->GetInteger("width", &width
));
469 EXPECT_FALSE(property
->GetInteger("height", &height
));
471 // Revert the change. When timeout, 2nd button is revert.
472 message_center::MessageCenter::Get()->ClickOnNotificationButton(
473 ResolutionNotificationController::kNotificationId
, 1);
474 RunAllPendingInMessageLoop();
476 message_center::MessageCenter::Get()->FindVisibleNotificationById(
477 ResolutionNotificationController::kNotificationId
));
479 // Once the notification is removed, the specified resolution will be stored
480 // by SetDisplayMode.
481 ash::Shell::GetInstance()->display_manager()->SetDisplayMode(
482 id
, ash::DisplayMode(gfx::Size(300, 200), 60.0f
, false, true));
483 UpdateDisplay("300x200#500x400|400x300|300x200");
486 EXPECT_TRUE(properties
->GetDictionary(base::Int64ToString(id
), &property
));
487 EXPECT_TRUE(property
->GetInteger("width", &width
));
488 EXPECT_TRUE(property
->GetInteger("height", &height
));
489 EXPECT_EQ(300, width
);
490 EXPECT_EQ(200, height
);
493 TEST_F(DisplayPreferencesTest
, StoreForSwappedDisplay
) {
494 UpdateDisplay("100x100,200x200");
495 int64 id1
= gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id();
496 int64 id2
= ash::ScreenUtil::GetSecondaryDisplay().id();
498 ash::DisplayController
* display_controller
=
499 ash::Shell::GetInstance()->display_controller();
500 display_controller
->SwapPrimaryDisplay();
501 ASSERT_EQ(id1
, ash::ScreenUtil::GetSecondaryDisplay().id());
504 ash::DisplayLayout
layout(ash::DisplayLayout::TOP
, 10);
505 SetCurrentDisplayLayout(layout
);
506 layout
= layout
.Invert();
508 const base::DictionaryValue
* displays
=
509 local_state()->GetDictionary(prefs::kSecondaryDisplays
);
510 const base::DictionaryValue
* new_value
= NULL
;
511 std::string key
= base::Int64ToString(id1
) + "," + base::Int64ToString(id2
);
512 EXPECT_TRUE(displays
->GetDictionary(key
, &new_value
));
514 ash::DisplayLayout stored_layout
;
515 EXPECT_TRUE(ash::DisplayLayout::ConvertFromValue(*new_value
, &stored_layout
));
516 EXPECT_EQ(layout
.position
, stored_layout
.position
);
517 EXPECT_EQ(layout
.offset
, stored_layout
.offset
);
518 EXPECT_EQ(id2
, stored_layout
.primary_id
);
520 display_controller
->SwapPrimaryDisplay();
521 EXPECT_TRUE(displays
->GetDictionary(key
, &new_value
));
522 EXPECT_TRUE(ash::DisplayLayout::ConvertFromValue(*new_value
, &stored_layout
));
523 EXPECT_EQ(layout
.position
, stored_layout
.position
);
524 EXPECT_EQ(layout
.offset
, stored_layout
.offset
);
525 EXPECT_EQ(id1
, stored_layout
.primary_id
);
528 TEST_F(DisplayPreferencesTest
, RestoreColorProfiles
) {
529 ash::DisplayManager
* display_manager
=
530 ash::Shell::GetInstance()->display_manager();
532 int64 id1
= gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id();
534 StoreColorProfile(id1
, "dynamic");
537 LoadDisplayPreferences(false);
539 // id1's available color profiles list is empty, means somehow the color
540 // profile suport is temporary in trouble.
541 EXPECT_NE(ui::COLOR_PROFILE_DYNAMIC
,
542 display_manager
->GetDisplayInfo(id1
).color_profile());
544 // Once the profile is supported, the color profile should be restored.
545 std::vector
<ui::ColorCalibrationProfile
> profiles
;
546 profiles
.push_back(ui::COLOR_PROFILE_STANDARD
);
547 profiles
.push_back(ui::COLOR_PROFILE_DYNAMIC
);
548 profiles
.push_back(ui::COLOR_PROFILE_MOVIE
);
549 profiles
.push_back(ui::COLOR_PROFILE_READING
);
550 ash::test::DisplayManagerTestApi
test_api(display_manager
);
551 test_api
.SetAvailableColorProfiles(id1
, profiles
);
553 LoadDisplayPreferences(false);
554 EXPECT_EQ(ui::COLOR_PROFILE_DYNAMIC
,
555 display_manager
->GetDisplayInfo(id1
).color_profile());
558 TEST_F(DisplayPreferencesTest
, DontStoreInGuestMode
) {
559 ash::DisplayController
* display_controller
=
560 ash::Shell::GetInstance()->display_controller();
561 ash::DisplayManager
* display_manager
=
562 ash::Shell::GetInstance()->display_manager();
564 UpdateDisplay("200x200*2,200x200");
567 int64 id1
= ash::Shell::GetScreen()->GetPrimaryDisplay().id();
568 ash::test::DisplayManagerTestApi(display_manager
)
569 .SetInternalDisplayId(id1
);
570 int64 id2
= ash::ScreenUtil::GetSecondaryDisplay().id();
571 ash::DisplayLayout
layout(ash::DisplayLayout::TOP
, 10);
572 SetCurrentDisplayLayout(layout
);
573 display_manager
->SetDisplayUIScale(id1
, 1.25f
);
574 display_controller
->SetPrimaryDisplayId(id2
);
575 int64 new_primary
= ash::Shell::GetScreen()->GetPrimaryDisplay().id();
576 display_controller
->SetOverscanInsets(
578 gfx::Insets(10, 11, 12, 13));
579 display_manager
->SetDisplayRotation(new_primary
, gfx::Display::ROTATE_90
);
581 // Does not store the preferences locally.
582 EXPECT_FALSE(local_state()->FindPreference(
583 prefs::kSecondaryDisplays
)->HasUserSetting());
584 EXPECT_FALSE(local_state()->FindPreference(
585 prefs::kDisplayProperties
)->HasUserSetting());
587 // Settings are still notified to the system.
588 gfx::Screen
* screen
= gfx::Screen::GetNativeScreen();
589 EXPECT_EQ(id2
, screen
->GetPrimaryDisplay().id());
590 EXPECT_EQ(ash::DisplayLayout::BOTTOM
,
591 display_manager
->GetCurrentDisplayLayout().position
);
592 EXPECT_EQ(-10, display_manager
->GetCurrentDisplayLayout().offset
);
593 const gfx::Display
& primary_display
= screen
->GetPrimaryDisplay();
594 EXPECT_EQ("178x176", primary_display
.bounds().size().ToString());
595 EXPECT_EQ(gfx::Display::ROTATE_90
, primary_display
.rotation());
597 const ash::DisplayInfo
& info1
= display_manager
->GetDisplayInfo(id1
);
598 EXPECT_EQ(1.25f
, info1
.configured_ui_scale());
600 const ash::DisplayInfo
& info_primary
=
601 display_manager
->GetDisplayInfo(new_primary
);
602 EXPECT_EQ(gfx::Display::ROTATE_90
, info_primary
.rotation());
603 EXPECT_EQ(1.0f
, info_primary
.configured_ui_scale());
606 TEST_F(DisplayPreferencesTest
, StorePowerStateNoLogin
) {
607 EXPECT_FALSE(local_state()->HasPrefPath(prefs::kDisplayPowerState
));
609 // Stores display prefs without login, which still stores the power state.
611 EXPECT_TRUE(local_state()->HasPrefPath(prefs::kDisplayPowerState
));
614 TEST_F(DisplayPreferencesTest
, StorePowerStateGuest
) {
615 EXPECT_FALSE(local_state()->HasPrefPath(prefs::kDisplayPowerState
));
619 EXPECT_TRUE(local_state()->HasPrefPath(prefs::kDisplayPowerState
));
622 TEST_F(DisplayPreferencesTest
, StorePowerStateNormalUser
) {
623 EXPECT_FALSE(local_state()->HasPrefPath(prefs::kDisplayPowerState
));
627 EXPECT_TRUE(local_state()->HasPrefPath(prefs::kDisplayPowerState
));
630 TEST_F(DisplayPreferencesTest
, DisplayPowerStateAfterRestart
) {
631 StoreDisplayPowerStateForTest(
632 chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON
);
633 LoadDisplayPreferences(false);
634 EXPECT_EQ(chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON
,
635 ash::Shell::GetInstance()->display_configurator()->
636 requested_power_state());
639 TEST_F(DisplayPreferencesTest
, DontSaveAndRestoreAllOff
) {
640 ash::Shell
* shell
= ash::Shell::GetInstance();
641 StoreDisplayPowerStateForTest(
642 chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON
);
643 LoadDisplayPreferences(false);
644 // DisplayPowerState should be ignored at boot.
645 EXPECT_EQ(chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON
,
646 shell
->display_configurator()->requested_power_state());
648 StoreDisplayPowerStateForTest(
649 chromeos::DISPLAY_POWER_ALL_OFF
);
650 EXPECT_EQ(chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON
,
651 shell
->display_configurator()->requested_power_state());
652 EXPECT_EQ("internal_off_external_on",
653 local_state()->GetString(prefs::kDisplayPowerState
));
656 local_state()->SetString(prefs::kDisplayPowerState
, "all_off");
657 LoadDisplayPreferences(false);
658 EXPECT_EQ(chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON
,
659 shell
->display_configurator()->requested_power_state());
662 // Tests that display configuration changes caused by MaximizeModeController
664 TEST_F(DisplayPreferencesTest
, DontSaveMaximizeModeControllerRotations
) {
665 ash::Shell
* shell
= ash::Shell::GetInstance();
666 gfx::Display::SetInternalDisplayId(
667 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id());
668 ash::DisplayManager
* display_manager
= shell
->display_manager();
670 // Populate the properties.
671 display_manager
->SetDisplayRotation(gfx::Display::InternalDisplayId(),
672 gfx::Display::ROTATE_180
);
673 // Reset property to avoid rotation lock
674 display_manager
->SetDisplayRotation(gfx::Display::InternalDisplayId(),
675 gfx::Display::ROTATE_0
);
677 // Open up 270 degrees to trigger maximize mode
678 scoped_refptr
<chromeos::AccelerometerUpdate
> update(
679 new chromeos::AccelerometerUpdate());
680 update
->Set(chromeos::ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD
, 0.0f
, 0.0f
,
682 update
->Set(chromeos::ACCELEROMETER_SOURCE_SCREEN
, 0.0f
, -kMeanGravity
, 0.0f
);
683 ash::MaximizeModeController
* controller
= shell
->maximize_mode_controller();
684 controller
->OnAccelerometerUpdated(update
);
685 EXPECT_TRUE(controller
->IsMaximizeModeWindowManagerEnabled());
687 // Trigger 90 degree rotation
688 update
->Set(chromeos::ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD
, -kMeanGravity
,
690 update
->Set(chromeos::ACCELEROMETER_SOURCE_SCREEN
, -kMeanGravity
, 0.0f
, 0.0f
);
691 controller
->OnAccelerometerUpdated(update
);
692 shell
->screen_orientation_controller()->OnAccelerometerUpdated(update
);
693 EXPECT_EQ(gfx::Display::ROTATE_90
, display_manager
->
694 GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation());
696 const base::DictionaryValue
* properties
=
697 local_state()->GetDictionary(prefs::kDisplayProperties
);
698 const base::DictionaryValue
* property
= NULL
;
699 EXPECT_TRUE(properties
->GetDictionary(
700 base::Int64ToString(gfx::Display::InternalDisplayId()), &property
));
702 EXPECT_TRUE(property
->GetInteger("rotation", &rotation
));
703 EXPECT_EQ(gfx::Display::ROTATE_0
, rotation
);
706 // Tests that the rotation state is saved without a user being logged in.
707 TEST_F(DisplayPreferencesTest
, StoreRotationStateNoLogin
) {
708 gfx::Display::SetInternalDisplayId(
709 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id());
710 EXPECT_FALSE(local_state()->HasPrefPath(prefs::kDisplayRotationLock
));
712 bool current_rotation_lock
= IsRotationLocked();
713 StoreDisplayRotationPrefs(current_rotation_lock
);
714 EXPECT_TRUE(local_state()->HasPrefPath(prefs::kDisplayRotationLock
));
716 const base::DictionaryValue
* properties
=
717 local_state()->GetDictionary(prefs::kDisplayRotationLock
);
719 EXPECT_TRUE(properties
->GetBoolean("lock", &rotation_lock
));
720 EXPECT_EQ(current_rotation_lock
, rotation_lock
);
723 gfx::Display::Rotation current_rotation
= ash::Shell::GetInstance()->
725 GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation();
726 EXPECT_TRUE(properties
->GetInteger("orientation", &orientation
));
727 EXPECT_EQ(current_rotation
, orientation
);
730 // Tests that the rotation state is saved when a guest is logged in.
731 TEST_F(DisplayPreferencesTest
, StoreRotationStateGuest
) {
732 gfx::Display::SetInternalDisplayId(
733 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id());
734 EXPECT_FALSE(local_state()->HasPrefPath(prefs::kDisplayRotationLock
));
737 bool current_rotation_lock
= IsRotationLocked();
738 StoreDisplayRotationPrefs(current_rotation_lock
);
739 EXPECT_TRUE(local_state()->HasPrefPath(prefs::kDisplayRotationLock
));
741 const base::DictionaryValue
* properties
=
742 local_state()->GetDictionary(prefs::kDisplayRotationLock
);
744 EXPECT_TRUE(properties
->GetBoolean("lock", &rotation_lock
));
745 EXPECT_EQ(current_rotation_lock
, rotation_lock
);
748 gfx::Display::Rotation current_rotation
= ash::Shell::GetInstance()->
750 GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation();
751 EXPECT_TRUE(properties
->GetInteger("orientation", &orientation
));
752 EXPECT_EQ(current_rotation
, orientation
);
755 // Tests that the rotation state is saved when a normal user is logged in.
756 TEST_F(DisplayPreferencesTest
, StoreRotationStateNormalUser
) {
757 gfx::Display::SetInternalDisplayId(
758 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id());
759 EXPECT_FALSE(local_state()->HasPrefPath(prefs::kDisplayRotationLock
));
762 bool current_rotation_lock
= IsRotationLocked();
763 StoreDisplayRotationPrefs(current_rotation_lock
);
764 EXPECT_TRUE(local_state()->HasPrefPath(prefs::kDisplayRotationLock
));
766 const base::DictionaryValue
* properties
=
767 local_state()->GetDictionary(prefs::kDisplayRotationLock
);
769 EXPECT_TRUE(properties
->GetBoolean("lock", &rotation_lock
));
770 EXPECT_EQ(current_rotation_lock
, rotation_lock
);
773 gfx::Display::Rotation current_rotation
= ash::Shell::GetInstance()->
775 GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation();
776 EXPECT_TRUE(properties
->GetInteger("orientation", &orientation
));
777 EXPECT_EQ(current_rotation
, orientation
);
780 // Tests that rotation state is loaded without a user being logged in, and that
781 // entering maximize mode applies the state.
782 TEST_F(DisplayPreferencesTest
, LoadRotationNoLogin
) {
783 gfx::Display::SetInternalDisplayId(
784 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id());
785 ASSERT_FALSE(local_state()->HasPrefPath(prefs::kDisplayRotationLock
));
787 ash::Shell
* shell
= ash::Shell::GetInstance();
788 bool initial_rotation_lock
= IsRotationLocked();
789 ASSERT_FALSE(initial_rotation_lock
);
790 ash::DisplayManager
* display_manager
= shell
->display_manager();
791 gfx::Display::Rotation initial_rotation
= display_manager
->
792 GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation();
793 ASSERT_EQ(gfx::Display::ROTATE_0
, initial_rotation
);
795 StoreDisplayRotationPrefs(initial_rotation_lock
);
796 ASSERT_TRUE(local_state()->HasPrefPath(prefs::kDisplayRotationLock
));
798 StoreDisplayRotationPrefsForTest(true, gfx::Display::ROTATE_90
);
799 LoadDisplayPreferences(false);
801 bool display_rotation_lock
=
802 display_manager
->registered_internal_display_rotation_lock();
803 bool display_rotation
=
804 display_manager
->registered_internal_display_rotation();
805 EXPECT_TRUE(display_rotation_lock
);
806 EXPECT_EQ(gfx::Display::ROTATE_90
, display_rotation
);
808 bool rotation_lock
= IsRotationLocked();
809 gfx::Display::Rotation before_maximize_mode_rotation
= display_manager
->
810 GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation();
812 // Settings should not be applied until maximize mode activates
813 EXPECT_FALSE(rotation_lock
);
814 EXPECT_EQ(gfx::Display::ROTATE_0
, before_maximize_mode_rotation
);
816 // Open up 270 degrees to trigger maximize mode
817 scoped_refptr
<chromeos::AccelerometerUpdate
> update(
818 new chromeos::AccelerometerUpdate());
819 update
->Set(chromeos::ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD
, 0.0f
, 0.0f
,
821 update
->Set(chromeos::ACCELEROMETER_SOURCE_SCREEN
, 0.0f
, -kMeanGravity
, 0.0f
);
822 ash::MaximizeModeController
* maximize_mode_controller
=
823 shell
->maximize_mode_controller();
824 maximize_mode_controller
->OnAccelerometerUpdated(update
);
825 EXPECT_TRUE(maximize_mode_controller
->IsMaximizeModeWindowManagerEnabled());
826 bool screen_orientation_rotation_lock
= IsRotationLocked();
827 gfx::Display::Rotation maximize_mode_rotation
= display_manager
->
828 GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation();
829 EXPECT_TRUE(screen_orientation_rotation_lock
);
830 EXPECT_EQ(gfx::Display::ROTATE_90
, maximize_mode_rotation
);
833 // Tests that rotation lock being set causes the rotation state to be saved.
834 TEST_F(DisplayPreferencesTest
, RotationLockTriggersStore
) {
835 gfx::Display::SetInternalDisplayId(
836 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id());
837 ASSERT_FALSE(local_state()->HasPrefPath(prefs::kDisplayRotationLock
));
839 ash::Shell::GetInstance()->screen_orientation_controller()->SetRotationLocked(
842 EXPECT_TRUE(local_state()->HasPrefPath(prefs::kDisplayRotationLock
));
844 const base::DictionaryValue
* properties
=
845 local_state()->GetDictionary(prefs::kDisplayRotationLock
);
847 EXPECT_TRUE(properties
->GetBoolean("lock", &rotation_lock
));
850 } // namespace chromeos