| 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 |