Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(94)

Side by Side Diff: ui/display/manager/display_preferences.cc

Issue 2760453003: Work In Progess
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 #include "ui/display/manager/display_preferences.h"
6
7 #include <stddef.h>
8
9 #include "ash/shell.h"
10 #include "base/strings/string16.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/string_split.h"
13 #include "base/strings/string_util.h"
14 #include "base/sys_info.h"
15 #include "base/values.h"
16 #include "chrome/browser/browser_process.h"
17 #include "chrome/common/pref_names.h"
18 #include "components/prefs/pref_registry_simple.h"
19 #include "components/prefs/pref_service.h"
20 #include "components/prefs/scoped_user_pref_update.h"
21 #include "components/user_manager/user_manager.h"
22 #include "third_party/cros_system_api/dbus/service_constants.h"
23 #include "ui/display/display.h"
24 #include "ui/display/manager/display_layout_store.h"
25 #include "ui/display/manager/display_manager_utilities.h"
26 #include "ui/display/manager/display_pref_util.h"
27 #include "ui/display/manager/json_converter.h"
28 #include "ui/display/types/display_constants.h"
29 #include "ui/gfx/geometry/insets.h"
30 #include "url/url_canon.h"
31 #include "url/url_util.h"
32
33 #include "services/preferences/public/cpp/pref_client_store.h"
34 #include "services/preferences/public/interfaces/preferences.mojom.h"
35
36 namespace display {
37 namespace {
38
39 const char kInsetsTopKey[] = "insets_top";
40 const char kInsetsLeftKey[] = "insets_left";
41 const char kInsetsBottomKey[] = "insets_bottom";
42 const char kInsetsRightKey[] = "insets_right";
43
44 const char kTouchCalibrationWidth[] = "touch_calibration_width";
45 const char kTouchCalibrationHeight[] = "touch_calibration_height";
46 const char kTouchCalibrationPointPairs[] = "touch_calibration_point_pairs";
47
48 // This kind of boilerplates should be done by base::JSONValueConverter but it
49 // doesn't support classes like gfx::Insets for now.
50 // TODO(mukai): fix base::JSONValueConverter and use it here.
51 bool ValueToInsets(const base::DictionaryValue& value, gfx::Insets* insets) {
52 DCHECK(insets);
53 int top = 0;
54 int left = 0;
55 int bottom = 0;
56 int right = 0;
57 if (value.GetInteger(kInsetsTopKey, &top) &&
58 value.GetInteger(kInsetsLeftKey, &left) &&
59 value.GetInteger(kInsetsBottomKey, &bottom) &&
60 value.GetInteger(kInsetsRightKey, &right)) {
61 insets->Set(top, left, bottom, right);
62 return true;
63 }
64 return false;
65 }
66
67 void InsetsToValue(const gfx::Insets& insets, base::DictionaryValue* value) {
68 DCHECK(value);
69 value->SetInteger(kInsetsTopKey, insets.top());
70 value->SetInteger(kInsetsLeftKey, insets.left());
71 value->SetInteger(kInsetsBottomKey, insets.bottom());
72 value->SetInteger(kInsetsRightKey, insets.right());
73 }
74
75 // Unmarshalls the string containing CalibrationPointPairQuad and populates
76 // |point_pair_quad| with the unmarshalled data.
77 bool ParseTouchCalibrationStringValue(
78 const std::string& str,
79 display::TouchCalibrationData::CalibrationPointPairQuad* point_pair_quad) {
80 DCHECK(point_pair_quad);
81 int x = 0, y = 0;
82 std::vector<std::string> parts = base::SplitString(
83 str, " ", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
84 size_t total = point_pair_quad->size();
85 gfx::Point display_point, touch_point;
86 for (std::size_t row = 0; row < total; row++) {
87 if (!base::StringToInt(parts[row * total], &x) ||
88 !base::StringToInt(parts[row * total + 1], &y)) {
89 return false;
90 }
91 display_point.SetPoint(x, y);
92
93 if (!base::StringToInt(parts[row * total + 2], &x) ||
94 !base::StringToInt(parts[row * total + 3], &y)) {
95 return false;
96 }
97 touch_point.SetPoint(x, y);
98
99 (*point_pair_quad)[row] = std::make_pair(display_point, touch_point);
100 }
101 return true;
102 }
103
104 // Retrieves touch calibration associated data from the dictionary and stores
105 // it in an instance of TouchCalibrationData struct.
106 bool ValueToTouchData(const base::DictionaryValue& value,
107 display::TouchCalibrationData* touch_calibration_data) {
108 display::TouchCalibrationData::CalibrationPointPairQuad* point_pair_quad =
109 &(touch_calibration_data->point_pairs);
110
111 std::string str;
112 if (!value.GetString(kTouchCalibrationPointPairs, &str))
113 return false;
114
115 if (!ParseTouchCalibrationStringValue(str, point_pair_quad))
116 return false;
117
118 int width, height;
119 if (!value.GetInteger(kTouchCalibrationWidth, &width) ||
120 !value.GetInteger(kTouchCalibrationHeight, &height)) {
121 return false;
122 }
123 touch_calibration_data->bounds = gfx::Size(width, height);
124 return true;
125 }
126
127 // Stores the touch calibration data into the dictionary.
128 void TouchDataToValue(
129 const display::TouchCalibrationData& touch_calibration_data,
130 base::DictionaryValue* value) {
131 DCHECK(value);
132 std::string str;
133 for (std::size_t row = 0; row < touch_calibration_data.point_pairs.size();
134 row++) {
135 str +=
136 base::IntToString(touch_calibration_data.point_pairs[row].first.x()) +
137 " ";
138 str +=
139 base::IntToString(touch_calibration_data.point_pairs[row].first.y()) +
140 " ";
141 str +=
142 base::IntToString(touch_calibration_data.point_pairs[row].second.x()) +
143 " ";
144 str +=
145 base::IntToString(touch_calibration_data.point_pairs[row].second.y());
146 if (row != touch_calibration_data.point_pairs.size() - 1)
147 str += " ";
148 }
149 value->SetString(kTouchCalibrationPointPairs, str);
150 value->SetInteger(kTouchCalibrationWidth,
151 touch_calibration_data.bounds.width());
152 value->SetInteger(kTouchCalibrationHeight,
153 touch_calibration_data.bounds.height());
154 }
155
156 std::string ColorProfileToString(display::ColorCalibrationProfile profile) {
157 switch (profile) {
158 case display::COLOR_PROFILE_STANDARD:
159 return "standard";
160 case display::COLOR_PROFILE_DYNAMIC:
161 return "dynamic";
162 case display::COLOR_PROFILE_MOVIE:
163 return "movie";
164 case display::COLOR_PROFILE_READING:
165 return "reading";
166 case display::NUM_COLOR_PROFILES:
167 break;
168 }
169 NOTREACHED();
170 return "";
171 }
172
173 display::ColorCalibrationProfile StringToColorProfile(
174 const std::string& value) {
175 if (value == "standard")
176 return display::COLOR_PROFILE_STANDARD;
177 else if (value == "dynamic")
178 return display::COLOR_PROFILE_DYNAMIC;
179 else if (value == "movie")
180 return display::COLOR_PROFILE_MOVIE;
181 else if (value == "reading")
182 return display::COLOR_PROFILE_READING;
183 NOTREACHED();
184 return display::COLOR_PROFILE_STANDARD;
185 }
186
187 // Returns true id the current user can write display preferences to
188 // Local State.
189 bool UserCanSaveDisplayPreference() {
190 user_manager::UserManager* user_manager = user_manager::UserManager::Get();
191 return user_manager->IsUserLoggedIn() &&
192 (user_manager->IsLoggedInAsUserWithGaiaAccount() ||
193 user_manager->IsLoggedInAsSupervisedUser() ||
194 user_manager->IsLoggedInAsKioskApp());
195 }
196
197 void LoadDisplayLayouts(DisplayManager* display_manager,
198 preferences::PrefClientStore* pref_client_store_) {
199 // PrefService* local_state = g_browser_process->local_state();
200 PrefService* local_state = NULL;
201 display::DisplayLayoutStore* layout_store = display_manager->layout_store();
202
203 const base::DictionaryValue* layouts =
204 local_state->GetDictionary(prefs::kSecondaryDisplays);
205 for (base::DictionaryValue::Iterator it(*layouts); !it.IsAtEnd();
206 it.Advance()) {
207 std::unique_ptr<display::DisplayLayout> layout(new display::DisplayLayout);
208 if (!display::JsonToDisplayLayout(it.value(), layout.get())) {
209 LOG(WARNING) << "Invalid preference value for " << it.key();
210 continue;
211 }
212
213 if (it.key().find(",") != std::string::npos) {
214 std::vector<std::string> ids_str = base::SplitString(
215 it.key(), ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
216 std::vector<int64_t> ids;
217 for (std::string id_str : ids_str) {
218 int64_t id;
219 if (!base::StringToInt64(id_str, &id))
220 continue;
221 ids.push_back(id);
222 }
223 display::DisplayIdList list =
224 display::GenerateDisplayIdList(ids.begin(), ids.end());
225 layout_store->RegisterLayoutForDisplayIdList(list, std::move(layout));
226 }
227 }
228 }
229
230 void LoadDisplayProperties(DisplayManager* display_manager,
231 preferences::PrefClientStore* pref_client_store_) {
232 // PrefService* local_state = g_browser_process->local_state();
233 PrefService* local_state = NULL;
234 const base::DictionaryValue* properties =
235 local_state->GetDictionary(prefs::kDisplayProperties);
236 for (base::DictionaryValue::Iterator it(*properties); !it.IsAtEnd();
237 it.Advance()) {
238 const base::DictionaryValue* dict_value = nullptr;
239 if (!it.value().GetAsDictionary(&dict_value) || dict_value == nullptr)
240 continue;
241 int64_t id = display::kInvalidDisplayId;
242 if (!base::StringToInt64(it.key(), &id) ||
243 id == display::kInvalidDisplayId) {
244 continue;
245 }
246 display::Display::Rotation rotation = display::Display::ROTATE_0;
247 float ui_scale = 1.0f;
248 const gfx::Insets* insets_to_set = nullptr;
249
250 int rotation_value = 0;
251 if (dict_value->GetInteger("rotation", &rotation_value)) {
252 rotation = static_cast<display::Display::Rotation>(rotation_value);
253 }
254 int ui_scale_value = 0;
255 if (dict_value->GetInteger("ui-scale", &ui_scale_value))
256 ui_scale = static_cast<float>(ui_scale_value) / 1000.0f;
257
258 int width = 0, height = 0;
259 dict_value->GetInteger("width", &width);
260 dict_value->GetInteger("height", &height);
261 gfx::Size resolution_in_pixels(width, height);
262
263 float device_scale_factor = 1.0;
264 int dsf_value = 0;
265 if (dict_value->GetInteger("device-scale-factor", &dsf_value))
266 device_scale_factor = static_cast<float>(dsf_value) / 1000.0f;
267
268 gfx::Insets insets;
269 if (ValueToInsets(*dict_value, &insets))
270 insets_to_set = &insets;
271
272 display::TouchCalibrationData calibration_data;
273 display::TouchCalibrationData* calibration_data_to_set = nullptr;
274 if (ValueToTouchData(*dict_value, &calibration_data))
275 calibration_data_to_set = &calibration_data;
276
277 display::ColorCalibrationProfile color_profile =
278 display::COLOR_PROFILE_STANDARD;
279 std::string color_profile_name;
280 if (dict_value->GetString("color_profile_name", &color_profile_name))
281 color_profile = StringToColorProfile(color_profile_name);
282 display_manager->RegisterDisplayProperty(
283 id, rotation, ui_scale, insets_to_set, resolution_in_pixels,
284 device_scale_factor, color_profile, calibration_data_to_set);
285 }
286 }
287
288 void LoadDisplayRotationState(
289 DisplayManager* display_manager,
290 preferences::PrefClientStore* pref_client_store_) {
291 // PrefService* local_state = g_browser_process->local_state();
292 PrefService* local_state = NULL;
293 const base::DictionaryValue* properties =
294 local_state->GetDictionary(prefs::kDisplayRotationLock);
295
296 bool rotation_lock = false;
297 if (!properties->GetBoolean("lock", &rotation_lock))
298 return;
299
300 int rotation = display::Display::ROTATE_0;
301 if (!properties->GetInteger("orientation", &rotation))
302 return;
303
304 display_manager->RegisterDisplayRotationProperties(
305 rotation_lock, static_cast<display::Display::Rotation>(rotation));
306 }
307
308 void StoreDisplayLayoutPref(const display::DisplayIdList& list,
309 const display::DisplayLayout& display_layout) {
310 std::string name = display::DisplayIdListToString(list);
311
312 // PrefService* local_state = g_browser_process->local_state();
313 PrefService* local_state = NULL;
314 DictionaryPrefUpdate update(local_state, prefs::kSecondaryDisplays);
315 base::DictionaryValue* pref_data = update.Get();
316 std::unique_ptr<base::Value> layout_value(new base::DictionaryValue());
317 if (pref_data->HasKey(name)) {
318 base::Value* value = nullptr;
319 if (pref_data->Get(name, &value) && value != nullptr)
320 layout_value.reset(value->DeepCopy());
321 }
322 if (display::DisplayLayoutToJson(display_layout, layout_value.get()))
323 pref_data->Set(name, layout_value.release());
324 }
325
326 void StoreCurrentDisplayLayoutPrefs(DisplayManager* display_manager) {
327 if (!UserCanSaveDisplayPreference() ||
328 display_manager->num_connected_displays() < 2) {
329 return;
330 }
331
332 display::DisplayIdList list = display_manager->GetCurrentDisplayIdList();
333 const display::DisplayLayout& display_layout =
334 display_manager->layout_store()->GetRegisteredDisplayLayout(list);
335 StoreDisplayLayoutPref(list, display_layout);
336 }
337
338 void StoreCurrentDisplayProperties(DisplayManager* display_manager) {
339 // PrefService* local_state = g_browser_process->local_state();
340 PrefService* local_state = NULL;
341
342 DictionaryPrefUpdate update(local_state, prefs::kDisplayProperties);
343 base::DictionaryValue* pref_data = update.Get();
344
345 size_t num = display_manager->GetNumDisplays();
346 for (size_t i = 0; i < num; ++i) {
347 const display::Display& display = display_manager->GetDisplayAt(i);
348 int64_t id = display.id();
349 display::ManagedDisplayInfo info = display_manager->GetDisplayInfo(id);
350
351 std::unique_ptr<base::DictionaryValue> property_value(
352 new base::DictionaryValue());
353 // Don't save the display preference in unified mode because its
354 // size and modes can change depending on the combination of displays.
355 if (display_manager->IsInUnifiedMode())
356 continue;
357 property_value->SetInteger("rotation",
358 static_cast<int>(info.GetRotation(
359 display::Display::ROTATION_SOURCE_USER)));
360 property_value->SetInteger(
361 "ui-scale", static_cast<int>(info.configured_ui_scale() * 1000));
362
363 scoped_refptr<display::ManagedDisplayMode> mode =
364 display_manager->GetSelectedModeForDisplayId(id);
365 if (!display.IsInternal() && mode && !mode->native()) {
366 property_value->SetInteger("width", mode->size().width());
367 property_value->SetInteger("height", mode->size().height());
368 property_value->SetInteger(
369 "device-scale-factor",
370 static_cast<int>(mode->device_scale_factor() * 1000));
371 }
372 if (!info.overscan_insets_in_dip().IsEmpty())
373 InsetsToValue(info.overscan_insets_in_dip(), property_value.get());
374 if (info.color_profile() != display::COLOR_PROFILE_STANDARD) {
375 property_value->SetString("color_profile_name",
376 ColorProfileToString(info.color_profile()));
377 }
378 if (info.has_touch_calibration_data())
379 TouchDataToValue(info.GetTouchCalibrationData(), property_value.get());
380 pref_data->Set(base::Int64ToString(id), property_value.release());
381 }
382 }
383
384 typedef std::map<chromeos::DisplayPowerState, std::string>
385 DisplayPowerStateToStringMap;
386
387 const DisplayPowerStateToStringMap* GetDisplayPowerStateToStringMap() {
388 // Don't save or retore ALL_OFF state. crbug.com/318456.
389 static const DisplayPowerStateToStringMap* map = display::CreateToStringMap(
390 chromeos::DISPLAY_POWER_ALL_ON, "all_on",
391 chromeos::DISPLAY_POWER_INTERNAL_OFF_EXTERNAL_ON,
392 "internal_off_external_on",
393 chromeos::DISPLAY_POWER_INTERNAL_ON_EXTERNAL_OFF,
394 "internal_on_external_off");
395 return map;
396 }
397
398 bool GetDisplayPowerStateFromString(const base::StringPiece& state,
399 chromeos::DisplayPowerState* field) {
400 if (display::ReverseFind(GetDisplayPowerStateToStringMap(), state, field))
401 return true;
402 LOG(ERROR) << "Invalid display power state value:" << state;
403 return false;
404 }
405
406 void StoreDisplayPowerState(chromeos::DisplayPowerState power_state) {
407 const DisplayPowerStateToStringMap* map = GetDisplayPowerStateToStringMap();
408 DisplayPowerStateToStringMap::const_iterator iter = map->find(power_state);
409 if (iter != map->end()) {
410 // PrefService* local_state = g_browser_process->local_state();
411 PrefService* local_state = NULL;
412 local_state->SetString(prefs::kDisplayPowerState, iter->second);
413 }
414 }
415
416 void StoreCurrentDisplayPowerState(DisplayConfigurator* display_configurator) {
417 StoreDisplayPowerState(display_configurator->requested_power_state());
418 }
419
420 void StoreDisplayRotationPrefs(DisplayManager* display_manager,
421 bool rotation_lock) {
422 if (!display::Display::HasInternalDisplay())
423 return;
424
425 // PrefService* local_state = g_browser_process->local_state();
426 PrefService* local_state = NULL;
427 DictionaryPrefUpdate update(local_state, prefs::kDisplayRotationLock);
428 base::DictionaryValue* pref_data = update.Get();
429 pref_data->SetBoolean("lock", rotation_lock);
430 display::Display::Rotation rotation =
431 display_manager->GetDisplayInfo(display::Display::InternalDisplayId())
432 .GetRotation(display::Display::ROTATION_SOURCE_ACCELEROMETER);
433 pref_data->SetInteger("orientation", static_cast<int>(rotation));
434 }
435
436 void StoreCurrentDisplayRotationLockPrefs(DisplayManager* display_manager) {
437 bool rotation_lock =
438 display_manager->registered_internal_display_rotation_lock();
439 StoreDisplayRotationPrefs(display_manager, rotation_lock);
440 }
441
442 } // namespace
443
444 void RegisterDisplayLocalStatePrefs(PrefRegistrySimple* registry) {
445 // Per-display preference.
446 registry->RegisterDictionaryPref(prefs::kSecondaryDisplays);
447 registry->RegisterDictionaryPref(prefs::kDisplayProperties);
448 DisplayPowerStateToStringMap::const_iterator iter =
449 GetDisplayPowerStateToStringMap()->find(chromeos::DISPLAY_POWER_ALL_ON);
450 registry->RegisterStringPref(prefs::kDisplayPowerState, iter->second);
451 registry->RegisterDictionaryPref(prefs::kDisplayRotationLock);
452 }
453
454 void StoreDisplayPrefs(DisplayConfigurator* display_configurator,
455 DisplayManager* display_manager) {
456 // Stores the power state regardless of the login status, because the power
457 // state respects to the current status (close/open) of the lid which can be
458 // changed in any situation. See crbug.com/285360
459 StoreCurrentDisplayPowerState(display_configurator);
460 StoreCurrentDisplayRotationLockPrefs(display_manager);
461
462 // Do not store prefs when the confirmation dialog is shown.
463 if (!UserCanSaveDisplayPreference() ||
464 !ash::Shell::GetInstance()->ShouldSaveDisplaySettings()) {
465 return;
466 }
467
468 StoreCurrentDisplayLayoutPrefs(display_manager);
469 StoreCurrentDisplayProperties(display_manager);
470 }
471
472 void LoadDisplayPreferences(bool first_run_after_boot,
473 DisplayConfigurator* display_configurator,
474 DisplayManager* display_manager,
475 preferences::PrefClientStore* pref_client_store_) {
476 // void LoadDisplayPreferences(bool first_run_after_boot, DisplayConfigurator*
477 // display_configurator, DisplayManager* display_manager) {
478 LoadDisplayLayouts(display_manager, pref_client_store_);
479 LoadDisplayProperties(display_manager, pref_client_store_);
480 LoadDisplayRotationState(display_manager, pref_client_store_);
481 if (!first_run_after_boot) {
482 // PrefService* local_state = g_browser_process->local_state();
483 PrefService* local_state = NULL;
484 // Restore DisplayPowerState:
485 std::string value = local_state->GetString(prefs::kDisplayPowerState);
486 chromeos::DisplayPowerState power_state;
487 if (GetDisplayPowerStateFromString(value, &power_state)) {
488 display_configurator->SetInitialDisplayPower(power_state);
489 }
490 }
491 }
492
493 // Stores the display layout for given display pairs.
494 void StoreDisplayLayoutPrefForTest(const display::DisplayIdList& list,
495 const display::DisplayLayout& layout) {
496 StoreDisplayLayoutPref(list, layout);
497 }
498
499 // Stores the given |power_state|.
500 void StoreDisplayPowerStateForTest(chromeos::DisplayPowerState power_state) {
501 StoreDisplayPowerState(power_state);
502 }
503
504 bool ParseTouchCalibrationStringForTest(
505 const std::string& str,
506 display::TouchCalibrationData::CalibrationPointPairQuad* point_pair_quad) {
507 return ParseTouchCalibrationStringValue(str, point_pair_quad);
508 }
509
510 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698