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/display/display_controller.h"
11 #include "ash/display/display_layout_store.h"
12 #include "ash/display/display_manager.h"
13 #include "ash/display/resolution_notification_controller.h"
14 #include "ash/screen_util.h"
15 #include "ash/shell.h"
16 #include "ash/test/ash_test_base.h"
17 #include "ash/test/display_manager_test_api.h"
18 #include "ash/wm/maximize_mode/maximize_mode_controller.h"
19 #include "base/prefs/scoped_user_pref_update.h"
20 #include "base/prefs/testing_pref_service.h"
21 #include "base/strings/string_number_conversions.h"
22 #include "base/values.h"
23 #include "chrome/browser/chromeos/display/display_configuration_observer.h"
24 #include "chrome/browser/chromeos/login/users/mock_user_manager.h"
25 #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h"
26 #include "chrome/common/pref_names.h"
27 #include "chrome/test/base/testing_browser_process.h"
28 #include "ui/display/chromeos/display_configurator.h"
29 #include "ui/gfx/geometry/vector3d_f.h"
30 #include "ui/message_center/message_center.h"
32 using ash::ResolutionNotificationController
;
36 const char kPrimaryIdKey
[] = "primary-id";
37 const char kMirroredKey
[] = "mirrored";
38 const char kPositionKey
[] = "position";
39 const char kOffsetKey
[] = "offset";
41 // The mean acceleration due to gravity on Earth in m/s^2.
42 const float kMeanGravity
= 9.80665f
;
44 class DisplayPreferencesTest
: public ash::test::AshTestBase
{
46 DisplayPreferencesTest()
47 : mock_user_manager_(new MockUserManager
),
48 user_manager_enabler_(mock_user_manager_
) {
51 virtual ~DisplayPreferencesTest() {}
53 virtual void SetUp() override
{
54 EXPECT_CALL(*mock_user_manager_
, IsUserLoggedIn())
55 .WillRepeatedly(testing::Return(false));
56 EXPECT_CALL(*mock_user_manager_
, Shutdown());
57 ash::test::AshTestBase::SetUp();
58 RegisterDisplayLocalStatePrefs(local_state_
.registry());
59 TestingBrowserProcess::GetGlobal()->SetLocalState(&local_state_
);
60 observer_
.reset(new DisplayConfigurationObserver());
63 virtual void TearDown() override
{
65 TestingBrowserProcess::GetGlobal()->SetLocalState(NULL
);
66 ash::test::AshTestBase::TearDown();
69 void LoggedInAsUser() {
70 EXPECT_CALL(*mock_user_manager_
, IsUserLoggedIn())
71 .WillRepeatedly(testing::Return(true));
72 EXPECT_CALL(*mock_user_manager_
, IsLoggedInAsUserWithGaiaAccount())
73 .WillRepeatedly(testing::Return(true));
76 void LoggedInAsGuest() {
77 EXPECT_CALL(*mock_user_manager_
, IsUserLoggedIn())
78 .WillRepeatedly(testing::Return(true));
79 EXPECT_CALL(*mock_user_manager_
, IsLoggedInAsUserWithGaiaAccount())
80 .WillRepeatedly(testing::Return(false));
81 EXPECT_CALL(*mock_user_manager_
, IsLoggedInAsSupervisedUser())
82 .WillRepeatedly(testing::Return(false));
85 // Do not use the implementation of display_preferences.cc directly to avoid
86 // notifying the update to the system.
87 void StoreDisplayLayoutPrefForName(const std::string
& name
,
88 ash::DisplayLayout::Position layout
,
91 DictionaryPrefUpdate
update(&local_state_
, prefs::kSecondaryDisplays
);
92 ash::DisplayLayout
display_layout(layout
, offset
);
93 display_layout
.primary_id
= primary_id
;
95 DCHECK(!name
.empty());
97 base::DictionaryValue
* pref_data
= update
.Get();
98 scoped_ptr
<base::Value
>layout_value(new base::DictionaryValue());
99 if (pref_data
->HasKey(name
)) {
100 base::Value
* value
= NULL
;
101 if (pref_data
->Get(name
, &value
) && value
!= NULL
)
102 layout_value
.reset(value
->DeepCopy());
104 if (ash::DisplayLayout::ConvertToValue(display_layout
, layout_value
.get()))
105 pref_data
->Set(name
, layout_value
.release());
108 void StoreDisplayLayoutPrefForPair(int64 id1
,
110 ash::DisplayLayout::Position layout
,
112 StoreDisplayLayoutPrefForName(
113 base::Int64ToString(id1
) + "," + base::Int64ToString(id2
),
114 layout
, offset
, id1
);
117 void StoreDisplayLayoutPrefForSecondary(int64 id
,
118 ash::DisplayLayout::Position layout
,
121 StoreDisplayLayoutPrefForName(
122 base::Int64ToString(id
), layout
, offset
, primary_id
);
125 void StoreDisplayOverscan(int64 id
, const gfx::Insets
& insets
) {
126 DictionaryPrefUpdate
update(&local_state_
, prefs::kDisplayProperties
);
127 const std::string name
= base::Int64ToString(id
);
129 base::DictionaryValue
* pref_data
= update
.Get();
130 base::DictionaryValue
* insets_value
= new base::DictionaryValue();
131 insets_value
->SetInteger("insets_top", insets
.top());
132 insets_value
->SetInteger("insets_left", insets
.left());
133 insets_value
->SetInteger("insets_bottom", insets
.bottom());
134 insets_value
->SetInteger("insets_right", insets
.right());
135 pref_data
->Set(name
, insets_value
);
138 void StoreColorProfile(int64 id
, const std::string
& profile
) {
139 DictionaryPrefUpdate
update(&local_state_
, prefs::kDisplayProperties
);
140 const std::string name
= base::Int64ToString(id
);
142 base::DictionaryValue
* pref_data
= update
.Get();
143 base::DictionaryValue
* property
= new base::DictionaryValue();
144 property
->SetString("color_profile_name", profile
);
145 pref_data
->Set(name
, property
);
148 void StoreDisplayRotationPrefsForTest(bool rotation_lock
,
149 gfx::Display::Rotation rotation
) {
150 DictionaryPrefUpdate
update(local_state(), prefs::kDisplayRotationLock
);
151 base::DictionaryValue
* pref_data
= update
.Get();
152 pref_data
->SetBoolean("lock", rotation_lock
);
153 pref_data
->SetInteger("orientation", static_cast<int>(rotation
));
156 std::string
GetRegisteredDisplayLayoutStr(int64 id1
, int64 id2
) {
157 ash::DisplayIdPair pair
;
160 return ash::Shell::GetInstance()->display_manager()->layout_store()->
161 GetRegisteredDisplayLayout(pair
).ToString();
164 PrefService
* local_state() { return &local_state_
; }
167 MockUserManager
* mock_user_manager_
; // Not owned.
168 ScopedUserManagerEnabler user_manager_enabler_
;
169 TestingPrefServiceSimple local_state_
;
170 scoped_ptr
<DisplayConfigurationObserver
> observer_
;
172 DISALLOW_COPY_AND_ASSIGN(DisplayPreferencesTest
);
177 TEST_F(DisplayPreferencesTest
, PairedLayoutOverrides
) {
178 UpdateDisplay("100x100,200x200");
179 int64 id1
= gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id();
180 int64 id2
= ash::ScreenUtil::GetSecondaryDisplay().id();
181 int64 dummy_id
= id2
+ 1;
182 ASSERT_NE(id1
, dummy_id
);
184 StoreDisplayLayoutPrefForPair(id1
, id2
, ash::DisplayLayout::TOP
, 20);
185 StoreDisplayLayoutPrefForPair(id1
, dummy_id
, ash::DisplayLayout::LEFT
, 30);
186 StoreDisplayPowerStateForTest(
187 chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON
);
189 ash::Shell
* shell
= ash::Shell::GetInstance();
191 LoadDisplayPreferences(true);
192 // DisplayPowerState should be ignored at boot.
193 EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON
,
194 shell
->display_configurator()->requested_power_state());
196 shell
->display_manager()->UpdateDisplays();
197 // Check if the layout settings are notified to the system properly.
198 // The paired layout overrides old layout.
199 // Inverted one of for specified pair (id1, id2). Not used for the pair
200 // (id1, dummy_id) since dummy_id is not connected right now.
202 shell
->display_manager()->GetCurrentDisplayLayout().ToString());
203 EXPECT_EQ("top, 20", GetRegisteredDisplayLayoutStr(id1
, id2
));
204 EXPECT_EQ("left, 30", GetRegisteredDisplayLayoutStr(id1
, dummy_id
));
207 TEST_F(DisplayPreferencesTest
, BasicStores
) {
208 ash::DisplayController
* display_controller
=
209 ash::Shell::GetInstance()->display_controller();
210 ash::DisplayManager
* display_manager
=
211 ash::Shell::GetInstance()->display_manager();
213 UpdateDisplay("200x200*2, 400x300#400x400|300x200*1.25");
214 int64 id1
= gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id();
215 gfx::Display::SetInternalDisplayId(id1
);
216 int64 id2
= ash::ScreenUtil::GetSecondaryDisplay().id();
217 int64 dummy_id
= id2
+ 1;
218 ASSERT_NE(id1
, dummy_id
);
219 std::vector
<ui::ColorCalibrationProfile
> profiles
;
220 profiles
.push_back(ui::COLOR_PROFILE_STANDARD
);
221 profiles
.push_back(ui::COLOR_PROFILE_DYNAMIC
);
222 profiles
.push_back(ui::COLOR_PROFILE_MOVIE
);
223 profiles
.push_back(ui::COLOR_PROFILE_READING
);
224 ash::test::DisplayManagerTestApi
test_api(display_manager
);
225 // Allows only |id1|.
226 test_api
.SetAvailableColorProfiles(id1
, profiles
);
227 display_manager
->SetColorCalibrationProfile(id1
, ui::COLOR_PROFILE_DYNAMIC
);
228 display_manager
->SetColorCalibrationProfile(id2
, ui::COLOR_PROFILE_DYNAMIC
);
231 ash::DisplayLayout
layout(ash::DisplayLayout::TOP
, 10);
232 SetCurrentDisplayLayout(layout
);
233 StoreDisplayLayoutPrefForTest(
234 id1
, dummy_id
, ash::DisplayLayout(ash::DisplayLayout::LEFT
, 20));
235 // Can't switch to a display that does not exist.
236 display_controller
->SetPrimaryDisplayId(dummy_id
);
237 EXPECT_NE(dummy_id
, ash::Shell::GetScreen()->GetPrimaryDisplay().id());
239 display_controller
->SetOverscanInsets(id1
, gfx::Insets(10, 11, 12, 13));
240 display_manager
->SetDisplayRotation(id1
, gfx::Display::ROTATE_90
);
241 display_manager
->SetDisplayUIScale(id1
, 1.25f
);
242 display_manager
->SetDisplayUIScale(id2
, 1.25f
);
244 const base::DictionaryValue
* displays
=
245 local_state()->GetDictionary(prefs::kSecondaryDisplays
);
246 const base::DictionaryValue
* layout_value
= NULL
;
247 std::string key
= base::Int64ToString(id1
) + "," + base::Int64ToString(id2
);
248 EXPECT_TRUE(displays
->GetDictionary(key
, &layout_value
));
250 ash::DisplayLayout stored_layout
;
251 EXPECT_TRUE(ash::DisplayLayout::ConvertFromValue(*layout_value
,
253 EXPECT_EQ(layout
.position
, stored_layout
.position
);
254 EXPECT_EQ(layout
.offset
, stored_layout
.offset
);
256 bool mirrored
= true;
257 EXPECT_TRUE(layout_value
->GetBoolean(kMirroredKey
, &mirrored
));
258 EXPECT_FALSE(mirrored
);
260 const base::DictionaryValue
* properties
=
261 local_state()->GetDictionary(prefs::kDisplayProperties
);
262 const base::DictionaryValue
* property
= NULL
;
263 EXPECT_TRUE(properties
->GetDictionary(base::Int64ToString(id1
), &property
));
266 EXPECT_TRUE(property
->GetInteger("rotation", &rotation
));
267 EXPECT_TRUE(property
->GetInteger("ui-scale", &ui_scale
));
268 EXPECT_EQ(1, rotation
);
269 EXPECT_EQ(1250, ui_scale
);
271 // Internal display never registered the resolution.
272 int width
= 0, height
= 0;
273 EXPECT_FALSE(property
->GetInteger("width", &width
));
274 EXPECT_FALSE(property
->GetInteger("height", &height
));
276 int top
= 0, left
= 0, bottom
= 0, right
= 0;
277 EXPECT_TRUE(property
->GetInteger("insets_top", &top
));
278 EXPECT_TRUE(property
->GetInteger("insets_left", &left
));
279 EXPECT_TRUE(property
->GetInteger("insets_bottom", &bottom
));
280 EXPECT_TRUE(property
->GetInteger("insets_right", &right
));
283 EXPECT_EQ(12, bottom
);
284 EXPECT_EQ(13, right
);
286 std::string color_profile
;
287 EXPECT_TRUE(property
->GetString("color_profile_name", &color_profile
));
288 EXPECT_EQ("dynamic", color_profile
);
290 EXPECT_TRUE(properties
->GetDictionary(base::Int64ToString(id2
), &property
));
291 EXPECT_TRUE(property
->GetInteger("rotation", &rotation
));
292 EXPECT_TRUE(property
->GetInteger("ui-scale", &ui_scale
));
293 EXPECT_EQ(0, rotation
);
294 // ui_scale works only on 2x scale factor/1st display.
295 EXPECT_EQ(1000, ui_scale
);
296 EXPECT_FALSE(property
->GetInteger("insets_top", &top
));
297 EXPECT_FALSE(property
->GetInteger("insets_left", &left
));
298 EXPECT_FALSE(property
->GetInteger("insets_bottom", &bottom
));
299 EXPECT_FALSE(property
->GetInteger("insets_right", &right
));
301 // |id2| doesn't have the color_profile because it doesn't have 'dynamic' in
302 // its available list.
303 EXPECT_FALSE(property
->GetString("color_profile_name", &color_profile
));
305 // Resolution is saved only when the resolution is set
306 // by DisplayManager::SetDisplayMode
309 EXPECT_FALSE(property
->GetInteger("width", &width
));
310 EXPECT_FALSE(property
->GetInteger("height", &height
));
312 ash::DisplayMode
mode(gfx::Size(300, 200), 60.0f
, false, true);
313 mode
.device_scale_factor
= 1.25f
;
314 display_manager
->SetDisplayMode(id2
, mode
);
316 display_controller
->SetPrimaryDisplayId(id2
);
318 EXPECT_TRUE(properties
->GetDictionary(base::Int64ToString(id1
), &property
));
321 // Internal display shouldn't store its resolution.
322 EXPECT_FALSE(property
->GetInteger("width", &width
));
323 EXPECT_FALSE(property
->GetInteger("height", &height
));
325 // External display's resolution must be stored this time because
327 int device_scale_factor
= 0;
328 EXPECT_TRUE(properties
->GetDictionary(base::Int64ToString(id2
), &property
));
329 EXPECT_TRUE(property
->GetInteger("width", &width
));
330 EXPECT_TRUE(property
->GetInteger("height", &height
));
331 EXPECT_TRUE(property
->GetInteger(
332 "device-scale-factor", &device_scale_factor
));
333 EXPECT_EQ(300, width
);
334 EXPECT_EQ(200, height
);
335 EXPECT_EQ(1250, device_scale_factor
);
337 // The layout remains the same.
338 EXPECT_TRUE(displays
->GetDictionary(key
, &layout_value
));
339 EXPECT_TRUE(ash::DisplayLayout::ConvertFromValue(*layout_value
,
341 EXPECT_EQ(layout
.position
, stored_layout
.position
);
342 EXPECT_EQ(layout
.offset
, stored_layout
.offset
);
343 EXPECT_EQ(id2
, stored_layout
.primary_id
);
346 EXPECT_TRUE(layout_value
->GetBoolean(kMirroredKey
, &mirrored
));
347 EXPECT_FALSE(mirrored
);
348 std::string primary_id_str
;
349 EXPECT_TRUE(layout_value
->GetString(kPrimaryIdKey
, &primary_id_str
));
350 EXPECT_EQ(base::Int64ToString(id2
), primary_id_str
);
352 SetCurrentDisplayLayout(
353 ash::DisplayLayout(ash::DisplayLayout::BOTTOM
, 20));
355 UpdateDisplay("1+0-200x200*2,1+0-200x200");
358 std::string position
;
359 EXPECT_TRUE(displays
->GetDictionary(key
, &layout_value
));
360 EXPECT_TRUE(layout_value
->GetString(kPositionKey
, &position
));
361 EXPECT_EQ("top", position
);
362 EXPECT_TRUE(layout_value
->GetInteger(kOffsetKey
, &offset
));
363 EXPECT_EQ(-20, offset
);
365 EXPECT_TRUE(layout_value
->GetBoolean(kMirroredKey
, &mirrored
));
366 EXPECT_TRUE(mirrored
);
367 EXPECT_TRUE(layout_value
->GetString(kPrimaryIdKey
, &primary_id_str
));
368 EXPECT_EQ(base::Int64ToString(id2
), primary_id_str
);
370 EXPECT_TRUE(properties
->GetDictionary(base::Int64ToString(id1
), &property
));
371 EXPECT_FALSE(property
->GetInteger("width", &width
));
372 EXPECT_FALSE(property
->GetInteger("height", &height
));
374 // External display's selected resolution must not change
376 EXPECT_TRUE(properties
->GetDictionary(base::Int64ToString(id2
), &property
));
377 EXPECT_TRUE(property
->GetInteger("width", &width
));
378 EXPECT_TRUE(property
->GetInteger("height", &height
));
379 EXPECT_EQ(300, width
);
380 EXPECT_EQ(200, height
);
382 // Set new display's selected resolution.
383 display_manager
->RegisterDisplayProperty(
384 id2
+ 1, gfx::Display::ROTATE_0
, 1.0f
, NULL
, gfx::Size(500, 400), 1.0f
,
385 ui::COLOR_PROFILE_STANDARD
);
387 UpdateDisplay("200x200*2, 600x500#600x500|500x400");
389 // Update key as the 2nd display gets new id.
390 id2
= ash::ScreenUtil::GetSecondaryDisplay().id();
391 key
= base::Int64ToString(id1
) + "," + base::Int64ToString(id2
);
392 EXPECT_TRUE(displays
->GetDictionary(key
, &layout_value
));
393 EXPECT_TRUE(layout_value
->GetString(kPositionKey
, &position
));
394 EXPECT_EQ("right", position
);
395 EXPECT_TRUE(layout_value
->GetInteger(kOffsetKey
, &offset
));
396 EXPECT_EQ(0, offset
);
398 EXPECT_TRUE(layout_value
->GetBoolean(kMirroredKey
, &mirrored
));
399 EXPECT_FALSE(mirrored
);
400 EXPECT_TRUE(layout_value
->GetString(kPrimaryIdKey
, &primary_id_str
));
401 EXPECT_EQ(base::Int64ToString(id1
), primary_id_str
);
403 // Best resolution should not be saved.
404 EXPECT_TRUE(properties
->GetDictionary(base::Int64ToString(id2
), &property
));
405 EXPECT_FALSE(property
->GetInteger("width", &width
));
406 EXPECT_FALSE(property
->GetInteger("height", &height
));
408 // Set yet another new display's selected resolution.
409 display_manager
->RegisterDisplayProperty(
410 id2
+ 1, gfx::Display::ROTATE_0
, 1.0f
, NULL
, gfx::Size(500, 400), 1.0f
,
411 ui::COLOR_PROFILE_STANDARD
);
412 // Disconnect 2nd display first to generate new id for external display.
413 UpdateDisplay("200x200*2");
414 UpdateDisplay("200x200*2, 500x400#600x500|500x400%60.0f");
415 // Update key as the 2nd display gets new id.
416 id2
= ash::ScreenUtil::GetSecondaryDisplay().id();
417 key
= base::Int64ToString(id1
) + "," + base::Int64ToString(id2
);
418 EXPECT_TRUE(displays
->GetDictionary(key
, &layout_value
));
419 EXPECT_TRUE(layout_value
->GetString(kPositionKey
, &position
));
420 EXPECT_EQ("right", position
);
421 EXPECT_TRUE(layout_value
->GetInteger(kOffsetKey
, &offset
));
422 EXPECT_EQ(0, offset
);
424 EXPECT_TRUE(layout_value
->GetBoolean(kMirroredKey
, &mirrored
));
425 EXPECT_FALSE(mirrored
);
426 EXPECT_TRUE(layout_value
->GetString(kPrimaryIdKey
, &primary_id_str
));
427 EXPECT_EQ(base::Int64ToString(id1
), primary_id_str
);
429 // External display's selected resolution must be updated.
430 EXPECT_TRUE(properties
->GetDictionary(base::Int64ToString(id2
), &property
));
431 EXPECT_TRUE(property
->GetInteger("width", &width
));
432 EXPECT_TRUE(property
->GetInteger("height", &height
));
433 EXPECT_EQ(500, width
);
434 EXPECT_EQ(400, height
);
437 TEST_F(DisplayPreferencesTest
, PreventStore
) {
438 ResolutionNotificationController::SuppressTimerForTest();
440 UpdateDisplay("400x300#500x400|400x300|300x200");
441 int64 id
= ash::Shell::GetScreen()->GetPrimaryDisplay().id();
442 // Set display's resolution in single display. It creates the notification and
443 // display preferences should not stored meanwhile.
444 ash::Shell
* shell
= ash::Shell::GetInstance();
445 ash::DisplayMode old_mode
;
446 ash::DisplayMode new_mode
;
447 old_mode
.size
= gfx::Size(400, 300);
448 new_mode
.size
= gfx::Size(500, 400);
449 if (shell
->display_manager()->SetDisplayMode(id
, new_mode
)) {
450 shell
->resolution_notification_controller()->PrepareNotification(
451 id
, old_mode
, new_mode
, base::Closure());
453 UpdateDisplay("500x400#500x400|400x300|300x200");
455 const base::DictionaryValue
* properties
=
456 local_state()->GetDictionary(prefs::kDisplayProperties
);
457 const base::DictionaryValue
* property
= NULL
;
458 EXPECT_TRUE(properties
->GetDictionary(base::Int64ToString(id
), &property
));
459 int width
= 0, height
= 0;
460 EXPECT_FALSE(property
->GetInteger("width", &width
));
461 EXPECT_FALSE(property
->GetInteger("height", &height
));
463 // Revert the change. When timeout, 2nd button is revert.
464 message_center::MessageCenter::Get()->ClickOnNotificationButton(
465 ResolutionNotificationController::kNotificationId
, 1);
466 RunAllPendingInMessageLoop();
468 message_center::MessageCenter::Get()->FindVisibleNotificationById(
469 ResolutionNotificationController::kNotificationId
));
471 // Once the notification is removed, the specified resolution will be stored
472 // by SetDisplayMode.
473 ash::Shell::GetInstance()->display_manager()->SetDisplayMode(
474 id
, ash::DisplayMode(gfx::Size(300, 200), 60.0f
, false, true));
475 UpdateDisplay("300x200#500x400|400x300|300x200");
478 EXPECT_TRUE(properties
->GetDictionary(base::Int64ToString(id
), &property
));
479 EXPECT_TRUE(property
->GetInteger("width", &width
));
480 EXPECT_TRUE(property
->GetInteger("height", &height
));
481 EXPECT_EQ(300, width
);
482 EXPECT_EQ(200, height
);
485 TEST_F(DisplayPreferencesTest
, StoreForSwappedDisplay
) {
486 UpdateDisplay("100x100,200x200");
487 int64 id1
= gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id();
488 int64 id2
= ash::ScreenUtil::GetSecondaryDisplay().id();
490 ash::DisplayController
* display_controller
=
491 ash::Shell::GetInstance()->display_controller();
492 display_controller
->SwapPrimaryDisplay();
493 ASSERT_EQ(id1
, ash::ScreenUtil::GetSecondaryDisplay().id());
496 ash::DisplayLayout
layout(ash::DisplayLayout::TOP
, 10);
497 SetCurrentDisplayLayout(layout
);
498 layout
= layout
.Invert();
500 const base::DictionaryValue
* displays
=
501 local_state()->GetDictionary(prefs::kSecondaryDisplays
);
502 const base::DictionaryValue
* new_value
= NULL
;
503 std::string key
= base::Int64ToString(id1
) + "," + base::Int64ToString(id2
);
504 EXPECT_TRUE(displays
->GetDictionary(key
, &new_value
));
506 ash::DisplayLayout stored_layout
;
507 EXPECT_TRUE(ash::DisplayLayout::ConvertFromValue(*new_value
, &stored_layout
));
508 EXPECT_EQ(layout
.position
, stored_layout
.position
);
509 EXPECT_EQ(layout
.offset
, stored_layout
.offset
);
510 EXPECT_EQ(id2
, stored_layout
.primary_id
);
512 display_controller
->SwapPrimaryDisplay();
513 EXPECT_TRUE(displays
->GetDictionary(key
, &new_value
));
514 EXPECT_TRUE(ash::DisplayLayout::ConvertFromValue(*new_value
, &stored_layout
));
515 EXPECT_EQ(layout
.position
, stored_layout
.position
);
516 EXPECT_EQ(layout
.offset
, stored_layout
.offset
);
517 EXPECT_EQ(id1
, stored_layout
.primary_id
);
520 TEST_F(DisplayPreferencesTest
, RestoreColorProfiles
) {
521 ash::DisplayManager
* display_manager
=
522 ash::Shell::GetInstance()->display_manager();
524 int64 id1
= gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id();
526 StoreColorProfile(id1
, "dynamic");
529 LoadDisplayPreferences(false);
531 // id1's available color profiles list is empty, means somehow the color
532 // profile suport is temporary in trouble.
533 EXPECT_NE(ui::COLOR_PROFILE_DYNAMIC
,
534 display_manager
->GetDisplayInfo(id1
).color_profile());
536 // Once the profile is supported, the color profile should be restored.
537 std::vector
<ui::ColorCalibrationProfile
> profiles
;
538 profiles
.push_back(ui::COLOR_PROFILE_STANDARD
);
539 profiles
.push_back(ui::COLOR_PROFILE_DYNAMIC
);
540 profiles
.push_back(ui::COLOR_PROFILE_MOVIE
);
541 profiles
.push_back(ui::COLOR_PROFILE_READING
);
542 ash::test::DisplayManagerTestApi
test_api(display_manager
);
543 test_api
.SetAvailableColorProfiles(id1
, profiles
);
545 LoadDisplayPreferences(false);
546 EXPECT_EQ(ui::COLOR_PROFILE_DYNAMIC
,
547 display_manager
->GetDisplayInfo(id1
).color_profile());
550 TEST_F(DisplayPreferencesTest
, DontStoreInGuestMode
) {
551 ash::DisplayController
* display_controller
=
552 ash::Shell::GetInstance()->display_controller();
553 ash::DisplayManager
* display_manager
=
554 ash::Shell::GetInstance()->display_manager();
556 UpdateDisplay("200x200*2,200x200");
559 int64 id1
= ash::Shell::GetScreen()->GetPrimaryDisplay().id();
560 gfx::Display::SetInternalDisplayId(id1
);
561 int64 id2
= ash::ScreenUtil::GetSecondaryDisplay().id();
562 ash::DisplayLayout
layout(ash::DisplayLayout::TOP
, 10);
563 SetCurrentDisplayLayout(layout
);
564 display_manager
->SetDisplayUIScale(id1
, 1.25f
);
565 display_controller
->SetPrimaryDisplayId(id2
);
566 int64 new_primary
= ash::Shell::GetScreen()->GetPrimaryDisplay().id();
567 display_controller
->SetOverscanInsets(
569 gfx::Insets(10, 11, 12, 13));
570 display_manager
->SetDisplayRotation(new_primary
, gfx::Display::ROTATE_90
);
572 // Does not store the preferences locally.
573 EXPECT_FALSE(local_state()->FindPreference(
574 prefs::kSecondaryDisplays
)->HasUserSetting());
575 EXPECT_FALSE(local_state()->FindPreference(
576 prefs::kDisplayProperties
)->HasUserSetting());
578 // Settings are still notified to the system.
579 gfx::Screen
* screen
= gfx::Screen::GetNativeScreen();
580 EXPECT_EQ(id2
, screen
->GetPrimaryDisplay().id());
581 EXPECT_EQ(ash::DisplayLayout::BOTTOM
,
582 display_manager
->GetCurrentDisplayLayout().position
);
583 EXPECT_EQ(-10, display_manager
->GetCurrentDisplayLayout().offset
);
584 const gfx::Display
& primary_display
= screen
->GetPrimaryDisplay();
585 EXPECT_EQ("178x176", primary_display
.bounds().size().ToString());
586 EXPECT_EQ(gfx::Display::ROTATE_90
, primary_display
.rotation());
588 const ash::DisplayInfo
& info1
= display_manager
->GetDisplayInfo(id1
);
589 EXPECT_EQ(1.25f
, info1
.configured_ui_scale());
591 const ash::DisplayInfo
& info_primary
=
592 display_manager
->GetDisplayInfo(new_primary
);
593 EXPECT_EQ(gfx::Display::ROTATE_90
, info_primary
.rotation());
594 EXPECT_EQ(1.0f
, info_primary
.configured_ui_scale());
597 TEST_F(DisplayPreferencesTest
, StorePowerStateNoLogin
) {
598 EXPECT_FALSE(local_state()->HasPrefPath(prefs::kDisplayPowerState
));
600 // Stores display prefs without login, which still stores the power state.
602 EXPECT_TRUE(local_state()->HasPrefPath(prefs::kDisplayPowerState
));
605 TEST_F(DisplayPreferencesTest
, StorePowerStateGuest
) {
606 EXPECT_FALSE(local_state()->HasPrefPath(prefs::kDisplayPowerState
));
610 EXPECT_TRUE(local_state()->HasPrefPath(prefs::kDisplayPowerState
));
613 TEST_F(DisplayPreferencesTest
, StorePowerStateNormalUser
) {
614 EXPECT_FALSE(local_state()->HasPrefPath(prefs::kDisplayPowerState
));
618 EXPECT_TRUE(local_state()->HasPrefPath(prefs::kDisplayPowerState
));
621 TEST_F(DisplayPreferencesTest
, DisplayPowerStateAfterRestart
) {
622 StoreDisplayPowerStateForTest(
623 chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON
);
624 LoadDisplayPreferences(false);
625 EXPECT_EQ(chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON
,
626 ash::Shell::GetInstance()->display_configurator()->
627 requested_power_state());
630 TEST_F(DisplayPreferencesTest
, DontSaveAndRestoreAllOff
) {
631 ash::Shell
* shell
= ash::Shell::GetInstance();
632 StoreDisplayPowerStateForTest(
633 chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON
);
634 LoadDisplayPreferences(false);
635 // DisplayPowerState should be ignored at boot.
636 EXPECT_EQ(chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON
,
637 shell
->display_configurator()->requested_power_state());
639 StoreDisplayPowerStateForTest(
640 chromeos::DISPLAY_POWER_ALL_OFF
);
641 EXPECT_EQ(chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON
,
642 shell
->display_configurator()->requested_power_state());
643 EXPECT_EQ("internal_off_external_on",
644 local_state()->GetString(prefs::kDisplayPowerState
));
647 local_state()->SetString(prefs::kDisplayPowerState
, "all_off");
648 LoadDisplayPreferences(false);
649 EXPECT_EQ(chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON
,
650 shell
->display_configurator()->requested_power_state());
653 // Tests that display configuration changes caused by MaximizeModeController
655 TEST_F(DisplayPreferencesTest
, DontSaveMaximizeModeControllerRotations
) {
656 ash::Shell
* shell
= ash::Shell::GetInstance();
657 ash::MaximizeModeController
* controller
= shell
->maximize_mode_controller();
658 gfx::Display::SetInternalDisplayId(
659 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id());
660 ash::DisplayManager
* display_manager
= shell
->display_manager();
662 // Populate the properties.
663 display_manager
->SetDisplayRotation(gfx::Display::InternalDisplayId(),
664 gfx::Display::ROTATE_180
);
665 // Reset property to avoid rotation lock
666 display_manager
->SetDisplayRotation(gfx::Display::InternalDisplayId(),
667 gfx::Display::ROTATE_0
);
669 // Open up 270 degrees to trigger maximize mode
670 ui::AccelerometerUpdate update
;
671 update
.Set(ui::ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD
,
672 0.0f
, 0.0f
, kMeanGravity
);
673 update
.Set(ui::ACCELEROMETER_SOURCE_SCREEN
,
674 0.0f
, -kMeanGravity
, 0.0f
);
675 controller
->OnAccelerometerUpdated(update
);
676 EXPECT_TRUE(controller
->IsMaximizeModeWindowManagerEnabled());
678 // Trigger 90 degree rotation
679 update
.Set(ui::ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD
,
680 -kMeanGravity
, 0.0f
, 0.0f
);
681 update
.Set(ui::ACCELEROMETER_SOURCE_SCREEN
,
682 -kMeanGravity
, 0.0f
, 0.0f
);
683 controller
->OnAccelerometerUpdated(update
);
684 EXPECT_EQ(gfx::Display::ROTATE_90
, display_manager
->
685 GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation());
687 const base::DictionaryValue
* properties
=
688 local_state()->GetDictionary(prefs::kDisplayProperties
);
689 const base::DictionaryValue
* property
= NULL
;
690 EXPECT_TRUE(properties
->GetDictionary(
691 base::Int64ToString(gfx::Display::InternalDisplayId()), &property
));
693 EXPECT_TRUE(property
->GetInteger("rotation", &rotation
));
694 EXPECT_EQ(gfx::Display::ROTATE_0
, rotation
);
697 // Tests that the rotation state is saved without a user being logged in.
698 TEST_F(DisplayPreferencesTest
, StoreRotationStateNoLogin
) {
699 gfx::Display::SetInternalDisplayId(
700 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id());
701 EXPECT_FALSE(local_state()->HasPrefPath(prefs::kDisplayRotationLock
));
703 bool current_rotation_lock
=
704 ash::Shell::GetInstance()->maximize_mode_controller()->rotation_locked();
705 StoreDisplayRotationPrefs(current_rotation_lock
);
706 EXPECT_TRUE(local_state()->HasPrefPath(prefs::kDisplayRotationLock
));
708 const base::DictionaryValue
* properties
=
709 local_state()->GetDictionary(prefs::kDisplayRotationLock
);
711 EXPECT_TRUE(properties
->GetBoolean("lock", &rotation_lock
));
712 EXPECT_EQ(current_rotation_lock
, rotation_lock
);
715 gfx::Display::Rotation current_rotation
= ash::Shell::GetInstance()->
717 GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation();
718 EXPECT_TRUE(properties
->GetInteger("orientation", &orientation
));
719 EXPECT_EQ(current_rotation
, orientation
);
722 // Tests that the rotation state is saved when a guest is logged in.
723 TEST_F(DisplayPreferencesTest
, StoreRotationStateGuest
) {
724 gfx::Display::SetInternalDisplayId(
725 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id());
726 EXPECT_FALSE(local_state()->HasPrefPath(prefs::kDisplayRotationLock
));
729 bool current_rotation_lock
=
730 ash::Shell::GetInstance()->maximize_mode_controller()->rotation_locked();
731 StoreDisplayRotationPrefs(current_rotation_lock
);
732 EXPECT_TRUE(local_state()->HasPrefPath(prefs::kDisplayRotationLock
));
734 const base::DictionaryValue
* properties
=
735 local_state()->GetDictionary(prefs::kDisplayRotationLock
);
737 EXPECT_TRUE(properties
->GetBoolean("lock", &rotation_lock
));
738 EXPECT_EQ(current_rotation_lock
, rotation_lock
);
741 gfx::Display::Rotation current_rotation
= ash::Shell::GetInstance()->
743 GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation();
744 EXPECT_TRUE(properties
->GetInteger("orientation", &orientation
));
745 EXPECT_EQ(current_rotation
, orientation
);
748 // Tests that the rotation state is saved when a normal user is logged in.
749 TEST_F(DisplayPreferencesTest
, StoreRotationStateNormalUser
) {
750 gfx::Display::SetInternalDisplayId(
751 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id());
752 EXPECT_FALSE(local_state()->HasPrefPath(prefs::kDisplayRotationLock
));
755 bool current_rotation_lock
=
756 ash::Shell::GetInstance()->maximize_mode_controller()->rotation_locked();
757 StoreDisplayRotationPrefs(current_rotation_lock
);
758 EXPECT_TRUE(local_state()->HasPrefPath(prefs::kDisplayRotationLock
));
760 const base::DictionaryValue
* properties
=
761 local_state()->GetDictionary(prefs::kDisplayRotationLock
);
763 EXPECT_TRUE(properties
->GetBoolean("lock", &rotation_lock
));
764 EXPECT_EQ(current_rotation_lock
, rotation_lock
);
767 gfx::Display::Rotation current_rotation
= ash::Shell::GetInstance()->
769 GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation();
770 EXPECT_TRUE(properties
->GetInteger("orientation", &orientation
));
771 EXPECT_EQ(current_rotation
, orientation
);
774 // Tests that rotation state is loaded without a user being logged in, and that
775 // entering maximize mode applies the state.
776 TEST_F(DisplayPreferencesTest
, LoadRotationNoLogin
) {
777 gfx::Display::SetInternalDisplayId(
778 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id());
779 ASSERT_FALSE(local_state()->HasPrefPath(prefs::kDisplayRotationLock
));
781 ash::Shell
* shell
= ash::Shell::GetInstance();
782 ash::MaximizeModeController
* maximize_mode_controller
=
783 shell
->maximize_mode_controller();
784 bool initial_rotation_lock
= maximize_mode_controller
->rotation_locked();
785 ASSERT_FALSE(initial_rotation_lock
);
786 ash::DisplayManager
* display_manager
= shell
->display_manager();
787 gfx::Display::Rotation initial_rotation
= display_manager
->
788 GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation();
789 ASSERT_EQ(gfx::Display::ROTATE_0
, initial_rotation
);
791 StoreDisplayRotationPrefs(initial_rotation_lock
);
792 ASSERT_TRUE(local_state()->HasPrefPath(prefs::kDisplayRotationLock
));
794 StoreDisplayRotationPrefsForTest(true, gfx::Display::ROTATE_90
);
795 LoadDisplayPreferences(false);
797 bool display_rotation_lock
=
798 display_manager
->registered_internal_display_rotation_lock();
799 bool display_rotation
=
800 display_manager
->registered_internal_display_rotation();
801 EXPECT_TRUE(display_rotation_lock
);
802 EXPECT_EQ(gfx::Display::ROTATE_90
, display_rotation
);
804 bool rotation_lock
= maximize_mode_controller
->rotation_locked();
805 gfx::Display::Rotation before_maximize_mode_rotation
= display_manager
->
806 GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation();
808 // Settings should not be applied until maximize mode activates
809 EXPECT_FALSE(rotation_lock
);
810 EXPECT_EQ(gfx::Display::ROTATE_0
, before_maximize_mode_rotation
);
812 // Open up 270 degrees to trigger maximize mode
813 ui::AccelerometerUpdate update
;
814 update
.Set(ui::ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD
,
815 0.0f
, 0.0f
, kMeanGravity
);
816 update
.Set(ui::ACCELEROMETER_SOURCE_SCREEN
,
817 0.0f
, -kMeanGravity
, 0.0f
);
818 maximize_mode_controller
->OnAccelerometerUpdated(update
);
819 EXPECT_TRUE(maximize_mode_controller
->IsMaximizeModeWindowManagerEnabled());
820 bool maximize_mode_rotation_lock
=
821 maximize_mode_controller
->rotation_locked();
822 gfx::Display::Rotation maximize_mode_rotation
= display_manager
->
823 GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation();
824 EXPECT_TRUE(maximize_mode_rotation_lock
);
825 EXPECT_EQ(gfx::Display::ROTATE_90
, maximize_mode_rotation
);
828 // Tests that loaded rotation state is ignored if the device starts in normal
829 // mode, and that they are not applied upon first entering maximize mode.
830 TEST_F(DisplayPreferencesTest
, LoadRotationIgnoredInNormalMode
) {
831 gfx::Display::SetInternalDisplayId(
832 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id());
833 ASSERT_FALSE(local_state()->HasPrefPath(prefs::kDisplayRotationLock
));
834 StoreDisplayRotationPrefs(false /* rotation_lock*/);
835 ASSERT_TRUE(local_state()->HasPrefPath(prefs::kDisplayRotationLock
));
837 StoreDisplayRotationPrefsForTest(true, gfx::Display::ROTATE_90
);
838 LoadDisplayPreferences(false);
840 ash::MaximizeModeController
* maximize_mode_controller
=
841 ash::Shell::GetInstance()->maximize_mode_controller();
842 // Lid open to 90 degrees
843 ui::AccelerometerUpdate update
;
844 update
.Set(ui::ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD
,
845 -kMeanGravity
, 0.0f
, 0.0f
);
846 update
.Set(ui::ACCELEROMETER_SOURCE_SCREEN
,
847 -kMeanGravity
, 0.0f
, 0.0f
);
848 maximize_mode_controller
->OnAccelerometerUpdated(update
);
849 EXPECT_FALSE(maximize_mode_controller
->IsMaximizeModeWindowManagerEnabled());
850 EXPECT_FALSE(maximize_mode_controller
->rotation_locked());
852 // Open up 270 degrees to trigger maximize mode
853 update
.Set(ui::ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD
,
854 0.0f
, 0.0f
, kMeanGravity
);
855 update
.Set(ui::ACCELEROMETER_SOURCE_SCREEN
,
856 0.0f
, -kMeanGravity
, 0.0f
);
857 maximize_mode_controller
->OnAccelerometerUpdated(update
);
858 EXPECT_TRUE(maximize_mode_controller
->IsMaximizeModeWindowManagerEnabled());
859 EXPECT_FALSE(maximize_mode_controller
->rotation_locked());
862 // Tests that rotation lock being set causes the rotation state to be saved.
863 TEST_F(DisplayPreferencesTest
, RotationLockTriggersStore
) {
864 gfx::Display::SetInternalDisplayId(
865 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id());
866 ASSERT_FALSE(local_state()->HasPrefPath(prefs::kDisplayRotationLock
));
868 ash::MaximizeModeController
* maximize_mode_controller
=
869 ash::Shell::GetInstance()->maximize_mode_controller();
870 maximize_mode_controller
->SetRotationLocked(true);
872 EXPECT_TRUE(local_state()->HasPrefPath(prefs::kDisplayRotationLock
));
874 const base::DictionaryValue
* properties
=
875 local_state()->GetDictionary(prefs::kDisplayRotationLock
);
877 EXPECT_TRUE(properties
->GetBoolean("lock", &rotation_lock
));
880 } // namespace chromeos