OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/chromeos/display/display_preferences.h" | 5 #include "chrome/browser/chromeos/display/display_preferences.h" |
6 | 6 |
7 #include "ash/display/display_controller.h" | 7 #include "ash/display/display_controller.h" |
8 #include "ash/display/display_manager.h" | 8 #include "ash/display/display_manager.h" |
9 #include "ash/shell.h" | 9 #include "ash/shell.h" |
10 #include "base/prefs/pref_registry_simple.h" | 10 #include "base/prefs/pref_registry_simple.h" |
11 #include "base/prefs/pref_service.h" | 11 #include "base/prefs/pref_service.h" |
12 #include "base/string16.h" | 12 #include "base/string16.h" |
13 #include "base/string_util.h" | 13 #include "base/string_util.h" |
14 #include "base/strings/string_number_conversions.h" | 14 #include "base/strings/string_number_conversions.h" |
15 #include "base/strings/string_split.h" | 15 #include "base/strings/string_split.h" |
16 #include "base/values.h" | 16 #include "base/values.h" |
17 #include "chrome/browser/browser_process.h" | 17 #include "chrome/browser/browser_process.h" |
18 #include "chrome/browser/chromeos/login/user_manager.h" | 18 #include "chrome/browser/chromeos/login/user_manager.h" |
19 #include "chrome/browser/prefs/scoped_user_pref_update.h" | 19 #include "chrome/browser/prefs/scoped_user_pref_update.h" |
20 #include "chrome/common/pref_names.h" | 20 #include "chrome/common/pref_names.h" |
21 #include "googleurl/src/url_canon.h" | 21 #include "googleurl/src/url_canon.h" |
22 #include "googleurl/src/url_util.h" | 22 #include "googleurl/src/url_util.h" |
23 #include "ui/gfx/display.h" | 23 #include "ui/gfx/display.h" |
24 #include "ui/gfx/insets.h" | 24 #include "ui/gfx/insets.h" |
25 #include "ui/gfx/screen.h" | 25 #include "ui/gfx/screen.h" |
26 | 26 |
27 namespace chromeos { | 27 namespace chromeos { |
28 namespace { | 28 namespace { |
29 | 29 |
| 30 const char kInsetsTopKey[] = "insets_top"; |
| 31 const char kInsetsLeftKey[] = "insets_left"; |
| 32 const char kInsetsBottomKey[] = "insets_bottom"; |
| 33 const char kInsetsRightKey[] = "insets_right"; |
| 34 |
30 // This kind of boilerplates should be done by base::JSONValueConverter but it | 35 // This kind of boilerplates should be done by base::JSONValueConverter but it |
31 // doesn't support classes like gfx::Insets for now. | 36 // doesn't support classes like gfx::Insets for now. |
32 // TODO(mukai): fix base::JSONValueConverter and use it here. | 37 // TODO(mukai): fix base::JSONValueConverter and use it here. |
33 bool ValueToInsets(const base::DictionaryValue& value, gfx::Insets* insets) { | 38 bool ValueToInsets(const base::DictionaryValue& value, gfx::Insets* insets) { |
34 DCHECK(insets); | 39 DCHECK(insets); |
35 int top = 0; | 40 int top = 0; |
36 int left = 0; | 41 int left = 0; |
37 int bottom = 0; | 42 int bottom = 0; |
38 int right = 0; | 43 int right = 0; |
39 if (value.GetInteger("top", &top) && | 44 if (value.GetInteger(kInsetsTopKey, &top) && |
40 value.GetInteger("left", &left) && | 45 value.GetInteger(kInsetsLeftKey, &left) && |
41 value.GetInteger("bottom", &bottom) && | 46 value.GetInteger(kInsetsBottomKey, &bottom) && |
42 value.GetInteger("right", &right)) { | 47 value.GetInteger(kInsetsRightKey, &right)) { |
43 insets->Set(top, left, bottom, right); | 48 insets->Set(top, left, bottom, right); |
44 return true; | 49 return true; |
45 } | 50 } |
46 return false; | 51 return false; |
47 } | 52 } |
48 | 53 |
49 void InsetsToValue(const gfx::Insets& insets, base::DictionaryValue* value) { | 54 void InsetsToValue(const gfx::Insets& insets, base::DictionaryValue* value) { |
50 DCHECK(value); | 55 DCHECK(value); |
51 value->SetInteger("top", insets.top()); | 56 value->SetInteger(kInsetsTopKey, insets.top()); |
52 value->SetInteger("left", insets.left()); | 57 value->SetInteger(kInsetsLeftKey, insets.left()); |
53 value->SetInteger("bottom", insets.bottom()); | 58 value->SetInteger(kInsetsBottomKey, insets.bottom()); |
54 value->SetInteger("right", insets.right()); | 59 value->SetInteger(kInsetsRightKey, insets.right()); |
55 } | 60 } |
56 | 61 |
57 ash::internal::DisplayManager* GetDisplayManager() { | 62 ash::internal::DisplayManager* GetDisplayManager() { |
58 return ash::Shell::GetInstance()->display_manager(); | 63 return ash::Shell::GetInstance()->display_manager(); |
59 } | 64 } |
60 | 65 |
61 // Returns true id the current user can write display preferences to | 66 // Returns true id the current user can write display preferences to |
62 // Local State. | 67 // Local State. |
63 bool IsValidUser() { | 68 bool IsValidUser() { |
64 UserManager* user_manager = UserManager::Get(); | 69 UserManager* user_manager = UserManager::Get(); |
65 return (user_manager->IsUserLoggedIn() && | 70 return (user_manager->IsUserLoggedIn() && |
66 !user_manager->IsLoggedInAsDemoUser() && | 71 !user_manager->IsLoggedInAsDemoUser() && |
67 !user_manager->IsLoggedInAsGuest() && | 72 !user_manager->IsLoggedInAsGuest() && |
68 !user_manager->IsLoggedInAsStub()); | 73 !user_manager->IsLoggedInAsStub()); |
69 } | 74 } |
70 | 75 |
71 ash::DisplayController* GetDisplayController() { | 76 ash::DisplayController* GetDisplayController() { |
72 return ash::Shell::GetInstance()->display_controller(); | 77 return ash::Shell::GetInstance()->display_controller(); |
73 } | 78 } |
74 | 79 |
75 void NotifyDisplayLayoutChanged() { | 80 void LoadDisplayLayouts() { |
76 PrefService* local_state = g_browser_process->local_state(); | 81 PrefService* local_state = g_browser_process->local_state(); |
77 ash::DisplayController* display_controller = GetDisplayController(); | 82 ash::DisplayController* display_controller = GetDisplayController(); |
78 | 83 |
79 ash::DisplayLayout default_layout = ash::DisplayLayout::FromInts( | 84 ash::DisplayLayout default_layout = ash::DisplayLayout::FromInts( |
80 local_state->GetInteger(prefs::kSecondaryDisplayLayout), | 85 local_state->GetInteger(prefs::kSecondaryDisplayLayout), |
81 local_state->GetInteger(prefs::kSecondaryDisplayOffset)); | 86 local_state->GetInteger(prefs::kSecondaryDisplayOffset)); |
82 display_controller->SetDefaultDisplayLayout(default_layout); | 87 display_controller->SetDefaultDisplayLayout(default_layout); |
83 | 88 |
84 const base::DictionaryValue* layouts = local_state->GetDictionary( | 89 const base::DictionaryValue* layouts = local_state->GetDictionary( |
85 prefs::kSecondaryDisplays); | 90 prefs::kSecondaryDisplays); |
(...skipping 20 matching lines...) Expand all Loading... |
106 int64 id = gfx::Display::kInvalidDisplayID; | 111 int64 id = gfx::Display::kInvalidDisplayID; |
107 if (!base::StringToInt64(it.key(), &id) || | 112 if (!base::StringToInt64(it.key(), &id) || |
108 id == gfx::Display::kInvalidDisplayID) { | 113 id == gfx::Display::kInvalidDisplayID) { |
109 continue; | 114 continue; |
110 } | 115 } |
111 display_controller->RegisterLayoutForDisplayId(id, layout); | 116 display_controller->RegisterLayoutForDisplayId(id, layout); |
112 } | 117 } |
113 } | 118 } |
114 } | 119 } |
115 | 120 |
116 void NotifyDisplayOverscans() { | 121 void LoadDisplayProperties() { |
117 PrefService* local_state = g_browser_process->local_state(); | 122 PrefService* local_state = g_browser_process->local_state(); |
118 | 123 const base::DictionaryValue* properties = local_state->GetDictionary( |
119 const base::DictionaryValue* overscans = local_state->GetDictionary( | 124 prefs::kDisplayProperties); |
120 prefs::kDisplayOverscans); | 125 for (DictionaryValue::Iterator it(*properties); !it.IsAtEnd(); it.Advance()) { |
121 for (DictionaryValue::Iterator it(*overscans); | 126 const base::DictionaryValue* dict_value = NULL; |
122 !it.IsAtEnd(); | 127 if (!it.value().GetAsDictionary(&dict_value) || dict_value == NULL) |
123 it.Advance()) { | 128 continue; |
124 int64 display_id = gfx::Display::kInvalidDisplayID; | 129 int64 id = gfx::Display::kInvalidDisplayID; |
125 if (!base::StringToInt64(it.key(), &display_id)) { | 130 if (!base::StringToInt64(it.key(), &id) || |
126 LOG(WARNING) << "Invalid key, cannot convert to display ID: " << it.key(); | 131 id == gfx::Display::kInvalidDisplayID) { |
127 continue; | 132 continue; |
128 } | 133 } |
| 134 gfx::Display::Rotation rotation = gfx::Display::ROTATE_0; |
| 135 float ui_scale = 1.0f; |
| 136 const gfx::Insets* insets_to_set = NULL; |
129 | 137 |
130 const base::DictionaryValue* value = NULL; | 138 int rotation_value = 0; |
131 if (!it.value().GetAsDictionary(&value)) { | 139 if (dict_value->GetInteger("rotation", &rotation_value)) { |
132 LOG(WARNING) << "Can't find dictionary value for " << it.key(); | 140 rotation = static_cast<gfx::Display::Rotation>(rotation_value); |
133 continue; | |
134 } | 141 } |
135 | 142 int ui_scale_value = 0; |
| 143 if (dict_value->GetInteger("ui-scale", &ui_scale_value)) |
| 144 ui_scale = static_cast<float>(ui_scale_value) / 100.0f; |
136 gfx::Insets insets; | 145 gfx::Insets insets; |
137 if (!ValueToInsets(*value, &insets)) { | 146 if (ValueToInsets(*dict_value, &insets)) |
138 LOG(WARNING) << "Can't convert the data into insets for " << it.key(); | 147 insets_to_set = &insets; |
139 continue; | 148 GetDisplayManager()->RegisterDisplayProperty(id, |
140 } | 149 rotation, |
141 | 150 ui_scale, |
142 GetDisplayController()->SetOverscanInsets(display_id, insets); | 151 insets_to_set); |
143 } | 152 } |
144 } | 153 } |
145 | 154 |
146 void StoreDisplayLayoutPref(const ash::DisplayIdPair& pair, | 155 void StoreDisplayLayoutPref(const ash::DisplayIdPair& pair, |
147 const ash::DisplayLayout& display_layout) { | 156 const ash::DisplayLayout& display_layout) { |
148 std::string name = | 157 std::string name = |
149 base::Int64ToString(pair.first) + "," + base::Int64ToString(pair.second); | 158 base::Int64ToString(pair.first) + "," + base::Int64ToString(pair.second); |
150 | 159 |
151 PrefService* local_state = g_browser_process->local_state(); | 160 PrefService* local_state = g_browser_process->local_state(); |
152 DictionaryPrefUpdate update(local_state, prefs::kSecondaryDisplays); | 161 DictionaryPrefUpdate update(local_state, prefs::kSecondaryDisplays); |
(...skipping 12 matching lines...) Expand all Loading... |
165 if (!IsValidUser() || gfx::Screen::GetNativeScreen()->GetNumDisplays() < 2) | 174 if (!IsValidUser() || gfx::Screen::GetNativeScreen()->GetNumDisplays() < 2) |
166 return; | 175 return; |
167 | 176 |
168 ash::DisplayController* display_controller = GetDisplayController(); | 177 ash::DisplayController* display_controller = GetDisplayController(); |
169 ash::DisplayIdPair pair = display_controller->GetCurrentDisplayIdPair(); | 178 ash::DisplayIdPair pair = display_controller->GetCurrentDisplayIdPair(); |
170 ash::DisplayLayout display_layout = | 179 ash::DisplayLayout display_layout = |
171 display_controller->GetRegisteredDisplayLayout(pair); | 180 display_controller->GetRegisteredDisplayLayout(pair); |
172 StoreDisplayLayoutPref(pair, display_layout); | 181 StoreDisplayLayoutPref(pair, display_layout); |
173 } | 182 } |
174 | 183 |
| 184 void StoreCurrentDisplayProperties() { |
| 185 ash::internal::DisplayManager* display_manager = GetDisplayManager(); |
| 186 PrefService* local_state = g_browser_process->local_state(); |
| 187 |
| 188 DictionaryPrefUpdate update(local_state, prefs::kDisplayProperties); |
| 189 base::DictionaryValue* pref_data = update.Get(); |
| 190 |
| 191 size_t num = display_manager->GetNumDisplays(); |
| 192 for (size_t i = 0; i < num; ++i) { |
| 193 int64 id = display_manager->GetDisplayAt(i)->id(); |
| 194 ash::internal::DisplayInfo info = display_manager->GetDisplayInfo(id); |
| 195 |
| 196 scoped_ptr<base::DictionaryValue> property_value( |
| 197 new base::DictionaryValue()); |
| 198 property_value->SetInteger("rotation", static_cast<int>(info.rotation())); |
| 199 property_value->SetInteger("ui-scale", |
| 200 static_cast<int>(info.ui_scale() * 100)); |
| 201 if (info.has_custom_overscan_insets()) |
| 202 InsetsToValue(info.overscan_insets_in_dip(), property_value.get()); |
| 203 pref_data->Set(base::Int64ToString(id), property_value.release()); |
| 204 } |
| 205 } |
175 | 206 |
176 void StorePrimaryDisplayIDPref(int64 display_id) { | 207 void StorePrimaryDisplayIDPref(int64 display_id) { |
177 if (!IsValidUser() || gfx::Screen::GetNativeScreen()->GetNumDisplays() < 2) | 208 if (!IsValidUser() || gfx::Screen::GetNativeScreen()->GetNumDisplays() < 2) |
178 return; | 209 return; |
179 | 210 |
180 PrefService* local_state = g_browser_process->local_state(); | 211 PrefService* local_state = g_browser_process->local_state(); |
181 if (GetDisplayManager()->IsInternalDisplayId(display_id)) | 212 if (GetDisplayManager()->IsInternalDisplayId(display_id)) |
182 local_state->ClearPref(prefs::kPrimaryDisplayID); | 213 local_state->ClearPref(prefs::kPrimaryDisplayID); |
183 else | 214 else |
184 local_state->SetInt64(prefs::kPrimaryDisplayID, display_id); | 215 local_state->SetInt64(prefs::kPrimaryDisplayID, display_id); |
185 } | 216 } |
186 | 217 |
187 } // namespace | 218 } // namespace |
188 | 219 |
189 void RegisterDisplayLocalStatePrefs(PrefRegistrySimple* registry) { | 220 void RegisterDisplayLocalStatePrefs(PrefRegistrySimple* registry) { |
190 // The default secondary display layout. | 221 // The default secondary display layout. |
191 registry->RegisterIntegerPref(prefs::kSecondaryDisplayLayout, | 222 registry->RegisterIntegerPref(prefs::kSecondaryDisplayLayout, |
192 static_cast<int>(ash::DisplayLayout::RIGHT)); | 223 static_cast<int>(ash::DisplayLayout::RIGHT)); |
193 // The default offset of the secondary display position from the primary | 224 // The default offset of the secondary display position from the primary |
194 // display. | 225 // display. |
195 registry->RegisterIntegerPref(prefs::kSecondaryDisplayOffset, 0); | 226 registry->RegisterIntegerPref(prefs::kSecondaryDisplayOffset, 0); |
196 // Per-display preference. | 227 // Per-display preference. |
197 registry->RegisterDictionaryPref(prefs::kSecondaryDisplays); | 228 registry->RegisterDictionaryPref(prefs::kSecondaryDisplays); |
| 229 registry->RegisterDictionaryPref(prefs::kDisplayProperties); |
198 | 230 |
199 // Primary output name. | 231 // Primary output name. |
200 registry->RegisterInt64Pref(prefs::kPrimaryDisplayID, | 232 registry->RegisterInt64Pref(prefs::kPrimaryDisplayID, |
201 gfx::Display::kInvalidDisplayID); | 233 gfx::Display::kInvalidDisplayID); |
202 | |
203 // Display overscan preference. | |
204 registry->RegisterDictionaryPref(prefs::kDisplayOverscans); | |
205 } | 234 } |
206 | 235 |
207 void StoreDisplayPrefs() { | 236 void StoreDisplayPrefs() { |
208 if (!IsValidUser()) | 237 if (!IsValidUser()) |
209 return; | 238 return; |
210 if (gfx::Screen::GetNativeScreen()->GetNumDisplays() == 2) { | 239 if (gfx::Screen::GetNativeScreen()->GetNumDisplays() == 2) { |
211 StorePrimaryDisplayIDPref( | 240 StorePrimaryDisplayIDPref( |
212 ash::Shell::GetScreen()->GetPrimaryDisplay().id()); | 241 ash::Shell::GetScreen()->GetPrimaryDisplay().id()); |
213 StoreCurrentDisplayLayoutPrefs(); | 242 StoreCurrentDisplayLayoutPrefs(); |
214 } | 243 } |
| 244 StoreCurrentDisplayProperties(); |
215 } | 245 } |
216 | 246 |
217 void SetCurrentAndDefaultDisplayLayout(const ash::DisplayLayout& layout) { | 247 void SetCurrentAndDefaultDisplayLayout(const ash::DisplayLayout& layout) { |
218 ash::DisplayController* display_controller = GetDisplayController(); | 248 ash::DisplayController* display_controller = GetDisplayController(); |
219 display_controller->SetLayoutForCurrentDisplays(layout); | 249 display_controller->SetLayoutForCurrentDisplays(layout); |
220 | 250 |
221 if (IsValidUser()) { | 251 if (IsValidUser()) { |
222 PrefService* local_state = g_browser_process->local_state(); | 252 PrefService* local_state = g_browser_process->local_state(); |
223 ash::DisplayIdPair pair = display_controller->GetCurrentDisplayIdPair(); | 253 ash::DisplayIdPair pair = display_controller->GetCurrentDisplayIdPair(); |
224 // Use registered layout as the layout might have been inverted when | 254 // Use registered layout as the layout might have been inverted when |
225 // the displays are swapped. | 255 // the displays are swapped. |
226 ash::DisplayLayout display_layout = | 256 ash::DisplayLayout display_layout = |
227 display_controller->GetRegisteredDisplayLayout(pair); | 257 display_controller->GetRegisteredDisplayLayout(pair); |
228 local_state->SetInteger(prefs::kSecondaryDisplayLayout, | 258 local_state->SetInteger(prefs::kSecondaryDisplayLayout, |
229 static_cast<int>(display_layout.position)); | 259 static_cast<int>(display_layout.position)); |
230 local_state->SetInteger(prefs::kSecondaryDisplayOffset, | 260 local_state->SetInteger(prefs::kSecondaryDisplayOffset, |
231 display_layout.offset); | 261 display_layout.offset); |
232 } | 262 } |
233 } | 263 } |
234 | 264 |
235 void SetAndStoreDisplayOverscan(const gfx::Display& display, | 265 void LoadDisplayPreferences() { |
236 const gfx::Insets& insets) { | |
237 if (IsValidUser()) { | |
238 DictionaryPrefUpdate update( | |
239 g_browser_process->local_state(), prefs::kDisplayOverscans); | |
240 const std::string id = base::Int64ToString(display.id()); | |
241 | |
242 base::DictionaryValue* pref_data = update.Get(); | |
243 base::DictionaryValue* insets_value = new base::DictionaryValue(); | |
244 InsetsToValue(insets, insets_value); | |
245 pref_data->Set(id, insets_value); | |
246 } | |
247 | |
248 ash::Shell::GetInstance()->display_controller()->SetOverscanInsets( | |
249 display.id(), insets); | |
250 } | |
251 | |
252 void NotifyDisplayLocalStatePrefChanged() { | |
253 PrefService* local_state = g_browser_process->local_state(); | 266 PrefService* local_state = g_browser_process->local_state(); |
254 ash::Shell::GetInstance()->display_controller()->SetPrimaryDisplayId( | 267 ash::Shell::GetInstance()->display_controller()->SetPrimaryDisplayId( |
255 local_state->GetInt64(prefs::kPrimaryDisplayID)); | 268 local_state->GetInt64(prefs::kPrimaryDisplayID)); |
256 NotifyDisplayLayoutChanged(); | 269 LoadDisplayLayouts(); |
257 NotifyDisplayOverscans(); | 270 LoadDisplayProperties(); |
| 271 GetDisplayManager()->UpdateDisplays(); |
258 } | 272 } |
259 | 273 |
260 // Stores the display layout for given display pairs. | 274 // Stores the display layout for given display pairs. |
261 void StoreDisplayLayoutPrefForTest(int64 id1, | 275 void StoreDisplayLayoutPrefForTest(int64 id1, |
262 int64 id2, | 276 int64 id2, |
263 const ash::DisplayLayout& layout) { | 277 const ash::DisplayLayout& layout) { |
264 StoreDisplayLayoutPref(std::make_pair(id1, id2), layout); | 278 StoreDisplayLayoutPref(std::make_pair(id1, id2), layout); |
265 } | 279 } |
266 | 280 |
267 } // namespace chromeos | 281 } // namespace chromeos |
OLD | NEW |